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: script and predicate blobs #1520

Merged
merged 54 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
b818345
can upload script as a blob and replace its data section in a loader
segfault-magnet Oct 4, 2024
42b2ec2
loader with data section support
segfault-magnet Oct 4, 2024
58a481f
added configurables
segfault-magnet Oct 4, 2024
55864a7
type state pattern for executable
segfault-magnet Oct 4, 2024
0155704
high level api done
segfault-magnet Oct 4, 2024
b6d7c87
push changes
segfault-magnet Oct 4, 2024
5564c39
fix tests
segfault-magnet Oct 4, 2024
c6ef475
add predicate test (failing until core changes)
segfault-magnet Oct 4, 2024
1c9303a
correct author
segfault-magnet Oct 4, 2024
dc01b51
replace unwrap with ? marks
Br1ght0ne Oct 4, 2024
70d2a80
Changes from co-review
Br1ght0ne Oct 5, 2024
5f111cc
start replacing unwraps in executable, delegate to ahmed
Br1ght0ne Oct 5, 2024
c44ad94
nits
segfault-magnet Oct 5, 2024
fa89c1e
add check for blob existence
segfault-magnet Oct 5, 2024
41ad964
add test for blob reupload
segfault-magnet Oct 5, 2024
026752a
some unit tests
segfault-magnet Oct 5, 2024
0520b96
add extra wallet to predicate test
segfault-magnet Oct 5, 2024
f317059
add docstrings
segfault-magnet Oct 5, 2024
10e187a
add docs
segfault-magnet Oct 5, 2024
cbb739e
FIx typo
Br1ght0ne Oct 5, 2024
c8f376e
set extra_wallets's provider
hal3e Oct 5, 2024
c25e469
predicates working, about to update the loader
segfault-magnet Oct 5, 2024
72649da
use ldc to push data
segfault-magnet Oct 5, 2024
991c11d
blob upload hangs
segfault-magnet Oct 5, 2024
5e87023
bump block transaction size limit introduced in 0.36.0
segfault-magnet Oct 5, 2024
41f8ffa
lint
segfault-magnet Oct 5, 2024
7df69b1
add patch branch to fuel core
segfault-magnet Oct 5, 2024
e1c5a98
fix typo
segfault-magnet Oct 5, 2024
a19b16f
fix flaky tests
segfault-magnet Oct 5, 2024
7cb2c8c
disable fuel-core-lib tests
segfault-magnet Oct 5, 2024
5d6f563
remove max queries directives
segfault-magnet Oct 5, 2024
5099664
add back fuel core patches so that we can use the optimal endpoint
segfault-magnet Oct 5, 2024
f275434
point to blobs exist branch
segfault-magnet Oct 5, 2024
1f5827a
fix branch
segfault-magnet Oct 5, 2024
b140e8c
add a comprehensive predicate+configurables+blobs test
Br1ght0ne Oct 5, 2024
652ecea
format sway code
segfault-magnet Oct 5, 2024
bd8f1fd
Apply suggestions from code review
segfault-magnet Oct 5, 2024
dc1e478
remove unwrap
segfault-magnet Oct 5, 2024
6b96269
fuel-vm branch deleted, point to commit
segfault-magnet Oct 5, 2024
50c24b4
add test for loader script calling loader contract
Br1ght0ne Oct 5, 2024
8684663
add test: loader script -> loader proxy -> loader huge_contract
Br1ght0ne Oct 5, 2024
b752773
update authors
segfault-magnet Oct 5, 2024
603c297
tests passing
segfault-magnet Oct 5, 2024
bfc7106
use main feature branch
segfault-magnet Oct 5, 2024
31c20f5
ci patch
segfault-magnet Oct 5, 2024
622f8e0
separate fuel core building/downloading so that we can repeat flaky
segfault-magnet Oct 5, 2024
79de549
branch deleted, revision pointing to master
segfault-magnet Oct 5, 2024
c511298
point to revision
segfault-magnet Oct 5, 2024
d3556bd
add wasm target
segfault-magnet Oct 5, 2024
f54d1c9
change cache key
segfault-magnet Oct 5, 2024
c07d866
dont fail fast
segfault-magnet Oct 5, 2024
ce09cbb
fix gas usages
segfault-magnet Oct 5, 2024
b901b0c
bump fuel core
segfault-magnet Oct 6, 2024
7f4af23
fix version
segfault-magnet Oct 6, 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
61 changes: 49 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ 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.36.0
FUEL_CORE_PATCH_BRANCH:
FUEL_CORE_VERSION: 0.37.0
FUEL_CORE_PATCH_BRANCH: ""
FUEL_CORE_PATCH_REVISION: ""
RUST_VERSION: 1.79.0
FORC_VERSION: 0.64.0
FORC_PATCH_BRANCH: ""
Expand Down Expand Up @@ -99,6 +100,42 @@ jobs:
echo "Comparing minimum supported toolchain ($MIN_VERSION) with ci toolchain (RUST_VERSION)"
test "$MIN_VERSION" == "$RUST_VERSION"

