|
| 1 | +//! # Features |
| 2 | +//! |
| 3 | +//! The SDK provides several Cargo features that enable additional functionality. |
| 4 | +//! |
| 5 | +//! ## `testutils` |
| 6 | +//! |
| 7 | +//! Enables test utilities for writing tests that interact with contracts. |
| 8 | +//! Required for using [`Env::default()`] in tests, generating test addresses, |
| 9 | +//! and other test helpers. Only available for non-Wasm targets. |
| 10 | +//! |
| 11 | +//! ## `alloc` |
| 12 | +//! |
| 13 | +//! Enables the [`alloc`][crate::alloc] module, providing access to the global |
| 14 | +//! allocator for use in contracts. |
| 15 | +//! |
| 16 | +//! ## `hazmat-crypto` |
| 17 | +//! |
| 18 | +//! Exposes low-level cryptographic primitives (e.g. |
| 19 | +//! [`CryptoHazmat`][crate::crypto::CryptoHazmat]) that are easy to misuse. |
| 20 | +//! Use with care. |
| 21 | +//! |
| 22 | +//! ## `hazmat-address` |
| 23 | +//! |
| 24 | +//! Exposes low-level address primitives (e.g. |
| 25 | +//! [`Address::to_payload`][crate::Address::to_payload], |
| 26 | +//! [`Address::from_payload`][crate::Address::from_payload]) that are easy to |
| 27 | +//! misuse. Use with care. |
| 28 | +//! |
| 29 | +//! ## `experimental_spec_shaking_v2` |
| 30 | +//! |
| 31 | +//! Enables spec shaking, a mechanism for stripping unused type and event |
| 32 | +//! definitions from a contract's spec after building. |
| 33 | +//! |
| 34 | +//! A contract's spec (the `contractspecv0` custom section in the Wasm binary) |
| 35 | +//! contains entries for every function, type, and event defined by the contract. |
| 36 | +//! When types or events are defined but not actually used at a contract boundary |
| 37 | +//! (parameters, return values, error returns, or event publishes), their spec |
| 38 | +//! entries are dead weight. Spec shaking removes them. |
| 39 | +//! |
| 40 | +//! ### How It Works |
| 41 | +//! |
| 42 | +//! When this feature is enabled, the SDK embeds 14-byte **markers** in the Wasm |
| 43 | +//! data section for each exported type and event. A marker consists of a |
| 44 | +//! `SpEcV1` magic prefix followed by 8 bytes of a SHA-256 hash of the spec |
| 45 | +//! entry's XDR. |
| 46 | +//! |
| 47 | +//! Markers are placed inside functions that are only called when the type is |
| 48 | +//! actually used: |
| 49 | +//! - **Function parameters**: marker is triggered when deserializing the input. |
| 50 | +//! - **Function return values**: marker is triggered when serializing the output. |
| 51 | +//! - **Error returns**: marker is triggered via `Result<T, E>` serialization. |
| 52 | +//! - **Event publishes**: marker is triggered inside the `publish()` call. |
| 53 | +//! - **Nested types**: a type's marker function calls the marker functions of |
| 54 | +//! its field types, so nested types are transitively marked. |
| 55 | +//! - **Container types**: `Vec<T>`, `Map<K, V>`, `Option<T>`, and `Result<T, E>` |
| 56 | +//! propagate markers to their inner types. |
| 57 | +//! |
| 58 | +//! The Rust compiler's dead code elimination (DCE) removes markers for types |
| 59 | +//! that are never used, while keeping markers for types that are. |
| 60 | +//! |
| 61 | +//! Post-build tools (e.g. `stellar-cli`) scan the Wasm data section for |
| 62 | +//! `SpEcV1` markers, match them against spec entries, and strip any entries |
| 63 | +//! without a corresponding marker. |
| 64 | +//! |
| 65 | +//! ### Changed Behaviour |
| 66 | +//! |
| 67 | +//! When this feature is enabled the following macros change behaviour: |
| 68 | +//! |
| 69 | +//! #### [`contracttype`] |
| 70 | +//! |
| 71 | +//! Without this feature, spec entries are only generated for `pub` types (or |
| 72 | +//! when `export = true` is explicitly set). With this feature, spec entries |
| 73 | +//! and markers are generated for all types regardless of visibility, unless |
| 74 | +//! `export = false` is explicitly set. This ensures all types can participate |
| 75 | +//! in spec shaking. |
| 76 | +//! |
| 77 | +//! #### [`contracterror`] |
| 78 | +//! |
| 79 | +//! Same as [`contracttype`]: without this feature, spec entries are only |
| 80 | +//! generated for `pub` types. With this feature, spec entries and markers are |
| 81 | +//! generated for all error enums regardless of visibility, unless |
| 82 | +//! `export = false` is explicitly set. |
| 83 | +//! |
| 84 | +//! #### [`contractevent`] |
| 85 | +//! |
| 86 | +//! Markers are embedded for all events, allowing post-build tools to strip |
| 87 | +//! spec entries for events that are never published at a contract boundary. |
| 88 | +//! |
| 89 | +//! #### [`contractimport!`] |
| 90 | +//! |
| 91 | +//! Without this feature, [`contractimport!`] generates imported types with |
| 92 | +//! `export = false`. Imported types do not produce spec entries in the |
| 93 | +//! importing contract's spec. They are purely local Rust types used for |
| 94 | +//! serialization. The importing contract's spec only contains its own function |
| 95 | +//! definitions, and callers must look at the imported contract's spec to find |
| 96 | +//! the type definitions. |
| 97 | +//! |
| 98 | +//! With this feature, [`contractimport!`] generates imported types with |
| 99 | +//! `export = true`. Imported types produce spec entries and markers in the |
| 100 | +//! importing contract, just like locally defined types. This changes the |
| 101 | +//! contract's spec to be self-contained — it includes the type definitions for |
| 102 | +//! all types used at the contract boundary, regardless of where those types |
| 103 | +//! were originally defined. Specifically: |
| 104 | +//! |
| 105 | +//! - Imported types that are used in the contract's function signatures or |
| 106 | +//! events will have their markers survive DCE and their spec entries will be |
| 107 | +//! kept after shaking. |
| 108 | +//! - Imported types that are **not** used at any contract boundary will have |
| 109 | +//! their markers eliminated by DCE and their spec entries will be stripped. |
| 110 | +//! |
| 111 | +//! This ensures that a contract importing a large interface only includes spec |
| 112 | +//! entries for the types it actually uses, while still producing a |
| 113 | +//! self-contained spec. |
| 114 | +//! |
| 115 | +//! ### Build Requirements |
| 116 | +//! |
| 117 | +//! This feature requires building with `stellar contract build` from |
| 118 | +//! `stellar-cli` v26 or newer. Building directly with `cargo build` will |
| 119 | +//! produce a build error unless the |
| 120 | +//! `SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2` environment variable is |
| 121 | +//! set. |
| 122 | +//! |
| 123 | +//! [`contracttype`]: crate::contracttype |
| 124 | +//! [`contracterror`]: crate::contracterror |
| 125 | +//! [`contractevent`]: crate::contractevent |
| 126 | +//! [`contractimport!`]: crate::contractimport |
0 commit comments