-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Attribute for checking of trivial encoding and decoding #7575
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
Merged
Merged
Changes from all commits
Commits
Show all changes
66 commits
Select commit
Hold shift + click to select a range
93a9459
trivial check attributes
xunilrj aff48d6
fmt and clippy issues
xunilrj d146418
update tests
xunilrj 05c7be4
error message improvements
xunilrj a6af3b7
improve docs
xunilrj e95a148
improve docs
xunilrj 4c21b92
improve docs
xunilrj 16e9ec8
better error message
xunilrj 7a83a5d
TrivialBool and TrivialEnum
xunilrj 3263e62
fmt and clippy issues
xunilrj ab14d18
remove sway-lib-std warnings
xunilrj eac268d
better error message for tuples and arrays
xunilrj 2d0b975
TrivialBool and TrivialEnum using auto-impl
xunilrj dffb58a
TrivialBool and TrivialEnum using auto-impl
xunilrj c030457
fmt and clippy issues
xunilrj 5c8c433
correctly call is_decode_trivial
xunilrj 98fcc0a
correctly call is_decode_trivial
xunilrj 2bdca40
fmt and clippy issues
xunilrj 1598670
PR fixes
xunilrj 76f0067
fmt and clippy issues
xunilrj f201c3b
runninf forc-fmt
xunilrj b793bb8
PR fixes
xunilrj 99f1484
fmt and clippy issues
xunilrj 0512177
fmt and clippy issues
xunilrj acb1fa3
update tests
xunilrj 4dfa273
fix tests
xunilrj 5d10452
update tests
xunilrj 5c95a4d
link to the final documentation url
xunilrj 5bff24f
link to the final documentation url
xunilrj 5fa34a3
fixing typos
xunilrj 2c624de
error improvements and gas benchmark
xunilrj ba1b543
improve error message
xunilrj f1fbc33
removing range from memory representation
xunilrj dab9588
fmt and clippy issues
xunilrj c3dd664
update tests
xunilrj 2f42b09
fmt and clippy issues
xunilrj 0828be0
update tests
xunilrj 2aef0db
fixing typos
xunilrj be5bc00
moving ir check to inside the type phase
xunilrj eab029c
rebase issues
xunilrj 89bf63f
rebase issues
xunilrj ba9e791
removing intrinsic
xunilrj f3cb23d
check abi fns
xunilrj 2c50019
require attribute for abis
xunilrj c4a5d5a
update tests
xunilrj 46123e7
ignore for gc test: it needs experimental features
xunilrj ad6537e
checking abi function for enums
xunilrj 46fdce1
also check return type
xunilrj 60d0680
small refactor to the check code
xunilrj 988f91b
more tests
xunilrj 48bd60e
fmt and clippy issues
xunilrj 20deb6d
update tests
xunilrj e988ca8
update tests
xunilrj 89c25a9
fmt and clippy issues
xunilrj 07a5072
remove redundant manager
xunilrj 50894e1
TrivialVec and tests
xunilrj cc0c155
rollback TrivialVec
xunilrj 50a2638
fmt and clippy issues
xunilrj 7b2b315
new values for the attribute require
xunilrj 3c432ee
fmt and clippy
xunilrj 52d4f77
update tests
xunilrj 8a24b03
PR adjustments
xunilrj c1943fd
pr adjustments
xunilrj 0c2a1e7
fmt and clippy issues
xunilrj 511867b
fmt and clippy issues
xunilrj 094041d
fix attribute args quantity
xunilrj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -275,3 +275,9 @@ Preload | |
| preloads | ||
| Preloads | ||
| VM's | ||
| Decodable | ||
| Encodable | ||
| callee | ||
| decodable | ||
| encodable | ||
| Vec | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # Trivially Encodable & Decodable Types | ||
|
|
||
| When a contract calls another contract, all arguments are **encoded** just before the call is actually executed, | ||
| and the callee **decodes** these arguments right before the target method starts. | ||
| This adds a small but non‑negligible gas cost, from hundreds to thousands of gas depending on the complexity of the arguments. | ||
|
|
||
| The Sway compiler mitigates this overhead for a subset of types that can be **trivially encoded** and/or **trivially decoded** – | ||
| that is, types that their *runtime representation*, how the type bytes are laid out inside the VM, is *identical* to their *encoded representation*, | ||
| how their bytes are laid out in the encoded buffer. | ||
|
|
||
| For such types the compiler can skip the encoding/decoding process entirely, saving gas and simplifying the generated code. | ||
|
|
||
| > **Trivial encoding** – encoding is replaced with a simple "transmute". | ||
| > **Trivial decoding** – encoding is replaced with a simple "transmute". | ||
|
|
||
| The compiler can skip each individually, but the whole gain comes only when both are skipped together. | ||
|
|
||
| ## Checking Triviality | ||
|
|
||
| Each struct that should be treated as trivially encodable/decodable can be annotated with the `#[trivial]` attribute: | ||
|
|
||
| ```sway | ||
| #[trivial(encode = "require", decode = "require")] | ||
| pub struct SomeArgument { | ||
| a: bool, | ||
| b: SomeEnum, | ||
| } | ||
| ``` | ||
|
|
||
| - `encode = "require"` – the compiler will check if the type is trivially encodable; if not, the build fails. | ||
| - `decode = "require"` – similarly for decoding. | ||
|
|
||
| Possible values are: | ||
|
|
||
| - required: compiler will check and error if the check fails; | ||
| - optional: compiler will only warn non-compliance; | ||
| - any: nothing will be checked. | ||
|
|
||
| This attributed can be used directly on types, but also on entry points such as "main" function for scripts and predicates; and contract methods for contracts. | ||
|
|
||
| ## Which Types Are Trivial? | ||
|
|
||
| | Type | Trivially Encodable | Trivially Decodable | Notes | | ||
| |------|---------------------|---------------------|-------| | ||
| | `bool` | ✅ | ❌ | `bool` encodes to a single byte (`0` or `1`), but decoding must validate that the byte is a legal value. | | ||
| | `u8`, `u64`, `u256`, `b256` | ✅ | ✅ | | | ||
| | `u16`, `u32` | ❌ | ❌ | Their runtime representation is actually a `u64` | | ||
| | Structs | ✅ If all their members are trivial | ✅ If all their member are trivial | Recursively evaluated. | | ||
| | Enums | ✅ If all variants are trivial | ❌ | Enums have an `u64` discriminant that cannot be trivially decodable. | | ||
| | Arrays | ✅ If the item type is trivial | ✅ if the item type is trivial | | ||
| | String Arrays | ✅ See * | ✅ See * | | | ||
| | Vec, Dictionary, String, etc. | ❌ | ❌ | Data Structures are never trivial | | ||
|
|
||
| Only when the feature "str_array_no_padding" is turned on. When the feature toggle is off, only string arrays that its length is multiple of 8. | ||
|
|
||
| ### Why `bool` and `enum` are not trivially decodable | ||
|
|
||
| Probably the most surprising non trivial base data type is `bool`. Mainly because `bool` is obviously trivially encodable. But there is no guarantee | ||
| that buffer does not have a value like `2`, that being "transmuted" into a bool would be allow its runtime representation to be `2`, which is **undefined behaviour**. | ||
|
|
||
| The same limitation applies to enums. Enums are implemented as "tagged unions" which means that their runtime representation has a discriminant value as `u64`. There | ||
| is no guarantee that the buffer would have a valid value for its discriminant. | ||
|
|
||
| --- | ||
|
|
||
| ## 3. Workaround for Non‑trivial Types | ||
|
|
||
| If you need to expose a `bool` or an enum as a public argument, you can either: | ||
|
|
||
| 1. **Manual validation** – expose a raw `u64` (or `u8`) and check its value in the callee. | ||
|
|
||
| ```sway | ||
| #[trivial(encode = "require", decode = "require")] | ||
| pub struct Flag(u8); // manually validate that value <= 1 | ||
| ``` | ||
|
|
||
| 1. **Custom wrappers** – Sway ships with `TrivialBool`, `TrivialEnum<T>` and `TrivialVec<T, N>` that enforce the bounds at compile time. | ||
|
|
||
| ```sway | ||
| use sway::codec::TrivialBool; | ||
| use sway::codec::TrivialEnum; | ||
| use sway::codec::TrivialVec; | ||
|
|
||
| #[trivial(encode = "require", decode = "require")] | ||
| pub struct SomeArgument { | ||
| a: TrivialBool, | ||
| b: TrivialEnum<SomeEnum>, | ||
| c: TrivialVec<u64, 16>, | ||
| } | ||
| ``` | ||
|
|
||
| These wrappers automatically provide the guard checks and still let the compiler treat them as trivial. | ||
| Their usage is very similar to `Option<bool>`. | ||
|
|
||
| ```sway | ||
| let a: bool = some_argument.a.unwrap(); | ||
| let b: SomeEnum = some_argument.b.unwrap(); | ||
| let c: &[u64] = some_argument.c.as_slice(); | ||
| ``` |
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.