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

feat!: deploying large contracts (loader + blob support) #1472

Merged
merged 55 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
58602ae
support blob tx
segfault-magnet Jul 22, 2024
5290ad9
chunked deployment of contracts works
segfault-magnet Jul 23, 2024
2f88e09
Merge remote-tracking branch 'origin/master' into feat/chunked_contra…
segfault-magnet Jul 23, 2024
51c7446
move blob tx to separate module
segfault-magnet Jul 23, 2024
eccff68
predicates fixed
segfault-magnet Jul 23, 2024
9187f55
turn on validation, remove repro
segfault-magnet Jul 23, 2024
f0ec31d
crude estimation available
segfault-magnet Jul 24, 2024
7a8c377
about to review
segfault-magnet Jul 24, 2024
e0aa28c
remove unused deps
segfault-magnet Jul 24, 2024
9669203
change authors
segfault-magnet Jul 24, 2024
26dea47
refactoring the test
segfault-magnet Jul 24, 2024
50e1467
nits
segfault-magnet Jul 24, 2024
b6f6dce
nits
segfault-magnet Jul 24, 2024
90f3896
comments
segfault-magnet Jul 24, 2024
96a9a38
use git revisions
segfault-magnet Jul 24, 2024
ef9b095
clippy
segfault-magnet Jul 24, 2024
d0b9692
typo
segfault-magnet Jul 24, 2024
a576efa
Apply suggestions from code review
segfault-magnet Jul 25, 2024
3680315
pr suggestions
segfault-magnet Jul 25, 2024
5b83cfe
Update e2e/tests/contracts.rs
segfault-magnet Jul 25, 2024
b8aeb90
pr comment
segfault-magnet Jul 25, 2024
d7d2d5a
Apply suggestions from code review
segfault-magnet Jul 27, 2024
50359f1
Merge branch 'master' into feat/chunked_contract_deploy_w_blobs
segfault-magnet Jul 27, 2024
cc15d74
Merge branch 'master' into feat/chunked_contract_deploy_w_blobs
Br1ght0ne Jul 29, 2024
a18dc0a
Merge branch 'master' into feat/chunked_contract_deploy_w_blobs
hal3e Jul 29, 2024
a4fcfa5
fix loader code
segfault-magnet Jul 30, 2024
61b797f
clippy
segfault-magnet Jul 30, 2024
66d416d
step enumeration
segfault-magnet Jul 30, 2024
2624c7b
use patched binary until a release is made
segfault-magnet Jul 30, 2024
0b63ceb
binary patch cannot build, go back to waiting for a release
segfault-magnet Jul 30, 2024
24b7fe3
docs
segfault-magnet Jul 31, 2024
7079321
remove patch branch
segfault-magnet Jul 31, 2024
619aa6b
turn of fuel core lib by default in contracts examples
segfault-magnet Jul 31, 2024
f95f384
comment on jump amount
segfault-magnet Jul 31, 2024
caa8356
add gql body size limit configuration parameter
segfault-magnet Aug 2, 2024
941059e
Merge branch 'master' into feat/chunked_contract_deploy_w_blobs
hal3e Aug 5, 2024
2f2f692
update to latest release
segfault-magnet Aug 7, 2024
d0c85ec
pause for sleep
segfault-magnet Aug 7, 2024
9820cb9
docs work
segfault-magnet Aug 8, 2024
b9fd5de
pause
segfault-magnet Aug 8, 2024
a73260a
tests passing
segfault-magnet Aug 8, 2024
284e088
unused imports
segfault-magnet Aug 8, 2024
4c8fbfe
unused imports
segfault-magnet Aug 8, 2024
622336a
group imports
segfault-magnet Aug 8, 2024
a11fd5f
docs
segfault-magnet Aug 8, 2024
423d750
docstrings
segfault-magnet Aug 8, 2024
fed2af4
separate out unit tests
segfault-magnet Aug 8, 2024
8cd28bd
clippy
segfault-magnet Aug 8, 2024
455644e
fix lint
segfault-magnet Aug 8, 2024
1ad1bb2
pr comments
segfault-magnet Aug 9, 2024
fa13330
Update e2e/tests/contracts.rs
segfault-magnet Aug 9, 2024
e2ef75d
Update docs/src/deploying/large_contract.md
segfault-magnet Aug 9, 2024
3006169
docstring
segfault-magnet Aug 9, 2024
12ff58a
Update docs/src/SUMMARY.md
segfault-magnet Aug 9, 2024
98babb0
rename to large contracts
segfault-magnet Aug 9, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ env:
CARGO_TERM_COLOR: always
DASEL_VERSION: https://github.com/TomWright/dasel/releases/download/v2.3.6/dasel_linux_amd64
RUSTFLAGS: "-D warnings"
FUEL_CORE_VERSION: 0.31.0
FUEL_CORE_VERSION: 0.32.0
FUEL_CORE_PATCH_BRANCH:
RUST_VERSION: 1.79.0
FORC_VERSION: 0.62.0
Expand Down
27 changes: 14 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ futures = "0.3.29"
hex = { version = "0.4.3", default-features = false }
itertools = "0.12.0"
portpicker = "0.1.1"
pretty_assertions = { version = "1.4", default-features = false }
proc-macro2 = "1.0.70"
quote = "1.0.33"
rand = { version = "0.8.5", default-features = false, features = [
Expand All @@ -81,21 +82,21 @@ which = { version = "6.0.0", default-features = false }
zeroize = "1.7.0"

# Dependencies from the `fuel-core` repository:
fuel-core = { version = "0.31.0", default-features = false }
fuel-core-chain-config = { version = "0.31.0", default-features = false }
fuel-core-client = { version = "0.31.0", default-features = false }
fuel-core-poa = { version = "0.31.0", default-features = false }
fuel-core-services = { version = "0.31.0", default-features = false }
fuel-core-types = { version = "0.31.0", default-features = false }
fuel-core = { version = "0.32.0", default-features = false }
fuel-core-chain-config = { version = "0.32.0", default-features = false }
fuel-core-client = { version = "0.32.0", default-features = false }
fuel-core-poa = { version = "0.32.0", default-features = false }
fuel-core-services = { version = "0.32.0", default-features = false }
fuel-core-types = { version = "0.32.0", default-features = false }

# Dependencies from the `fuel-vm` repository:
fuel-asm = { version = "0.55.0" }
fuel-crypto = { version = "0.55.0" }
fuel-merkle = { version = "0.55.0" }
fuel-storage = { version = "0.55.0" }
fuel-tx = { version = "0.55.0" }
fuel-types = { version = "0.55.0" }
fuel-vm = { version = "0.55.0" }
fuel-asm = { version = "0.56.0" }
fuel-crypto = { version = "0.56.0" }
fuel-merkle = { version = "0.56.0" }
fuel-storage = { version = "0.56.0" }
fuel-tx = { version = "0.56.0" }
fuel-types = { version = "0.56.0" }
fuel-vm = { version = "0.56.0" }

# Workspace projects
fuels = { version = "0.65.1", path = "./packages/fuels", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- [Storage slots](./deploying/storage-slots.md)
- [Interacting with contracts](./deploying/interacting-with-contracts.md)
- [The FuelVM Binary file](./deploying/the-fuelvm-binary-file.md)
- [Large contract](./deploying/large_contract.md)
segfault-magnet marked this conversation as resolved.
Show resolved Hide resolved
- [Calling contracts](./calling-contracts/index.md)
- [Connecting wallets](./calling-contracts/calls-with-different-wallets.md)
- [Transaction policies](./calling-contracts/tx-policies.md)
Expand Down
82 changes: 82 additions & 0 deletions docs/src/deploying/large_contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Deploying Large Contracts

If your contract exceeds the size limit for a single deployment:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:show_contract_is_too_big}}
```

you can deploy it in segments using a partitioned approach:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:deploy_via_loader}}
```

When you convert a standard contract into a loader contract, the following changes occur:

* The original contract code is replaced with the loader contract code.
* The original contract code is split into blobs, which will be deployed via blob transactions before deploying the contract itself.
* The new loader code, when invoked, loads these blobs into memory and executes your original contract.

After deploying the loader contract, you can interact with it just as you would with a standard contract:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:use_loader}}
```

A helper function is available to deploy your contract normally if it is within the size limit, or as a loader contract if it exceeds the limit:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:auto_convert_to_loader}}
```

