-
Notifications
You must be signed in to change notification settings - Fork 971
XLS-102: Wasm VM #407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
XLS-102: Wasm VM #407
Conversation
|
|
||
| There are only 4 native types in the [WASM spec](https://webassembly.github.io/spec/core/syntax/types.html): `i32` (a signed 32-bit integer), `i64` (a signed 64-bit integer), `f32` (a 32-bit floating point number), and `f64` (a 64-bit floating point number). However, the floating point numbers use a different encoding from what `rippled` uses. | ||
|
|
||
| So essentially, we only have `i32` and `i64` in terms of useful types. **Every parameter and return type must be represented as these two types.** This is manifested as [pointers](https://en.wikipedia.org/wiki/Pointer_%28computer_programming%29) and lengths. _Note that any language that has full support for extensions will have helper functions to abstract away most of the complexity (especially involving pointers and lengths)._ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| So essentially, we only have `i32` and `i64` in terms of useful types. **Every parameter and return type must be represented as these two types.** This is manifested as [pointers](https://en.wikipedia.org/wiki/Pointer_%28computer_programming%29) and lengths. _Note that any language that has full support for extensions will have helper functions to abstract away most of the complexity (especially involving pointers and lengths)._ | |
| So essentially, we only have `i32` and `i64` in terms of useful types. **Every parameter and return type must be represented as these two types.** This is manifested as [pointers](https://en.wikipedia.org/wiki/Pointer_%28computer_programming%29) and lengths. _Note that any language that has full support for XRPL extensions will have helper functions to abstract away most of the complexity (especially involving pointers and lengths)._ |
Correct me if I'm wrong, but I want to disambiguate between Smart features/extensions and WASM extensions.
|
|
||
| While WebAssembly has a [core specification](https://webassembly.github.io/spec/), different runtimes have flexibility in how they implement certain features that are not a part of the formal specification. For example, not all WASM runtimes can easily be embedded in a C++ project (such as `rippled`). | ||
|
|
||
| The most relevant part for the purpose of consensus is the gas cost for any operation or function. Different implementations may have different gas costs for executing a given function, due to implementation differences - e.g. some calculate gas costs by inserting additional instructions, while others have a counter in the VM logic. For instance, one basic Smart Escrow function cost 110 gas to run with [WasmEdge](https://wasmedge.org/), while it only cost 4 gas with [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime). This would cause consensus issues if the computation limit was set at 100, for example - one runtime would succeed, while the other would fail. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any objection to citing WASMi instead of WAMR?
(fine if that's too much work, but I would imagine the costs is similar).
|
|
||
| ### 2.1. Gas | ||
|
|
||
| Gas consumption is determined by the WASM runtime used for execution. Different implementations may use different metering strategies, which yields different gas costs for identical WASM code. For example, [this issue](https://github.com/bytecodealliance/wasm-micro-runtime/issues/3927) discusses how WAMR measures gas consumption. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adapting for Wasmi?
|
|
||
| ## 4. Memory Management Strategies | ||
|
|
||
| WebAssembly does not include built-in memory management - there is no garbage collector or automatic heap allocation. Instead, memory is a contiguous linear buffer that can only grow (in fixed 64 KiB pages) and never shrink. That means WASM code must allocate and manage its own memory, typically via a custom allocator or language runtime, and explicitly track when memory is no longer needed. While there is [progress](https://developer.chrome.com/blog/wasmgc) on this front with WasmGC, it does not have full-fledged tooling support yet, and is currently only really useful for browser applications of WASM. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| WebAssembly does not include built-in memory management - there is no garbage collector or automatic heap allocation. Instead, memory is a contiguous linear buffer that can only grow (in fixed 64 KiB pages) and never shrink. That means WASM code must allocate and manage its own memory, typically via a custom allocator or language runtime, and explicitly track when memory is no longer needed. While there is [progress](https://developer.chrome.com/blog/wasmgc) on this front with WasmGC, it does not have full-fledged tooling support yet, and is currently only really useful for browser applications of WASM. | |
| WebAssembly 1.0 (which is the WASM profile XRPL smart features will support) does not include built-in memory management - there is no garbage collector or automatic heap allocation. Instead, memory is a contiguous linear buffer that can only grow (in fixed 64 KiB pages) and never shrink. That means WASM code must allocate and manage its own memory, typically via a custom allocator or language runtime, and explicitly track when memory is no longer needed. While there is [progress](https://developer.chrome.com/blog/wasmgc) on this front with WasmGC, it does not have full-fledged tooling support yet, and is currently only really useful for browser applications of WASM. |
|
|
||
| This is a bit of a problem for host functions, since data has to go back and forth between the caller (WASM dev) and the engine (`rippled`). Some data (e.g. parameters) may be generated on the WASM side, while some data (e.g. the return data) may be generated on the rippled side. | ||
|
|
||
| Therefore, in this design, the caller is responsible for allocating memory in advance, and must reuse or deallocate memory manually. See Appendix B for alternative designs that were considered and rejected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding something about how we'll just terminate the WASM VM after each execution (or zero-out memory allocated by rippled for the WASM VM) as a final memory cleanup mechanism that yields increased safety?
| | `ticket_keylet(`<br/> `account_ptr: i32,`<br/> `account_len: i32,`<br/> `sequence: i32,`<br/> `out_buff_ptr: i32,`<br/> `out_buff_len: i32`<br />`)` | Calculate a `Ticket`'s keylet from its pieces. | 350 | | ||
| | `vault_keylet(`<br/> `account_ptr: i32,`<br/> `account_len: i32,`<br/> `sequence: i32,`<br/> `out_buff_ptr: i32,`<br/> `out_buff_len: i32`<br />`)` | Calculate a `Vault`’s keylet from its pieces. | 350 | | ||
|
|
||
| The singleton keylets (e.g. `Amendments`) are a bit unnecessary to include, as a dev can simply copy the keylet directly instead. They will be included as constants in `craft` as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| The singleton keylets (e.g. `Amendments`) are a bit unnecessary to include, as a dev can simply copy the keylet directly instead. They will be included as constants in `craft` as well. | |
| The singleton keylets (e.g. `Amendments`) are a bit unnecessary to include, as a dev can simply copy the keylet directly instead (these will be included as constants in `xrpl-wasm-stdlib` as well). |
|
|
||
| ### 5.9. Trace | ||
|
|
||
| Output debug info to the `rippled` debug log. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should specify the caps for traced data.
|
|
||
| <img width="768" height="381" alt="image" src="https://github.com/user-attachments/assets/c3e4255c-f956-41f2-941f-90b643b3d567" /> | ||
|
|
||
| Based on these findings, we narrowed down the search to **WasmEdge** and **WAMR**, which we then did further performance testing and analysis on. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit?
| 1. Caller-Allocated: The contract developer (on the WASM side) allocates fixed size arrays for returning data. The user knows the pointer and the length. | ||
| - This is really easy to implement, but means that the WASM dev needs to do their own memory allocation. | ||
| 2. Host-Allocated: The host (rippled) allocates WASM memory in host functions and passes the pointer and the length to the WASM program. | ||
| - This is super easy to use for devs, as they don’t need to worry about allocation and all of that. However, more research is needed to determine how possible it is, because currently the only way that we know how to do this involves allocating a new page every time (to ensure the host isn’t overwriting addresses in use). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| - This is super easy to use for devs, as they don’t need to worry about allocation and all of that. However, more research is needed to determine how possible it is, because currently the only way that we know how to do this involves allocating a new page every time (to ensure the host isn’t overwriting addresses in use). | |
| - This is super easy to use for devs, as they don’t need to worry about allocation. However, more research is needed to determine how possible it is, because currently the only way that we know how to do this involves allocating a new page every time (to ensure the host isn’t overwriting addresses in use). |
|
|
||
| These graphs clearly show that WAMR is much more performant. | ||
|
|
||
| ## Appendix B: Other Memory Management Strategies Considered |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ## Appendix B: Other Memory Management Strategies Considered | |
| ## Appendix B: Memory Management Strategies Considered |
No description provided.