Skip to content

Commit

Permalink
BLOCKCHAIN-260 Added a way for company owner to request unregistration
Browse files Browse the repository at this point in the history
  • Loading branch information
Michal Lustyk authored and Michal Lustyk committed Nov 16, 2023
1 parent e9b6bb9 commit d35f8f1
Show file tree
Hide file tree
Showing 4 changed files with 403 additions and 227 deletions.
29 changes: 25 additions & 4 deletions frame/registry/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ benchmarks_instance_pallet! {
}: _<T::RuntimeOrigin>(origin, 0, data.clone(), false)
verify {
let entity_id: T::EntityId = 0u8.into();
assert!(matches!(Registry::<T, I>::requests(0, entity_id), Some(Request { data: ndata, .. }) if ndata == data));
assert!(matches!(Registry::<T, I>::requests(0, entity_id), Some(Some(Request { data: ndata, .. })) if ndata == data));
}

request_registration {
Expand All @@ -59,7 +59,7 @@ benchmarks_instance_pallet! {
Registry::<T, I>::request_entity(origin.clone(), 0, data.clone(), false).unwrap();
}: _<T::RuntimeOrigin>(origin, 0, entity_id.clone(), data.clone(), false)
verify {
assert!(matches!(Registry::<T, I>::requests(0, entity_id), Some(Request { data: ndata, .. }) if ndata == data));
assert!(matches!(Registry::<T, I>::requests(0, entity_id), Some(Some(Request { data: ndata, .. })) if ndata == data));
}

cancel_request {
Expand All @@ -69,7 +69,7 @@ benchmarks_instance_pallet! {
let data = get_data::<T, I>(1, 100 as usize);
Registry::<T, I>::request_entity(origin.clone(), 0, data.clone(), false).unwrap();
let entity_id: T::EntityId = 0u8.into();
assert!(matches!(Registry::<T, I>::requests(0, entity_id.clone()), Some(Request { data: ndata, .. }) if ndata == data));
assert!(matches!(Registry::<T, I>::requests(0, entity_id.clone()), Some(Some(Request { data: ndata, .. })) if ndata == data));
}: _<T::RuntimeOrigin>(origin, 0, entity_id.clone())
verify {
assert_eq!(Registry::<T, I>::requests(0, entity_id), None);
Expand Down Expand Up @@ -116,7 +116,7 @@ benchmarks_instance_pallet! {
Some(Registration { data: ndata, .. }) if ndata == data
)
);
}: _<T::RuntimeOrigin>(registrar, reg_idx, entity_id.clone())
}: _<T::RuntimeOrigin>(registrar, reg_idx, entity_id.clone(), false)
verify {
assert_eq!(Registry::<T, I>::registries(reg_idx, entity_id), None);
}
Expand Down Expand Up @@ -183,6 +183,27 @@ benchmarks_instance_pallet! {
Some(Registration { data: ndata, .. }) if ndata == reg_data
));
}

request_entity_unregister {
let registrar: T::RuntimeOrigin = RawOrigin::Signed(account("registrar", 1, SEED)).into();
add_registries::<T, I>(1)?;
let reg_idx: u32 = Registry::<T, I>::registrars().len() as u32 - 1;
let acc: T::AccountId = account("owner", 0, SEED);
let origin: T::RuntimeOrigin = RawOrigin::Signed(acc.clone()).into();
let _ = T::Currency::make_free_balance_be(&acc, BalanceOf::<T, I>::max_value() / 2u32.into());
let entity_id: T::EntityId = 0u8.into();
let data = get_data::<T, I>(1, 1000);

Registry::<T, I>::request_entity(origin.clone(), reg_idx, data.clone(), true).unwrap();
Registry::<T, I>::register_entity(registrar.clone(), reg_idx, entity_id.clone(), T::Hashing::hash_of(&data)).unwrap();
assert!(matches!(
Registry::<T, I>::registries(reg_idx, entity_id.clone()),
Some(Registration { data: ndata, .. }) if ndata == data
));
}: _<T::RuntimeOrigin>(origin.clone(), reg_idx, entity_id.clone())
verify {
assert!(matches!(Registry::<T, I>::requests(reg_idx, entity_id), Some(None)));
}
}

