Skip to content

Commit

Permalink
feat: handle deployment plans in simnet (#1360)
Browse files Browse the repository at this point in the history
* feat: handle deployment plans in simnet

* chore: update clarity

* refactor: improve simnet deployment plan handling and vfs

* test: custom deployment plan in simnet

* feat: keep customs txs when generating a new deployment plan in simnet

* tests: deployment plan behaviour in simnet

* chore: bump sdk version

* refactor: revert vfs changes

* chore: bump sdk version
  • Loading branch information
hugocaillard authored Mar 1, 2024
1 parent 80be703 commit a340d48
Show file tree
Hide file tree
Showing 27 changed files with 902 additions and 564 deletions.
378 changes: 129 additions & 249 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion components/clarinet-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ segment = { version = "0.1.2", optional = true }
mac_address = { version = "1.1.2", optional = true }
tower-lsp = { version = "0.19.0", optional = true }
hex = "0.4.3"
serde_yaml = "0.8.23"
num_cpus = "1.13.1"
mio = "0.8"
similar = "2.1.0"
Expand Down
9 changes: 1 addition & 8 deletions components/clarinet-cli/src/deployments/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,6 @@ pub fn write_deployment(
}
}

let file = deployment.to_specification_file();

let content = match serde_yaml::to_string(&file) {
Ok(res) => res,
Err(err) => return Err(format!("failed serializing deployment\n{}", err)),
};

target_location.write_content(content.as_bytes())?;
target_location.write_content(&deployment.to_file_content()?)?;
Ok(())
}
7 changes: 4 additions & 3 deletions components/clarinet-cli/src/deployments/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ impl DeploymentSynthesis {
}
}
}
let file = deployment.to_specification_file();
let content = match serde_yaml::to_string(&file) {

let content = match deployment.to_file_content() {
Ok(res) => res,
Err(err) => panic!("unable to serialize deployment {}", err),
};

DeploymentSynthesis {
total_cost,
blocks_count,
content,
content: std::str::from_utf8(&content).unwrap().to_string(),
}
}
}
Expand Down
57 changes: 30 additions & 27 deletions components/clarinet-cli/src/frontend/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,21 +618,16 @@ pub fn main() {
}

let write_plan = if default_deployment_path.exists() {
let existing_deployment =
match load_deployment(&manifest, &default_deployment_path) {
Ok(deployment) => deployment,
Err(message) => {
println!(
"{}",
format_err!(format!(
"unable to load {}\n{}",
default_deployment_path.to_string(),
message
))
);
process::exit(1);
}
};
let existing_deployment = load_deployment(&manifest, &default_deployment_path)
.unwrap_or_else(|message| {
println!(
"{}",
format_err!(format!(
"unable to load {default_deployment_path}\n{message}",
))
);
process::exit(1);
});
should_existing_plan_be_replaced(&existing_deployment, &deployment)
} else {
true
Expand Down Expand Up @@ -1300,23 +1295,29 @@ fn load_deployment_and_artifacts_or_exit(
}
}

