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

namespace, registries: Update lookup table on create #569

Merged
merged 1 commit into from
Jan 19, 2025
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
55 changes: 54 additions & 1 deletion pallets/namespace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ pub mod pallet {
AuthorizationNotFound,
/// Delegate not found.
DelegateNotFound,
/// Namespace Registry list limit exceeded.
NameSpaceRegistryListLimitExceeded,
}

#[pallet::call]
Expand Down Expand Up @@ -571,7 +573,7 @@ pub mod pallet {
digest,
creator: creator.clone(),
archive: false,
registry_id: Some(BoundedVec::default()),
registry_ids: Some(BoundedVec::default()),
},
);

Expand Down Expand Up @@ -943,6 +945,57 @@ impl<T: Config> Pallet<T> {
Ok(())
}

/// Adds a registry ID to the list of registry IDs associated with a namespace.
///
/// This function updates the namespace's `registry_ids` list by appending the specified
/// `registry_id` if it is not already present. If the list is uninitialized (i.e., `None`),
/// it initializes the list and adds the `registry_id`. The function ensures that the
/// `BoundedVec` does not exceed its capacity, returning an error if the limit is reached.
///
/// # Parameters
/// - `namespace_id`: A reference to the ID of the namespace where the registry ID should be
/// added.
/// - `registry_id`: A reference to the registry ID to be added to the namespace's list of
/// registry IDs.
///
/// # Returns
/// - `Ok(())`: If the `registry_id` was successfully added or was already present in the list.
/// - `Err(Error<T>::NameSpaceNotFound)`: If the specified namespace does not exist.
/// - `Err(Error<T>::NameSpaceRegistryListLimitExceeded)`: If the `registry_ids` list exceeds
/// its maximum capacity while attempting to add the `registry_id`.
///
/// # Errors
/// - Returns `NameSpaceNotFound` if the `namespace_id` does not exist in the storage.
/// - Returns `NameSpaceRegistryListLimitExceeded` if the `registry_ids` list cannot accommodate
/// any more entries.
pub fn add_registry_id_to_namespace_details(
namespace_id: &NameSpaceIdOf,
registry_id: &RegistryIdOf,
) -> Result<(), Error<T>> {
NameSpaces::<T>::try_mutate(namespace_id, |space_opt| {
if let Some(space_details) = space_opt {
if let Some(ref mut registry_ids) = space_details.registry_ids {
if !registry_ids.contains(registry_id) {
registry_ids
.try_push(registry_id.clone())
.map_err(|_| Error::<T>::NameSpaceRegistryListLimitExceeded)?;
}
} else {
// Below is required to avoid runtime panic when intialized with None.
let mut new_registry_ids = BoundedVec::default();
new_registry_ids
.try_push(registry_id.clone())
.map_err(|_| Error::<T>::NameSpaceRegistryListLimitExceeded)?;
space_details.registry_ids = Some(new_registry_ids);
}

Ok(())
} else {
Err(Error::<T>::NameSpaceNotFound)
}
})
}

/// Updates the global timeline with a new activity event for a namespace.
///
/// This function is an internal mechanism that logs each significant change
Expand Down
2 changes: 1 addition & 1 deletion pallets/namespace/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub struct NameSpaceDetails<NameSpaceHashOf, NameSpaceCreatorOf, StatusOf, Regis
pub digest: NameSpaceHashOf,
pub creator: NameSpaceCreatorOf,
pub archive: StatusOf,
pub registry_id: Option<RegistryIdOf>,
pub registry_ids: Option<RegistryIdOf>,
}

/// Authorization details for a namespace delegate.
Expand Down
14 changes: 12 additions & 2 deletions pallets/registries/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ use sp_runtime::traits::{Hash, UniqueSaturatedInto};
pub type RegistryAuthorizationIdOf = Ss58Identifier;
/// Namespace Authorization Identifier
pub type NamespaceAuthorizationIdOf = Ss58Identifier;
/// Type of the Namespace Id
pub type NameSpaceIdOf = Ss58Identifier;
/// Type of the Registry Id
pub type RegistryIdOf = Ss58Identifier;
/// Tyoe of the Registry Digest
Expand All @@ -131,7 +133,7 @@ pub type RegistryAuthorizationOf<T> =
RegistryAuthorization<RegistryIdOf, RegistryCreatorOf<T>, Permissions>;
/// Type of Registry Details
pub type RegistryDetailsOf<T> =
RegistryDetails<RegistryCreatorOf<T>, StatusOf, RegistryHashOf<T>, SchemaIdOf>;
RegistryDetails<RegistryCreatorOf<T>, StatusOf, RegistryHashOf<T>, NameSpaceIdOf, SchemaIdOf>;

#[frame_support::pallet]
pub mod pallet {
Expand Down Expand Up @@ -607,7 +609,7 @@ pub mod pallet {
) -> DispatchResult {
let creator = ensure_signed(origin)?;

let _namespace_id = pallet_namespace::Pallet::<T>::ensure_authorization_origin(
let namespace_id = pallet_namespace::Pallet::<T>::ensure_authorization_origin(
&namespace_authorization,
&creator,
)
Expand Down Expand Up @@ -669,10 +671,18 @@ pub mod pallet {
revoked: false,
archived: false,
digest,
namespace_id: namespace_id.clone(),
schema_id,
},
);

// Update the namespace with the newly added registry.
pallet_namespace::Pallet::<T>::add_registry_id_to_namespace_details(
&namespace_id,
&identifier,
)
.map_err(<pallet_namespace::Error<T>>::from)?;

Self::update_activity(&identifier, IdentifierTypeOf::Registries, CallTypeOf::Genesis)
.map_err(Error::<T>::from)?;

Expand Down
116 changes: 116 additions & 0 deletions pallets/registries/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2035,3 +2035,119 @@ fn add_delegator_should_fail_if_registry_delegates_limit_exceeded() {
);
});
}