impl_benchmark_test_suite!(Registry, crate::mock::new_test_ext(), crate::mock::Test,);
125 changes: 81 additions & 44 deletions frame/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ pub mod pallet {
InsufficientDeposit,
/// Entity doesn't allow edits by registrars
NotEditableByRegistrar,
/// Trying to register entity that requested to be deregistered
EntityIsNone,
/// Trying to soft unregister company that do not apply for that
NotRequestedToUnregister
}

#[pallet::event]
Expand All @@ -246,13 +250,15 @@ pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn requests)]
/// Registration requests. See `request_registration` and `cancel_request`
/// If Request data is None it means a request to remove entity from registry
/// Some means request to add or to change data in registry
pub(super) type Requests<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
_,
Blake2_128Concat,
RegistryIndex,
Blake2_128Concat,
T::EntityId,
RequestOf<T, I>,
Option<RequestOf<T, I>>,
OptionQuery,
>;

Expand Down Expand Up @@ -458,10 +464,12 @@ pub mod pallet {
let owner = T::EntityOrigin::ensure_origin(origin)?;
Self::ensure_entity_owner(&owner, &entity_id)?;

if let Some(Request { deposit, .. }) = Self::requests(&registry_index, &entity_id) {
// refund deposit
let owner = Self::entity_owner(&entity_id).ok_or(Error::<T, I>::InvalidEntity)?;
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit);
if let Some(req) = Self::requests(&registry_index, &entity_id) {
if let Some(Request { deposit, .. }) = req {
// refund deposit
let owner = Self::entity_owner(&entity_id).ok_or(Error::<T, I>::InvalidEntity)?;
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit);
}
} else {
return Err(Error::<T, I>::InvalidEntity.into());
}
Expand All @@ -476,6 +484,7 @@ pub mod pallet {
///
/// * `registry_index` - Registry index to remove from
/// * `entity_id` - AccountId of entity to unregister
/// * `soft` - Boolean information should we accept delete request or hard unregister Registries
///
/// Will refund deposit of stored data.
///
Expand All @@ -489,23 +498,18 @@ pub mod pallet {
origin: OriginFor<T>,
registry_index: RegistryIndex,
entity_id: T::EntityId,
soft: bool
) -> DispatchResult {
let sender = T::RegistrarOrigin::ensure_origin(origin)?;
Self::ensure_registrar(&sender, registry_index)?;

if let Some(Registration { deposit, .. }) =
Self::registries(&registry_index, &entity_id)
{
// refund deposit
let owner = Self::entity_owner(&entity_id).ok_or(Error::<T, I>::InvalidEntity)?;
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit);
if soft {
Self::unregister_soft(&registry_index, &entity_id)?
} else {
return Err(Error::<T, I>::InvalidEntity.into());
Self::unregister_hard(&registry_index, &entity_id)?
}
Registries::<T, I>::remove(&registry_index, &entity_id);

Self::deposit_event(Event::EntityUnregistered { entity_id, registry_index });

Ok(())
}

Expand Down Expand Up @@ -536,7 +540,9 @@ pub mod pallet {

// get the request and verify it matches what we want to register
let Request { data: request_data, deposit: request_deposit, editable_by_registrar } =
Self::requests(&registry_index, &entity_id).ok_or(Error::<T, I>::InvalidEntity)?;
Self::requests(&registry_index, &entity_id)
.ok_or(Error::<T, I>::InvalidEntity)?
.ok_or(Error::<T, I>::EntityIsNone)?;
ensure!(T::Hashing::hash_of(&request_data) == data, Error::<T, I>::MismatchedData);

// ensure deposit is ok - mostly defensive, it should never fail,
Expand Down Expand Up @@ -587,7 +593,6 @@ pub mod pallet {
entity_id: T::EntityId,
data: T::EntityData,
) -> DispatchResult {
// make sure origin is ok for registry_index
let sender = T::RegistrarOrigin::ensure_origin(origin)?;
Self::ensure_registrar(&sender, registry_index)?;

Expand All @@ -612,33 +617,31 @@ pub mod pallet {
Ok(())
}

/* see https://github.com/liberland/liberland_substrate/issues/250
/// Remove Entity from given registry.
///
/// * `registry_index` - Registry index to remove from
///
/// Will refund deposit of stored data.
///
/// Emits `EntityUnregistered`.
///
/// Must be called by `EntityOrigin`
#[pallet::call_index(3)]
#[pallet::weight(T::WeightInfo::unregister())]
pub fn unregister(origin: OriginFor<T>, registry_index: RegistryIndex) -> DispatchResult {
let entity = T::EntityOrigin::ensure_origin(origin)?;
if let Some(Registration { deposit, .. }) = Self::registries(&entity, registry_index) {
// refund deposit
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &entity, deposit);
} else {
return Err(Error::<T, I>::InvalidEntity.into())

#[pallet::call_index(7)]
#[pallet::weight(T::WeightInfo::request_entity_unregister())]
pub fn request_entity_unregister(
origin: OriginFor<T>,
registry_index: RegistryIndex,
entity_id: T::EntityId,
) -> DispatchResult {
// make sure origin is ok for registry_index
let sender = T::EntityOrigin::ensure_origin(origin)?;
Self::ensure_entity_owner(&sender, &entity_id)?;

if let Some(Some(req)) = Self::requests(&registry_index, &entity_id) {
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &sender, req.deposit);
}
EntityRegistries::<T, I>::remove(&entity, registry_index);

Self::deposit_event(Event::EntityUnregistered { entity, registry_index });
Requests::<T, I>::insert(
&registry_index,
&entity_id,
None::<RequestOf<T, I>>,
);

Self::deposit_event(Event::RegistrationRequested { registry_index, entity_id });
Ok(())
}
*/
}

impl<T: Config<I>, I: 'static> Pallet<T, I> {
Expand Down Expand Up @@ -683,25 +686,59 @@ pub mod pallet {
editable_by_registrar: bool,
) -> DispatchResult {
let required_deposit = Self::calculate_deposit(&data);
let old_deposit = Self::requests(&registry_index, &entity_id)
.map(|Request { deposit, .. }| deposit)
.unwrap_or_default();


// refund old deposit, if any
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, old_deposit);
if let Some(Some(req)) = Self::requests(&registry_index, &entity_id) {
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, req.deposit);
}

// reserve new deposit
T::Currency::reserve_named(T::ReserveIdentifier::get(), &owner, required_deposit)?;

Requests::<T, I>::insert(
&registry_index,
&entity_id,
Request { deposit: required_deposit, data, editable_by_registrar },
Some(
Request { deposit: required_deposit, data, editable_by_registrar }
),
);

Self::deposit_event(Event::RegistrationRequested { registry_index, entity_id });

Ok(())
}

fn unregister_hard(
registry_index: &RegistryIndex,
entity_id: &T::EntityId,
) -> DispatchResult {
if let Some(Registration { deposit, .. }) =
Self::registries(&registry_index, entity_id)
{
// refund deposit
let owner = Self::entity_owner(entity_id).ok_or(Error::<T, I>::InvalidEntity)?;
T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit);
} else {
return Err(Error::<T, I>::InvalidEntity.into());
}
Registries::<T, I>::remove(registry_index, entity_id);

Ok(())
}

fn unregister_soft(
registry_index: &RegistryIndex,
entity_id: &T::EntityId,
) -> DispatchResult {
if let Some(req) = Self::requests(registry_index, entity_id) {
if req.is_some() {
return Err(Error::<T, I>::NotRequestedToUnregister.into());
}
}
Requests::<T, I>::remove(registry_index, entity_id);
Registries::<T, I>::remove(registry_index, entity_id);

Ok(())
}
}
}
Loading

0 comments on commit d35f8f1

Please sign in to comment.