pub fn should_existing_plan_be_replaced(
fn should_existing_plan_be_replaced(
existing_plan: &DeploymentSpecification,
new_plan: &DeploymentSpecification,
) -> bool {
use similar::{ChangeTag, TextDiff};

let existing_file = serde_yaml::to_string(&existing_plan.to_specification_file()).unwrap();

let new_file = serde_yaml::to_string(&new_plan.to_specification_file()).unwrap();
let existing_file = existing_plan
.to_file_content()
.expect("unable to serialize deployment");
let new_file = new_plan
.to_file_content()
.expect("unable to serialize deployment");

if existing_file == new_file {
return false;
}

println!("{}", blue!("A new deployment plan was computed and differs from the default deployment plan currently saved on disk:"));

let diffs = TextDiff::from_lines(&existing_file, &new_file);
let diffs = TextDiff::from_lines(
std::str::from_utf8(&existing_file).unwrap(),
std::str::from_utf8(&new_file).unwrap(),
);

for change in diffs.iter_all_changes() {
let formatted_change = match change.tag() {
Expand All @@ -1338,7 +1339,7 @@ pub fn should_existing_plan_be_replaced(
!buffer.starts_with('n')
}

pub fn load_deployment_if_exists(
fn load_deployment_if_exists(
manifest: &ProjectManifest,
network: &StacksNetwork,
force_on_disk: bool,
Expand All @@ -1357,13 +1358,12 @@ pub fn load_deployment_if_exists(
Ok((deployment, _)) => {
use similar::{ChangeTag, TextDiff};

let current_version = match default_deployment_location.read_content_as_utf8() {
let current_version = match default_deployment_location.read_content() {
Ok(content) => content,
Err(message) => return Some(Err(message)),
};

let file = deployment.to_specification_file();
let updated_version = match serde_yaml::to_string(&file) {
let updated_version = match deployment.to_file_content() {
Ok(res) => res,
Err(err) => {
return Some(Err(format!("failed serializing deployment\n{}", err)))
Expand All @@ -1377,7 +1377,10 @@ pub fn load_deployment_if_exists(
if !force_computed {
println!("{}", blue!("A new deployment plan was computed and differs from the default deployment plan currently saved on disk:"));

let diffs = TextDiff::from_lines(&current_version, &updated_version);
let diffs = TextDiff::from_lines(
std::str::from_utf8(&current_version).unwrap(),
std::str::from_utf8(&updated_version).unwrap(),
);

for change in diffs.iter_all_changes() {
let formatted_change = match change.tag() {
Expand All @@ -1399,13 +1402,13 @@ pub fn load_deployment_if_exists(
Some(load_deployment(manifest, &default_deployment_location))
} else {
default_deployment_location
.write_content(updated_version.as_bytes())
.write_content(&updated_version)
.ok()?;
Some(Ok(deployment))
}
} else {
default_deployment_location
.write_content(updated_version.as_bytes())
.write_content(&updated_version)
.ok()?;
Some(Ok(deployment))
}
Expand Down
117 changes: 117 additions & 0 deletions components/clarinet-deployments/src/deployment_plan_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use std::collections::BTreeMap;

use clarinet_files::{chainhook_types::StacksNetwork, FileLocation};
use clarity_repl::clarity::{
vm::types::{QualifiedContractIdentifier, StandardPrincipalData},
ClarityName, ClarityVersion, ContractName,
};

use crate::types::*;

fn get_test_txs() -> (TransactionSpecification, TransactionSpecification) {
let contract_id =
QualifiedContractIdentifier::parse("ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.test")
.unwrap();
let tx_sender = StandardPrincipalData::from(contract_id.issuer.clone());

let contract_publish_tx =
TransactionSpecification::EmulatedContractPublish(EmulatedContractPublishSpecification {
contract_name: ContractName::try_from("test".to_string()).unwrap(),
emulated_sender: tx_sender.clone(),
location: FileLocation::from_path_string("/contracts/test.clar").unwrap(),
source: "(ok true)".to_string(),
clarity_version: ClarityVersion::Clarity2,
});

let contract_call_txs =
TransactionSpecification::EmulatedContractCall(EmulatedContractCallSpecification {
contract_id: QualifiedContractIdentifier::parse(
"ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.test",
)
.unwrap(),
emulated_sender: tx_sender.clone(),
method: ClarityName::try_from("test".to_string()).unwrap(),
parameters: vec![],
});

(contract_publish_tx, contract_call_txs)
}

fn build_test_deployement_plan(
batches: Vec<TransactionsBatchSpecification>,
) -> DeploymentSpecification {
DeploymentSpecification {
id: 1,
name: "test".to_string(),
network: StacksNetwork::Simnet,
stacks_node: None,
bitcoin_node: None,
genesis: None,
contracts: BTreeMap::new(),
plan: TransactionPlanSpecification { batches },
}
}

#[test]
fn test_extract_no_contract_publish_txs() {
let (contract_publish_tx, contract_call_txs) = get_test_txs();

let plan = build_test_deployement_plan(vec![
TransactionsBatchSpecification {
id: 0,
transactions: vec![contract_publish_tx.clone()],
epoch: Some(EpochSpec::Epoch2_4),
},
TransactionsBatchSpecification {
id: 1,
transactions: vec![contract_call_txs.clone()],
epoch: Some(EpochSpec::Epoch2_4),
},
]);

let (new_plan, custom_txs) = plan.extract_no_contract_publish_txs();

assert_eq!(
new_plan,
build_test_deployement_plan(vec![TransactionsBatchSpecification {
id: 0,
transactions: vec![contract_publish_tx.clone()],
epoch: Some(EpochSpec::Epoch2_4),
},])
);

assert_eq!(
custom_txs,
vec![TransactionsBatchSpecification {
id: 1,
transactions: vec![contract_call_txs.clone()],
epoch: Some(EpochSpec::Epoch2_4),
}]
);
}

#[test]
fn test_merge_batches() {
let (contract_publish_tx, contract_call_txs) = get_test_txs();

let plan = build_test_deployement_plan(vec![
TransactionsBatchSpecification {
id: 0,
transactions: vec![contract_publish_tx.clone()],
epoch: Some(EpochSpec::Epoch2_4),
},
TransactionsBatchSpecification {
id: 1,
transactions: vec![contract_call_txs.clone()],
epoch: Some(EpochSpec::Epoch2_4),
},
]);

let (mut new_plan, custom_txs) = plan.extract_no_contract_publish_txs();

assert_ne!(plan, new_plan);

new_plan.merge_batches(custom_txs);

assert_eq!(plan, new_plan);
}
7 changes: 4 additions & 3 deletions components/clarinet-deployments/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ pub mod onchain;
pub mod requirements;
pub mod types;

#[cfg(test)]
mod deployment_plan_test;

use self::types::{
DeploymentSpecification, EmulatedContractPublishSpecification, GenesisSpecification,
TransactionPlanSpecification, TransactionsBatchSpecification, WalletSpecification,
Expand Down Expand Up @@ -564,9 +567,7 @@ pub async fn generate_default_deployment(
contract_location.to_string()
})
.collect();
file_accessor
.read_contracts_content(contracts_location)
.await?
file_accessor.read_files(contracts_location).await?
}
};

Expand Down
Loading

0 comments on commit a340d48

Please sign in to comment.