Skip to content
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

Enable storage initializers and emit a storage initialization JSON #2078

Merged
merged 26 commits into from
Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
caffa42
Enable storage initializers and dump out a JSON file
mohammadfawaz Jun 21, 2022
697b04b
merge with masteR
mohammadfawaz Jun 22, 2022
f4f6c9d
Move the new functions into a separate storage module
mohammadfawaz Jun 22, 2022
239d42c
Use StorageSlot directly from fuel-tx
mohammadfawaz Jun 22, 2022
b566ac3
forc deploy now uses the storage slots
mohammadfawaz Jun 23, 2022
6d1da33
add some tests
mohammadfawaz Jun 23, 2022
e03c197
lint, change initializers -> slots, and fixing some tests
mohammadfawaz Jun 23, 2022
405c84a
Merge branch 'master' into mohammadfawaz/1185
mohammadfawaz Jun 23, 2022
d22e8cc
enhance a comment
mohammadfawaz Jun 23, 2022
4bdc5f6
Merge branch 'mohammadfawaz/1185' of github.com:FuelLabs/sway into mo…
mohammadfawaz Jun 23, 2022
b0cef6a
Revert unneeded changes to sway-types
mohammadfawaz Jun 23, 2022
e7db254
merge with master and error handling
mohammadfawaz Jun 23, 2022
0f877eb
add a failing test
mohammadfawaz Jun 23, 2022
9a57b9e
Merge branch 'master' into mohammadfawaz/1185
mohammadfawaz Jun 23, 2022
6bd2195
Fix failing test
mohammadfawaz Jun 23, 2022
103793e
renaming some functions
mohammadfawaz Jun 23, 2022
e1e3cef
Test the storage slots JSON in e2e tests and add forc json-storage-sl…
mohammadfawaz Jun 23, 2022
322e412
ignore *_output.json
mohammadfawaz Jun 23, 2022
2820e35
forc documenter changes
mohammadfawaz Jun 23, 2022
dbeae01
Remove forc json-storage-slots and stop relying on forc json-abi
mohammadfawaz Jun 24, 2022
e194ebd
merge with master
mohammadfawaz Jun 24, 2022
2936e7b
merge with master
mohammadfawaz Jun 25, 2022
186378d
Enhance some comments
mohammadfawaz Jun 25, 2022
29dd491
Remove unnecessary oracle
mohammadfawaz Jun 25, 2022
0d9f00e
Merge branch 'master' into mohammadfawaz/1185
mohammadfawaz Jun 27, 2022
77a35ee
Merge branch 'master' into mohammadfawaz/1185
mohammadfawaz Jun 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# will have compiled files and executables
**/*/target/
**/*/json_abi_output.json
**/*/json_storage_slots_output.json
target

# These are backup files generated by rustfmt
Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions forc-pkg/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description = "Building, locking, fetching and updating Sway projects as Forc pa
[dependencies]
anyhow = "1"
forc-util = { version = "0.16.2", path = "../forc-util" }
fuel-tx = "0.12"
mohammadfawaz marked this conversation as resolved.
Show resolved Hide resolved
fuels-types = "0.12"
git2 = { version = "0.14", features = ["vendored-libgit2", "vendored-openssl"] }
petgraph = { version = "0.6", features = ["serde-1"] }
Expand Down
8 changes: 8 additions & 0 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use forc_util::{
find_file_name, git_checkouts_directory, kebab_to_snake_case, print_on_failure,
print_on_success, print_on_success_library, println_yellow_err,
};
use fuel_tx::StorageSlot;
use fuels_types::JsonABI;
use petgraph::{
self,
Expand Down Expand Up @@ -45,6 +46,7 @@ pub struct PinnedId(u64);
/// The result of successfully compiling a package.
pub struct Compiled {
pub json_abi: JsonABI,
pub storage_slots: Vec<StorageSlot>,
pub bytecode: Vec<u8>,
pub tree_type: TreeType,
}
Expand Down Expand Up @@ -1503,6 +1505,7 @@ pub fn compile(
warnings,
} => {
let json_abi = time_expr!("generate JSON ABI", typed_program.kind.generate_json_abi());
let storage_slots = typed_program.storage_slots.clone();
let tree_type = typed_program.kind.tree_type();
match tree_type {
// If we're compiling a library, we don't need to compile any further.
Expand All @@ -1513,6 +1516,7 @@ pub fn compile(
let lib_namespace = typed_program.root.namespace.clone();
let compiled = Compiled {
json_abi,
storage_slots,
bytecode,
tree_type,
};
Expand All @@ -1535,6 +1539,7 @@ pub fn compile(
let bytecode = bytes;
let compiled = Compiled {
json_abi,
storage_slots,
bytecode,
tree_type,
};
Expand Down Expand Up @@ -1567,6 +1572,7 @@ pub fn build(
let mut namespace_map = Default::default();
let mut source_map = SourceMap::new();
let mut json_abi = vec![];
let mut storage_slots = vec![];
let mut bytecode = vec![];
let mut tree_type = None;
for &node in &plan.compilation_order {
Expand All @@ -1581,6 +1587,7 @@ pub fn build(
namespace_map.insert(node, namespace.into());
}
json_abi.extend(compiled.json_abi);
storage_slots.extend(compiled.storage_slots);
bytecode = compiled.bytecode;
tree_type = Some(compiled.tree_type);
source_map.insert_dependency(path.clone());
Expand All @@ -1590,6 +1597,7 @@ pub fn build(
let compiled = Compiled {
bytecode,
json_abi,
storage_slots,
tree_type,
};
Ok((compiled, source_map))
Expand Down
4 changes: 4 additions & 0 deletions forc/src/cli/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ pub struct Command {
/// output will be "minified", i.e. all on one line without whitespace.
#[clap(long)]
pub minify_json_abi: bool,
/// By default the JSON for initial storage slots is formatted for human readability. By using
/// this option JSON output will be "minified", i.e. all on one line without whitespace.
#[clap(long)]
pub minify_json_storage_slots: bool,
/// Requires that the Forc.lock file is up-to-date. If the lock file is missing, or it
/// needs to be updated, Forc will exit with an error
#[clap(long)]
Expand Down
4 changes: 4 additions & 0 deletions forc/src/cli/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ pub struct Command {
/// output will be "minified", i.e. all on one line without whitespace.
#[clap(long)]
pub minify_json_abi: bool,
/// By default the JSON for initial storage slots is formatted for human readability. By using
/// this option JSON output will be "minified", i.e. all on one line without whitespace.
#[clap(long)]
pub minify_json_storage_slots: bool,
/// Requires that the Forc.lock file is up-to-date. If the lock file is missing, or it
/// needs to be updated, Forc will exit with an error
#[clap(long)]
Expand Down
5 changes: 5 additions & 0 deletions forc/src/cli/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ pub struct Command {
#[clap(long)]
pub minify_json_abi: bool,

/// By default the JSON for initial storage slots is formatted for human readability. By using
/// this option JSON output will be "minified", i.e. all on one line without whitespace.
#[clap(long)]
pub minify_json_storage_slots: bool,

/// Set the transaction byte price. Defaults to 0.
#[clap(long)]
pub byte_price: Option<u64>,
Expand Down
30 changes: 23 additions & 7 deletions forc/src/ops/forc_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub fn build(command: BuildCommand) -> Result<pkg::Compiled> {
silent_mode,
output_directory,
minify_json_abi,
minify_json_storage_slots,
locked,
build_profile,
release,
Expand Down Expand Up @@ -116,14 +117,21 @@ pub fn build(command: BuildCommand) -> Result<pkg::Compiled> {

info!(" Bytecode size is {} bytes.", compiled.bytecode.len());

// Additional ops required depending on the program type
match compiled.tree_type {
TreeType::Script => {
// hash the bytecode for scripts and store the result in a file in the output directory
let bytecode_hash = format!("0x{}", fuel_crypto::Hasher::hash(&compiled.bytecode));
let hash_file_name = format!("{}{}", &manifest.project.name, SWAY_BIN_HASH_SUFFIX);
let hash_path = output_dir.join(hash_file_name);
fs::write(hash_path, &bytecode_hash)?;
info!(" Script bytecode hash: {}", bytecode_hash);
TreeType::Contract => {
// For contracts, emit a JSON file with all the initialized storage slots.
let json_storage_slots_stem = format!("{}-storage_slots", manifest.project.name);
let json_storage_slots_path = output_dir
.join(&json_storage_slots_stem)
.with_extension("json");
let file = File::create(json_storage_slots_path)?;
let res = if minify_json_storage_slots {
serde_json::to_writer(&file, &compiled.storage_slots)
} else {
serde_json::to_writer_pretty(&file, &compiled.storage_slots)
};
res?;
}
TreeType::Predicate => {
// get the root hash of the bytecode for predicates and store the result in a file in the output directory
Expand All @@ -133,6 +141,14 @@ pub fn build(command: BuildCommand) -> Result<pkg::Compiled> {
fs::write(root_path, &root)?;
info!(" Predicate root: {}", root);
}
TreeType::Script => {
// hash the bytecode for scripts and store the result in a file in the output directory
let bytecode_hash = format!("0x{}", fuel_crypto::Hasher::hash(&compiled.bytecode));
let hash_file_name = format!("{}{}", &manifest.project.name, SWAY_BIN_HASH_SUFFIX);
let hash_path = output_dir.join(hash_file_name);
fs::write(hash_path, &bytecode_hash)?;
info!(" Script bytecode hash: {}", bytecode_hash);
}
_ => (),
}

Expand Down
13 changes: 10 additions & 3 deletions forc/src/ops/forc_deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
use anyhow::{bail, Result};
use forc_pkg::ManifestFile;
use fuel_gql_client::client::FuelClient;
use fuel_tx::{Output, Salt, Transaction};
use fuel_tx::{Output, Salt, StorageSlot, Transaction};
use fuel_vm::prelude::*;
use std::path::PathBuf;
use sway_core::TreeType;
Expand All @@ -33,6 +33,7 @@ pub async fn deploy(command: DeployCommand) -> Result<fuel_tx::ContractId> {
silent_mode,
output_directory,
minify_json_abi,
minify_json_storage_slots,
locked,
url,
build_profile,
Expand All @@ -51,6 +52,7 @@ pub async fn deploy(command: DeployCommand) -> Result<fuel_tx::ContractId> {
silent_mode,
output_directory,
minify_json_abi,
minify_json_storage_slots,
locked,
build_profile,
release,
Expand All @@ -62,6 +64,7 @@ pub async fn deploy(command: DeployCommand) -> Result<fuel_tx::ContractId> {
compiled.bytecode,
Vec::<fuel_tx::Input>::new(),
Vec::<fuel_tx::Output>::new(),
compiled.storage_slots,
);

let node_url = match &manifest.network {
Expand Down Expand Up @@ -89,6 +92,7 @@ fn create_contract_tx(
compiled_contract: Vec<u8>,
inputs: Vec<Input>,
outputs: Vec<Output>,
storage_slots: Vec<StorageSlot>,
) -> (Transaction, fuel_tx::ContractId) {
let gas_price = 0;
let gas_limit = fuel_tx::default_parameters::MAX_GAS_PER_TX;
Expand All @@ -99,11 +103,14 @@ fn create_contract_tx(

let salt = Salt::new([0; 32]);
let static_contracts = vec![];
let storage_slots = vec![];

let contract = Contract::from(compiled_contract);
let root = contract.root();
let state_root = Contract::default_state_root();

// The VM requires that storage slots are sorted.
mohammadfawaz marked this conversation as resolved.
Show resolved Hide resolved
let mut storage_slots = storage_slots;
storage_slots.sort();
let state_root = Contract::initial_state_root(storage_slots.iter());
let id = contract.id(&salt, &root, &state_root);
info!("Contract id: 0x{}", hex::encode(id));
let outputs = [
Expand Down
1 change: 1 addition & 0 deletions forc/src/ops/forc_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub async fn run(command: RunCommand) -> Result<Vec<fuel_tx::Receipt>> {
silent_mode: command.silent_mode,
output_directory: command.output_directory,
minify_json_abi: command.minify_json_abi,
minify_json_storage_slots: command.minify_json_storage_slots,
locked: command.locked,
build_profile: None,
release: false,
Expand Down
1 change: 1 addition & 0 deletions sway-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dirs = "3.0"
either = "1.6"
fuel-asm = "0.5"
fuel-crypto = "0.5"
fuel-tx = "0.12"
fuel-types = "0.5"
fuel-vm = "0.11"
fuels-types = "0.12"
Expand Down
5 changes: 4 additions & 1 deletion sway-core/src/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1867,7 +1867,10 @@ fn storage_field_to_storage_field(
let storage_field = StorageField {
name: storage_field.name,
type_info: ty_to_type_info(ec, storage_field.ty)?,
//initializer: expr_to_expression(storage_field.expr),
initializer: storage_field
.initializer
.map(|initializer| expr_to_expression(ec, initializer.1))
.transpose()?,
};
Ok(storage_field)
}
Expand Down
5 changes: 3 additions & 2 deletions sway-core/src/ir_generation.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
mod compile;
mod const_eval;
pub mod const_eval;
mod convert;
mod function;
mod lexical_map;
mod purity;
pub mod storage;
mod types;

use crate::{
Expand All @@ -17,7 +18,7 @@ use sway_types::span::Span;
pub(crate) use purity::PurityChecker;

pub(crate) fn compile_program(program: TypedProgram) -> Result<Context, CompileError> {
let TypedProgram { kind, root } = program;
let TypedProgram { kind, root, .. } = program;

let mut ctx = Context::default();
match kind {
Expand Down
22 changes: 18 additions & 4 deletions sway-core/src/ir_generation/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
},
};

use super::types::*;
use super::{convert::convert_literal_to_constant, types::*};

use sway_ir::{
constant::{Constant, ConstantValue},
Expand All @@ -26,6 +26,20 @@ pub(super) fn compile_constant_expression(
const_expr: &TypedExpression,
) -> Result<Value, CompileError> {
let span_id_idx = MetadataIndex::from_span(context, &const_expr.span);

let constant_evaluated = compile_constant_expression_to_constant(context, module, const_expr)?;
Ok(Value::new_constant(
context,
constant_evaluated,
span_id_idx,
))
}

pub(crate) fn compile_constant_expression_to_constant(
context: &mut Context,
module: Module,
const_expr: &TypedExpression,
) -> Result<Constant, CompileError> {
let err = match &const_expr.expression {
// Special case functions because the span in `const_expr` is to the inlined function
// definition, rather than the actual call site.
Expand All @@ -39,8 +53,8 @@ pub(super) fn compile_constant_expression(
}),
};
let mut known_consts = MappedStack::<Ident, Constant>::new();
const_eval_typed_expr(context, module, &mut known_consts, const_expr)
.map_or(err, |c| Ok(Value::new_constant(context, c, span_id_idx)))

const_eval_typed_expr(context, module, &mut known_consts, const_expr).map_or(err, Ok)
}

// A HashMap that can hold multiple values and
Expand Down Expand Up @@ -97,7 +111,7 @@ fn const_eval_typed_expr(
expr: &TypedExpression,
) -> Option<Constant> {
match &expr.expression {
TypedExpressionVariant::Literal(l) => Some(super::convert::convert_literal_to_constant(l)),
TypedExpressionVariant::Literal(l) => Some(convert_literal_to_constant(l)),
TypedExpressionVariant::FunctionApplication {
arguments,
function_body,
Expand Down
17 changes: 0 additions & 17 deletions sway-core/src/ir_generation/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,20 +140,3 @@ fn convert_resolved_type(
TypeInfo::Storage { .. } => reject_type!("Storage"),
})
}

use uint::construct_uint;

#[allow(
// These two warnings are generated by the `construct_uint!()` macro below.
clippy::assign_op_pattern,
clippy::ptr_offset_with_cast
)]
pub(super) fn add_to_b256(x: fuel_types::Bytes32, y: u64) -> fuel_types::Bytes32 {
construct_uint! {
struct U256(4);
}
let x = U256::from(*x);
let y = U256::from(y);
let res: [u8; 32] = (x + y).into();
fuel_types::Bytes32::from(res)
}
Loading