Skip to content

Commit

Permalink
Merge a36179a into 6e9130b
Browse files Browse the repository at this point in the history
  • Loading branch information
esdrubal committed Jun 18, 2024
2 parents 6e9130b + a36179a commit 342ffec
Show file tree
Hide file tree
Showing 64 changed files with 1,279 additions and 445 deletions.
2 changes: 1 addition & 1 deletion docs/book/src/forc/plugins/forc_client/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Another alternative is the `--target` option, which provides useful aliases to a
forc-deploy --target beta-3
```

Since deploying and running projects on the testnet cost gas, you will need coins to pay for them. You can get some using the [testnet faucet](https://faucet-beta-4.fuel.network/).
Since deploying and running projects on the testnet cost gas, you will need coins to pay for them. You can get some using the [testnet faucet](https://faucet-testnet.fuel.network/).

## Deployment Artifacts

Expand Down
18 changes: 11 additions & 7 deletions docs/reference/src/code/language/annotations/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
contract;

// ANCHOR: storage_namespace
#[namespace(my_storage_namespace)]
storage {
// ANCHOR_END: storage_namespace
var: u64 = 0,
my_storage_namespace {
// ANCHOR_END: storage_namespace
var: u64 = 0,
}
}

// ANCHOR: read
#[storage(read)]
// ANCHOR_END: read
fn read() {
let variable = storage.var.read();
// ANCHOR: storage_namespace_access
let variable = storage::my_storage_namespace.var.read();
// ANCHOR_END: storage_namespace_access

}

// ANCHOR: write
#[storage(write)]
// ANCHOR_END: write
fn write() {
storage.var.write(storage.var.read() + 1);
storage::my_storage_namespace.var.write(storage::my_storage_namespace.var.read() + 1);
}

// ANCHOR: read_write
#[storage(read, write)]
// ANCHOR_END: read_write
fn read_write() {
let var = storage.var.read();
storage.var.write(var + 1);
let var = storage::my_storage_namespace.var.read();
storage::my_storage_namespace.var.write(var + 1);
}

fn example() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
out
target
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[[package]]
name = 'core'
source = 'path+from-root-815C32BB386C1563'
dependencies = []

[[package]]
name = 'std'
source = 'git+https://github.com/fuellabs/sway?tag=v0.25.2#dfa6224932a97c514b707dcfc300715b2a0895dc'
dependencies = ['core']

[[package]]
name = 'storage_init'
source = 'root'
dependencies = ['std']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "storage_in_keyword"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
contract;

// ANCHOR: data_structures
struct Owner {
maximum_owners: u64,
role: Role,
}

impl Owner {
// a constructor that can be evaluated to a constant `Owner` during compilation
fn default() -> Self {
Self {
maximum_owners: 10,
role: Role::FullAccess,
}
}
}

enum Role {
FullAccess: (),
PartialAccess: (),
NoAccess: (),
}

const HASH_KEY: b256 = 0x7616e5793ef977b22465f0c843bcad56155c4369245f347bcc8a61edb08b7645;

// ANCHOR_END: data_structures
// ANCHOR: initialization
storage {
// ANCHOR: in_keyword
current_owners in HASH_KEY: u64 = 0,
// ANCHOR_END: in_keyword
explicit_declaration: Owner = Owner {
maximum_owners: 10,
role: Role::FullAccess,
},
encapsulated_declaration: Owner = Owner::default(),
}
// ANCHOR_END: initialization

This file was deleted.

14 changes: 14 additions & 0 deletions docs/reference/src/documentation/operations/storage/in-keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

# Storage `in` keyword

The `in` keyword can be used within a storage variable to override the position where the value is stored.

## Example

The `in` keyword and position value are used as follows:

```sway
{{#include ../../../../code/operations/storage/storage_in_keyword/src/main.sw:in_keyword}}
```

The code above will force the storage of the variable into the position `HASH_KEY` which is set to `0x7616e5793ef977b22465f0c843bcad56155c4369245f347bcc8a61edb08b7645` instead of the position that would be calculated from the variable name `sha256("storage.current_owners")` which would be `0x84f905e3f560d70fbfab9ffcd92198998ce6f936e3d45f8fcb16b00f6a6a8d7e`
2 changes: 2 additions & 0 deletions docs/reference/src/documentation/operations/storage/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ In the following sections we'll take a look at how Sway handles `storage` throug
- [Storage Initialization](init.md): How to declare a `storage` block
- [Reading & Writing](read-write.md): How to read from and write to storage
- [Libraries](libraries/index.md): Additional functionality provided by the [storage library](https://github.com/FuelLabs/sway/blob/master/sway-lib-std/src/storage.sw)
- [Namespaces](namespace.md): How to use `storage` namespaces
- [In keyword](in-keyword.md): How to override storage variable position
20 changes: 20 additions & 0 deletions docs/reference/src/documentation/operations/storage/namespace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

# Namespace

Namespaces can be used on a `storage` block and variables placed inside the namespaces. A single `storage` block may contain multiple namespaces placed sequentially and or nested.

The hash calculations determining the position of variables in a block with namespace `my_namespace` that contains the variable `foobar` are calculated from `sha256("storage::my_namespace.foobar")`.

## Example

A namespace can be declared as follows:

```sway
{{#include ../../../../code/language/annotations/src/main.sw:storage_namespace}}
```

A variable inside a namespace can be accessed as follows:

```sway
{{#include ../../../../code/language/annotations/src/main.sw:storage_namespace_access}}
```
27 changes: 25 additions & 2 deletions sway-ast/src/item/item_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,41 @@ use crate::priv_prelude::*;
#[derive(Clone, Debug, Serialize)]
pub struct ItemStorage {
pub storage_token: StorageToken,
pub fields: Braces<Punctuated<Annotated<StorageField>, CommaToken>>,
pub entries: Braces<Punctuated<Annotated<StorageEntry>, CommaToken>>,
}

impl Spanned for ItemStorage {
fn span(&self) -> Span {
Span::join(self.storage_token.span(), &self.fields.span())
Span::join(self.storage_token.span(), &self.entries.span())
}
}

#[derive(Clone, Debug, Serialize)]

pub struct StorageEntry {
pub name: Ident,
pub namespace: Option<Braces<Punctuated<Annotated<Box<StorageEntry>>, CommaToken>>>,
pub field: Option<StorageField>,
}

impl Spanned for StorageEntry {
fn span(&self) -> Span {
if let Some(namespace) = &self.namespace {
Span::join(self.name.span(), &namespace.span())
} else if let Some(field) = &self.field {
Span::join(self.name.span(), &field.span())
} else {
self.name.span()
}
}
}

#[derive(Clone, Debug, Serialize)]

pub struct StorageField {
pub name: Ident,
pub in_token: Option<InToken>,
pub key_expr: Option<Expr>,
pub colon_token: ColonToken,
pub ty: Ty,
pub eq_token: EqToken,
Expand Down
2 changes: 1 addition & 1 deletion sway-ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub use crate::{
item_enum::ItemEnum,
item_fn::ItemFn,
item_impl::{ItemImpl, ItemImplItem},
item_storage::{ItemStorage, StorageField},
item_storage::{ItemStorage, StorageEntry, StorageField},
item_struct::ItemStruct,
item_trait::{ItemTrait, ItemTraitItem, Traits},
item_type_alias::ItemTypeAlias,
Expand Down
55 changes: 42 additions & 13 deletions sway-core/src/ir_generation/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{
convert::*,
lexical_map::LexicalMap,
storage::{add_to_b256, get_storage_key},
storage::{add_to_b256, get_storage_field_id, get_storage_key},
types::*,
CompiledFunctionCache,
};
Expand All @@ -11,7 +11,10 @@ use crate::{
compile_constant_expression, compile_constant_expression_to_constant,
},
language::{
ty::{self, ProjectionKind, TyConfigurableDecl, TyConstantDecl, TyExpressionVariant},
ty::{
self, ProjectionKind, TyConfigurableDecl, TyConstantDecl, TyExpressionVariant,
TyStorageField,
},
*,
},
metadata::MetadataManager,
Expand All @@ -28,7 +31,6 @@ use sway_types::{
ident::Ident,
integer_bits::IntegerBits,
span::{Span, Spanned},
state::StateIndex,
u256::U256,
Named,
};
Expand Down Expand Up @@ -595,9 +597,22 @@ impl<'eng> FnCompiler<'eng> {
Ok(TerminatorValue::new(val, context))
}
ty::TyExpressionVariant::StorageAccess(access) => {
let span_md_idx = md_mgr.span_to_md(context, &access.span());
let ns = access.namespace.as_ref().map(|ns| ns.as_str());
self.compile_storage_access(context, ns, &access.ix, &access.fields, span_md_idx)
let span_md_idx: Option<MetadataIndex> = md_mgr.span_to_md(context, &access.span());
let key = TyStorageField::get_key_expression_const(
&access.key_expression.clone().map(|v| *v),
self.engines,
context,
md_mgr,
self.module,
)?;
self.compile_storage_access(
context,
access.storage_field_names.clone(),
access.struct_field_names.clone(),
key,
&access.fields,
span_md_idx,
)
}
ty::TyExpressionVariant::IntrinsicFunction(kind) => {
self.compile_intrinsic_function(context, md_mgr, kind, ast_expr.span.clone())
Expand Down Expand Up @@ -3677,8 +3692,9 @@ impl<'eng> FnCompiler<'eng> {
fn compile_storage_access(
&mut self,
context: &mut Context,
ns: Option<&str>,
ix: &StateIndex,
storage_field_names: Vec<String>,
struct_field_names: Vec<String>,
key: Option<U256>,
fields: &[ty::TyStorageAccessDescriptor],
span_md_idx: Option<MetadataIndex>,
) -> Result<TerminatorValue, CompileError> {
Expand All @@ -3703,7 +3719,15 @@ impl<'eng> FnCompiler<'eng> {

// Do the actual work. This is a recursive function because we want to drill down
// to load each primitive type in the storage field in its own storage slot.
self.compile_storage_read(context, ns, ix, &field_idcs, &base_type, span_md_idx)
self.compile_storage_read(
context,
storage_field_names,
struct_field_names,
key,
&field_idcs,
&base_type,
span_md_idx,
)
}

#[allow(clippy::too_many_arguments)]
Expand Down Expand Up @@ -3805,11 +3829,13 @@ impl<'eng> FnCompiler<'eng> {
Ok(TerminatorValue::new(val, context))
}

#[allow(clippy::too_many_arguments)]
fn compile_storage_read(
&mut self,
context: &mut Context,
ns: Option<&str>,
ix: &StateIndex,
storage_field_names: Vec<String>,
struct_field_names: Vec<String>,
key: Option<U256>,
indices: &[u64],
base_type: &Type,
span_md_idx: Option<MetadataIndex>,
Expand Down Expand Up @@ -3846,7 +3872,10 @@ impl<'eng> FnCompiler<'eng> {
// plus the offset, in number of slots, computed above. The offset within this
// particular slot is the remaining offset, in words.
(
add_to_b256(get_storage_key::<u64>(ns, ix, &[]), offset_in_slots),
add_to_b256(
get_storage_key(storage_field_names.clone(), key.clone()),
offset_in_slots,
),
offset_remaining,
)
};
Expand Down Expand Up @@ -3901,7 +3930,7 @@ impl<'eng> FnCompiler<'eng> {
.add_metadatum(context, span_md_idx);

// Store the field identifier as the third field in the `StorageKey` struct
let unique_field_id = get_storage_key(ns, ix, indices); // use the indices to get a field id that is unique even for zero-sized values that live in the same slot
let unique_field_id = get_storage_field_id(storage_field_names, struct_field_names); // use the struct_field_names to get a field id that is unique even for zero-sized values that live in the same slot
let field_id = convert_literal_to_value(context, &Literal::B256(unique_field_id.into()))
.add_metadatum(context, span_md_idx);
let gep_2_val =
Expand Down
Loading

0 comments on commit 342ffec

Please sign in to comment.