You also have the option to separate the blob upload from the contract deployment for more granular control:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:upload_blobs_then_deploy}}
```

Alternatively, you can manually split your contract code into blobs and then create and deploy a loader:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:manual_blobs_then_deploy}}
```

Or you can upload the blobs yourself and proceed with just the loader deployment:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:manual_blob_upload_then_deploy}}
```

## Blob Size Considerations

The size of a Blob transaction is constrained by three factors:

<!--Needed to disable lints because the multiline ordered list is messing with the linter. It keeps suggesting that each item is a start of a new list.-->
<!-- markdownlint-disable -->
1. The maximum size of a single transaction:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:show_max_tx_size}}
```

2. The maximum gas usage for a single transaction:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:show_max_tx_gas}}
```

3. The maximum HTTP body size accepted by the Fuel node.
To estimate an appropriate size for your blobs, you can run:
segfault-magnet marked this conversation as resolved.
Show resolved Hide resolved

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:estimate_max_blob_size}}
```
<!-- markdownlint-restore -->

However, keep in mind the following limitations:

* The estimation only considers the maximum transaction size, not the max gas usage or HTTP body limit.
* It does not account for any size increase that may occur after the transaction is funded.

Therefore, it is advisable to make your blobs a few percent smaller than the estimated maximum size.
3 changes: 3 additions & 0 deletions e2e/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ members = [
'sway/bindings/simple_contract',
'sway/bindings/type_paths',
'sway/contracts/asserts',
'sway/contracts/huge_contract',
'sway/contracts/auth_testing_abi',
'sway/contracts/auth_testing_contract',
'sway/contracts/block_timestamp',
Expand Down Expand Up @@ -110,3 +111,5 @@ members = [
'sway/types/scripts/script_u256',
'sway/types/scripts/script_vectors',
]
[patch.'https://github.com/fuellabs/sway']
std = { git = "https://github.com/fuellabs/sway", branch = "esdrubal/abi_changes" }
digorithm marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 7 additions & 0 deletions e2e/sway/contracts/huge_contract/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "huge_contract"

[dependencies]
14 changes: 14 additions & 0 deletions e2e/sway/contracts/huge_contract/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
contract;

abi MyContract {
fn something() -> u64;
}

impl MyContract for Contract {
fn something() -> u64 {
asm() {
blob i450000;
}
1001
}
}
67 changes: 67 additions & 0 deletions e2e/tests/configurables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,73 @@ async fn contract_configurables() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn contract_manual_configurables() -> Result<()> {
setup_program_test!(
Abigen(Contract(
name = "MyContract",
project = "e2e/sway/contracts/configurables"
)),
Wallets("wallet")
);

let str_4: SizedAsciiString<4> = "FUEL".try_into()?;
let new_struct = StructWithGeneric {
field_1: 16u8,
field_2: 32,
};
let new_enum = EnumWithGeneric::VariantTwo;

let configurables = MyContractConfigurables::default()
.with_BOOL(false)?
.with_U8(7)?
.with_U16(15)?
.with_U32(31)?
.with_U64(63)?
.with_U256(U256::from(8))?
.with_B256(Bits256([2; 32]))?
.with_STR_4(str_4.clone())?
.with_TUPLE((7, false))?
.with_ARRAY([252, 253, 254])?
.with_STRUCT(new_struct.clone())?
.with_ENUM(new_enum.clone())?;

let contract_id = Contract::load_from(
"sway/contracts/configurables/out/release/configurables.bin",
LoadConfiguration::default(),
)?
.with_configurables(configurables)
MujkicA marked this conversation as resolved.
Show resolved Hide resolved
.deploy(&wallet, TxPolicies::default())
.await?;

let contract_instance = MyContract::new(contract_id, wallet.clone());

let response = contract_instance
.methods()
.return_configurables()
.call()
.await?;

let expected_value = (
false,
7,
15,
31,
63,
U256::from(8),
Bits256([2; 32]),
str_4,
(7, false),
[252, 253, 254],
new_struct,
new_enum,
);

assert_eq!(response.value, expected_value);

Ok(())
}

#[tokio::test]
async fn script_configurables() -> Result<()> {
// ANCHOR: script_configurables
Expand Down
Loading
Loading