From ccd9a599ffdae463e5076ce090bb74edab0258b5 Mon Sep 17 00:00:00 2001 From: lambda-0x <0xlambda@protonmail.com> Date: Wed, 31 Jul 2024 15:56:13 +0530 Subject: [PATCH] map selector resource type to other resource type where possible --- crates/sozo/ops/src/migration/migrate.rs | 43 +++++++++++++- crates/sozo/ops/src/migration/utils.rs | 71 +++++++++++++++++++++++- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/crates/sozo/ops/src/migration/migrate.rs b/crates/sozo/ops/src/migration/migrate.rs index 5f8e529d64..99d8f955f4 100644 --- a/crates/sozo/ops/src/migration/migrate.rs +++ b/crates/sozo/ops/src/migration/migrate.rs @@ -39,6 +39,7 @@ use starknet::providers::{Provider, ProviderError}; use tokio::fs; use super::ui::{bold_message, italic_message, MigrationUi}; +use super::utils::generate_resource_map; use super::{ ContractDeploymentOutput, ContractMigrationOutput, ContractUpgradeOutput, MigrationOutput, }; @@ -900,6 +901,12 @@ where .collect::>() } + // Generate a map of `Felt` (resource selector) -> `ResourceType` that are available locally + // so we can check if the resource being revoked is known locally. + // + // if the selector is not found in the map we just print its selector + let resource_map = generate_resource_map(ui, world, diff).await?; + for c in &diff.contracts { // remote is none meants it was not previously deployed. // but if it didn't get deployed even during this run we should skip migration for it @@ -945,7 +952,22 @@ where ui.print_sub(format!( "Granting write access to {} for resources: {:?}", c.tag, - contract_grants.iter().map(|rw| rw.resource.clone()).collect::>() + contract_grants + .iter() + .map(|rw| { + let resource = &rw.resource; + match resource { + ResourceType::Selector(s) => { + if let Some(r) = resource_map.get(&s.to_hex_string()) { + r.clone() + } else { + resource.clone() + } + } + _ => resource.clone(), + } + }) + .collect::>() )); } @@ -955,7 +977,24 @@ where ui.print_sub(format!( "Revoking write access to {} for resources: {:?}", c.tag, - contract_revokes.iter().map(|rw| rw.resource.clone()).collect::>() + contract_revokes + .iter() + .map(|rw| { + let resource = &rw.resource; + match resource { + // Replace selector with appropriate resource type if present in + // resource_map + ResourceType::Selector(s) => { + if let Some(r) = resource_map.get(&s.to_hex_string()) { + r.clone() + } else { + resource.clone() + } + } + _ => resource.clone(), + } + }) + .collect::>() )); } diff --git a/crates/sozo/ops/src/migration/utils.rs b/crates/sozo/ops/src/migration/utils.rs index dc91f26c1f..4e2aedeff6 100644 --- a/crates/sozo/ops/src/migration/utils.rs +++ b/crates/sozo/ops/src/migration/utils.rs @@ -1,13 +1,20 @@ -use anyhow::{anyhow, Result}; +use std::collections::HashMap; + +use anyhow::{anyhow, Context, Result}; use camino::Utf8PathBuf; +use dojo_world::contracts::naming::get_namespace_from_tag; +use dojo_world::contracts::WorldContract; use dojo_world::manifest::{ AbstractManifestError, BaseManifest, DeploymentManifest, OverlayManifest, }; +use dojo_world::migration::world::WorldDiff; +use itertools::Itertools; use scarb_ui::Ui; -use starknet::accounts::ConnectedAccount; +use starknet::accounts::{Account, ConnectedAccount}; use starknet::core::types::Felt; use super::ui::MigrationUi; +use crate::auth::{get_resource_selector, ResourceType}; /// Loads: /// - `BaseManifest` from filesystem @@ -63,3 +70,63 @@ where Ok((local_manifest, remote_manifest)) } + +pub async fn generate_resource_map( + ui: &Ui, + world: &WorldContract, + diff: &WorldDiff, +) -> Result> +where + A: ConnectedAccount + Sync + Send, + ::SignError: 'static, +{ + let mut resource_map = HashMap::new(); + + for contract in diff.contracts.iter() { + let resource = ResourceType::Contract(contract.tag.clone()); + // we know the tag already contains the namespace + let default_namespace = get_namespace_from_tag(&contract.tag); + let selector = + get_resource_selector(ui, world, &resource, &default_namespace).await.with_context( + || format!("Failed to get resource selector for contract: {}", contract.tag), + )?; + + resource_map.insert(selector.to_hex_string(), resource); + } + + for model in diff.models.iter() { + let resource = ResourceType::Model(model.tag.clone()); + // we know the tag already contains the namespace + let default_namespace = get_namespace_from_tag(&model.tag); + let selector = get_resource_selector(ui, world, &resource, &default_namespace) + .await + .with_context(|| format!("Failed to get resource selector for model: {}", model.tag))?; + + resource_map.insert(selector.to_hex_string(), resource); + } + + // Collect all the namespaces from the contracts and models + let namespaces = { + let mut namespaces = + diff.models.iter().map(|m| get_namespace_from_tag(&m.tag)).collect::>(); + + namespaces.extend( + diff.contracts.iter().map(|c| get_namespace_from_tag(&c.tag)).collect::>(), + ); + + // remove duplicates + namespaces.into_iter().unique().collect::>() + }; + + for namespace in &namespaces { + let resource = ResourceType::Namespace(namespace.clone()); + let selector = + get_resource_selector(ui, world, &resource, "").await.with_context(|| { + format!("Failed to get resource selector for namespace: {}", namespace) + })?; + + resource_map.insert(selector.to_hex_string(), resource); + } + + Ok(resource_map) +}