gear icon indicating copy to clipboard operation
gear copied to clipboard

Store smart contracts code as shared libraries

Open grishasobol opened this issue 2 years ago • 1 comments

Problem to Solve

Currently we store contracts code in storage as solid wasm file. This is simple and fast solution, but it has one disadvantage. Each contracts which has been built from rust using gstd has a lot of common parts in code. For example dlmalloc, which has size == 5 kBytes, it is almost the same in each contracts currently. Also there is a lot of parts of gstd, which is equal for many contracts. So, the idea is to store separately some common parts of smart contracts.

This has another advantage: this reduces size of data which must be sent to relay chain for block finalisation.

Possible Solution

  1. First possible solution is to identify common parts during program submit. Unfortunately this cannot be done in simple way because of call instructions, which contains function number as argument. This number can differ in different wasm files, even in equal code parts.

  2. Second solution is to submit program code as already separate libraries. We encourage users to do this reducing cost for program submit if some libraries are already in code storage. And before execution this libraries will be linked.

Unfortunately, currently I cannot find a way, how to compile rust code into several separate libraries: https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md

Notes

No response

grishasobol avatar Jun 14 '22 22:06 grishasobol

There is another idea probably worth noting.

The most space of original program code is occupied by an allocator. The allocator has (should?) C interface so we could mark all of its functions as extern "C" and provide this modified rs-file with declarations to contracts code (or gcore/gstd). After compilation program binary will have all used allocators functions in wasm-import section hence the program would be smaller in size. Then we could remove import sections, inject compiled binary code of the allocators functions and adjust calling indexes accordingly. To sum up this approach could help reduce the size of the original program binary code.

gshep avatar Oct 14 '22 13:10 gshep

First possible solution is to identify common parts during program submit. Unfortunately this cannot be done in simple way because of call instructions, which contains function number as argument. This number can differ in different wasm files, even in equal code parts.

this is easy to go once we compile the contracts with name-sections at the first time, then, just keep the names of the functions before the optimization, this also requires some pre-check for the shared library list on chain to optimize the wasm code in our builder

...extern "C" and provide this modified rs-file with declarations to contracts code (or gcore/gstd) ... Then we could remove import sections, inject compiled binary code of the allocators functions and adjust calling indexes accordingly.

makes sense as well but hope the Linker in both wasmtime and wasmi works after the last year that we don't have to reach this solution

clearloop avatar Jun 27 '23 12:06 clearloop

In addition to the memory allocator, each smart contract duplicates functions such as memset, memcpy (aka https://github.com/rust-lang/compiler-builtins). I'm not sure if it can be easily dynamically linked, but it makes sense to try extracting them into a shared library.

For example, when you write Linux programs in C, you import memset from libc. We could introduce in something like lib-gear-runtime instead of libc.

StackOverflowExcept1on avatar Jul 25 '23 19:07 StackOverflowExcept1on