What problem does your feature solve?
Contract WASM files can contain unused type definitions in the contractspecv0 custom section. These unused types increase WASM binary size unnecessarily.
Any exported contracttypes defined in the SDK, or any library for that matter, that don't get used in the importing contract still end up in the contract spec. This results in some awkward behaviour where we avoid exporting contracttypes in the SDK, even though doing so would be convenient and enable using contracttypes more frequently there.
Because of how proc-macros run in isolation and cannot coordinate in wasm builds in Rust (the ctor crate cannot be used like we use it in non-wasm builds in tests to coordinate), there's nothing the soroban-sdk can do to identify whether a contracttype that sometimes needs to be exported hasn't been used and can be excluded.
Examples of unused types that bloat the spec:
- Error enums from imported libraries (e.g.,
#[contracterror] types from dependencies) that are never used by any function
- Types that are defined but never referenced by any function inputs/outputs
- Transitive type dependencies that no longer apply after refactoring
What would you like to see?
During stellar contract build, automatically filter the contractspecv0 section to remove unused types:
- Parse the spec entries from the compiled WASM after cargo build
- Perform reachability analysis starting from all functions using fixed-point iteration
- Keep:
- All functions (
FunctionV0)
- All events (
EventV0)
- All UDTs (
UdtStructV0, UdtUnionV0, UdtEnumV0, UdtErrorEnumV0) that are directly or transitively referenced by function inputs/outputs
- Remove: UDT types that are defined but never referenced by any function
- Replace the
contractspecv0 custom section with the filtered version using wasm-encoder
Types reference other types via ScSpecTypeDef::Udt(name). The reachability analysis recursively traverses Vec, Map, Option, Result, and Tuple type definitions to find all referenced UDTs.
This will require rewriting the wasm file after build. Currently the stellar-cli does modify the wasm (for meta injection), but only in an append fashion. The new approach uses wasm-encoder with RawSection to copy sections verbatim and replace only the target custom section.
What alternatives are there?
- Manual cleanup: Developers could manually remove unused type imports, but this is error-prone and tedious
- SDK-level filtering: The Soroban SDK could avoid emitting unused types, but proc-macros run in isolation and cannot coordinate to identify unused types
- Filter by library: Only filter types exported from the soroban-sdk (types can specify what library they came from), but filtering all unused types is more comprehensive
Related
What problem does your feature solve?
Contract WASM files can contain unused type definitions in the
contractspecv0custom section. These unused types increase WASM binary size unnecessarily.Any exported
contracttypesdefined in the SDK, or any library for that matter, that don't get used in the importing contract still end up in the contract spec. This results in some awkward behaviour where we avoid exporting contracttypes in the SDK, even though doing so would be convenient and enable using contracttypes more frequently there.Because of how proc-macros run in isolation and cannot coordinate in wasm builds in Rust (the ctor crate cannot be used like we use it in non-wasm builds in tests to coordinate), there's nothing the soroban-sdk can do to identify whether a contracttype that sometimes needs to be exported hasn't been used and can be excluded.
Examples of unused types that bloat the spec:
#[contracterror]types from dependencies) that are never used by any functionWhat would you like to see?
During
stellar contract build, automatically filter thecontractspecv0section to remove unused types:FunctionV0)EventV0)UdtStructV0,UdtUnionV0,UdtEnumV0,UdtErrorEnumV0) that are directly or transitively referenced by function inputs/outputscontractspecv0custom section with the filtered version usingwasm-encoderTypes reference other types via
ScSpecTypeDef::Udt(name). The reachability analysis recursively traversesVec,Map,Option,Result, andTupletype definitions to find all referenced UDTs.This will require rewriting the wasm file after build. Currently the stellar-cli does modify the wasm (for meta injection), but only in an append fashion. The new approach uses
wasm-encoderwithRawSectionto copy sections verbatim and replace only the target custom section.What alternatives are there?
Related