#[test]
fn registry_id_should_be_updated_on_namespace_chainstorage_on_create() {
let creator = ACCOUNT_00;

let namespace = [2u8; 256].to_vec();
let namespace_digest = <Test as frame_system::Config>::Hashing::hash(&namespace.encode()[..]);

let id_digest = <Test as frame_system::Config>::Hashing::hash(
&[&namespace_digest.encode()[..], &creator.encode()[..]].concat()[..],
);
let namespace_id: NameSpaceIdOf = generate_namespace_id::<Test>(&id_digest);

let namespace_auth_id_digest = <Test as frame_system::Config>::Hashing::hash(
&[&namespace_id.encode()[..], &creator.encode()[..], &creator.encode()[..]].concat()[..],
);
let namespace_authorization_id: NamespaceAuthorizationIdOf =
generate_namespace_authorization_id::<Test>(&namespace_auth_id_digest);

let registry = [2u8; 256].to_vec();

let raw_blob = [2u8; 256].to_vec();
let blob: RegistryBlobOf<Test> = BoundedVec::try_from(raw_blob)
.expect("Test blob should fit into the expected input length of for the test runtime.");

let registry_digest = <Test as frame_system::Config>::Hashing::hash(&registry.encode()[..]);

let id_digest = <Test as frame_system::Config>::Hashing::hash(
&[&registry_digest.encode()[..], &creator.encode()[..]].concat()[..],
);

let registry_id: RegistryIdOf = generate_registry_id::<Test>(&id_digest);

let registry_2 = [3u8; 256].to_vec();

let raw_blob_2 = [3u8; 256].to_vec();
let blob_2: RegistryBlobOf<Test> = BoundedVec::try_from(raw_blob_2)
.expect("Test blob should fit into the expected input length of for the test runtime.");

let registry_digest_2 = <Test as frame_system::Config>::Hashing::hash(&registry_2.encode()[..]);

let id_digest_2 = <Test as frame_system::Config>::Hashing::hash(
&[&registry_digest_2.encode()[..], &creator.encode()[..]].concat()[..],
);

let registry_id_2: RegistryIdOf = generate_registry_id::<Test>(&id_digest_2);

let raw_schema = [2u8; 256].to_vec();
let schema: InputSchemaOf<Test> = BoundedVec::try_from(raw_schema)
.expect("Test Schema should fit into the expected input length of for the test runtime.");
let _digest: SchemaHashOf<Test> = <Test as frame_system::Config>::Hashing::hash(&schema[..]);
let schema_id_digest = <Test as frame_system::Config>::Hashing::hash(&schema.encode()[..]);
let schema_id: SchemaIdOf = generate_schema_id::<Test>(&schema_id_digest);

new_test_ext().execute_with(|| {
assert_ok!(NameSpace::create(
frame_system::RawOrigin::Signed(creator.clone()).into(),
namespace_digest,
None,
));

// Create Registry 1
assert_ok!(Registries::create(
frame_system::RawOrigin::Signed(creator.clone()).into(),
registry_digest,
namespace_authorization_id.clone(),
Some(schema_id.clone()),
Some(blob)
));

// Create Registry 2
assert_ok!(Registries::create(
frame_system::RawOrigin::Signed(creator.clone()).into(),
registry_digest_2,
namespace_authorization_id.clone(),
Some(schema_id),
Some(blob_2)
));

// Verify if the newly created registry-id is added as a list in the Namespace Chain
// Storage.
let name_space_details = pallet_namespace::NameSpaces::<Test>::get(namespace_id.clone())
.ok_or(pallet_namespace::pallet::Error::<Test>::NameSpaceNotFound)
.unwrap();
assert!(
name_space_details
.registry_ids
.clone()
.unwrap_or_default()
.contains(&registry_id),
"Registry ID 1 not found in the Namespace Chain Storage."
);
assert!(
name_space_details.registry_ids.unwrap_or_default().contains(&registry_id_2),
"Registry ID 2 not found in the Namespace Chain Storage."
);

// Verify if the newly created registry-id 1 is present in the Registry Chain Storage.
let registry_info = RegistryInfo::<Test>::get(&registry_id)
.ok_or(Error::<Test>::RegistryNotFound)
.unwrap();
assert_eq!(
registry_info.namespace_id, namespace_id,
"Namespace ID not found in the Registry 1 Chain Storage."
);

// Verify if the newly created registry-id 2 is present in the Registry Chain Storage.
let registry_info = RegistryInfo::<Test>::get(&registry_id_2)
.ok_or(Error::<Test>::RegistryNotFound)
.unwrap();
assert_eq!(
registry_info.namespace_id, namespace_id,
"Namespace ID not found in the Registry 2 Chain Storage."
);
});
}
3 changes: 2 additions & 1 deletion pallets/registries/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ impl Default for Permissions {
/// - `digest`: A hash representing unique content or metadata of the registry.
/// - `schema_id`: (Optional) Identifier linking the registry to a specific schema.
#[derive(Encode, Decode, Clone, MaxEncodedLen, RuntimeDebug, PartialEq, Eq, TypeInfo)]
pub struct RegistryDetails<RegistryCreatorOf, StatusOf, RegistryHashOf, SchemaIdOf> {
pub struct RegistryDetails<RegistryCreatorOf, StatusOf, RegistryHashOf, NameSpaceIdOf, SchemaIdOf> {
pub creator: RegistryCreatorOf,
pub revoked: StatusOf,
pub archived: StatusOf,
pub digest: RegistryHashOf,
pub namespace_id: NameSpaceIdOf,
pub schema_id: Option<SchemaIdOf>,
}

Expand Down
Loading