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

Open
wants to merge 35 commits into
base: master
Choose a base branch
from

Conversation

segfault-magnet
Copy link
Contributor

@segfault-magnet segfault-magnet commented Jul 24, 2024

closes: #1470

Let me know what you think of the interface. Haven't written docs or examples until we finalize the design.

PR is blocked until the work in fuel-core and fuel-vm lands.

Highest level API:

    abigen!(Contract(
        name = "MyContract",
        abi = "e2e/sway/contracts/huge_contract/out/release/huge_contract-abi.json"
    ));
    let contract_id = Contract::load_from(huge_contract_binary_path, LoadConfiguration::default())?
        .deploy_as_loader(
            &wallet,
            TxPolicies::default(),
            BlobSizePolicy::AtMost { bytes: 100_000 },
        )
        .await?;
    let contract_instance = MyContract::new(contract_id, wallet);
    let response = contract_instance.methods().something().call().await?.value;
    assert_eq!(response, 1001);

This will split the contract into blobs of size 100k, submit all of them, then craft a loading contract that will, when deployed and called, load all the blobs into memory and jump to the start of that memory effectively running the huge_contract.

I've tested all our e2e tests forcing contract deployment to happen via blobs and couldn't find any issue with contract behavior.

Lower level API

If the user wants total control over how the contract is deployed he can:

  1. split the contract into blobs:
    let blobs = contract
        .generate_blobs(&provider, BlobSizePolicy::AtMost { bytes: 100_000 })
        .await?;
  1. submit and await each blob:
        for blob in blobs {
            let mut tb = BlobTransactionBuilder::default()
                .with_blob(blob);

            account.adjust_for_fee(&mut tb, 0).await?;
            account.add_witnesses(&mut tb)?;

            let tx = tb.build(provider).await?;
            provider
                .send_transaction_and_await_commit(tx)
                .await?
                .check(None)?;
        }

Generate a loader contract with the blob ids of the blobs previously submitted and deploy it:

        Contract::new_loader(&blob_ids, salt, storage_slots)?
            .deploy(account, tx_policies)
            .await

Estimating max blob size

This is a bit tricky. Blob sizes are limited by two things: max transaction size and max transaction gas (both part of consensus parameters). So a blob can be as big as you want as long as the overall tx respects these two global tx limits.

So that means that properly estimating the max blob the user can send becomes a bit tricky. If you fund the tx with 2 coins instead of 1 the answer changes. If you use a predicate instead of a coin also changes the result. Basically whatever impacts the size or gas usage will impact how big the blob can be.

Say you put a blob of 20kb, and fund the tx. Oh look you have extra size and gas to spare. You increase that a bit but you no longer have 1 coin that can cover that but need to use 2. Ok the new blob size is no longer acceptable since you took up a bit of space adding that coin. Remove it. Ok now you can increase the blob size again. But now you again need 2 coins...

As a start, and until we figure something better and robust, there is a crude estimation available in the form of:

            BlobSizePolicy::Estimate { percentage_of_theoretical_max: 0.95 }

Where the theoretical maximum is calculated as max_tx_size - size_of_a_blob_tx. So this accounts only for the storage limitation. e2e tests showed that keeping under 95% of the max tx size works without issues. The remainder 5% is room for space inputs and witnesses might take. The docstrings (and future docs) explain the nature of this estimation to the user.

Checklist

  • I have linked to any relevant issues.
  • I have updated the documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary labels.
  • I have done my best to ensure that my PR adheres to the Fuel Labs Code Review Standards.
  • I have requested a review from the relevant team or maintainers.

Copy link
Member

@Br1ght0ne Br1ght0ne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing but nits/typos - exceptional work. Still woozy after that asm, but I've never seen an asm block so well commented. LFG!

e2e/tests/contracts.rs Outdated Show resolved Hide resolved
Cargo.toml Outdated Show resolved Hide resolved
packages/fuels-programs/src/contract.rs Outdated Show resolved Hide resolved
packages/fuels-programs/src/contract.rs Outdated Show resolved Hide resolved
packages/fuels-programs/src/contract.rs Outdated Show resolved Hide resolved
packages/fuels-programs/src/contract.rs Outdated Show resolved Hide resolved
Br1ght0ne added a commit to FuelLabs/fuel-specs that referenced this pull request Jul 25, 2024
Found while reviewing FuelLabs/fuels-rs#1472.

### Before requesting review
- [x] I have reviewed the code myself
Br1ght0ne
Br1ght0ne previously approved these changes Jul 27, 2024
Salka1988
Salka1988 previously approved these changes Jul 28, 2024
MujkicA
MujkicA previously approved these changes Jul 29, 2024
MujkicA
MujkicA previously approved these changes Jul 31, 2024
Salka1988
Salka1988 previously approved these changes Jul 31, 2024
hal3e
hal3e previously approved these changes Jul 31, 2024
Br1ght0ne
Br1ght0ne previously approved these changes Aug 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Blob tx / large contract support
5 participants