Skip to content

Commit

Permalink
Namespace feature
Browse files Browse the repository at this point in the history
  • Loading branch information
remybar committed Jun 10, 2024
1 parent 9ea6574 commit 58c7205
Show file tree
Hide file tree
Showing 75 changed files with 3,220 additions and 8,329 deletions.
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@
"apply"
]
},
{
"name": "Sozo",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/target/debug/sozo",
"args": [
"--manifest-path",
"examples/spawn-and-move/Scarb.toml",
"events",
"--world",
"0x04c972a756d796d716f665a8079dbf9aff05bbba41a2b8194553073f31d7d393",
"--chunk-size",
"100"
]
},
{
"type": "lldb",
"request": "launch",
Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 46 additions & 10 deletions bin/sozo/src/commands/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ pub enum ModelCommand {
#[arg(help = "The name of the model")]
name: String,

#[arg(short, long)]
#[arg(help = "The model namespace. If not set, the main package ID is used.")]
namespace: Option<String>,

#[command(flatten)]
world: WorldOptions,

Expand All @@ -34,6 +38,10 @@ pub enum ModelCommand {
#[arg(help = "The name of the model")]
name: String,

#[arg(short, long)]
#[arg(help = "The model namespace. If not set, the main package ID is used.")]
namespace: Option<String>,

#[command(flatten)]
world: WorldOptions,

Expand Down Expand Up @@ -65,6 +73,10 @@ hashes, called 'hash' in the following documentation.
#[arg(help = "The name of the model")]
name: String,

#[arg(short, long)]
#[arg(help = "The model namespace. If not set, the main package ID is used.")]
namespace: Option<String>,

#[command(flatten)]
world: WorldOptions,

Expand All @@ -77,6 +89,10 @@ hashes, called 'hash' in the following documentation.
#[arg(help = "The name of the model")]
name: String,

#[arg(short, long)]
#[arg(help = "The model namespace. If not set, the main package ID is used.")]
namespace: Option<String>,

#[command(flatten)]
world: WorldOptions,

Expand All @@ -93,6 +109,10 @@ hashes, called 'hash' in the following documentation.
#[arg(help = "The name of the model")]
name: String,

#[arg(short, long)]
#[arg(help = "The model namespace. If not set, the main package ID is used.")]
namespace: Option<String>,

#[arg(value_name = "KEYS")]
#[arg(value_delimiter = ',')]
#[arg(help = "Comma seperated values e.g., 0x12345,0x69420,...")]
Expand All @@ -109,34 +129,50 @@ hashes, called 'hash' in the following documentation.
impl ModelArgs {
pub fn run(self, config: &Config) -> Result<()> {
trace!(args = ?self);
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let env_metadata = utils::load_metadata_from_config(config)?;
let get_namespace = |ns: Option<String>| -> String {
match ns {
Some(x) => x,
None => {
let default_namespace = ws.current_package().unwrap().id.name.to_string();
println!("[default namespace: {}]", default_namespace);
default_namespace
}
}
};

config.tokio_handle().block_on(async {
match self.command {
ModelCommand::ClassHash { name, starknet, world } => {
ModelCommand::ClassHash { name, namespace, starknet, world } => {
let namespace = get_namespace(namespace);
let world_address = world.address(env_metadata.as_ref()).unwrap();
let provider = starknet.provider(env_metadata.as_ref()).unwrap();
model::model_class_hash(name, world_address, provider).await
model::model_class_hash(namespace, name, world_address, provider).await
}
ModelCommand::ContractAddress { name, starknet, world } => {
ModelCommand::ContractAddress { name, namespace, starknet, world } => {
let namespace = get_namespace(namespace);
let world_address = world.address(env_metadata.as_ref()).unwrap();
let provider = starknet.provider(env_metadata.as_ref()).unwrap();
model::model_contract_address(name, world_address, provider).await
model::model_contract_address(namespace, name, world_address, provider).await
}
ModelCommand::Layout { name, starknet, world } => {
ModelCommand::Layout { name, namespace, starknet, world } => {
let namespace = get_namespace(namespace);
let world_address = world.address(env_metadata.as_ref()).unwrap();
let provider = starknet.provider(env_metadata.as_ref()).unwrap();
model::model_layout(name, world_address, provider).await
model::model_layout(namespace, name, world_address, provider).await
}
ModelCommand::Schema { name, to_json, starknet, world } => {
ModelCommand::Schema { name, namespace, to_json, starknet, world } => {
let namespace = get_namespace(namespace);
let world_address = world.address(env_metadata.as_ref()).unwrap();
let provider = starknet.provider(env_metadata.as_ref()).unwrap();
model::model_schema(name, world_address, provider, to_json).await
model::model_schema(namespace, name, world_address, provider, to_json).await
}
ModelCommand::Get { name, keys, starknet, world } => {
ModelCommand::Get { name, namespace, keys, starknet, world } => {
let namespace = get_namespace(namespace);
let world_address = world.address(env_metadata.as_ref()).unwrap();
let provider = starknet.provider(env_metadata.as_ref()).unwrap();
model::model_get(name, keys, world_address, provider).await
model::model_get(namespace, name, keys, world_address, provider).await
}
}
})
Expand Down
18 changes: 15 additions & 3 deletions bin/sozo/src/commands/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ pub enum RegisterCommand {
#[arg(help = "The class hash of the models to register.")]
models: Vec<FieldElement>,

#[arg(short, long)]
#[arg(help = "The namespace to use to register these models. If not set, the main \
package ID is used.")]
namespace: Option<String>,

#[command(flatten)]
world: WorldOptions,

Expand All @@ -47,14 +52,20 @@ impl RegisterArgs {
pub fn run(self, config: &Config) -> Result<()> {
trace!(args = ?self);
let env_metadata = utils::load_metadata_from_config(config)?;
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;

let (starknet, world, account, transaction, models) = match self.command {
RegisterCommand::Model { starknet, world, account, transaction, models } => {
let (namespace, starknet, world, account, transaction, models) = match self.command {
RegisterCommand::Model { namespace, starknet, world, account, transaction, models } => {
trace!(?models, "Registering models.");
(starknet, world, account, transaction, models)
(namespace, starknet, world, account, transaction, models)
}
};

let namespace = match namespace {
Some(x) => x,
None => ws.current_package().unwrap().id.name.to_string(),
};

let world_address = world.world_address.unwrap_or_default();
trace!(?world_address, "Using world address.");

Expand All @@ -66,6 +77,7 @@ impl RegisterArgs {
world_reader.set_block(BlockId::Tag(BlockTag::Pending));

register::model_register(
namespace,
models,
&world,
transaction.into(),
Expand Down
2 changes: 1 addition & 1 deletion crates/benches/contracts/src/tests/test_world.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mod tests {
let mut models = array![position::TEST_CLASS_HASH, moves::TEST_CLASS_HASH];

// deploy world with models
let world = spawn_test_world(models);
let world = spawn_test_world("benches", models);

// deploy systems contract
let contract_address = world
Expand Down
38 changes: 36 additions & 2 deletions crates/dojo-core/src/base_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use contract_upgrade::{IQuantumLeapDispatcher, IQuantumLeapDispatcherTrait};

// Utils
fn deploy_world() -> IWorldDispatcher {
spawn_test_world(array![])
spawn_test_world("dojo", array![])
}

// A test contract needs to be used instead of previously used base contract since.
Expand Down Expand Up @@ -111,6 +111,8 @@ fn test_upgrade_direct() {
trait IMetadataOnly<T> {
fn selector(self: @T) -> felt252;
fn name(self: @T) -> ByteArray;
fn namespace(self: @T) -> ByteArray;
fn namespace_selector(self: @T) -> felt252;
}

#[starknet::contract]
Expand All @@ -125,6 +127,14 @@ mod invalid_legacy_model {
0x742c3d09472a40914dedcbd609788fd547bde613d6c4d4c2f15d41f4e241f25
}

fn namespace(self: @ContractState) -> ByteArray {
"dojo"
}

fn namespace_selector(self: @ContractState) -> felt252 {
dojo::utils::hash(@Self::namespace(self))
}

fn name(self: @ContractState) -> ByteArray {
"invalid_legacy_model"
}
Expand All @@ -144,6 +154,14 @@ mod invalid_legacy_model_world {
0
}

fn namespace(self: @ContractState) -> ByteArray {
"dojo"
}

fn namespace_selector(self: @ContractState) -> felt252 {
dojo::utils::hash(@Self::namespace(self))
}

fn name(self: @ContractState) -> ByteArray {
"invalid_legacy_model"
}
Expand All @@ -160,7 +178,15 @@ mod invalid_model {
fn selector(self: @ContractState) -> felt252 {
// NOTE: Need to update this value if address changes
// Pre-computed address of a contract deployed through the world.
0x42503befcd7ad05718645aca9c5ddd83b53dca440f9239ce2dcf63018fba16
0x20a4f1249aaad81a2fa291b8fa7cd579c01a6c399639b279066031629481c60
}

fn namespace(self: @ContractState) -> ByteArray {
"dojo"
}

fn namespace_selector(self: @ContractState) -> felt252 {
dojo::utils::hash(@Self::namespace(self))
}

fn name(self: @ContractState) -> ByteArray {
Expand All @@ -182,6 +208,14 @@ mod invalid_model_world {
0
}

fn namespace(self: @ContractState) -> ByteArray {
"dojo"
}

fn namespace_selector(self: @ContractState) -> felt252 {
dojo::utils::hash(@Self::namespace(self))
}

fn name(self: @ContractState) -> ByteArray {
"invalid_model_world"
}
Expand Down
3 changes: 3 additions & 0 deletions crates/dojo-core/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ mod packing_test;
mod world;
#[cfg(test)]
mod world_test;
mod utils;
#[cfg(test)]
mod utils_test;

// Since Scarb 2.6.0 there's an optimization that does not
// build tests for dependencies and it's not configurable.
Expand Down
21 changes: 19 additions & 2 deletions crates/dojo-core/src/model.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@ trait Model<T> {
fn entity(
world: IWorldDispatcher, keys: Span<felt252>, layout: dojo::database::introspect::Layout
) -> T;

/// Returns the name of the model in Pascal case.
fn name() -> ByteArray;
fn version() -> u8;

/// Returns the model selector built from its name and its namespace.
/// model selector = hash(hash(namespace_name), hash(model_name))
fn selector() -> felt252;
fn instance_selector(self: @T) -> felt252;

/// Returns the namespace name of the model (no special case for namespace).
fn namespace() -> ByteArray;

/// Returns the model namespace selector built from its namespace name.
/// namespace_selector = hash(namespace_name)
fn namespace_selector() -> felt252;

fn keys(self: @T) -> Span<felt252>;
fn values(self: @T) -> Span<felt252>;
fn layout() -> dojo::database::introspect::Layout;
Expand All @@ -21,6 +34,8 @@ trait IModel<T> {
fn selector(self: @T) -> felt252;
fn name(self: @T) -> ByteArray;
fn version(self: @T) -> u8;
fn namespace(self: @T) -> ByteArray;
fn namespace_selector(self: @T) -> felt252;
fn unpacked_size(self: @T) -> Option<usize>;
fn packed_size(self: @T) -> Option<usize>;
fn layout(self: @T) -> dojo::database::introspect::Layout;
Expand All @@ -36,12 +51,14 @@ trait IModel<T> {
/// * `class_hash` - Class Hash of the model.
fn deploy_and_get_metadata(
salt: felt252, class_hash: starknet::ClassHash
) -> SyscallResult<(starknet::ContractAddress, ByteArray, felt252)> {
) -> SyscallResult<(starknet::ContractAddress, ByteArray, felt252, ByteArray, felt252)> {
let (contract_address, _) = starknet::deploy_syscall(
class_hash, salt, array![].span(), false,
)?;
let model = IModelDispatcher { contract_address };
let name = model.name();
let selector = model.selector();
Result::Ok((contract_address, name, selector))
let namespace = model.namespace();
let namespace_selector = model.namespace_selector();
Result::Ok((contract_address, name, selector, namespace, namespace_selector))
}
3 changes: 0 additions & 3 deletions crates/dojo-core/src/packing_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,6 @@ fn test_pack_with_offset() {

assert!(packed.len() == 2, "bad packed length");

println!("first item: {}", *packed.at(0));
println!("second item: {}", *packed.at(1));

assert!(*packed.at(0) == 0x70006, "bad packed first item");
assert!(*packed.at(1) == 0x0900000000000000000000000000000008, "bad packed second item");
}
Expand Down
Loading

0 comments on commit 58c7205

Please sign in to comment.