# Fetch Fuel Core and upload as artifact, useful when we build the core from a
# revision so that we can repeat flaky tests without rebuilding the core.
fetch-fuel-core:
runs-on: ubuntu-latest
steps:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_VERSION }}
targets: wasm32-unknown-unknown

# selecting a toolchain either by action or manual `rustup` calls should happen
# before the cache plugin, as it uses the current rustc version as its cache key
- uses: Swatinem/rust-cache@v2.7.3
continue-on-error: true
with:
key: "fuel-core-build"
- name: Install Fuel Core
run: |
if [[ -n $FUEL_CORE_PATCH_BRANCH ]]; then
cargo install --locked fuel-core-bin --git https://github.com/FuelLabs/fuel-core --branch "$FUEL_CORE_PATCH_BRANCH" --root fuel-core-install
elif [[ -n $FUEL_CORE_PATCH_REVISION ]]; then
cargo install --locked fuel-core-bin --git https://github.com/FuelLabs/fuel-core --rev "$FUEL_CORE_PATCH_REVISION" --root fuel-core-install

else
curl -sSLf https://github.com/FuelLabs/fuel-core/releases/download/v${{ env.FUEL_CORE_VERSION }}/fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu.tar.gz -L -o fuel-core.tar.gz
tar -xvf fuel-core.tar.gz
chmod +x fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu/fuel-core
mkdir -p fuel-core-install/bin
mv fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu/fuel-core fuel-core-install/bin/fuel-core
fi

- uses: actions/upload-artifact@v4
with:
name: fuel-core
path: fuel-core-install/bin/fuel-core

# Ensure workspace is publishable
publish-crates-check:
runs-on: ubuntu-latest
Expand All @@ -123,6 +160,7 @@ jobs:
- verify-rust-version
- get-workspace-members
- publish-crates-check
- fetch-fuel-core
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -136,11 +174,11 @@ jobs:
args: --all-targets
download_sway_artifacts: sway-examples
- cargo_command: nextest
args: run --all-targets --features "default fuel-core-lib coin-cache" --workspace --cargo-quiet
args: run --all-targets --features "default fuel-core-lib coin-cache" --workspace --cargo-quiet --no-fail-fast
download_sway_artifacts: sway-examples
install_fuel_core: true
- cargo_command: nextest
args: run --all-targets --workspace --cargo-quiet
args: run --all-targets --workspace --cargo-quiet --no-fail-fast
download_sway_artifacts: sway-examples
install_fuel_core: true
- cargo_command: test
Expand Down Expand Up @@ -175,17 +213,16 @@ jobs:
with:
key: "${{ matrix.cargo_command }} ${{ matrix.args }} ${{ matrix.package }}"

- name: Download Fuel Core
if: ${{ matrix.install_fuel_core }}
uses: actions/download-artifact@v4
with:
name: fuel-core
- name: Install Fuel Core
if: ${{ matrix.install_fuel_core }}
run: |
if [[ -n $FUEL_CORE_PATCH_BRANCH ]]; then
cargo install --locked fuel-core-bin --git https://github.com/FuelLabs/fuel-core --branch "$FUEL_CORE_PATCH_BRANCH"
else
curl -sSLf https://github.com/FuelLabs/fuel-core/releases/download/v${{ env.FUEL_CORE_VERSION }}/fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu.tar.gz -L -o fuel-core.tar.gz
tar -xvf fuel-core.tar.gz
chmod +x fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu/fuel-core
mv fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu/fuel-core /usr/local/bin/fuel-core
fi
chmod +x fuel-core
mv fuel-core /usr/local/bin/fuel-core

- name: Download sway example artifacts
if: ${{ matrix.download_sway_artifacts }}
Expand Down
26 changes: 13 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,23 @@ octocrab = { version = "0.39", default-features = false }
dotenv = { version = "0.15", default-features = false }

