Skip to content

Commit

Permalink
namespace, registries: Update lookup table on create (#569)
Browse files Browse the repository at this point in the history
Signed-off-by: Shreevatsa N <[email protected]>
  • Loading branch information
vatsa287 authored Jan 19, 2025
1 parent 6eba730 commit 2b49de3
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 5 deletions.
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

0 comments on commit 2b49de3

Please sign in to comment.