From 73a82b33e8ed0ffd42fe881b6910bffbfb52e288 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Sun, 13 Oct 2024 16:09:21 -0400 Subject: [PATCH] chore(sozo): update `slot` due to credentials format change (#2530) --- Cargo.lock | 5 +-- Cargo.toml | 2 +- .../commands/options/account/controller.rs | 38 ++++++++-------- crates/katana/controller/src/lib.rs | 43 ++++++++++++------- 4 files changed, 49 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de1ac5d278..f86cde32ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13033,8 +13033,8 @@ dependencies = [ [[package]] name = "slot" -version = "0.17.0" -source = "git+https://github.com/cartridge-gg/slot?rev=942be15#942be15fae2f17a9f520c18ceddcbae00037a695" +version = "0.18.0" +source = "git+https://github.com/cartridge-gg/slot?rev=1298a30#1298a302db76767e28af5cbce842acdfb507bb29" dependencies = [ "account_sdk", "anyhow", @@ -13046,7 +13046,6 @@ dependencies = [ "reqwest 0.12.7", "serde", "serde_json", - "serde_with 3.9.0", "starknet 0.12.0", "tempfile", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index bc9a23ca77..46b2d497e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -232,7 +232,7 @@ alloy-sol-types = { version = "0.8.3", default-features = false } criterion = "0.5.1" # Slot integration. Dojo don't need to manually include `account_sdk` as dependency as `slot` already re-exports it. -slot = { git = "https://github.com/cartridge-gg/slot", rev = "942be15" } +slot = { git = "https://github.com/cartridge-gg/slot", rev = "1298a30" } alloy-contract = { version = "0.3", default-features = false } alloy-json-rpc = { version = "0.3", default-features = false } diff --git a/bin/sozo/src/commands/options/account/controller.rs b/bin/sozo/src/commands/options/account/controller.rs index 68ced5c81b..a0f66ee28d 100644 --- a/bin/sozo/src/commands/options/account/controller.rs +++ b/bin/sozo/src/commands/options/account/controller.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; use dojo_world::contracts::naming::get_name_from_tag; use dojo_world::manifest::{BaseManifest, Class, DojoContract, Manifest}; @@ -34,9 +34,9 @@ pub type ControllerSessionAccount

= SessionAccount>; /// Create a new Catridge Controller account based on session key. /// -/// Controller guarantees that if the provided network is among one of the supported networks, -/// then the Controller account should exist. If it doesn't yet exist, it will automatically -/// be created when a session is created (ie during the session registration stage). +/// For now, Controller guarantees that if the provided network is among one of the supported +/// networks, then the Controller account should exist. If it doesn't yet exist, it will +/// automatically be created when a session is created (ie during the session registration stage). /// /// # Supported networks /// @@ -60,31 +60,31 @@ where P: Send + Sync, { let chain_id = provider.chain_id().await?; - let credentials = slot::credential::Credentials::load()?; + trace!(target: "account::controller", "Loading Slot credentials."); + let credentials = slot::credential::Credentials::load()?; let username = credentials.account.id; - let contract_address = credentials.account.contract_address; - trace!( - %username, - chain = format!("{chain_id:#x}"), - address = format!("{contract_address:#x}"), - "Creating Controller session account" - ); + // Right now, the Cartridge Controller API ensures that there's always a Controller associated + // with an account, but that might change in the future. + let Some(contract_address) = credentials.account.controllers.first().map(|c| c.address) else { + bail!("No Controller is associated with this account."); + }; // Check if the session exists, if not create a new one let session_details = match slot::session::get(chain_id)? { Some(session) => { - trace!(expires_at = %session.session.expires_at, policies = session.session.policies.len(), "Found existing session."); + trace!(target: "account::controller", expires_at = %session.session.expires_at, policies = session.session.policies.len(), "Found existing session."); + // Check if the policies have changed let policies = collect_policies(world_addr_or_name, contract_address, config)?; - // check if the policies have changed let is_equal = is_equal_to_existing(&policies, &session); if is_equal { session } else { trace!( + target: "account::controller", new_policies = policies.len(), existing_policies = session.session.policies.len(), "Policies have changed. Creating new session." @@ -98,7 +98,7 @@ where // Create a new session if not found None => { - trace!(%username, chain = format!("{chain_id:#}"), "Creating new session."); + trace!(target: "account::controller", %username, chain = format!("{chain_id:#}"), "Creating new session."); let policies = collect_policies(world_addr_or_name, contract_address, config)?; let session = slot::session::create(rpc_url.clone(), &policies).await?; slot::session::store(chain_id, &session)?; @@ -149,7 +149,7 @@ fn collect_policies( let manifest = get_project_base_manifest(root_dir, config.profile().as_str())?; let policies = collect_policies_from_base_manifest(world_addr_or_name, user_address, root_dir, manifest)?; - trace!(policies_count = policies.len(), "Extracted policies from project."); + trace!(target: "account::controller", policies_count = policies.len(), "Extracted policies from project."); Ok(policies) } @@ -188,14 +188,14 @@ fn collect_policies_from_base_manifest( // corresponds to [account_sdk::account::DECLARATION_SELECTOR] let method = "__declare_transaction__".to_string(); policies.push(PolicyMethod { target: user_address, method }); - trace!("Adding declare transaction policy"); + trace!(target: "account::controller", "Adding declare transaction policy"); // for deploying using udc let method = "deployContract".to_string(); const UDC_ADDRESS: Felt = felt!("0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf"); policies.push(PolicyMethod { target: UDC_ADDRESS, method }); - trace!("Adding UDC deployment policy"); + trace!(target: "account::controller", "Adding UDC deployment policy"); Ok(policies) } @@ -215,7 +215,7 @@ fn policies_from_abis( if let StateMutability::External = f.state_mutability { let policy = PolicyMethod { target: contract_address, method: f.name.to_string() }; - trace!(tag = contract_tag, target = format!("{:#x}", policy.target), method = %policy.method, "Adding policy"); + trace!(target: "account::controller", tag = contract_tag, target = format!("{:#x}", policy.target), method = %policy.method, "Adding policy"); policies.push(policy); } } diff --git a/crates/katana/controller/src/lib.rs b/crates/katana/controller/src/lib.rs index c3763473f7..7ed0e0542f 100644 --- a/crates/katana/controller/src/lib.rs +++ b/crates/katana/controller/src/lib.rs @@ -27,12 +27,16 @@ pub fn add_controller_account(genesis: &mut Genesis) -> Result<()> { add_controller_account_inner(genesis, credentials.account) } -fn add_controller_account_inner(genesis: &mut Genesis, user: slot::account::Account) -> Result<()> { - let cred = user.credentials.webauthn.first().unwrap(); +fn add_controller_account_inner( + genesis: &mut Genesis, + user: slot::account::AccountInfo, +) -> Result<()> { + let cred = user.credentials.first().unwrap(); + let contract_address = user.controllers.first().unwrap().address; trace!( username = user.id, - address = format!("{:#x}", user.contract_address), + address = format!("{:#x}", contract_address), "Adding Cartridge Controller account to genesis." ); @@ -47,7 +51,7 @@ fn add_controller_account_inner(genesis: &mut Genesis, user: slot::account::Acco storage: Some(get_contract_storage(credential_id, public_key)?), }; - let address = ContractAddress::from(user.contract_address); + let address = ContractAddress::from(contract_address); (address, GenesisAllocation::Contract(account)) }; @@ -56,7 +60,7 @@ fn add_controller_account_inner(genesis: &mut Genesis, user: slot::account::Acco trace!( username = user.id, - address = format!("{:#x}", user.contract_address), + address = format!("{:#x}", contract_address), "Cartridge Controller account added to genesis." ); @@ -81,7 +85,8 @@ pub mod json { pub fn add_controller_account_json(genesis: &mut GenesisJson) -> Result<()> { // bouncer that checks if there is an authenticated slot user let user = Credentials::load()?; - let cred = user.account.credentials.webauthn.first().unwrap(); + let cred = user.account.credentials.first().unwrap(); + let contract_address = user.account.controllers.first().unwrap().address; let credential_id = webauthn::credential::from_base64(&cred.id)?; let public_key = webauthn::cose_key::from_base64(&cred.public_key)?; @@ -96,7 +101,7 @@ pub mod json { storage: Some(get_contract_storage(credential_id, public_key)?), }; - let address = ContractAddress::from(user.account.contract_address); + let address = ContractAddress::from(contract_address); (address, account) }; @@ -190,8 +195,9 @@ fn get_contract_storage( #[cfg(test)] mod tests { + use assert_matches::assert_matches; - use slot::account::WebAuthnCredential; + use slot::account::{Controller, ControllerSigner, SignerType, WebAuthnCredential}; use starknet::macros::felt; use super::*; @@ -216,21 +222,26 @@ mod tests { fn test_add_controller_account() { let mut genesis = Genesis::default(); - let account = slot::account::Account { + let account = slot::account::AccountInfo { id: "johnsmith".to_string(), name: None, - contract_address: CONTROLLER_ADDRESS, - credentials: slot::account::AccountCredentials { - webauthn: vec![WebAuthnCredential { - id: WEBAUTHN_CREDENTIAL_ID.to_string(), - public_key: WEBAUTHN_PUBLIC_KEY.to_string(), + controllers: vec![Controller { + id: "controller1".to_string(), + address: CONTROLLER_ADDRESS, + signers: vec![ControllerSigner { + id: "signer1".to_string(), + r#type: SignerType::WebAuthn, }], - }, + }], + credentials: vec![WebAuthnCredential { + id: WEBAUTHN_CREDENTIAL_ID.to_string(), + public_key: WEBAUTHN_PUBLIC_KEY.to_string(), + }], }; add_controller_account_inner(&mut genesis, account.clone()).unwrap(); - let address = ContractAddress::from(account.contract_address); + let address = ContractAddress::from(account.controllers[0].address); let allocation = genesis.allocations.get(&address).unwrap(); assert!(genesis.allocations.contains_key(&address));