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

fix: ensure wide block range supported mainnet + refactor auth #2665

Merged
merged 3 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
178 changes: 146 additions & 32 deletions bin/sozo/src/commands/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,22 @@
#[command(about = "Clone all permissions that one contract has to another.")]
Clone {
#[arg(help = "The tag or address of the source contract to clone the permissions from.")]
source: String,
#[arg(long)]
#[arg(global = true)]
from: String,

Check warning on line 73 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L73

Added line #L73 was not covered by tests

#[arg(help = "The tag or address of the target contract to clone the permissions to.")]
target: String,
#[arg(long)]
#[arg(global = true)]
to: String,

Check warning on line 78 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L78

Added line #L78 was not covered by tests

#[arg(
long,
help = "Revoke the permissions from the source contract after cloning them to the \
target contract."
)]
revoke_source: bool,
#[arg(global = true)]
revoke_from: bool,

Check warning on line 86 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L86

Added line #L86 was not covered by tests

#[command(flatten)]
common: CommonAuthOptions,
Expand Down Expand Up @@ -189,15 +194,15 @@
AuthCommand::List { resource, show_address, starknet, world } => {
list_permissions(resource, show_address, starknet, world, &ws).await?;
}
AuthCommand::Clone { revoke_source, common, source, target } => {
if source == target {
AuthCommand::Clone { revoke_from, common, from, to } => {
if from == to {

Check warning on line 198 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L197-L198

Added lines #L197 - L198 were not covered by tests
anyhow::bail!(
"Source and target are the same, please specify different source and \
target."
);
}

clone_permissions(common, &ws, revoke_source, source, target).await?;
clone_permissions(common, &ws, revoke_from, from, to).await?;

Check warning on line 205 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L205

Added line #L205 was not covered by tests
}
};

Expand All @@ -210,9 +215,9 @@
async fn clone_permissions(
options: CommonAuthOptions,
ws: &Workspace<'_>,
revoke_source: bool,
source_tag_or_address: String,
target_tag_or_address: String,
revoke_from: bool,
from_tag_or_address: String,
to_tag_or_address: String,

Check warning on line 220 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L218-L220

Added lines #L218 - L220 were not covered by tests
) -> Result<()> {
let mut migration_ui = MigrationUi::new_with_frames(
"Gathering permissions from the world...",
Expand All @@ -224,12 +229,30 @@
options.starknet,
options.world,
ws,
&mut None,
&mut Some(&mut migration_ui),

Check warning on line 232 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L232

Added line #L232 was not covered by tests
)
.await?;

let source_address = resolve_address_or_tag(&source_tag_or_address, &world_diff)?;
let target_address = resolve_address_or_tag(&target_tag_or_address, &world_diff)?;
let from_address = resolve_address_or_tag(&from_tag_or_address, &world_diff)?;
let to_address = resolve_address_or_tag(&to_tag_or_address, &world_diff)?;

Check warning on line 237 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L236-L237

Added lines #L236 - L237 were not covered by tests

let external_writer_of: Vec<Felt> =
world_diff
.external_writers
.iter()
.filter_map(|(resource_selector, writers)| {
if writers.contains(&from_address) { Some(*resource_selector) } else { None }
})
.collect();

let external_owner_of: Vec<Felt> =
world_diff
.external_owners
.iter()
.filter_map(|(resource_selector, owners)| {
if owners.contains(&from_address) { Some(*resource_selector) } else { None }
})
.collect();

Check warning on line 255 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L239-L255

Added lines #L239 - L255 were not covered by tests

let mut writer_of = HashSet::new();
let mut owner_of = HashSet::new();
Expand All @@ -245,16 +268,20 @@
// We need to check remote only resources if we want to be exhaustive.
// But in this version, only synced permissions are supported.

if writers.synced().iter().any(|w| w.address == source_address) {
if writers.synced().iter().any(|w| w.address == from_address) {

Check warning on line 271 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L271

Added line #L271 was not covered by tests
writer_of.insert(resource.tag().clone());
}

if owners.synced().iter().any(|o| o.address == source_address) {
if owners.synced().iter().any(|o| o.address == from_address) {

Check warning on line 275 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L275

Added line #L275 was not covered by tests
owner_of.insert(resource.tag().clone());
}
}

if writer_of.is_empty() && owner_of.is_empty() {
if writer_of.is_empty()
&& owner_of.is_empty()
&& external_writer_of.is_empty()
&& external_owner_of.is_empty()

Check warning on line 283 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L280-L283

Added lines #L280 - L283 were not covered by tests
{
migration_ui.stop();

println!("No permissions to clone.");
Expand All @@ -263,28 +290,59 @@

migration_ui.stop();

let writers_resource_selectors = writer_of
let mut writers_resource_selectors = writer_of

Check warning on line 293 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L293

Added line #L293 was not covered by tests
.iter()
.map(|r| dojo_types::naming::compute_selector_from_tag_or_name(r))
.collect::<Vec<_>>();
let owners_resource_selectors = owner_of
let mut owners_resource_selectors = owner_of

Check warning on line 297 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L297

Added line #L297 was not covered by tests
.iter()
.map(|r| dojo_types::naming::compute_selector_from_tag_or_name(r))
.collect::<Vec<_>>();

writers_resource_selectors.extend(external_writer_of.iter().copied());
owners_resource_selectors.extend(external_owner_of.iter().copied());

writer_of.extend(
external_writer_of
.iter()
.map(|r| if r != &Felt::ZERO { format!("{:#066x}", r) } else { "World".to_string() }),
);
owner_of.extend(
external_owner_of
.iter()
.map(|r| if r != &Felt::ZERO { format!("{:#066x}", r) } else { "World".to_string() }),
);

// Sort the tags to have a deterministic output.
let mut writer_of = writer_of.into_iter().collect::<Vec<_>>();
writer_of.sort();
let mut owner_of = owner_of.into_iter().collect::<Vec<_>>();
owner_of.sort();

Check warning on line 321 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L302-L321

Added lines #L302 - L321 were not covered by tests
let writers_of_tags = writer_of.into_iter().collect::<Vec<_>>().join(", ");
let owners_of_tags = owner_of.into_iter().collect::<Vec<_>>().join(", ");

let writers_txt = if writers_of_tags.is_empty() {
"".to_string()

Check warning on line 326 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L325-L326

Added lines #L325 - L326 were not covered by tests
} else {
format!("\n writers: {}", writers_of_tags)

Check warning on line 328 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L328

Added line #L328 was not covered by tests
};

let owners_txt = if owners_of_tags.is_empty() {
"".to_string()

Check warning on line 332 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L331-L332

Added lines #L331 - L332 were not covered by tests
} else {
format!("\n owners: {}", owners_of_tags)

Check warning on line 334 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L334

Added line #L334 was not covered by tests
};

println!(
"Confirm the following permissions to be cloned from {} to {}\n writers: {}\n \
owners: {}",
source_tag_or_address.bright_blue(),
target_tag_or_address.bright_blue(),
writers_of_tags.bright_green(),
owners_of_tags.bright_yellow(),
"Confirm the following permissions to be cloned from {} to {}\n{}{}",
from_tag_or_address.bright_blue(),
to_tag_or_address.bright_blue(),
writers_txt.bright_green(),
owners_txt.bright_yellow(),

Check warning on line 342 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L338-L342

Added lines #L338 - L342 were not covered by tests
);

let confirm = utils::prompt_confirm("Continue?")?;
let confirm = utils::prompt_confirm("\nContinue?")?;

Check warning on line 345 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L345

Added line #L345 was not covered by tests
if !confirm {
return Ok(());
}
Expand All @@ -293,28 +351,28 @@
let mut invoker = Invoker::new(&account, options.transaction.clone().try_into()?);

for w in writers_resource_selectors.iter() {
invoker.add_call(world.grant_writer_getcall(w, &ContractAddress(target_address)));
invoker.add_call(world.grant_writer_getcall(w, &ContractAddress(to_address)));

Check warning on line 354 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L354

Added line #L354 was not covered by tests
}

for o in owners_resource_selectors.iter() {
invoker.add_call(world.grant_owner_getcall(o, &ContractAddress(target_address)));
invoker.add_call(world.grant_owner_getcall(o, &ContractAddress(to_address)));

Check warning on line 358 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L358

Added line #L358 was not covered by tests
}

if revoke_source {
if revoke_from {

Check warning on line 361 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L361

Added line #L361 was not covered by tests
println!(
"{}",
format!("\n!Permissions from {} will be revoked!", source_tag_or_address).bright_red()
format!("\n!Permissions from {} will be revoked!", from_tag_or_address).bright_red()

Check warning on line 364 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L364

Added line #L364 was not covered by tests
);
if !utils::prompt_confirm("Continue?")? {
if !utils::prompt_confirm("\nContinue?")? {

Check warning on line 366 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L366

Added line #L366 was not covered by tests
return Ok(());
}

for w in writers_resource_selectors.iter() {
invoker.add_call(world.revoke_writer_getcall(w, &ContractAddress(source_address)));
invoker.add_call(world.revoke_writer_getcall(w, &ContractAddress(from_address)));

Check warning on line 371 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L371

Added line #L371 was not covered by tests
}

for o in owners_resource_selectors.iter() {
invoker.add_call(world.revoke_owner_getcall(o, &ContractAddress(source_address)));
invoker.add_call(world.revoke_owner_getcall(o, &ContractAddress(from_address)));

Check warning on line 375 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L375

Added line #L375 was not covered by tests
}
}

Expand Down Expand Up @@ -357,6 +415,39 @@

migration_ui.stop();

let mut world_writers = world_diff
.external_writers
.get(&Felt::ZERO)
.map(|writers| writers.iter().cloned().collect::<Vec<_>>())
.unwrap_or_default();

let mut world_owners = world_diff
.external_owners
.get(&Felt::ZERO)
.map(|owners| owners.iter().cloned().collect::<Vec<_>>())
.unwrap_or_default();

// Sort the tags to have a deterministic output.
world_writers.sort();
world_owners.sort();

println!("{}", "World".bright_red());
if !world_writers.is_empty() {
println!(
"writers: {}",
world_writers.iter().map(|w| format!("{:#066x}", w)).collect::<Vec<_>>().join(", ")
);
}

Check warning on line 440 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L418-L440

Added lines #L418 - L440 were not covered by tests

if !world_owners.is_empty() {
println!(
"owners: {}",
world_owners.iter().map(|o| format!("{:#066x}", o)).collect::<Vec<_>>().join(", ")
);
}

Check warning on line 447 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L442-L447

Added lines #L442 - L447 were not covered by tests

println!();

Check warning on line 449 in bin/sozo/src/commands/auth.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/auth.rs#L449

Added line #L449 was not covered by tests

if let Some(resource) = resource {
let selector = dojo_types::naming::compute_selector_from_tag_or_name(&resource);
resources.retain(|r| r.dojo_selector() == selector);
Expand Down Expand Up @@ -585,7 +676,14 @@
&self,
contracts: &HashMap<String, ContractInfo>,
) -> Result<(Felt, Felt)> {
let selector = dojo_types::naming::compute_selector_from_tag_or_name(&self.resource_tag);
let selector = if self.resource_tag == "world" {
Felt::ZERO
} else if self.resource_tag.starts_with("0x") {
Felt::from_str(&self.resource_tag)
.map_err(|_| anyhow!("Invalid resource selector: {}", self.resource_tag))?
} else {
dojo_types::naming::compute_selector_from_tag_or_name(&self.resource_tag)
};

let contract_address = if self.grantee_tag_or_address.starts_with("0x") {
Felt::from_str(&self.grantee_tag_or_address)
Expand Down Expand Up @@ -684,5 +782,21 @@
grantee_tag_or_address: "0xinvalid".to_string(),
};
assert!(pair.to_selector_and_address(&contracts).is_err());

let pair = PermissionPair {
resource_tag: "world".to_string(),
grantee_tag_or_address: "0x123".to_string(),
};
let (selector, address) = pair.to_selector_and_address(&contracts).unwrap();
assert_eq!(selector, Felt::ZERO);
assert_eq!(address, Felt::from_str("0x123").unwrap());

let pair = PermissionPair {
resource_tag: "0x123".to_string(),
grantee_tag_or_address: "0x456".to_string(),
};
let (selector, address) = pair.to_selector_and_address(&contracts).unwrap();
assert_eq!(selector, Felt::from_str("0x123").unwrap());
assert_eq!(address, Felt::from_str("0x456").unwrap());
}
}
11 changes: 10 additions & 1 deletion bin/sozo/src/commands/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use dojo_world::diff::WorldDiff;
use scarb::core::Config;
use sozo_ops::model;
use sozo_scarbext::WorkspaceExt;
use starknet::core::types::{BlockId, BlockTag, EventFilter, Felt};
use starknet::core::utils::starknet_keccak;
use starknet::providers::Provider;
Expand Down Expand Up @@ -54,13 +55,21 @@
pub fn run(self, config: &Config) -> Result<()> {
config.tokio_handle().block_on(async {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let profile_config = ws.load_profile_config()?;

Check warning on line 58 in bin/sozo/src/commands/events.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/events.rs#L58

Added line #L58 was not covered by tests

let (world_diff, provider, _) =
utils::get_world_diff_and_provider(self.starknet, self.world, &ws).await?;

let provider = Arc::new(provider);

let from_block = self.from_block.map(BlockId::Number);
let from_block = if let Some(world_block) =
profile_config.env.as_ref().and_then(|e| e.world_block)

Check warning on line 66 in bin/sozo/src/commands/events.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/events.rs#L65-L66

Added lines #L65 - L66 were not covered by tests
{
Some(BlockId::Number(world_block))

Check warning on line 68 in bin/sozo/src/commands/events.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/events.rs#L68

Added line #L68 was not covered by tests
} else {
self.from_block.map(BlockId::Number)

Check warning on line 70 in bin/sozo/src/commands/events.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/events.rs#L70

Added line #L70 was not covered by tests
};

let to_block = self.to_block.map(BlockId::Number);
let keys = self
.events
Expand Down
9 changes: 8 additions & 1 deletion bin/sozo/src/commands/options/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@
let client =
ClientBuilder::default().timeout(Self::DEFAULT_REQUEST_TIMEOUT).build().unwrap();

let transport = HttpTransport::new_with_client(url.clone(), client);
let mut transport = HttpTransport::new_with_client(url.clone(), client);

Check warning on line 41 in bin/sozo/src/commands/options/starknet.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/options/starknet.rs#L41

Added line #L41 was not covered by tests

if let Some(headers) = env_metadata.and_then(|env| env.http_headers.as_ref()) {
for header in headers.iter() {
transport.add_header(header.name.clone(), header.value.clone());
}
}

Check warning on line 47 in bin/sozo/src/commands/options/starknet.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/commands/options/starknet.rs#L43-L47

Added lines #L43 - L47 were not covered by tests

Ok((JsonRpcClient::new(transport), url.to_string()))
}

Expand Down
8 changes: 7 additions & 1 deletion bin/sozo/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,13 @@
.with_context(|| "Cannot parse chain_id as string")?;
trace!(chain_id);

let world_diff = WorldDiff::new_from_chain(world_address, world_local, &provider).await?;
let world_diff = WorldDiff::new_from_chain(
world_address,
world_local,
&provider,
env.and_then(|e| e.world_block),
)
.await?;

Check warning on line 140 in bin/sozo/src/utils.rs

View check run for this annotation

Codecov / codecov/patch

bin/sozo/src/utils.rs#L134-L140

Added lines #L134 - L140 were not covered by tests

Ok((world_diff, provider, rpc_url))
}
Expand Down
8 changes: 8 additions & 0 deletions crates/dojo/world/src/config/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
pub keystore_path: Option<String>,
pub keystore_password: Option<String>,
pub world_address: Option<String>,
pub world_block: Option<u64>,
pub http_headers: Option<Vec<HttpHeader>>,
}

#[derive(Debug, Clone, Deserialize)]

Check warning on line 15 in crates/dojo/world/src/config/environment.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/environment.rs#L15

Added line #L15 was not covered by tests
pub struct HttpHeader {
pub name: String,
pub value: String,
}

impl Environment {
Expand Down
Loading
Loading