# Dependencies from the `fuel-core` repository:
fuel-core = { version = "0.36.0", default-features = false, features = [
fuel-core = { version = "0.37.0", default-features = false, features = [
"wasm-executor",
] }
fuel-core-chain-config = { version = "0.36.0", default-features = false }
fuel-core-client = { version = "0.36.0", default-features = false }
fuel-core-poa = { version = "0.36.0", default-features = false }
fuel-core-services = { version = "0.36.0", default-features = false }
fuel-core-types = { version = "0.36.0", default-features = false }
fuel-core-chain-config = { version = "0.37.0", default-features = false }
fuel-core-client = { version = "0.37.0", default-features = false }
fuel-core-poa = { version = "0.37.0", default-features = false }
fuel-core-services = { version = "0.37.0", default-features = false }
fuel-core-types = { version = "0.37.0", default-features = false }

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

# Workspace projects
fuels = { version = "0.66.5", 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 @@ -44,6 +44,7 @@
- [Running scripts](./running-scripts.md)
- [Predicates](./predicates/index.md)
- [Signatures example](./predicates/send-spend-predicate.md)
- [Pre-uploading code](./preuploading-code.md)
- [Custom transactions](./custom-transactions/index.md)
- [Transaction builders](./custom-transactions/transaction-builders.md)
- [Custom contract and script calls](./custom-transactions/custom-calls.md)
Expand Down
42 changes: 42 additions & 0 deletions docs/src/preuploading-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Pre-uploading code

If you have a script or predicate that is larger than normal or which you plan
on calling often, you can pre-upload its code as a blob to the network and run a
loader script/predicate instead. The loader can be configured with the
script/predicate configurables, so you can change how the script/predicate is
configured on each run without having large transactions due to the code
duplication.

## Scripts

A high level pre-upload:

```rust,ignore
{{#include ../../e2e/tests/scripts.rs:preload_high_level}}
```

The upload of the blob is handled inside of the `convert_into_loader` method. If you
want more fine-grained control over it, you can create the script transaction
manually:

```rust,ignore
{{#include ../../e2e/tests/scripts.rs:preload_low_level}}
```

## Predicates

You can prepare a predicate for pre-uploading without doing network requests:

```rust,ignore
{{#include ../../e2e/tests/predicates.rs:preparing_the_predicate}}
```

Once you want to execute the predicate, you must beforehand upload the blob
containing its code:

```rust,ignore
{{#include ../../e2e/tests/predicates.rs:uploading_the_blob}}
```

By pre-uploading the predicate code, you allow for cheaper calls to the predicate
from subsequent callers.
4 changes: 4 additions & 0 deletions e2e/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,23 @@ members = [
'sway/logs/script_needs_custom_decoder_logging',
'sway/logs/script_with_contract_logs',
'sway/predicates/basic_predicate',
'sway/predicates/predicate_blobs',
'sway/predicates/predicate_configurables',
'sway/predicates/predicate_witnesses',
'sway/predicates/signatures',
'sway/predicates/swap',
'sway/scripts/arguments',
'sway/scripts/basic_script',
'sway/scripts/empty',
'sway/scripts/require_from_contract',
'sway/scripts/reverting',
'sway/scripts/script_array',
'sway/scripts/script_asserts',
'sway/scripts/script_blobs',
'sway/scripts/script_configurables',
'sway/scripts/script_enum',
'sway/scripts/script_needs_custom_decoder',
'sway/scripts/script_proxy',
'sway/scripts/script_require',
'sway/scripts/script_struct',
'sway/scripts/transfer_script',
Expand Down
5 changes: 5 additions & 0 deletions e2e/sway/predicates/predicate_blobs/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "predicate_blobs"
9 changes: 9 additions & 0 deletions e2e/sway/predicates/predicate_blobs/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
predicate;

configurable {
SECRET_NUMBER: u64 = 9000,
}

fn main(arg1: u8, arg2: u8) -> bool {
arg1 == 1 && arg2 == 19 && SECRET_NUMBER == 10001
}
6 changes: 5 additions & 1 deletion e2e/sway/predicates/predicate_configurables/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ struct StructWithGeneric<D> {
configurable {
BOOL: bool = true,
U8: u8 = 8,
TUPLE: (u8, bool) = (8, true),
ARRAY: [u32; 3] = [253, 254, 255],
STRUCT: StructWithGeneric<u8> = StructWithGeneric {
field_1: 8,
field_2: 16,
Expand All @@ -41,9 +43,11 @@ configurable {
fn main(
switch: bool,
u_8: u8,
some_tuple: (u8, bool),
some_array: [u32; 3],
some_struct: StructWithGeneric<u8>,
some_enum: EnumWithGeneric<bool>,
) -> bool {
switch == BOOL && u_8 == U8 && some_struct == STRUCT && some_enum == ENUM
switch == BOOL && u_8 == U8 && some_tuple.0 == TUPLE.0 && some_tuple.1 == TUPLE.1 && some_array[0] == ARRAY[0] && some_array[1] == ARRAY[1] && some_array[2] == ARRAY[2] && some_struct == STRUCT && some_enum == ENUM
}
// ANCHOR_END: predicate_configurables
7 changes: 7 additions & 0 deletions e2e/sway/scripts/empty/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "empty"

[dependencies]
3 changes: 3 additions & 0 deletions e2e/sway/scripts/empty/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
script;

fn main() {}
5 changes: 5 additions & 0 deletions e2e/sway/scripts/script_blobs/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "script_blobs"
36 changes: 36 additions & 0 deletions e2e/sway/scripts/script_blobs/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
script;

configurable {
SECRET_NUMBER: u64 = 9000,
}

enum MyEnum {
A: u64,
B: u8,
C: (),
}

struct MyStruct {
field_a: MyEnum,
field_b: b256,
}

fn main(arg1: MyStruct) -> u64 {
assert_eq(SECRET_NUMBER, 10001);

match arg1.field_a {
MyEnum::B(value) => {
assert_eq(value, 99);
}
_ => {
assert(false)
}
}

assert_eq(
arg1.field_b,
0x1111111111111111111111111111111111111111111111111111111111111111,
);

return SECRET_NUMBER;
}
5 changes: 5 additions & 0 deletions e2e/sway/scripts/script_proxy/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "script_proxy"
24 changes: 24 additions & 0 deletions e2e/sway/scripts/script_proxy/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
script;

abi Proxy {
#[storage(write)]
fn set_target_contract(id: ContractId);

// methods of the `huge_contract` in our e2e sway contracts
#[storage(read)]
fn something() -> u64;

#[storage(read)]
fn write_some_u64(some: u64);

#[storage(read)]
fn read_some_u64() -> u64;
}

fn main(proxy_contract_id: ContractId) -> bool {
let proxy_instance = abi(Proxy, proxy_contract_id.into());
let _ = proxy_instance.something();
proxy_instance.write_some_u64(10001);
let read_u_64 = proxy_instance.read_some_u64();
return read_u_64 == 10001;
}
3 changes: 3 additions & 0 deletions e2e/tests/configurables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ async fn script_default_configurables() -> Result<()> {
)
);

let mut script_instance = script_instance;
script_instance.convert_into_loader().await?;

let response = script_instance.main().call().await?;

let expected_value = (
Expand Down
6 changes: 6 additions & 0 deletions e2e/tests/contracts.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::time::Duration;

use fuel_tx::{
consensus_parameters::{ConsensusParametersV1, FeeParametersV1},
ConsensusParameters, FeeParameters,
Expand Down Expand Up @@ -1476,6 +1478,7 @@ async fn test_contract_submit_and_response() -> Result<()> {
let contract_methods = contract_instance.methods();

let submitted_tx = contract_methods.get(1, 2).submit().await?;
tokio::time::sleep(Duration::from_millis(500)).await;
digorithm marked this conversation as resolved.
Show resolved Hide resolved
let value = submitted_tx.response().await?.value;

assert_eq!(value, 3);
Expand All @@ -1489,6 +1492,7 @@ async fn test_contract_submit_and_response() -> Result<()> {
.add_call(call_handler_2);

let handle = multi_call_handler.submit().await?;
tokio::time::sleep(Duration::from_millis(500)).await;
let (val_1, val_2): (u64, u64) = handle.response().await?.value;

assert_eq!(val_1, 7);
Expand Down Expand Up @@ -1683,6 +1687,8 @@ async fn contract_custom_call_no_signatures_strategy() -> Result<()> {
// ANCHOR_END: tb_no_signatures_strategy

let tx_id = provider.send_transaction(tx).await?;
tokio::time::sleep(Duration::from_millis(500)).await;

let tx_status = provider.tx_status(&tx_id).await?;

let response = call_handler.get_response_from(tx_status)?;
Expand Down
Loading
Loading