Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
remybar committed Nov 15, 2024
1 parent f6659db commit f38113c
Show file tree
Hide file tree
Showing 22 changed files with 448 additions and 62 deletions.
2 changes: 2 additions & 0 deletions bin/sozo/src/commands/migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ impl MigrateArgs {
let MigrationResult { manifest, has_changes } =
migration.migrate(&mut spinner).await.context("Migration failed.")?;

migration.upload_metadata(&mut spinner).await.context("Metadata upload failed.")?;

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

View check run for this annotation

Codecov / codecov/patch

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

Added line #L78 was not covered by tests

spinner.update_text("Writing manifest...");
ws.write_manifest_profile(manifest).context("🪦 Failed to write manifest.")?;

Expand Down
11 changes: 6 additions & 5 deletions crates/dojo/core-cairo-test/src/tests/world/metadata.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn test_set_metadata_world() {
let world = world.dispatcher;

let metadata = ResourceMetadata {
resource_id: 0, metadata_uri: format!("ipfs:world_with_a_long_uri_that")
resource_id: 0, metadata_uri: format!("ipfs:world_with_a_long_uri_that"), metadata_hash: 42
};

world.set_metadata(metadata.clone());
Expand All @@ -30,7 +30,7 @@ fn test_set_metadata_resource_owner() {
starknet::testing::set_contract_address(bob);

let metadata = ResourceMetadata {
resource_id: model_selector, metadata_uri: format!("ipfs:bob")
resource_id: model_selector, metadata_uri: format!("ipfs:bob"), metadata_hash: 42
};

drop_all_events(world.contract_address);
Expand All @@ -46,6 +46,7 @@ fn test_set_metadata_resource_owner() {
if let world::Event::MetadataUpdate(event) = event.unwrap() {
assert(event.resource == metadata.resource_id, 'bad resource');
assert(event.uri == metadata.metadata_uri, 'bad uri');
assert(event.hash == metadata.metadata_hash, 'bad hash');
} else {
core::panic_with_felt252('no EventUpgraded event');
}
Expand All @@ -70,7 +71,7 @@ fn test_set_metadata_not_possible_for_resource_writer() {
starknet::testing::set_contract_address(bob);

let metadata = ResourceMetadata {
resource_id: model_selector, metadata_uri: format!("ipfs:bob")
resource_id: model_selector, metadata_uri: format!("ipfs:bob"), metadata_hash: 42
};

world.set_metadata(metadata.clone());
Expand All @@ -85,7 +86,7 @@ fn test_set_metadata_not_possible_for_random_account() {
let world = world.dispatcher;

let metadata = ResourceMetadata { // World metadata.
resource_id: 0, metadata_uri: format!("ipfs:bob"),
resource_id: 0, metadata_uri: format!("ipfs:bob"), metadata_hash: 42
};

let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -112,7 +113,7 @@ fn test_set_metadata_through_malicious_contract() {
starknet::testing::set_contract_address(malicious_contract);

let metadata = ResourceMetadata {
resource_id: model_selector, metadata_uri: format!("ipfs:bob")
resource_id: model_selector, metadata_uri: format!("ipfs:bob"), metadata_hash: 42
};

world.set_metadata(metadata.clone());
Expand Down
1 change: 1 addition & 0 deletions crates/dojo/core/src/model/metadata.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub struct ResourceMetadata {
#[key]
pub resource_id: felt252,
pub metadata_uri: ByteArray,
pub metadata_hash: felt252
}

pub fn default_address() -> starknet::ContractAddress {
Expand Down
9 changes: 7 additions & 2 deletions crates/dojo/core/src/world/world_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ pub mod world {
pub struct MetadataUpdate {
#[key]
pub resource: felt252,
pub uri: ByteArray
pub uri: ByteArray,
pub hash: felt252
}

#[derive(Drop, starknet::Event)]
Expand Down Expand Up @@ -356,7 +357,11 @@ pub mod world {

self
.emit(
MetadataUpdate { resource: metadata.resource_id, uri: metadata.metadata_uri }
MetadataUpdate {
resource: metadata.resource_id,
uri: metadata.metadata_uri,
hash: metadata.metadata_hash
}
);
}

Expand Down
62 changes: 61 additions & 1 deletion crates/dojo/world/src/config/metadata_config.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Metadata configuration for the world.
use std::collections::HashMap;
use std::hash::{Hash, Hasher};

use serde::{Deserialize, Serialize};
use serde_json::json;
use url::Url;

use crate::config::WorldConfig;
use crate::config::{ResourceConfig, WorldConfig};
use crate::uri::Uri;

/// World metadata that describes the world.
Expand Down Expand Up @@ -33,3 +35,61 @@ impl From<WorldConfig> for WorldMetadata {
}
}
}

impl Hash for WorldMetadata {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.seed.hash(state);
self.description.hash(state);
self.cover_uri.hash(state);
self.icon_uri.hash(state);
self.website.hash(state);

json!(self.socials).to_string().hash(state);

Check warning on line 48 in crates/dojo/world/src/config/metadata_config.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/metadata_config.rs#L40-L48

Added lines #L40 - L48 were not covered by tests

// include icon and cover data into the hash to
// detect data changes even if the filename is the same.
if let Some(Uri::File(icon)) = &self.icon_uri {
let icon_data = std::fs::read(icon).expect("read icon failed");
icon_data.hash(state);
};

Check warning on line 55 in crates/dojo/world/src/config/metadata_config.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/metadata_config.rs#L52-L55

Added lines #L52 - L55 were not covered by tests

if let Some(Uri::File(cover)) = &self.cover_uri {
let cover_data = std::fs::read(cover).expect("read cover failed");
cover_data.hash(state);
};
}

Check warning on line 61 in crates/dojo/world/src/config/metadata_config.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/metadata_config.rs#L57-L61

Added lines #L57 - L61 were not covered by tests
}

/// resource metadata (for contracts, models, ...)
#[derive(Default, Serialize, Deserialize, Debug, Clone)]

Check warning on line 65 in crates/dojo/world/src/config/metadata_config.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/metadata_config.rs#L65

Added line #L65 was not covered by tests
pub struct ResourceMetadata {
pub name: String,
pub description: Option<String>,
pub icon_uri: Option<Uri>,
}

impl From<ResourceConfig> for ResourceMetadata {
fn from(config: ResourceConfig) -> Self {
ResourceMetadata {
name: config.name,
description: config.description,
icon_uri: config.icon_uri,
}
}

Check warning on line 79 in crates/dojo/world/src/config/metadata_config.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/metadata_config.rs#L73-L79

Added lines #L73 - L79 were not covered by tests
}

impl Hash for ResourceMetadata {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.description.hash(state);
self.icon_uri.hash(state);

Check warning on line 86 in crates/dojo/world/src/config/metadata_config.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/metadata_config.rs#L83-L86

Added lines #L83 - L86 were not covered by tests

// include icon and cover data into the hash to
// detect data changes even if the filename is the same.
if let Some(Uri::File(icon)) = &self.icon_uri {
let icon_data = std::fs::read(icon).expect("read icon failed");
icon_data.hash(state);
};
}

Check warning on line 94 in crates/dojo/world/src/config/metadata_config.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/config/metadata_config.rs#L90-L94

Added lines #L90 - L94 were not covered by tests
}
2 changes: 2 additions & 0 deletions crates/dojo/world/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ pub mod metadata_config;
pub mod migration_config;
pub mod namespace_config;
pub mod profile_config;
pub mod resource_config;
pub mod world_config;

pub use environment::Environment;
pub use metadata_config::WorldMetadata;
pub use namespace_config::NamespaceConfig;
pub use profile_config::ProfileConfig;
pub use resource_config::ResourceConfig;
pub use world_config::WorldConfig;
46 changes: 46 additions & 0 deletions crates/dojo/world/src/config/profile_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use toml;
use super::environment::Environment;
use super::migration_config::MigrationConfig;
use super::namespace_config::NamespaceConfig;
use super::resource_config::ResourceConfig;
use super::world_config::WorldConfig;

/// Profile configuration that is used to configure the world and its environment.
Expand All @@ -17,6 +18,9 @@ use super::world_config::WorldConfig;
#[derive(Debug, Clone, Default, Deserialize)]
pub struct ProfileConfig {
pub world: WorldConfig,
pub models: Option<Vec<ResourceConfig>>,
pub contracts: Option<Vec<ResourceConfig>>,
pub events: Option<Vec<ResourceConfig>>,
pub namespace: NamespaceConfig,
pub env: Option<Environment>,
pub migration: Option<MigrationConfig>,
Expand Down Expand Up @@ -134,6 +138,24 @@ mod tests {
website = "https://example.com"
socials = { "twitter" = "test", "discord" = "test" }
[[models]]
tag = "ns1-m1"
name = "m1"
description = "This is the m1 model"
icon_uri = "ipfs://dojo/m1.png"
[[contracts]]
tag = "ns1-c1"
name = "c1"
description = "This is the c1 contract"
icon_uri = "ipfs://dojo/c1.png"
[[events]]
tag = "ns1-e1"
name = "e1"
description = "This is the e1 event"
icon_uri = "ipfs://dojo/e1.png"
[namespace]
default = "test"
mappings = { "test" = ["test2"] }
Expand Down Expand Up @@ -190,6 +212,30 @@ mod tests {
]))
);

assert!(config.models.is_some());
let models = config.models.unwrap();
assert_eq!(models.len(), 1);
assert_eq!(models[0].tag, "ns1-m1");
assert_eq!(models[0].name, "m1");
assert_eq!(models[0].description, Some("This is the m1 model".to_string()));
assert_eq!(models[0].icon_uri, Some(Uri::from_string("ipfs://dojo/m1.png").unwrap()));

assert!(config.contracts.is_some());
let contracts = config.contracts.unwrap();
assert_eq!(contracts.len(), 1);
assert_eq!(contracts[0].tag, "ns1-c1");
assert_eq!(contracts[0].name, "c1");
assert_eq!(contracts[0].description, Some("This is the c1 contract".to_string()));
assert_eq!(contracts[0].icon_uri, Some(Uri::from_string("ipfs://dojo/c1.png").unwrap()));

assert!(config.events.is_some());
let events = config.events.unwrap();
assert_eq!(events.len(), 1);
assert_eq!(events[0].tag, "ns1-e1");
assert_eq!(events[0].name, "e1");
assert_eq!(events[0].description, Some("This is the e1 event".to_string()));
assert_eq!(events[0].icon_uri, Some(Uri::from_string("ipfs://dojo/e1.png").unwrap()));

assert_eq!(config.namespace.default, "test".to_string());
assert_eq!(
config.namespace.mappings,
Expand Down
11 changes: 11 additions & 0 deletions crates/dojo/world/src/config/resource_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use serde::Deserialize;

use crate::uri::Uri;

#[derive(Debug, Clone, Default, Deserialize)]
pub struct ResourceConfig {
pub tag: String,
pub name: String,
pub description: Option<String>,
pub icon_uri: Option<Uri>,
}
40 changes: 36 additions & 4 deletions crates/dojo/world/src/contracts/abigen/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ impl cainome::cairo_serde::CairoSerde for FieldLayout {
pub struct MetadataUpdate {
pub resource: starknet::core::types::Felt,
pub uri: cainome::cairo_serde::ByteArray,
pub hash: starknet::core::types::Felt,
}
impl cainome::cairo_serde::CairoSerde for MetadataUpdate {
type RustType = Self;
Expand All @@ -402,12 +403,14 @@ impl cainome::cairo_serde::CairoSerde for MetadataUpdate {
let mut __size = 0;
__size += starknet::core::types::Felt::cairo_serialized_size(&__rust.resource);
__size += cainome::cairo_serde::ByteArray::cairo_serialized_size(&__rust.uri);
__size += starknet::core::types::Felt::cairo_serialized_size(&__rust.hash);

Check warning on line 406 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L406

Added line #L406 was not covered by tests
__size
}
fn cairo_serialize(__rust: &Self::RustType) -> Vec<starknet::core::types::Felt> {
let mut __out: Vec<starknet::core::types::Felt> = vec![];
__out.extend(starknet::core::types::Felt::cairo_serialize(&__rust.resource));
__out.extend(cainome::cairo_serde::ByteArray::cairo_serialize(&__rust.uri));
__out.extend(starknet::core::types::Felt::cairo_serialize(&__rust.hash));

Check warning on line 413 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L413

Added line #L413 was not covered by tests
__out
}
fn cairo_deserialize(
Expand All @@ -419,7 +422,9 @@ impl cainome::cairo_serde::CairoSerde for MetadataUpdate {
__offset += starknet::core::types::Felt::cairo_serialized_size(&resource);
let uri = cainome::cairo_serde::ByteArray::cairo_deserialize(__felts, __offset)?;
__offset += cainome::cairo_serde::ByteArray::cairo_serialized_size(&uri);
Ok(MetadataUpdate { resource, uri })
let hash = starknet::core::types::Felt::cairo_deserialize(__felts, __offset)?;
__offset += starknet::core::types::Felt::cairo_serialized_size(&hash);
Ok(MetadataUpdate { resource, uri, hash })

Check warning on line 427 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L425-L427

Added lines #L425 - L427 were not covered by tests
}
}
impl MetadataUpdate {
Expand Down Expand Up @@ -625,6 +630,7 @@ impl OwnerUpdated {
pub struct ResourceMetadata {
pub resource_id: starknet::core::types::Felt,
pub metadata_uri: cainome::cairo_serde::ByteArray,
pub metadata_hash: starknet::core::types::Felt,
}
impl cainome::cairo_serde::CairoSerde for ResourceMetadata {
type RustType = Self;
Expand All @@ -634,12 +640,14 @@ impl cainome::cairo_serde::CairoSerde for ResourceMetadata {
let mut __size = 0;
__size += starknet::core::types::Felt::cairo_serialized_size(&__rust.resource_id);
__size += cainome::cairo_serde::ByteArray::cairo_serialized_size(&__rust.metadata_uri);
__size += starknet::core::types::Felt::cairo_serialized_size(&__rust.metadata_hash);

Check warning on line 643 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L643

Added line #L643 was not covered by tests
__size
}
fn cairo_serialize(__rust: &Self::RustType) -> Vec<starknet::core::types::Felt> {
let mut __out: Vec<starknet::core::types::Felt> = vec![];
__out.extend(starknet::core::types::Felt::cairo_serialize(&__rust.resource_id));
__out.extend(cainome::cairo_serde::ByteArray::cairo_serialize(&__rust.metadata_uri));
__out.extend(starknet::core::types::Felt::cairo_serialize(&__rust.metadata_hash));

Check warning on line 650 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L650

Added line #L650 was not covered by tests
__out
}
fn cairo_deserialize(
Expand All @@ -651,7 +659,9 @@ impl cainome::cairo_serde::CairoSerde for ResourceMetadata {
__offset += starknet::core::types::Felt::cairo_serialized_size(&resource_id);
let metadata_uri = cainome::cairo_serde::ByteArray::cairo_deserialize(__felts, __offset)?;
__offset += cainome::cairo_serde::ByteArray::cairo_serialized_size(&metadata_uri);
Ok(ResourceMetadata { resource_id, metadata_uri })
let metadata_hash = starknet::core::types::Felt::cairo_deserialize(__felts, __offset)?;
__offset += starknet::core::types::Felt::cairo_serialized_size(&metadata_hash);
Ok(ResourceMetadata { resource_id, metadata_uri, metadata_hash })

Check warning on line 664 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L662-L664

Added lines #L662 - L664 were not covered by tests
}
}
#[derive(Clone, serde::Serialize, serde::Deserialize, PartialEq, Debug)]
Expand Down Expand Up @@ -1791,7 +1801,18 @@ impl TryFrom<&starknet::core::types::EmittedEvent> for Event {
}
};
data_offset += cainome::cairo_serde::ByteArray::cairo_serialized_size(&uri);
return Ok(Event::MetadataUpdate(MetadataUpdate { resource, uri }));
let hash =
match starknet::core::types::Felt::cairo_deserialize(&event.data, data_offset) {
Ok(v) => v,
Err(e) => {
return Err(format!(
"Could not deserialize field {} for {}: {:?}",
"hash", "MetadataUpdate", e
));

Check warning on line 1811 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L1804-L1811

Added lines #L1804 - L1811 were not covered by tests
}
};
data_offset += starknet::core::types::Felt::cairo_serialized_size(&hash);
return Ok(Event::MetadataUpdate(MetadataUpdate { resource, uri, hash }));

Check warning on line 1815 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L1814-L1815

Added lines #L1814 - L1815 were not covered by tests
}
let selector = event.keys[0];
if selector
Expand Down Expand Up @@ -2660,7 +2681,18 @@ impl TryFrom<&starknet::core::types::Event> for Event {
}
};
data_offset += cainome::cairo_serde::ByteArray::cairo_serialized_size(&uri);
return Ok(Event::MetadataUpdate(MetadataUpdate { resource, uri }));
let hash =
match starknet::core::types::Felt::cairo_deserialize(&event.data, data_offset) {
Ok(v) => v,
Err(e) => {
return Err(format!(
"Could not deserialize field {} for {}: {:?}",
"hash", "MetadataUpdate", e
));

Check warning on line 2691 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L2684-L2691

Added lines #L2684 - L2691 were not covered by tests
}
};
data_offset += starknet::core::types::Felt::cairo_serialized_size(&hash);
return Ok(Event::MetadataUpdate(MetadataUpdate { resource, uri, hash }));

Check warning on line 2695 in crates/dojo/world/src/contracts/abigen/world.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo/world/src/contracts/abigen/world.rs#L2694-L2695

Added lines #L2694 - L2695 were not covered by tests
}
let selector = event.keys[0];
if selector
Expand Down
Loading

0 comments on commit f38113c

Please sign in to comment.