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: Implement ldc based automatic contract chunking #6250

Merged
merged 24 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
67b020d
feat: loader contract generation
kayagokalp Aug 8, 2024
9fed5ab
feat: implemented chunking and chunk deployment
kayagokalp Aug 8, 2024
11e3097
test: contract chunking
kayagokalp Aug 8, 2024
45a0358
minor ux improvements
kayagokalp Aug 8, 2024
b849312
test: add re route call
kayagokalp Aug 8, 2024
426d2da
test: chunked deploy with proxy
kayagokalp Aug 8, 2024
44168e4
run tests sequantially
kayagokalp Aug 8, 2024
11333a3
Merge branch 'master' into kayagokalp/proxy-with-chunks
sdankel Aug 9, 2024
8ede08d
Merge branch 'master' into kayagokalp/proxy-with-chunks
kayagokalp Aug 15, 2024
e0cfba5
feat: use sdk for chunked deployment
kayagokalp Aug 16, 2024
9c0b860
fix: invalid contract id reporting fixed for proxy and chunked
kayagokalp Aug 16, 2024
23a7bcc
add blobs keyword to details
kayagokalp Aug 16, 2024
2da7ee1
chore fix nits
kayagokalp Aug 16, 2024
1754854
Merge branch 'master' into kayagokalp/proxy-with-chunks
kayagokalp Aug 16, 2024
14bb5d5
fix comment
kayagokalp Aug 16, 2024
021330b
chore: clippy nits
kayagokalp Aug 16, 2024
495e80a
fmt
kayagokalp Aug 16, 2024
3688741
Update deploy.rs
kayagokalp Aug 16, 2024
d2562a5
Merge branch 'master' into kayagokalp/proxy-with-chunks
sdankel Aug 16, 2024
2fde7ea
Additional tests for contract chunking in forc (#6428)
sdankel Aug 16, 2024
7f8a6ee
Merge branch 'master' into kayagokalp/proxy-with-chunks
sdankel Aug 16, 2024
235aaf4
Merge branch 'master' into kayagokalp/proxy-with-chunks
sdankel Aug 16, 2024
e49fc52
Merge branch 'master' into kayagokalp/proxy-with-chunks
Voxelot Aug 16, 2024
2f861ae
Update forc-client docs
sdankel Aug 17, 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
97 changes: 95 additions & 2 deletions forc-plugins/forc-client/src/op/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
constants::TX_SUBMIT_TIMEOUT_MS,
util::{
node_url::get_node_url,
pkg::{built_pkgs, create_proxy_contract, update_proxy_address_in_manifest},
pkg::{
build_loader_contract, built_pkgs, create_proxy_contract, split_into_chunks,
update_proxy_address_in_manifest,
},
target::Target,
tx::{
bech32_from_secret, prompt_forc_wallet_password, select_secret_key,
Expand Down Expand Up @@ -38,10 +41,17 @@ use std::{
use sway_core::language::parsed::TreeType;
use sway_core::BuildTarget;

/// Maximum contract size allowed to be in a single contract. If the target
/// contract size is bigger than this amount, forc-deploy will automatically
/// starts dividing the contract and deploy them in chunks automatically.
/// The value is in bytes.
const MAX_CONTRACT_SIZE: usize = 1_000;
kayagokalp marked this conversation as resolved.
Show resolved Hide resolved

#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct DeployedContract {
pub id: fuel_tx::ContractId,
pub proxy: Option<fuel_tx::ContractId>,
pub chunks: Vec<fuel_tx::ContractId>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -122,6 +132,70 @@ fn validate_and_parse_salts<'a>(
Ok(contract_salt_map)
}

async fn deploy_chunked(
kayagokalp marked this conversation as resolved.
Show resolved Hide resolved
command: &cmd::Deploy,
compiled: &BuiltPackage,
salt: Salt,
signing_key: &SecretKey,
provider: &Provider,
pkg_name: &str,
) -> anyhow::Result<(ContractId, Vec<ContractId>)> {
println_action_green("Splitting", &format!("{pkg_name} into chunks"));
kayagokalp marked this conversation as resolved.
Show resolved Hide resolved
let contract_chunks = split_into_chunks(compiled.bytecode.bytes.clone(), MAX_CONTRACT_SIZE)?;
let mut deployed_contracts = vec![];
println_action_green("Deploying", &format!("{pkg_name} chunks"));
kayagokalp marked this conversation as resolved.
Show resolved Hide resolved
let chain_info = provider.chain_info().await?;
let target = Target::from_str(&chain_info.name).unwrap_or(Target::testnet());
kayagokalp marked this conversation as resolved.
Show resolved Hide resolved
let contract_url = match target.explorer_url() {
Some(explorer_url) => format!("{explorer_url}/contract/0x"),
None => "".to_string(),
};
for contract_chunk in contract_chunks {
let chunk_id = contract_chunk.id();
let deployed_chunk = contract_chunk.deploy(provider, &salt, signing_key).await?;
let chunk_contract_id = deployed_chunk.contract_id();
println_action_green(
"Finished",
&format!("deploying chunk {chunk_id} for {pkg_name}: {chunk_contract_id}"),
);
deployed_contracts.push(deployed_chunk);
}
println_action_green("Deployed", &format!("{pkg_name} chunks"));
Voxelot marked this conversation as resolved.
Show resolved Hide resolved
let deployed_contract_ids: Vec<String> = deployed_contracts
.iter()
.map(|deployed_contract| format!("0x{}", deployed_contract.contract_id()))
.collect();

let deployed_contracts: Vec<_> = deployed_contracts
.iter()
.map(|deployed_contract| *deployed_contract.contract_id())
.collect();

let program_abi = match &compiled.program_abi {
sway_core::asm_generation::ProgramABI::Fuel(abi) => abi,
_ => bail!("contract chunking is only supported with fuelVM"),
};

println_action_green("Building", &format!("loader contract for {pkg_name}"));
let loader_contract = build_loader_contract(
program_abi,
&deployed_contract_ids,
deployed_contracts.len(),
pkg_name,
&build_opts_from_cmd(command),
)?;

println_action_green("Deploying", &format!("loader contract for {pkg_name}"));
let deployed_id = deploy_pkg(command, &loader_contract, salt, provider, signing_key).await?;

println_action_green(
"Finished",
&format!("deploying loader contract for {pkg_name} {contract_url}{deployed_id}"),
);

Ok((deployed_id, deployed_contracts))
}

kayagokalp marked this conversation as resolved.
Show resolved Hide resolved
/// Deploys a new proxy contract for the given package.
async fn deploy_new_proxy(
pkg_name: &str,
Expand Down Expand Up @@ -277,7 +351,25 @@ pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedContract>> {
bail!("Both `--salt` and `--default-salt` were specified: must choose one")
}
};
let deployed_contract_id = deploy_pkg(&command, pkg, salt, &provider, &signing_key).await?;
let bytecode_size = pkg.bytecode.bytes.len();
let (deployed_contract_id, chunk_ids) = if bytecode_size > MAX_CONTRACT_SIZE {
// Deploy chunked
let node_url = get_node_url(&command.node, &pkg.descriptor.manifest_file.network)?;
let provider = Provider::connect(node_url).await?;
deploy_chunked(
&command,
pkg,
salt,
&signing_key,
&provider,
&pkg.descriptor.name,
)
.await?
} else {
let deployed_contract_id =
deploy_pkg(&command, pkg, salt, &provider, &signing_key).await?;
(deployed_contract_id, vec![])
};

let proxy_id = match &pkg.descriptor.manifest_file.proxy {
Some(forc_pkg::manifest::Proxy {
Expand Down Expand Up @@ -324,6 +416,7 @@ pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedContract>> {
let deployed_contract = DeployedContract {
id: deployed_contract_id,
proxy: proxy_id,
chunks: chunk_ids,
};
deployed_contracts.push(deployed_contract);
}
Expand Down
Loading
Loading