feat(Stellar): Represent vectors in storage as VecObjects#1851
Merged
salaheldinsoliman merged 6 commits intohyperledger-solang:mainfrom Mar 15, 2026
Merged
Conversation
Signed-off-by: salaheldinsoliman <salaheldin_sameh@aucegypt.edu>
Signed-off-by: salaheldinsoliman <salaheldin_sameh@aucegypt.edu>
Signed-off-by: salaheldinsoliman <salaheldin_sameh@aucegypt.edu>
Signed-off-by: salaheldinsoliman <salaheldin_sameh@aucegypt.edu>
901bfb9
into
hyperledger-solang:main
11 of 17 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In this PR, we improve the overall structure of how vectors are represented in memory and in storage.
We propose and implement the following:
Arrays representation in storage
Arrays of native types
Arrays of native types are represented in storage as a
VecObjecthandle. When storage array operations are called, theVecObjecthandle is retrieved from storage, updated, and then put back to storage.Arrays of custom types
Arrays of structs follow a sparse storage approach, where each element is stored independently in storage, with its own storage key. The key is a
VecObject, where the first index is the Solidity storage slot, and the following indexes are the specific indexes the program wants to access.For example:
We claim that this approach makes the mutation of nested type more efficient. We will follow up with experiments that prove this claim
The downside is that passing a nested array, a nested
VecObject, is not currently possible.One solution would be to encode/decode structs as a
MapObjectwhich will be done in following PRs.Arrays representation in linear memory
Passing an array as a function argument
Soroban contracts accept array function arguments as
VecObjects. We follow alazydecoding/encoding approach, where the element is only decoded/encoded if it is accessed.The array argument is first unpacked to the guest linear memory, where the type of the unpacked buffer is
Array(SorobanHandle). This makes sense since the underlying elements are not decoded yet.When a memory array element is accessed, this translates in Solang to a
Load/Storememory instruction. If the type is anArray(SorobanHandle), the innerSorobanHandleis lazily decoded/encoded.Allocating a memory array
When a memory array is allocated in linear memory, i.e:
It is allocated in the guest linear memory with a bump allocator. If an array passed in as an argument needs to be copied to an array allocated inside the function,
Array(SorobanHandle) -> Array(NativeType), the elements are decoded and copied in loop.This operation is expensive, and we usually advise against it in practice.