From 0ad98bc5e703f086310047fcbe0d444005c62c49 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Sun, 7 May 2023 21:37:40 -0700 Subject: [PATCH 1/4] setup basics --- packages/asm/CHANGELOG.md | 1 + packages/asm/LICENSE | 201 ++++++++++++++++++++++++++++++++++++ packages/asm/README.md | 51 +++++++++ packages/asm/package.json | 33 ++++++ packages/asm/tsconfig.json | 7 ++ packages/asm/tsup.config.ts | 11 ++ pnpm-lock.yaml | 9 ++ 7 files changed, 313 insertions(+) create mode 100644 packages/asm/CHANGELOG.md create mode 100644 packages/asm/LICENSE create mode 100644 packages/asm/README.md create mode 100644 packages/asm/package.json create mode 100644 packages/asm/tsconfig.json create mode 100644 packages/asm/tsup.config.ts diff --git a/packages/asm/CHANGELOG.md b/packages/asm/CHANGELOG.md new file mode 100644 index 00000000000..420e6f23d0e --- /dev/null +++ b/packages/asm/CHANGELOG.md @@ -0,0 +1 @@ +# Change Log diff --git a/packages/asm/LICENSE b/packages/asm/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/packages/asm/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/asm/README.md b/packages/asm/README.md new file mode 100644 index 00000000000..1e55b680267 --- /dev/null +++ b/packages/asm/README.md @@ -0,0 +1,51 @@ +# `@fuel-ts/asm` + +**@fuel-ts/asm** is a sub-module for interacting with **Fuel**. + +This module is responsible for tools to generate an instruction set for the FuelVM. + +# Table of contents + +- [Documentation](#documentation) +- [Usage](#usage) + - [Installation](#installation) + - [Full SDK Installation](#full-sdk-installation) +- [Contributing](#contributing) +- [Changelog](#changelog) +- [License](#license) + +## Documentation + +See [Fuel-ts Documentation](https://fuellabs.github.io/fuels-ts/packages/fuel-ts-asm/) + +## Usage + +### Installation + +```sh +yarn add @fuel-ts/asm +# or +npm add @fuel-ts/asm +``` + +### Full SDK Installation + +Alternatively, we recommend you install the [complete SDK](https://github.com/FuelLabs/fuels-ts) using the umbrella package: + +```sh +yarn add fuels +# or +npm add fuels +``` + +## Contributing + +In order to contribute to `@fuel-ts/asm`, please see the main [fuels-ts](https://github.com/FuelLabs/fuels-ts) monorepo. + +## Changelog + +The `@fuel-ts/asm` changelog can be found at [CHANGELOG](./CHANGELOG.md). + +## License + +The primary license for `@fuel-ts/asm` is `Apache 2.0`, see [LICENSE](./LICENSE). diff --git a/packages/asm/package.json b/packages/asm/package.json new file mode 100644 index 00000000000..f8a40581f3e --- /dev/null +++ b/packages/asm/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fuel-ts/asm", + "version": "0.41.0", + "description": "", + "author": "Fuel Labs (https://fuel.network/)", + "exports": { + ".": "./src/index.ts" + }, + "types": "src/index.ts", + "publishConfig": { + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "types": "./dist/index.d.ts" + } + } + }, + "files": [ + "dist" + ], + "license": "Apache-2.0", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@fuel-ts/math": "workspace:*" + }, + "scripts": { + "build": "tsup --dts" + } +} diff --git a/packages/asm/tsconfig.json b/packages/asm/tsconfig.json new file mode 100644 index 00000000000..b0fced27d72 --- /dev/null +++ b/packages/asm/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": ["src"] +} diff --git a/packages/asm/tsup.config.ts b/packages/asm/tsup.config.ts new file mode 100644 index 00000000000..e64b3dfa770 --- /dev/null +++ b/packages/asm/tsup.config.ts @@ -0,0 +1,11 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'tsup'; + +export default defineConfig((options) => ({ + entry: ['src/index.ts'], + format: ['cjs', 'esm', 'iife'], + splitting: false, + sourcemap: true, + clean: false, + minify: !options.watch, +})); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8cc71854a59..0b0fad9b189 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -277,6 +277,15 @@ importers: specifier: workspace:* version: link:../testcases + packages/asm: + dependencies: + '@ethersproject/bytes': + specifier: ^5.7.0 + version: 5.7.0 + '@fuel-ts/math': + specifier: workspace:* + version: link:../math + packages/contract: dependencies: '@ethersproject/bytes': From 2c7666e6aaedcf507bfbaeb1c56a89ff2ce5b760 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Sun, 7 May 2023 21:40:10 -0700 Subject: [PATCH 2/4] initial baseline implementation --- packages/asm/src/constants.ts | 617 +++++++++++++++++++++++++++ packages/asm/src/index.test.ts | 126 ++++++ packages/asm/src/index.ts | 3 + packages/asm/src/instruction.test.ts | 60 +++ packages/asm/src/instruction.ts | 78 ++++ packages/asm/src/opcode.ts | 355 +++++++++++++++ 6 files changed, 1239 insertions(+) create mode 100644 packages/asm/src/constants.ts create mode 100644 packages/asm/src/index.test.ts create mode 100644 packages/asm/src/index.ts create mode 100644 packages/asm/src/instruction.test.ts create mode 100644 packages/asm/src/instruction.ts create mode 100644 packages/asm/src/opcode.ts diff --git a/packages/asm/src/constants.ts b/packages/asm/src/constants.ts new file mode 100644 index 00000000000..bb869632c56 --- /dev/null +++ b/packages/asm/src/constants.ts @@ -0,0 +1,617 @@ +/* FLAG AND REGISTER TYPES */ + +/// Register count for checking constraints +export const VM_REGISTER_COUNT = 64; + +/// Contains zero (0), for convenience. +export const REG_ZERO = 0x00; + +/// Contains one (1), for convenience. +export const REG_ONE = 0x01; + +/// Contains overflow/underflow of addition, subtraction, and multiplication. +export const REG_OF = 0x02; + +/// The program counter. Memory address of the current instruction. +export const REG_PC = 0x03; + +/// Memory address of bottom of current writable stack area. +export const REG_SSP = 0x04; + +/// Memory address on top of current writable stack area (points to free +/// memory). +export const REG_SP = 0x05; + +/// Memory address of beginning of current call frame. +export const REG_FP = 0x06; + +/// Memory address below the current bottom of the heap (points to free memory). +export const REG_HP = 0x07; + +/// Error codes for particular operations. +export const REG_ERR = 0x08; + +/// Remaining gas globally. +export const REG_GGAS = 0x09; + +/// Remaining gas in the context. +export const REG_CGAS = 0x0a; + +/// Received balance for this context. +export const REG_BAL = 0x0b; + +/// Pointer to the start of the currently-executing code. +export const REG_IS = 0x0c; + +/// Return value or pointer. +export const REG_RET = 0x0d; + +/// Return value length in bytes. +export const REG_RETL = 0x0e; + +/// Flags register. +export const REG_FLAG = 0x0f; + +/// Smallest writable register +export const REG_WRITABLE = 0x10; + +/* END */ + +/* MEMORY TYPES */ + +/// Length of a word, in bytes +export const WORD_SIZE = 8; + +/// Maximum memory in MiB +export const FUEL_MAX_MEMORY_SIZE = 64; + +/// Maximum VM RAM, in bytes. +export const VM_MAX_RAM = 1024 * 1024 * FUEL_MAX_MEMORY_SIZE; + +/// Maximum memory access size, in bytes. +export const MEM_MAX_ACCESS_SIZE = VM_MAX_RAM; + +/// Tighter of the two bounds for VM_MAX_RAM and usize::MAX +export const MIN_VM_MAX_RAM_USIZE_MAX = VM_MAX_RAM; + +// no limits to heap for now. + +/// Offset for the assets balances in VM memory +export const VM_MEMORY_BALANCES_OFFSET = 32; + +/// Encoded len of a register id in an instruction (unused) +export const VM_REGISTER_WIDTH = 6; + +/// Empty merkle root for receipts tree +export const EMPTY_RECEIPTS_MERKLE_ROOT = [ + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, +]; + +export enum OpcodeRepr { + /// RESERV00 + RESERV00 = 0x00, + /// RESERV01 + RESERV01 = 0x01, + /// RESERV02 + RESERV02 = 0x02, + /// RESERV03 + RESERV03 = 0x03, + /// RESERV04 + RESERV04 = 0x04, + /// RESERV05 + RESERV05 = 0x05, + /// RESERV06 + RESERV06 = 0x06, + /// RESERV07 + RESERV07 = 0x07, + /// RESERV08 + RESERV08 = 0x08, + /// RESERV09 + RESERV09 = 0x09, + /// RESERV0A + RESERV0A = 0x0a, + /// RESERV0B + RESERV0B = 0x0b, + /// RESERV0C + RESERV0C = 0x0c, + /// RESERV0D + RESERV0D = 0x0d, + /// RESERV0E + RESERV0E = 0x0e, + /// RESERV0F + RESERV0F = 0x0f, + + // Classes 0x1_-0x4_ - No immediate value + /// ADD + ADD = 0x10, + /// AND + AND = 0x11, + /// DIV + DIV = 0x12, + /// EQ + EQ = 0x13, + /// EXP + EXP = 0x14, + /// GT + GT = 0x15, + /// LT + LT = 0x16, + /// MLOG + MLOG = 0x17, + /// MROO + MROO = 0x18, + /// MOD + MOD = 0x19, + /// MOVE + MOVE = 0x1a, + /// MUL + MUL = 0x1b, + /// NOT + NOT = 0x1c, + /// OR + OR = 0x1d, + /// SLL + SLL = 0x1e, + /// SRL + SRL = 0x1f, + /// SUB + SUB = 0x20, + /// XOR + XOR = 0x21, + /// RESERV22 + RESERV22 = 0x22, + /// RESERV23 + RESERV23 = 0x23, + /// RET + RET = 0x24, + /// RETD + RETD = 0x25, + /// ALOC + ALOC = 0x26, + /// MCL + MCL = 0x27, + /// MCP + MCP = 0x28, + /// MEQ + MEQ = 0x29, + /// BHSH + BHSH = 0x2a, + /// BHEI + BHEI = 0x2b, + /// BURN + BURN = 0x2c, + /// CALL + CALL = 0x2d, + /// CCP + CCP = 0x2e, + /// CROO + CROO = 0x2f, + /// CSIZ + CSIZ = 0x30, + /// CB + CB = 0x31, + /// LDC + LDC = 0x32, + /// LOG + LOG = 0x33, + /// LOGD + LOGD = 0x34, + /// MINT + MINT = 0x35, + /// RVRT + RVRT = 0x36, + /// SCWQ + SCWQ = 0x37, + /// SRW + SRW = 0x38, + /// SRWQ + SRWQ = 0x39, + /// SWW + SWW = 0x3a, + /// SWWQ + SWWQ = 0x3b, + /// TR + TR = 0x3c, + /// TRO + TRO = 0x3d, + /// ECR + ECR = 0x3e, + /// K256 + K256 = 0x3f, + /// S256 + S256 = 0x40, + /// TIME + TIME = 0x41, + /// RESERV42 + RESERV42 = 0x42, + /// RESERV43 + RESERV43 = 0x43, + /// RESERV44 + RESERV44 = 0x44, + /// RESERV45 + RESERV45 = 0x45, + /// RESERV46 + RESERV46 = 0x46, + /// NOOP + NOOP = 0x47, + /// FLAG + FLAG = 0x48, + /// BAL + BAL = 0x49, + /// JMP + JMP = 0x4a, + /// JNE + JNE = 0x4b, + /// SMO + SMO = 0x4c, + /// RESERV4D + RESERV4D = 0x4d, + /// RESERV4E + RESERV4E = 0x4e, + /// RESERV4F + RESERV4F = 0x4f, + + // Classes 0x5_-0x6_ - Immediate 12 bits + /// ADDI + ADDI = 0x50, + /// ANDI + ANDI = 0x51, + /// DIVI + DIVI = 0x52, + /// EXPI + EXPI = 0x53, + /// MODI + MODI = 0x54, + /// MULI + MULI = 0x55, + /// ORI + ORI = 0x56, + /// SLLI + SLLI = 0x57, + /// SRLI + SRLI = 0x58, + /// SUBI + SUBI = 0x59, + /// XORI + XORI = 0x5a, + /// JNEI + JNEI = 0x5b, + /// LB + LB = 0x5c, + /// LW + LW = 0x5d, + /// SB + SB = 0x5e, + /// SW + SW = 0x5f, + /// MCPI + MCPI = 0x60, + /// GTF + GTF = 0x61, + /// RESERV62 + RESERV62 = 0x62, + /// RESERV63 + RESERV63 = 0x63, + /// RESERV64 + RESERV64 = 0x64, + /// RESERV65 + RESERV65 = 0x65, + /// RESERV66 + RESERV66 = 0x66, + /// RESERV67 + RESERV67 = 0x67, + /// RESERV68 + RESERV68 = 0x68, + /// RESERV69 + RESERV69 = 0x69, + /// RESERV6A + RESERV6A = 0x6a, + /// RESERV6B + RESERV6B = 0x6b, + /// RESERV6C + RESERV6C = 0x6c, + /// RESERV6D + RESERV6D = 0x6d, + /// RESERV6E + RESERV6E = 0x6e, + /// RESERV6F + RESERV6F = 0x6f, + + // Classes 0x7_-0x8_ - Immediate 18 bits + /// MCLI + MCLI = 0x70, + /// GM + GM = 0x71, + /// MOVI + MOVI = 0x72, + /// JNZI + JNZI = 0x73, + /// RESERV74 + RESERV74 = 0x74, + /// RESERV75 + RESERV75 = 0x75, + /// RESERV76 + RESERV76 = 0x76, + /// RESERV77 + RESERV77 = 0x77, + /// RESERV78 + RESERV78 = 0x78, + /// RESERV79 + RESERV79 = 0x79, + /// RESERV7A + RESERV7A = 0x7a, + /// RESERV7B + RESERV7B = 0x7b, + /// RESERV7C + RESERV7C = 0x7c, + /// RESERV7D + RESERV7D = 0x7d, + /// RESERV7E + RESERV7E = 0x7e, + /// RESERV7F + RESERV7F = 0x7f, + /// RESERV80 + RESERV80 = 0x80, + /// RESERV81 + RESERV81 = 0x81, + /// RESERV82 + RESERV82 = 0x82, + /// RESERV83 + RESERV83 = 0x83, + /// RESERV84 + RESERV84 = 0x84, + /// RESERV85 + RESERV85 = 0x85, + /// RESERV86 + RESERV86 = 0x86, + /// RESERV87 + RESERV87 = 0x87, + /// RESERV88 + RESERV88 = 0x88, + /// RESERV89 + RESERV89 = 0x89, + /// RESERV8A + RESERV8A = 0x8a, + /// RESERV8B + RESERV8B = 0x8b, + /// RESERV8C + RESERV8C = 0x8c, + /// RESERV8D + RESERV8D = 0x8d, + /// RESERV8E + RESERV8E = 0x8e, + /// RESERV8F + RESERV8F = 0x8f, + + // Classes 0x9_-0xa_ - Immediate 24 bits + /// JI + JI = 0x90, + /// CFEI + CFEI = 0x91, + /// CFSI + CFSI = 0x92, + /// RESERV93 + RESERV93 = 0x93, + /// RESERV94 + RESERV94 = 0x94, + /// RESERV95 + RESERV95 = 0x95, + /// RESERV96 + RESERV96 = 0x96, + /// RESERV97 + RESERV97 = 0x97, + /// RESERV98 + RESERV98 = 0x98, + /// RESERV99 + RESERV99 = 0x99, + /// RESERV9A + RESERV9A = 0x9a, + /// RESERV9B + RESERV9B = 0x9b, + /// RESERV9C + RESERV9C = 0x9c, + /// RESERV9D + RESERV9D = 0x9d, + /// RESERV9E + RESERV9E = 0x9e, + /// RESERV9F + RESERV9F = 0x9f, + /// RESERVA0 + RESERVA0 = 0xa0, + /// RESERVA1 + RESERVA1 = 0xa1, + /// RESERVA2 + RESERVA2 = 0xa2, + /// RESERVA3 + RESERVA3 = 0xa3, + /// RESERVA4 + RESERVA4 = 0xa4, + /// RESERVA5 + RESERVA5 = 0xa5, + /// RESERVA6 + RESERVA6 = 0xa6, + /// RESERVA7 + RESERVA7 = 0xa7, + /// RESERVA8 + RESERVA8 = 0xa8, + /// RESERVA9 + RESERVA9 = 0xa9, + /// RESERVAA + RESERVAA = 0xaa, + /// RESERVAB + RESERVAB = 0xab, + /// RESERVAC + RESERVAC = 0xac, + /// RESERVAD + RESERVAD = 0xad, + /// RESERVAE + RESERVAE = 0xae, + /// RESERVAF + RESERVAF = 0xaf, + + /// RESERVB0 + RESERVB0 = 0xb0, + /// RESERVB1 + RESERVB1 = 0xb1, + /// RESERVB2 + RESERVB2 = 0xb2, + /// RESERVB3 + RESERVB3 = 0xb3, + /// RESERVB4 + RESERVB4 = 0xb4, + /// RESERVB5 + RESERVB5 = 0xb5, + /// RESERVB6 + RESERVB6 = 0xb6, + /// RESERVB7 + RESERVB7 = 0xb7, + /// RESERVB8 + RESERVB8 = 0xb8, + /// RESERVB9 + RESERVB9 = 0xb9, + /// RESERVBA + RESERVBA = 0xba, + /// RESERVBB + RESERVBB = 0xbb, + /// RESERVBC + RESERVBC = 0xbc, + /// RESERVBD + RESERVBD = 0xbd, + /// RESERVBE + RESERVBE = 0xbe, + /// RESERVBF + RESERVBF = 0xbf, + + /// RESERVC0 + RESERVC0 = 0xc0, + /// RESERVC1 + RESERVC1 = 0xc1, + /// RESERVC2 + RESERVC2 = 0xc2, + /// RESERVC3 + RESERVC3 = 0xc3, + /// RESERVC4 + RESERVC4 = 0xc4, + /// RESERVC5 + RESERVC5 = 0xc5, + /// RESERVC6 + RESERVC6 = 0xc6, + /// RESERVC7 + RESERVC7 = 0xc7, + /// RESERVC8 + RESERVC8 = 0xc8, + /// RESERVC9 + RESERVC9 = 0xc9, + /// RESERVCA + RESERVCA = 0xca, + /// RESERVCB + RESERVCB = 0xcb, + /// RESERVCC + RESERVCC = 0xcc, + /// RESERVCD + RESERVCD = 0xcd, + /// RESERVCE + RESERVCE = 0xce, + /// RESERVCF + RESERVCF = 0xcf, + + /// RESERVD0 + RESERVD0 = 0xd0, + /// RESERVD1 + RESERVD1 = 0xd1, + /// RESERVD2 + RESERVD2 = 0xd2, + /// RESERVD3 + RESERVD3 = 0xd3, + /// RESERVD4 + RESERVD4 = 0xd4, + /// RESERVD5 + RESERVD5 = 0xd5, + /// RESERVD6 + RESERVD6 = 0xd6, + /// RESERVD7 + RESERVD7 = 0xd7, + /// RESERVD8 + RESERVD8 = 0xd8, + /// RESERVD9 + RESERVD9 = 0xd9, + /// RESERVDA + RESERVDA = 0xda, + /// RESERVDB + RESERVDB = 0xdb, + /// RESERVDC + RESERVDC = 0xdc, + /// RESERVDD + RESERVDD = 0xdd, + /// RESERVDE + RESERVDE = 0xde, + /// RESERVDF + RESERVDF = 0xdf, + + /// RESERVE0 + RESERVE0 = 0xe0, + /// RESERVE1 + RESERVE1 = 0xe1, + /// RESERVE2 + RESERVE2 = 0xe2, + /// RESERVE3 + RESERVE3 = 0xe3, + /// RESERVE4 + RESERVE4 = 0xe4, + /// RESERVE5 + RESERVE5 = 0xe5, + /// RESERVE6 + RESERVE6 = 0xe6, + /// RESERVE7 + RESERVE7 = 0xe7, + /// RESERVE8 + RESERVE8 = 0xe8, + /// RESERVE9 + RESERVE9 = 0xe9, + /// RESERVEA + RESERVEA = 0xea, + /// RESERVEB + RESERVEB = 0xeb, + /// RESERVEC + RESERVEC = 0xec, + /// RESERVED + RESERVED = 0xed, + /// RESERVEE + RESERVEE = 0xee, + /// RESERVEF + RESERVEF = 0xef, + + /// RESERVF0 + RESERVF0 = 0xf0, + /// RESERVF1 + RESERVF1 = 0xf1, + /// RESERVF2 + RESERVF2 = 0xf2, + /// RESERVF3 + RESERVF3 = 0xf3, + /// RESERVF4 + RESERVF4 = 0xf4, + /// RESERVF5 + RESERVF5 = 0xf5, + /// RESERVF6 + RESERVF6 = 0xf6, + /// RESERVF7 + RESERVF7 = 0xf7, + /// RESERVF8 + RESERVF8 = 0xf8, + /// RESERVF9 + RESERVF9 = 0xf9, + /// RESERVFA + RESERVFA = 0xfa, + /// RESERVFB + RESERVFB = 0xfb, + /// RESERVFC + RESERVFC = 0xfc, + /// RESERVFD + RESERVFD = 0xfd, + /// RESERVFE + RESERVFE = 0xfe, + /// RESERVFF + RESERVFF = 0xff, +} diff --git a/packages/asm/src/index.test.ts b/packages/asm/src/index.test.ts new file mode 100644 index 00000000000..aa4fa2ae4fb --- /dev/null +++ b/packages/asm/src/index.test.ts @@ -0,0 +1,126 @@ +import { Opcode, toBytesFromProgram, toHex, toProgramFromHex, REG_ZERO, REG_ONE } from './index'; + +describe('asm full tests', () => { + it('can convert program [NOOP]', () => { + /* + Opcode::NOOP + */ + const program = [Opcode.noop()]; + const bytes = toBytesFromProgram(program); + const hex = toHex(program); + + expect(bytes).toStrictEqual(new Uint8Array([71, 0, 0, 0])); + expect(hex).toEqual('0x47000000'); + }); + + it('can convert hex to program [NOOP]', () => { + /* + Opcode::NOOP + */ + const hex = '0x47000000'; + const program = toProgramFromHex(hex); + const expected = [Opcode.noop()]; + + expect(program).toStrictEqual(expected); + }); + + it('can convert program [RET]', () => { + /* + Opcode::RET(REG_ZERO) + */ + const program = [Opcode.ret(REG_ZERO)]; + const bytes = toBytesFromProgram(program); + const hex = toHex(program); + + expect(bytes).toStrictEqual(new Uint8Array([36, 0, 0, 0])); + expect(hex).toEqual('0x24000000'); + }); + + it('can convert program [returnZeroScript]', () => { + /* + Opcode::RET(REG_ZERO) + Opcode::NOOP + */ + const program = [Opcode.ret(REG_ZERO), Opcode.noop()]; + const bytes = toBytesFromProgram(program); + const hex = toHex(program); + + expect(bytes).toStrictEqual(new Uint8Array([36, 0, 0, 0, 71, 0, 0, 0])); + expect(hex).toEqual('0x2400000047000000'); + }); + + it('can convert program [from provider.test]', () => { + /* + Opcode::ADDI(0x10, REG_ZERO, 0xCA) + Opcode::ADDI(0x11, REG_ZERO, 0xBA) + Opcode::LOG(0x10, 0x11, REG_ZERO, REG_ZERO) + Opcode::RET(REG_ONE) + */ + const program = [ + Opcode.addi(0x10, REG_ZERO, 0xca), + Opcode.addi(0x11, REG_ZERO, 0xba), + Opcode.log(0x10, 0x11, REG_ZERO, REG_ZERO), + Opcode.ret(REG_ONE), + ]; + const bytes = toBytesFromProgram(program); + const hex = toHex(program); + + expect(bytes).toStrictEqual( + new Uint8Array([80, 64, 0, 202, 80, 68, 0, 186, 51, 65, 16, 0, 36, 4, 0, 0]) + ); + expect(hex).toEqual('0x504000ca504400ba3341100024040000'); + }); + + it('can convert program [fuel-asm ecrecover sample]', () => { + /* + Opcode::MOVE(0x10, 0x01), // set r[0x10] := $one + Opcode::SLLI(0x20, 0x10, 5), // set r[0x20] := `r[0x10] << 5 == 32` + Opcode::SLLI(0x21, 0x10, 6), // set r[0x21] := `r[0x10] << 6 == 64` + Opcode::ALOC(0x21), // alloc `r[0x21] == 64` to the heap + Opcode::ADDI(0x10, 0x07, 1), // set r[0x10] := `$hp + 1` (allocated heap) + Opcode::MOVE(0x11, 0x04), // set r[0x11] := $ssp + Opcode::ADD(0x12, 0x04, 0x20), // set r[0x12] := `$ssp + r[0x20]` + Opcode::ECR(0x10, 0x11, 0x12), // recover public key in memory[r[0x10], 64] + Opcode::RET(0x01), // return `1` + */ + const program = [ + Opcode.move(0x10, 0x01), + Opcode.slli(0x20, 0x10, 5), + Opcode.slli(0x21, 0x10, 6), + Opcode.aloc(0x21), + Opcode.addi(0x10, 0x07, 1), + Opcode.move(0x11, 0x04), + Opcode.add(0x12, 0x04, 0x20), + Opcode.ecr(0x10, 0x11, 0x12), + Opcode.ret(REG_ONE), + ]; + const bytes = toBytesFromProgram(program); + const hex = toHex(program); + + expect(bytes).toStrictEqual( + new Uint8Array([ + 26, 64, 16, 0, 87, 129, 0, 5, 87, 133, 0, 6, 38, 132, 0, 0, 80, 64, 112, 1, 26, 68, 64, 0, + 16, 72, 72, 0, 62, 65, 20, 128, 36, 4, 0, 0, + ]) + ); + expect(hex).toEqual( + '0x1a401000578100055785000626840000504070011a444000104848003e41148024040000' + ); + }); + + // it.skip('can convert program to bytes [withdrawScript]', () => { + // /* + // The following code loads some basic values into registers and calls SMO to create an output message + // 5040C010 - ADDI r16 $is i16 [r16 now points to memory 16 bytes from the start of this program (start of receiver data)] + // 5D44C006 - LW r17 $is i6 [r17 set to the 6th word in this program (6*8=48 bytes from the start of this program)] + // 4C400011 - SMO r16 r0 r0 r17 [send message out to address starting at memory position r16 with amount in r17] + // 24000000 - RET [return 0] + // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [recipient address] + // 00000000 00000000 [amount value] + // */ + // const program = [Op.addi(), Op.ret(REG_ZERO)]; + // const bytes = toBytesFromOpcode(program); + + // expect(bytes).toEqual('0x5040C0105D44C0064C40001124000000'); + // }); +}); diff --git a/packages/asm/src/index.ts b/packages/asm/src/index.ts new file mode 100644 index 00000000000..31fb81bdb4b --- /dev/null +++ b/packages/asm/src/index.ts @@ -0,0 +1,3 @@ +export * from './constants'; +export * from './opcode'; +export * from './instruction'; diff --git a/packages/asm/src/instruction.test.ts b/packages/asm/src/instruction.test.ts new file mode 100644 index 00000000000..69047906cf4 --- /dev/null +++ b/packages/asm/src/instruction.test.ts @@ -0,0 +1,60 @@ +import { + Opcode, + toBytesFromProgram, + toHex, + toByteChunksFromHex, + toProgramFromHex, + REG_ONE, +} from './index'; + +describe('instructions', () => { + it('can convert program to Uint8Array bytes [NOOP]', () => { + const program = [Opcode.noop()]; + + const bytes = toBytesFromProgram(program); + + expect(bytes).toStrictEqual(new Uint8Array([71, 0, 0, 0])); + }); + + it('can convert program to hex string [NOOP]', () => { + const program = [Opcode.noop()]; + + const hex = toHex(program); + + expect(hex).toEqual('0x47000000'); + }); + + it('can convert hex string to byte chunks [NOOP]', () => { + const hex = '0x47000000'; + + const byteChunks = toByteChunksFromHex(hex); + + expect(byteChunks).toStrictEqual([new Uint8Array([71, 0, 0, 0])]); + }); + + it('can convert hex string to instruction list [NOOP]', () => { + const hex = '0x47000000'; + + const program = toProgramFromHex(hex); + + expect(program).toStrictEqual([Opcode.noop()]); + }); + + it('can convert hex string to instruction list [fuel-asm ecrecover]', () => { + const hex = '0x1a401000578100055785000626840000504070011a444000104848003e41148024040000'; + + const program = toProgramFromHex(hex); + + expect(program).toStrictEqual([ + Opcode.move(0x10, 0x01), + Opcode.slli(0x20, 0x10, 5), + Opcode.slli(0x21, 0x10, 6), + Opcode.aloc(0x21), + Opcode.addi(0x10, 0x07, 1), + Opcode.move(0x11, 0x04), + Opcode.add(0x12, 0x04, 0x20), + Opcode.ecr(0x10, 0x11, 0x12), + Opcode.ret(REG_ONE), + ]); + }); +}); diff --git a/packages/asm/src/instruction.ts b/packages/asm/src/instruction.ts new file mode 100644 index 00000000000..280fc5bbcdd --- /dev/null +++ b/packages/asm/src/instruction.ts @@ -0,0 +1,78 @@ +import { arrayify, concat, hexlify } from '@ethersproject/bytes'; +import { toNumber } from '@fuel-ts/math'; + +import { OpcodeRepr } from './constants'; +import { Opcode } from './opcode'; + +type Program = Opcode[]; + +/// Size of a code when serialized into bytes +const CODE_SIZE = 4; + +export const toBytesFromProgram = (program: Program): Uint8Array => + concat( + program.reduce((instructions, line) => { + instructions.push(line.toBytes()); + return instructions; + }, [] as Uint8Array[]) + ); + +export const toHex = (program: Program): string => hexlify(toBytesFromProgram(program)); + +export const toByteChunksFromHex = (hex: string): Uint8Array[] => { + const bytes = arrayify(hex); + + const byteChunks = []; + const LENGTH = bytes.length; + for (let i = 0; i < LENGTH; i += CODE_SIZE) { + byteChunks.push(bytes.slice(i, i + CODE_SIZE)); + } + + return byteChunks; +}; + +export class Instruction { + instruction: number; + /// Opcode + op: number; + /// Register A + ra: number; + /// Register B + rb: number; + /// Register C + rc: number; + /// Register D + rd: number; + /// Immediate with 6 bits + imm06: number; + /// Immediate with 12 bits + imm12: number; + /// Immediate with 18 bits + imm18: number; + /// Immediate with 24 bits + imm24: number; + constructor(instruction: number) { + this.instruction = instruction; + this.op = instruction >> 24; + this.ra = (instruction >> 18) & 0x3f; + this.rb = (instruction >> 12) & 0x3f; + this.rc = (instruction >> 6) & 0x3f; + this.rd = instruction & 0x3f; + this.imm06 = instruction & 0xff; + this.imm12 = instruction & 0x0fff; + this.imm18 = instruction & 0x3ffff; + this.imm24 = instruction & 0xffffff; + } + + static fromBytes(bytes: Uint8Array) { + const u32 = toNumber(bytes); + return new Instruction(u32); + } + + toOpcode(): Opcode { + return new Opcode(this.instruction); + } +} + +export const toProgramFromHex = (hex: string): Program => + toByteChunksFromHex(hex).map((byteChunk) => Instruction.fromBytes(byteChunk).toOpcode()); diff --git a/packages/asm/src/opcode.ts b/packages/asm/src/opcode.ts new file mode 100644 index 00000000000..f24bc591e65 --- /dev/null +++ b/packages/asm/src/opcode.ts @@ -0,0 +1,355 @@ +import { arrayify } from '@ethersproject/bytes'; + +import { OpcodeRepr } from './constants'; + +export class Opcode { + instruction: number; + + constructor(opcodeAsU32: number) { + this.instruction = opcodeAsU32; + } + + toBytes(): Uint8Array { + return arrayify(this.instruction); + } + + /// adds two registers. + static add(RegisterIdA: number, RegisterIdB: number, RegisterIdC: number) { + let code = OpcodeRepr.ADD; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + let registerC = RegisterIdC; + registerC <<= 6; + + return new Opcode(code | registerA | registerB | registerC); + } + + /// adds a register and an immediate value. + static addi(RegisterIdA: number, RegisterIdB: number, Immediate12: number) { + let code = OpcodeRepr.ADDI; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + return new Opcode(code | registerA | registerB | Immediate12); + } + + /// bitwise ands two registers. + static and() {} + + /// bitwise ands a register and an immediate value. + static andi() {} + + /// divides two registers. + static div() {} + + /// divides a register and an immediate value. + static divi() {} + + /// compares two registers for equality. + static eq() {} + + /// raises one register to the power of another. + static exp() {} + + /// raises one register to the power of an immediate value. + static expi() {} + + /// compares two registers for greater-than. + static gt() {} + + /// compares two registers for less-than. + static lt() {} + + /// the integer logarithm of a register. + static mlog() {} + + /// the integer root of a register. + static mroo() {} + + /// modulo remainder of two registers. + static mod() {} + + /// modulo remainder of a register and an immediate value. + static modi() {} + + /// copy from one register to another. + static move(RegisterIdA: number, RegisterIdB: number) { + let code = OpcodeRepr.MOVE; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + return new Opcode(code | registerA | registerB); + } + + /// copy immediate value into a register + static movi() {} + + /// multiplies two registers. + static mul() {} + + /// multiplies a register and an immediate value. + static muli() {} + + /// bitwise not a register. + static not() {} + + /// bitwise ors two registers. + static or() {} + + /// bitwise ors a register and an immediate value. + static ori() {} + + /// left shifts a register by a register. + static sll() {} + + /// left shifts a register by an immediate value. + static slli(RegisterIdA: number, RegisterIdB: number, Immediate12: number) { + let code = OpcodeRepr.SLLI; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + return new Opcode(code | registerA | registerB | Immediate12); + } + + /// right shifts a register by a register. + static srl() {} + + /// right shifts a register by an immediate value. + static srli() {} + + /// subtracts two registers. + static sub() {} + + /// subtracts a register and an immediate value. + static subi() {} + + /// bitwise xors two registers. + static xor() {} + + /// bitwise xors a register and an immediate value. + static xori() {} + + /// jump. + static ji() {} + + /// conditional jump. + static jnei() {} + + /// conditional jump against zero. + static jnzi() {} + + /// dynamic jump. + static jmp() {} + + /// conditional dynamic jump. + static jne() {} + + /// return from context. + static ret(RegisterIdA: number) { + let code = OpcodeRepr.RET; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + return new Opcode(code | registerA); + } + + /// return from context with data. + static retd(RegisterIdA: number, RegisterIdB: number) { + let code = OpcodeRepr.RETD; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + return new Opcode(code | registerA | registerB); + } + + /// extend the current call frame's stack by an immediate value. + static cfei() {} + + /// shrink the current call frame's stack by an immediate value. + static cfsi() {} + + /// a byte is loaded from the specified address offset by an immediate value. + static lb() {} + + /// a word is loaded from the specified address offset by an immediate value. + static lw(RegisterIdA: number, RegisterIdB: number, Immediate12: number) { + let code = OpcodeRepr.LW; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + return new Opcode(code | registerA | registerB | Immediate12); + } + + /// allocate a number of bytes from the heap. + static aloc(RegisterIdA: number) { + let code = OpcodeRepr.ALOC; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + return new Opcode(code | registerA); + } + + /// clear a variable number of bytes in memory. + static mcl() {} + + /// clear an immediate number of bytes in memory. + static mcli() {} + + /// copy a variable number of bytes in memory. + static mcp() {} + + /// copy an immediate number of bytes in memory. + static mcpi() {} + + /// compare bytes in memory. + static meq() {} + + /// write the least significant byte of a register to memory. + static sb() {} + + /// write a register to memory. + static sw() {} + + /// get the balance of contract of an asset id. + static bal() {} + + /// get block header hash for height. + static bhsh() {} + + /// get current block height. + static bhei() {} + + /// burn coins of the current contract's asset id. + static burn() {} + + /// call a contract. + static call() {} + + /// copy contract code for a contract. + static ccp() {} + + /// get code root of a contract. + static croo() {} + + /// get code size of a contract. + static csiz() {} + + /// get current block proposer's address. + static cb() {} + + /// load a contract's code as executable. + static ldc() {} + + /// log an event. + static log(RegisterIdA: number, RegisterIdB: number, RegisterIdC: number, RegisterIdD: number) { + let code = OpcodeRepr.LOG; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + let registerC = RegisterIdC; + registerC <<= 6; + + return new Opcode(code | registerA | registerB | registerC | RegisterIdD); + } + + /// log data. + static logd() {} + + /// mint coins of the current contract's asset id. + static mint() {} + + /// halt execution{} reverting state changes and returning a value. + static rvrt() {} + + /// send a message to recipient address with call abi{} coins{} and output. + static smo(RegisterIdA: number, RegisterIdB: number, RegisterIdC: number, RegisterIdD: number) { + let code = OpcodeRepr.SMO; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + let registerC = RegisterIdC; + registerC <<= 6; + + return new Opcode(code | registerA | registerB | registerC | RegisterIdD); + } + + /// clear a series of slots from contract storage. + static scwq() {} + + /// load a word from contract storage. + static srw() {} + + /// load a series of 32 byte slots from contract storage. + static srwq() {} + + /// store a word in contract storage. + static sww() {} + + /// store a series of 32 byte slots in contract storage. + static swwq() {} + + /// get timestamp of block at given height. + static time() {} + + /// transfer coins to a contract unconditionally. + static tr() {} + + /// transfer coins to a variable output. + static tro() {} + + /// the 64-byte public key (x{} y) recovered from 64-byte signature on 32-byte message. + static ecr(RegisterIdA: number, RegisterIdB: number, RegisterIdC: number) { + let code = OpcodeRepr.ECR; + code <<= 24; + let registerA = RegisterIdA; + registerA <<= 18; + let registerB = RegisterIdB; + registerB <<= 12; + let registerC = RegisterIdC; + registerC <<= 6; + + return new Opcode(code | registerA | registerB | registerC); + } + + /// the keccak-256 hash of a slice. + static k256() {} + + /// the sha-2-256 hash of a slice. + static s256() {} + + /// performs no operation. + static noop() { + let code = OpcodeRepr.NOOP; + code <<= 24; + return new Opcode(code); + } + + /// set flag register to a register. + static flag() {} + + /// get metadata from memory. + static gm() {} + + /// get transaction fields. + static gtf() {} + + /// Undefined opcode, potentially from inconsistent serialization. + static Undefined() {} +} From f1ed7373900a69e5a19ea6e1c90cb94c69161eba Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Sun, 7 May 2023 21:52:21 -0700 Subject: [PATCH 3/4] cs --- .changeset/spotty-tomatoes-clap.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/spotty-tomatoes-clap.md diff --git a/.changeset/spotty-tomatoes-clap.md b/.changeset/spotty-tomatoes-clap.md new file mode 100644 index 00000000000..8503ca40ddd --- /dev/null +++ b/.changeset/spotty-tomatoes-clap.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/asm": patch +--- + +Added new package to write ASM for fuel using TypeScript From 661bc735b80864ba667dae80b0957069aeb6ea6e Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Sun, 7 May 2023 22:44:00 -0700 Subject: [PATCH 4/4] rm unused --- packages/asm/src/instruction.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/asm/src/instruction.ts b/packages/asm/src/instruction.ts index 280fc5bbcdd..c898b689d92 100644 --- a/packages/asm/src/instruction.ts +++ b/packages/asm/src/instruction.ts @@ -1,7 +1,6 @@ import { arrayify, concat, hexlify } from '@ethersproject/bytes'; import { toNumber } from '@fuel-ts/math'; -import { OpcodeRepr } from './constants'; import { Opcode } from './opcode'; type Program = Opcode[];