forked from FuelLabs/sway
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce a
StorageBytes
type in the standard library (FuelLabs#4001)
## Description The following allows for the storage of a collection of tightly packed bytes with the use of the `Bytes` type. This will provide significant space savings over a `StorageVec<u8>` and will also unblock `StorageString` in the Sway-libs repo. Please note however that the bytes are still padded to the size of a quadword in storage. There will be at most 31 padded bytes for any `StorageBytes` type. I've initially opted to omit adding functions such as `push()`. This is to encourage any byte manipulation to be done in the heap using the `Bytes` type and prevent successive storage read/writes calls in the same transaction. Closes FuelLabs#3910 ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: bitzoic <[email protected]>
- Loading branch information
Showing
8 changed files
with
353 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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 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 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 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,2 @@ | ||
out | ||
target |
13 changes: 13 additions & 0 deletions
13
test/src/sdk-harness/test_projects/storage_bytes/Forc.lock
This file contains 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,13 @@ | ||
[[package]] | ||
name = 'core' | ||
source = 'path+from-root-B82B1B615F276312' | ||
|
||
[[package]] | ||
name = 'std' | ||
source = 'path+from-root-B82B1B615F276312' | ||
dependencies = ['core'] | ||
|
||
[[package]] | ||
name = 'storage_bytes' | ||
source = 'member' | ||
dependencies = ['std'] |
This file contains 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,8 @@ | ||
[project] | ||
authors = ["Fuel Labs <[email protected]>"] | ||
entry = "main.sw" | ||
license = "Apache-2.0" | ||
name = "storage_bytes" | ||
|
||
[dependencies] | ||
std = { path = "../../../../../sway-lib-std" } |
186 changes: 186 additions & 0 deletions
186
test/src/sdk-harness/test_projects/storage_bytes/mod.rs
This file contains 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,186 @@ | ||
use fuels::prelude::*; | ||
|
||
abigen!(Contract( | ||
name = "TestStorageBytesContract", | ||
abi = "test_projects/storage_bytes/out/debug/storage_bytes-abi.json", | ||
)); | ||
|
||
async fn setup() -> TestStorageBytesContract { | ||
let wallet = launch_provider_and_get_wallet().await; | ||
let id = Contract::deploy( | ||
"test_projects/storage_bytes/out/debug/storage_bytes.bin", | ||
&wallet, | ||
TxParameters::default(), | ||
StorageConfiguration::with_storage_path(Some( | ||
"test_projects/storage_bytes/out/debug/storage_bytes-storage_slots.json".to_string(), | ||
)), | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
TestStorageBytesContract::new(id, wallet) | ||
} | ||
|
||
#[tokio::test] | ||
async fn stores_byte() { | ||
let instance = setup().await; | ||
|
||
let input = vec![1u8]; | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, 0); | ||
|
||
instance.methods().store_bytes(input.clone()).call().await.unwrap(); | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, input.len() as u64); | ||
|
||
instance | ||
.methods() | ||
.assert_stored_bytes(input) | ||
.call() | ||
.await | ||
.unwrap(); | ||
} | ||
|
||
#[tokio::test] | ||
async fn stores_8_bytes() { | ||
let instance = setup().await; | ||
|
||
let input = vec![1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8]; | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, 0); | ||
|
||
instance.methods().store_bytes(input.clone()).call().await.unwrap(); | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, input.len() as u64); | ||
|
||
instance.methods().assert_stored_bytes(input).call().await.unwrap(); | ||
} | ||
|
||
#[tokio::test] | ||
async fn stores_32_bytes() { | ||
let instance = setup().await; | ||
|
||
let input = vec![ | ||
1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 1u8, 2u8, | ||
3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, | ||
]; | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, 0); | ||
|
||
instance.methods().store_bytes(input.clone()).call().await.unwrap(); | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, input.len() as u64); | ||
|
||
instance.methods().assert_stored_bytes(input).call().await.unwrap(); | ||
} | ||
|
||
#[tokio::test] | ||
async fn stores_string_as_bytes() { | ||
let instance = setup().await; | ||
|
||
let input = String::from("Fuel is blazingly fast!"); | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, 0); | ||
|
||
instance | ||
.methods() | ||
.store_bytes(input.clone().as_bytes().into()) | ||
.call() | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!( | ||
instance.methods().len().call().await.unwrap().value, | ||
input.clone().as_bytes().len() as u64 | ||
); | ||
|
||
instance | ||
.methods() | ||
.assert_stored_bytes(input.as_bytes().into()) | ||
.call() | ||
.await | ||
.unwrap(); | ||
} | ||
|
||
#[tokio::test] | ||
async fn stores_long_string_as_bytes() { | ||
let instance = setup().await; | ||
|
||
// 2060 bytes | ||
let input = String::from("Nam quis nulla. Integer malesuada. In in enim a arcu imperdiet malesuada. Sed vel lectus. Donec odio urna, tempus molestie, porttitor ut, iaculis quis, sem. Phasellus rhoncus. Aenean id metus id velit ullamcorper pulvinar. Vestibulum fermentum tortor id mi. Pellentesque ipsum. Nulla non arcu lacinia neque faucibus fringilla. Nulla non lectus sed nisl molestie malesuada. Proin in tellus sit amet nibh dignissim sagittis. Vivamus luctus egestas leo. Maecenas sollicitudin. Nullam rhoncus aliquam metus. Etiam egestas wisi a erat. | ||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam feugiat, turpis at pulvinar vulputate, erat libero tristique tellus, nec bibendum odio risus sit amet ante. Aliquam erat volutpat. Nunc auctor. Mauris pretium quam et urna. Fusce nibh. Duis risus. Curabitur sagittis hendrerit ante. Aliquam erat volutpat. Vestibulum erat nulla, ullamcorper nec, rutrum non, nonummy ac, erat. Duis condimentum augue id magna semper rutrum. Nullam justo enim, consectetuer nec, ullamcorper ac, vestibulum in, elit. Proin pede metus, vulputate nec, fermentum fringilla, vehicula vitae, justo. Fusce consectetuer risus a nunc. Aliquam ornare wisi eu metus. Integer pellentesque quam vel velit. Duis pulvinar. | ||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi gravida libero nec velit. Morbi scelerisque luctus velit. Etiam dui sem, fermentum vitae, sagittis id, malesuada in, quam. Proin mattis lacinia justo. Vestibulum facilisis auctor urna. Aliquam in lorem sit amet leo accumsan lacinia. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Phasellus et lorem id felis nonummy placerat. Fusce dui leo, imperdiet in, aliquam sit amet, feugiat eu, orci. Aenean vel massa quis mauris vehicula lacinia. Quisque tincidunt scelerisque libero. Maecenas libero. Etiam dictum tincidunt diam. Donec ipsum massa, ullamcorper in, auctor et, scelerisque sed, est. Suspendisse nisl. Sed convallis magna eu sem. Cras pede libero, dapibus nec, pretium"); | ||
|
||
assert_eq!(instance.methods().len().call().await.unwrap().value, 0); | ||
|
||
let tx_params = TxParameters::new(None, Some(12_000_000), None); | ||
instance | ||
.methods() | ||
.store_bytes(input.clone().as_bytes().into()) | ||
.tx_params(tx_params) | ||
.call() | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!( | ||
instance.methods().len().call().await.unwrap().value, | ||
input.clone().as_bytes().len() as u64 | ||
); | ||
|
||
let tx_params = TxParameters::new(None, Some(12_000_000), None); | ||
instance | ||
.methods() | ||
.assert_stored_bytes(input.as_bytes().into()) | ||
.tx_params(tx_params) | ||
.call() | ||
.await | ||
.unwrap(); | ||
} | ||
|
||
#[tokio::test] | ||
async fn stores_string_twice() { | ||
let instance = setup().await; | ||
|
||
let input1 = String::from("Fuel is the fastest modular execution layer"); | ||
let input2 = String::from("Fuel is blazingly fast!"); | ||
|
||
instance | ||
.methods() | ||
.store_bytes(input1.clone().as_bytes().into()) | ||
.call() | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!( | ||
instance.methods().len().call().await.unwrap().value, | ||
input1.clone().as_bytes().len() as u64 | ||
); | ||
|
||
instance | ||
.methods() | ||
.assert_stored_bytes(input1.as_bytes().into()) | ||
.call() | ||
.await | ||
.unwrap(); | ||
|
||
instance | ||
.methods() | ||
.store_bytes(input2.clone().as_bytes().into()) | ||
.call() | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!( | ||
instance.methods().len().call().await.unwrap().value, | ||
input2.clone().as_bytes().len() as u64 | ||
); | ||
|
||
instance | ||
.methods() | ||
.assert_stored_bytes(input2.as_bytes().into()) | ||
.call() | ||
.await | ||
.unwrap(); | ||
} |
Oops, something went wrong.