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: add blob deployments for scripts and predicates #6607

Merged
merged 24 commits into from
Oct 6, 2024

Conversation

kayagokalp
Copy link
Member

@kayagokalp kayagokalp commented Oct 5, 2024

Description

This PR adds support for deploying executables, namely predicates and scripts. Before this PR executing forc-deploy on a script or predicate was an hard error. With this PR we are enabling the deployment of them via converting them to a loader which loads the original bytecode deployed as a blob.

The loader binaries are serialized to disk under out folder for both predicates and scripts. For predicates we also save the root of the loader additionally. Every output related to generated loader is suffixed with -loader so that it can be distinguished easily.

Cargo.toml Outdated Show resolved Hide resolved
@JoshuaBatty
Copy link
Member

JoshuaBatty commented Oct 5, 2024

Now that we are generating more than contract deployment artifacts i.e DeployedScripts, perhaps it makes sense to introduce a new enum that can be returned from the deploy function. Something like

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum DeployedArtifact {
    Contract(DeployedContract),
    Script(DeployedScript),
    Predicate(DeployedPredicate),
}

Then the deploy function could be

/// Builds and deploys contracts, scripts, and predicates from the given path or workspace.
///
/// Contracts are deployed directly, while scripts and predicates are deployed as blobs with generated loaders.
///
/// Returns a vector of `DeployedArtifact` representing all successful deployments.
pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedArtifact>> {
    existing code...

    let mut deployed_artifacts = Vec::new();

    // Deploy contracts
    let deployed_contracts = deploy_contracts(command, contracts_to_deploy).await?; 
    deployed_artifacts.extend(deployed_contracts.into_iter().map(DeployedArtifact::Contract));

    // Deploy scripts
    let deployed_scripts = deploy_scripts(command, scripts_to_deploy).await?;
    deployed_artifacts.extend(deployed_scripts.into_iter().map(DeployedArtifact::Script));

    // Deploy predicates
    let deployed_predicates = deploy_predicates(command, predicates_to_deploy).await?;
    deployed_artifacts.extend(deployed_predicates.into_iter().map(DeployedArtifact::Predicate));

    Ok(deployed_artifacts)
}

What are your thoughts Kaya?

@kayagokalp
Copy link
Member Author

Now that we are generating more than contract deployment artifacts i.e DeployedScripts, perhaps it makes sense to introduce a new enum that can be returned from the deploy function. Something like

#[derive(Debug, PartialEq, Eq, Clone)]

pub enum DeployedArtifact {

    Contract(DeployedContract),

    Script(DeployedScript),

    Predicate(DeployedPredicate),

}

Then the deploy function could be

/// Builds and deploys contracts, scripts, and predicates from the given path or workspace.

///

/// Contracts are deployed directly, while scripts and predicates are deployed as blobs with generated loaders.

///

/// Returns a vector of `DeployedArtifact` representing all successful deployments.

pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedArtifact>> {

    existing code...



    let mut deployed_artifacts = Vec::new();



    // Deploy contracts

    let deployed_contracts = deploy_contracts(&command, contracts_to_deploy).await?; 

    deployed_artifacts.extend(deployed_contracts.into_iter().map(DeployedArtifact::Contract));



    // Deploy scripts

    let deployed_scripts = deploy_scripts(command.clone(), scripts_to_deploy).await?;

    deployed_artifacts.extend(deployed_scripts.into_iter().map(DeployedArtifact::Script));



    // Deploy predicates

    let deployed_predicates = deploy_predicates(command, predicates_to_deploy).await?;

    deployed_artifacts.extend(deployed_predicates.into_iter().map(DeployedArtifact::Predicate));



    Ok(deployed_artifacts)

}

What are your thoughts Kaya?

Yes, that is what I was planning exactly!

@kayagokalp
Copy link
Member Author

I had to make a slight renaming from our last discussion, rather than calling deployed instances DeployedArtifacts I called them DeployedPackage because we already have a notion of DeploymentArtifact (for serializing the deployment info) and don't want this to be confused with that.

@kayagokalp
Copy link
Member Author

Also please do not take the cargo.lock changes into account. They are going to be reverted back once we have the releases ready. I had to recreate it because cargo wasn't playing very nicely with git based patches that gets updated frequently.

@kayagokalp
Copy link
Member Author

Oh looks like cargo is going crazy because one of our patches is merged, and the branch does not exists anymore 😅, fixing it now.

forc-plugins/forc-client/src/op/deploy.rs Outdated Show resolved Hide resolved
forc-plugins/forc-client/src/op/deploy.rs Outdated Show resolved Hide resolved
forc-plugins/forc-client/src/op/deploy.rs Outdated Show resolved Hide resolved
forc-plugins/forc-client/src/op/deploy.rs Outdated Show resolved Hide resolved
Cargo.toml Show resolved Hide resolved
@kayagokalp kayagokalp self-assigned this Oct 6, 2024
@kayagokalp kayagokalp added enhancement New feature or request P: critical Should be looked at before anything else forc-client Everything related to the `forc-client` crate. forc-deploy Everything to do with forc-deploy labels Oct 6, 2024
sdankel
sdankel previously approved these changes Oct 6, 2024
Copy link
Member

@sdankel sdankel left a comment

Choose a reason for hiding this comment

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

Nice work, LGTM!

Copy link
Member

@JoshuaBatty JoshuaBatty left a comment

Choose a reason for hiding this comment

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

Great work on this Kaya! Just wondering if we can add something to the docs explaining the new functionality. I've drafted up something below. Feel free to edit.

## DEPLOYING SCRIPTS AND PREDICATES

`forc deploy` now supports deploying scripts and predicates in addition to contracts. These are deployed as blobs with generated loaders for efficiency.

Scripts and predicates are deployed automatically when you run `forc deploy` on a project that contains them. The deployment process differs slightly from contract deployment:

1. For scripts and predicates, the bytecode is uploaded as a blob.
2. A loader is generated that can load and execute the blob.
3. The loader bytecode is saved in the project's output directory.

After deployment, you'll find new files in your project's output directory:

- For scripts: `<script_name>-loader.bin`
- For predicates: `<predicate_name>-loader.bin` and `<predicate_name>-loader-root`

The loader files contain the bytecode necessary to load and execute your script or predicate from its blob storage.

This new deployment method allows for more efficient storage and execution of scripts and predicates on the Fuel network.

Note: Contracts are still deployed directly, not as blobs.

JoshuaBatty
JoshuaBatty previously approved these changes Oct 6, 2024
Copy link
Member

@JoshuaBatty JoshuaBatty left a comment

Choose a reason for hiding this comment

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

💪

@JoshuaBatty JoshuaBatty merged commit 347c834 into master Oct 6, 2024
43 checks passed
@JoshuaBatty JoshuaBatty deleted the kayagokalp/script-predicate-fix branch October 6, 2024 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request forc-client Everything related to the `forc-client` crate. forc-deploy Everything to do with forc-deploy P: critical Should be looked at before anything else
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants