diff --git a/frame/registry/src/benchmarking.rs b/frame/registry/src/benchmarking.rs index a314bc78d..ad179fb05 100644 --- a/frame/registry/src/benchmarking.rs +++ b/frame/registry/src/benchmarking.rs @@ -45,7 +45,7 @@ benchmarks_instance_pallet! { }: _(origin, 0, data.clone(), false) verify { let entity_id: T::EntityId = 0u8.into(); - assert!(matches!(Registry::::requests(0, entity_id), Some(Request { data: ndata, .. }) if ndata == data)); + assert!(matches!(Registry::::requests(0, entity_id), Some(Some(Request { data: ndata, .. })) if ndata == data)); } request_registration { @@ -59,7 +59,7 @@ benchmarks_instance_pallet! { Registry::::request_entity(origin.clone(), 0, data.clone(), false).unwrap(); }: _(origin, 0, entity_id.clone(), data.clone(), false) verify { - assert!(matches!(Registry::::requests(0, entity_id), Some(Request { data: ndata, .. }) if ndata == data)); + assert!(matches!(Registry::::requests(0, entity_id), Some(Some(Request { data: ndata, .. })) if ndata == data)); } cancel_request { @@ -69,7 +69,7 @@ benchmarks_instance_pallet! { let data = get_data::(1, 100 as usize); Registry::::request_entity(origin.clone(), 0, data.clone(), false).unwrap(); let entity_id: T::EntityId = 0u8.into(); - assert!(matches!(Registry::::requests(0, entity_id.clone()), Some(Request { data: ndata, .. }) if ndata == data)); + assert!(matches!(Registry::::requests(0, entity_id.clone()), Some(Some(Request { data: ndata, .. })) if ndata == data)); }: _(origin, 0, entity_id.clone()) verify { assert_eq!(Registry::::requests(0, entity_id), None); @@ -116,7 +116,7 @@ benchmarks_instance_pallet! { Some(Registration { data: ndata, .. }) if ndata == data ) ); - }: _(registrar, reg_idx, entity_id.clone()) + }: _(registrar, reg_idx, entity_id.clone(), false) verify { assert_eq!(Registry::::registries(reg_idx, entity_id), None); } @@ -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::(1)?; + let reg_idx: u32 = Registry::::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::::max_value() / 2u32.into()); + let entity_id: T::EntityId = 0u8.into(); + let data = get_data::(1, 1000); + + Registry::::request_entity(origin.clone(), reg_idx, data.clone(), true).unwrap(); + Registry::::register_entity(registrar.clone(), reg_idx, entity_id.clone(), T::Hashing::hash_of(&data)).unwrap(); + assert!(matches!( + Registry::::registries(reg_idx, entity_id.clone()), + Some(Registration { data: ndata, .. }) if ndata == data + )); + }: _(origin.clone(), reg_idx, entity_id.clone()) + verify { + assert!(matches!(Registry::::requests(reg_idx, entity_id), Some(None))); + } } impl_benchmark_test_suite!(Registry, crate::mock::new_test_ext(), crate::mock::Test,); diff --git a/frame/registry/src/lib.rs b/frame/registry/src/lib.rs index 398ea8c8a..530dac17b 100644 --- a/frame/registry/src/lib.rs +++ b/frame/registry/src/lib.rs @@ -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] @@ -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, I: 'static = ()> = StorageDoubleMap< _, Blake2_128Concat, RegistryIndex, Blake2_128Concat, T::EntityId, - RequestOf, + Option>, OptionQuery, >; @@ -458,10 +464,13 @@ pub mod pallet { let owner = T::EntityOrigin::ensure_origin(origin)?; Self::ensure_entity_owner(&owner, &entity_id)?; - if let Some(Request { deposit, .. }) = Self::requests(®istry_index, &entity_id) { - // refund deposit - let owner = Self::entity_owner(&entity_id).ok_or(Error::::InvalidEntity)?; - T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit); + if let Some(req) = Self::requests(®istry_index, &entity_id) { + if let Some(Request { deposit, .. }) = req { + // refund deposit + let owner = + Self::entity_owner(&entity_id).ok_or(Error::::InvalidEntity)?; + T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit); + } } else { return Err(Error::::InvalidEntity.into()); } @@ -476,6 +485,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. /// @@ -489,23 +499,18 @@ pub mod pallet { origin: OriginFor, 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(®istry_index, &entity_id) - { - // refund deposit - let owner = Self::entity_owner(&entity_id).ok_or(Error::::InvalidEntity)?; - T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit); + if soft { + Self::unregister_soft(®istry_index, &entity_id)? } else { - return Err(Error::::InvalidEntity.into()); + Self::unregister_hard(®istry_index, &entity_id)? } - Registries::::remove(®istry_index, &entity_id); Self::deposit_event(Event::EntityUnregistered { entity_id, registry_index }); - Ok(()) } @@ -536,7 +541,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(®istry_index, &entity_id).ok_or(Error::::InvalidEntity)?; + Self::requests(®istry_index, &entity_id) + .ok_or(Error::::InvalidEntity)? + .ok_or(Error::::EntityIsNone)?; ensure!(T::Hashing::hash_of(&request_data) == data, Error::::MismatchedData); // ensure deposit is ok - mostly defensive, it should never fail, @@ -587,7 +594,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)?; @@ -612,33 +618,26 @@ 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, 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::::InvalidEntity.into()) + #[pallet::call_index(7)] + #[pallet::weight(T::WeightInfo::request_entity_unregister())] + pub fn request_entity_unregister( + origin: OriginFor, + 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(®istry_index, &entity_id) { + T::Currency::unreserve_named(T::ReserveIdentifier::get(), &sender, req.deposit); } - EntityRegistries::::remove(&entity, registry_index); - Self::deposit_event(Event::EntityUnregistered { entity, registry_index }); + Requests::::insert(®istry_index, &entity_id, None::>); + Self::deposit_event(Event::RegistrationRequested { registry_index, entity_id }); Ok(()) } - */ } impl, I: 'static> Pallet { @@ -683,12 +682,11 @@ pub mod pallet { editable_by_registrar: bool, ) -> DispatchResult { let required_deposit = Self::calculate_deposit(&data); - let old_deposit = Self::requests(®istry_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(®istry_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)?; @@ -696,12 +694,44 @@ pub mod pallet { Requests::::insert( ®istry_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(®istry_index, entity_id) + { + // refund deposit + let owner = Self::entity_owner(entity_id).ok_or(Error::::InvalidEntity)?; + T::Currency::unreserve_named(T::ReserveIdentifier::get(), &owner, deposit); + } else { + return Err(Error::::InvalidEntity.into()); + } + Registries::::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::::NotRequestedToUnregister.into()); + } + } + Requests::::remove(registry_index, entity_id); + Registries::::remove(registry_index, entity_id); + + Ok(()) + } } } diff --git a/frame/registry/src/tests.rs b/frame/registry/src/tests.rs index 1be9078b9..d2e888021 100644 --- a/frame/registry/src/tests.rs +++ b/frame/registry/src/tests.rs @@ -123,31 +123,55 @@ fn request_entity_works() { assert_ok!(Registry::request_entity(RuntimeOrigin::signed(0), 0, data1.clone(), false)); assert_eq!( Registry::requests(0, 0), - Some(Request { deposit: 9u64, data: data1.clone(), editable_by_registrar: false }) + Some(Some(Request { + deposit: 9u64, + data: data1.clone(), + editable_by_registrar: false + })) ); assert_ok!(Registry::request_entity(RuntimeOrigin::signed(0), 0, data2.clone(), false)); assert_eq!( Registry::requests(0, 0), - Some(Request { deposit: 9u64, data: data1.clone(), editable_by_registrar: false }) + Some(Some(Request { + deposit: 9u64, + data: data1.clone(), + editable_by_registrar: false + })) ); assert_eq!( Registry::requests(0, 1), - Some(Request { deposit: 9u64, data: data2.clone(), editable_by_registrar: false }) + Some(Some(Request { + deposit: 9u64, + data: data2.clone(), + editable_by_registrar: false + })) ); assert_ok!(Registry::request_entity(RuntimeOrigin::signed(0), 0, data2.clone(), false)); assert_eq!( Registry::requests(0, 0), - Some(Request { deposit: 9u64, data: data1.clone(), editable_by_registrar: false }) + Some(Some(Request { + deposit: 9u64, + data: data1.clone(), + editable_by_registrar: false + })) ); assert_eq!( Registry::requests(0, 1), - Some(Request { deposit: 9u64, data: data2.clone(), editable_by_registrar: false }) + Some(Some(Request { + deposit: 9u64, + data: data2.clone(), + editable_by_registrar: false + })) ); assert_eq!( Registry::requests(0, 2), - Some(Request { deposit: 9u64, data: data2.clone(), editable_by_registrar: false }) + Some(Some(Request { + deposit: 9u64, + data: data2.clone(), + editable_by_registrar: false + })) ); }); } @@ -299,7 +323,7 @@ fn cancel_request_wipes_only_request() { assert_eq!( Registry::requests(0, 0), - Some(Request { deposit: 9u64, data: data.clone(), editable_by_registrar: false }) + Some(Some(Request { deposit: 9u64, data: data.clone(), editable_by_registrar: false })) ); assert_eq!( Registry::registries(0, 0), @@ -377,8 +401,8 @@ fn unregister_verifies_origin() { let owner = RuntimeOrigin::signed(1); assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); - assert_noop!(Registry::unregister(owner, 0, 0), Error::::InvalidRegistry); - assert_noop!(Registry::unregister(registrar, 1, 0), Error::::InvalidRegistry); + assert_noop!(Registry::unregister(owner, 0, 0, false), Error::::InvalidRegistry); + assert_noop!(Registry::unregister(registrar, 1, 0, false), Error::::InvalidRegistry); }) } @@ -388,7 +412,7 @@ fn unregister_fails_on_unregistered_entity() { let registrar = RuntimeOrigin::signed(0); assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); - assert_noop!(Registry::unregister(registrar, 0, 0), Error::::InvalidEntity); + assert_noop!(Registry::unregister(registrar, 0, 0, false), Error::::InvalidEntity); }) } @@ -408,7 +432,7 @@ fn unregister_works() { HashingOf::::hash_of(&data) )); assert!(matches!(Registry::registries(0, 0), Some(_))); - assert_ok!(Registry::unregister(registrar, 0, 0)); + assert_ok!(Registry::unregister(registrar, 0, 0, false)); assert_eq!(Registry::registries(0, 0), None); }) } @@ -429,7 +453,7 @@ fn unregister_refunds_deposit() { HashingOf::::hash_of(&data) )); assert_eq!(Balances::reserved_balance(1), 5u64); - assert_ok!(Registry::unregister(registrar, 0, 0)); + assert_ok!(Registry::unregister(registrar, 0, 0, false)); assert_eq!(Balances::reserved_balance(1), 0u64); assert_eq!(Balances::free_balance(1), 100u64); }) @@ -450,7 +474,7 @@ fn unregister_deposits_event() { 0, HashingOf::::hash_of(&data) )); - assert_ok!(Registry::unregister(registrar, 0, 0)); + assert_ok!(Registry::unregister(registrar, 0, 0, false)); System::assert_last_event( Event::::EntityUnregistered { entity_id: 0, registry_index: 0 }.into(), ); @@ -547,11 +571,11 @@ fn register_entity_verifies_deposit_amount() { Requests::::insert( 0, 1, - Request { + Some(Request { deposit: 4u64, // should be 5 to match data data: data1.clone(), editable_by_registrar: false, - }, + }), ); assert_noop!( Registry::register_entity(registrar.clone(), 0, 1, HashingOf::::hash_of(&data1)), @@ -725,7 +749,7 @@ fn new_requests_dont_overwrite_registry() { assert_ok!(Registry::request_registration(owner, 0, 0, data2.clone(), false)); assert_eq!( Registry::requests(0, 0), - Some(Request { deposit: 9u64, data: data2, editable_by_registrar: false }) + Some(Some(Request { deposit: 9u64, data: data2, editable_by_registrar: false })) ); assert_eq!( Registry::registries(0, 0), @@ -811,7 +835,7 @@ fn collective_can_be_registrar() { 0, HashingOf::::hash_of(&data) )); - assert_ok!(RegistryWithCollectives::unregister(registrar_origin.clone(), 0, 0)); + assert_ok!(RegistryWithCollectives::unregister(registrar_origin.clone(), 0, 0, false)); }) } @@ -830,7 +854,7 @@ fn collective_can_have_entity() { )); assert_eq!( RegistryWithCollectives::requests(0, 0), - Some(Request { deposit: 5u64, data: data.clone(), editable_by_registrar: true }) + Some(Some(Request { deposit: 5u64, data: data.clone(), editable_by_registrar: true })) ); assert_eq!(RegistryWithCollectives::entity_owner(0), Some(collective_account_id),); assert_ok!(RegistryWithCollectives::cancel_request(owner_origin.clone(), 0, 0)); @@ -883,7 +907,7 @@ fn whole_process_deposits_test() { assert_eq!(Balances::reserved_balance(1), 5u64); // unregister, refund - assert_ok!(Registry::unregister(registrar.clone(), 0, 0)); + assert_ok!(Registry::unregister(registrar.clone(), 0, 0, false)); assert_eq!(Balances::reserved_balance(1), 0u64); }) } @@ -903,117 +927,180 @@ fn genesis_build_works() { }) } -/* see https://github.com/liberland/liberland_substrate/issues/250 +/* request_entity_unregister */ + #[test] -fn unregister_wipes_only_single_registry_data() { +fn request_entity_unregister_deposit_event() { new_test_ext().execute_with(|| { let data: DataOf = vec![1, 2, 3].try_into().unwrap(); - let registrar1 = RuntimeOrigin::signed(0); - let registrar2 = RuntimeOrigin::signed(1); - let owner = RuntimeOrigin::signed(2); + let registrar = RuntimeOrigin::signed(0); + let owner = RuntimeOrigin::signed(1); assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); - assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 1)); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_ok!(Registry::register_entity( + registrar.clone(), + 0, + 0, + HashingOf::::hash_of(&data) + )); + assert_ok!(Registry::request_entity_unregister(owner.clone(), 0, 0)); + assert_ok!(Registry::unregister(registrar, 0, 0, true)); + assert_eq!(Registry::requests(1, 0), None); + System::assert_last_event( + Event::::EntityUnregistered { entity_id: 0, registry_index: 0 }.into(), + ); + }) +} - assert_ok!(Registry::request_entity(owner.clone(), data.clone(), false)); - assert_ok!(Registry::request_entity(owner.clone(), 0)); - assert_ok!(Registry::request_entity(owner.clone(), 1)); - assert_ok!(Registry::register_entity(registrar1, 0, 2, HashingOf::::hash_of(&data))); - assert_ok!(Registry::register_entity(registrar2, 1, 2, HashingOf::::hash_of(&data))); +#[test] +fn request_entity_unregister_only_owner_can_unregister() { + new_test_ext().execute_with(|| { + let data: DataOf = vec![1, 2, 3].try_into().unwrap(); + let registrar = RuntimeOrigin::signed(0); + let owner = RuntimeOrigin::signed(1); + let fake_owner = RuntimeOrigin::signed(2); - assert_eq!( - Registry::requests(2), - Some(Request { deposit: 9u64, data: data.clone(), editable_by_registrar: false }) - ); - assert_eq!( - Registry::registries(2, 0), - Some(Registration { - deposit: 9u64, - data: Some(data.clone()), - editable_by_registrar: false, - }) - ); - assert_eq!( - Registry::registries(2, 1), - Some(Registration { - deposit: 9u64, - data: Some(data.clone()), - editable_by_registrar: false, - }) + assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_ok!(Registry::register_entity( + registrar.clone(), + 0, + 0, + HashingOf::::hash_of(&data) + )); + assert_noop!( + Registry::request_entity_unregister(fake_owner, 0, 0), + Error::::InvalidEntity ); + }) +} - assert_ok!(Registry::unregister(owner.clone(), 0)); - assert_eq!( - Registry::requests(2), - Some(Request { deposit: 9u64, data: data.clone(), editable_by_registrar: false }) - ); - assert_eq!(Registry::registries(2, 0), None); - assert_eq!( - Registry::registries(2, 1), - Some(Registration { - deposit: 9u64, - data: Some(data.clone()), - editable_by_registrar: false, - }) - ); +#[test] +fn request_entity_unregister_refunds_deposit() { + new_test_ext().execute_with(|| { + let data3: DataOf = vec![1, 2, 3].try_into().unwrap(); + let owner = RuntimeOrigin::signed(0); - assert_ok!(Registry::unregister(entity, 1)); - assert_eq!(Registry::registries(2, 1), None); - }); + assert_ok!(Registry::request_entity(owner.clone(), 0, data3.clone(), false)); + assert_eq!(Balances::reserved_balance(0), 9u64); + assert_eq!(Balances::free_balance(0), 91u64); + assert_ok!(Registry::request_entity_unregister(owner.clone(), 0, 0)); + assert_eq!(Balances::reserved_balance(0), 0u64); + assert_eq!(Balances::free_balance(0), 100u64); + assert_ok!(Registry::request_entity(owner.clone(), 0, data3.clone(), false)); + assert_eq!(Balances::reserved_balance(0), 9u64); + }) } #[test] -fn unregister_refunds_deposits() { +fn request_entity_unregister_prevent_unregister_not_registered() { + new_test_ext().execute_with(|| { + let owner = RuntimeOrigin::signed(0); + assert_noop!( + Registry::request_entity_unregister(owner.clone(), 0, 0), + Error::::InvalidEntity + ); + }) +} + +#[test] +fn request_entity_unregister_do_not_refund_anything() { new_test_ext().execute_with(|| { let data: DataOf = vec![1, 2, 3].try_into().unwrap(); - let registrar1 = RuntimeOrigin::signed(0); - let registrar2 = RuntimeOrigin::signed(1); - let owner = RuntimeOrigin::signed(2); + let registrar = RuntimeOrigin::signed(0); + let owner = RuntimeOrigin::signed(1); assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); - assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 1)); - - assert_ok!(Registry::request_entity(owner.clone(), data.clone(), false)); - assert_ok!(Registry::request_entity(owner.clone(), 0)); - assert_ok!(Registry::request_entity(owner.clone(), 1)); - assert_ok!(Registry::register_entity(registrar1, 0, 2, HashingOf::::hash_of(&data))); - assert_ok!(Registry::register_entity(registrar2, 1, 2, HashingOf::::hash_of(&data))); - assert_ok!(Registry::cancel_request(owner.clone())); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_ok!(Registry::register_entity( + registrar.clone(), + 0, + 0, + HashingOf::::hash_of(&data) + )); + assert_ok!(Registry::request_entity_unregister(owner.clone(), 0, 0)); - assert_eq!(Balances::reserved_balance(2), 18u64); - assert_ok!(Registry::unregister(owner.clone(), 0)); - assert_eq!(Balances::reserved_balance(2), 9u64); - assert_eq!(Balances::free_balance(2), 91u64); - assert_ok!(Registry::unregister(entity, 1)); - assert_eq!(Balances::reserved_balance(2), 0u64); - assert_eq!(Balances::free_balance(2), 100u64); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_eq!(Balances::reserved_balance(0), 0u64); + assert_eq!(Balances::free_balance(0), 100u64); + assert_ok!(Registry::request_entity_unregister(owner.clone(), 0, 0)); + assert_eq!(Balances::reserved_balance(0), 0u64); + assert_eq!(Balances::free_balance(0), 100u64); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_eq!(Balances::reserved_balance(0), 0u64); }) } #[test] -fn unregister_deposits_event() { +fn can_can_cancel_request_entity_unregister() { new_test_ext().execute_with(|| { let data: DataOf = vec![1, 2, 3].try_into().unwrap(); let registrar = RuntimeOrigin::signed(0); let owner = RuntimeOrigin::signed(1); assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_ok!(Registry::register_entity( + registrar.clone(), + 0, + 0, + HashingOf::::hash_of(&data) + )); + assert_ok!(Registry::request_entity_unregister(owner.clone(), 0, 0)); + assert_eq!(Registry::requests(0, 0), Some(None)); + assert_ok!(Registry::cancel_request(owner.clone(), 0, 0)); + assert_eq!(Registry::requests(0, 0), None); + }) +} - assert_ok!(Registry::request_entity(owner.clone(), data.clone(), false)); - assert_ok!(Registry::request_entity(owner.clone(), 0)); - assert_ok!(Registry::register_entity(registrar, 0, 1, HashingOf::::hash_of(&data))); - assert_ok!(Registry::unregister(owner.clone(), 0)); - System::assert_last_event( - Event::::EntityUnregistered { entity: 1, registry_index: 0 }.into(), +#[test] +fn can_be_overwritten_request_entity_unregister() { + new_test_ext().execute_with(|| { + let data: DataOf = vec![1, 2, 3].try_into().unwrap(); + let registrar = RuntimeOrigin::signed(0); + let owner = RuntimeOrigin::signed(1); + + assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_ok!(Registry::register_entity( + registrar.clone(), + 0, + 0, + HashingOf::::hash_of(&data) + )); + assert_ok!(Registry::request_entity_unregister(owner.clone(), 0, 0)); + assert_eq!(Registry::requests(0, 0), Some(None)); + assert_ok!(RegistryWithCollectives::request_entity(owner.clone(), 0, data.clone(), true)); + assert_eq!( + RegistryWithCollectives::requests(0, 0), + Some(Some(Request { deposit: 9u64, data, editable_by_registrar: true })) ); }) } #[test] -fn unregister_fails_on_not_registered_entity() { +fn request_entity_unregister_accept_change_registry() { new_test_ext().execute_with(|| { - let owner = RuntimeOrigin::signed(0); - assert_noop!(Registry::unregister(owner.clone(), 0), Error::::InvalidEntity); + let data: DataOf = vec![1, 2, 3].try_into().unwrap(); + let registrar = RuntimeOrigin::signed(0); + let owner = RuntimeOrigin::signed(1); + + assert_ok!(Registry::add_registry(RuntimeOrigin::root(), 0)); + assert_ok!(Registry::request_entity(owner.clone(), 0, data.clone(), false)); + assert_ok!(Registry::register_entity( + registrar.clone(), + 0, + 0, + HashingOf::::hash_of(&data) + )); + assert_ok!(Registry::request_entity_unregister(owner.clone(), 0, 0)); + assert_eq!( + Registry::registries(0, 0), + Some(Registration { deposit: 9u64, data, editable_by_registrar: false }) + ); + assert_ok!(Registry::unregister(registrar, 0, 0, true)); + assert_eq!(Registry::requests(0, 0), None); + assert_eq!(Registry::registries(0, 0), None); }) } -*/ diff --git a/frame/registry/src/weights.rs b/frame/registry/src/weights.rs index 8e8bb6add..7594c5ca1 100644 --- a/frame/registry/src/weights.rs +++ b/frame/registry/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_registry //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-23, STEPS: `20`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-11-16, STEPS: `20`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `kacper-HP-ProBook-445-G7`, CPU: `AMD Ryzen 7 4700U with Radeon Graphics` +//! HOSTNAME: `michallustyk-HP-ProBook-445-G7`, CPU: `AMD Ryzen 7 4700U with Radeon Graphics` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: @@ -37,6 +37,7 @@ pub trait WeightInfo { fn unregister(r: u32, ) -> Weight; fn register_entity(r: u32, s: u32, ) -> Weight; fn set_registered_entity(r: u32, s: u32, ) -> Weight; + fn request_entity_unregister() -> Weight; } /// Weights for pallet_registry using the Substrate node and recommended hardware. @@ -49,17 +50,17 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `235 + r * (32 ±0)` // Estimated: `1806` - // Minimum execution time: 18_876_000 picoseconds. - Weight::from_parts(19_483_330, 1806) - // Standard Error: 69_679 - .saturating_add(Weight::from_parts(384_797, 0).saturating_mul(r.into())) + // Minimum execution time: 18_625_000 picoseconds. + Weight::from_parts(19_253_901, 1806) + // Standard Error: 9_859 + .saturating_add(Weight::from_parts(114_870, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: CompanyRegistry NextEntityId (r:1 w:1) /// Proof: CompanyRegistry NextEntityId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: Balances Reserves (r:1 w:1) /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) /// Storage: System Account (r:1 w:1) @@ -72,18 +73,18 @@ impl WeightInfo for SubstrateWeight { fn request_entity(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `316` - // Estimated: `11716` - // Minimum execution time: 61_807_000 picoseconds. - Weight::from_parts(64_763_447, 11716) - // Standard Error: 115 - .saturating_add(Weight::from_parts(412, 0).saturating_mul(s.into())) + // Estimated: `11717` + // Minimum execution time: 60_375_000 picoseconds. + Weight::from_parts(62_809_913, 11717) + // Standard Error: 49 + .saturating_add(Weight::from_parts(580, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: CompanyRegistry EntityOwner (r:1 w:0) /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: Balances Reserves (r:1 w:1) /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) /// Storage: System Account (r:1 w:1) @@ -91,29 +92,29 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[2, 8194]`. fn request_registration(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `593 + s * (1 ±0)` - // Estimated: `11716` - // Minimum execution time: 84_531_000 picoseconds. - Weight::from_parts(88_087_918, 11716) - // Standard Error: 63 - .saturating_add(Weight::from_parts(1_008, 0).saturating_mul(s.into())) + // Measured: `594 + s * (1 ±0)` + // Estimated: `11717` + // Minimum execution time: 82_357_000 picoseconds. + Weight::from_parts(85_982_329, 11717) + // Standard Error: 62 + .saturating_add(Weight::from_parts(1_060, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: CompanyRegistry EntityOwner (r:1 w:0) /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: Balances Reserves (r:1 w:1) /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) /// Storage: System Account (r:1 w:1) /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn cancel_request() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `11716` - // Minimum execution time: 61_646_000 picoseconds. - Weight::from_parts(62_619_000, 11716) + // Measured: `694` + // Estimated: `11717` + // Minimum execution time: 59_584_000 picoseconds. + Weight::from_parts(60_044_000, 11717) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -132,15 +133,15 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `712 + r * (32 ±0)` // Estimated: `11716` - // Minimum execution time: 60_505_000 picoseconds. - Weight::from_parts(63_352_987, 11716) + // Minimum execution time: 59_503_000 picoseconds. + Weight::from_parts(61_339_873, 11716) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: CompanyRegistry Registrars (r:1 w:0) /// Proof: CompanyRegistry Registrars (max_values: Some(1), max_size: Some(321), added: 816, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: CompanyRegistry EntityOwner (r:1 w:0) /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) /// Storage: CompanyRegistry Registries (r:1 w:1) @@ -149,14 +150,14 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[2, 8194]`. fn register_entity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `451 + r * (32 ±0) + s * (1 ±0)` - // Estimated: `11716` - // Minimum execution time: 37_541_000 picoseconds. - Weight::from_parts(39_476_882, 11716) - // Standard Error: 19_642 - .saturating_add(Weight::from_parts(11_047, 0).saturating_mul(r.into())) - // Standard Error: 17 - .saturating_add(Weight::from_parts(1_753, 0).saturating_mul(s.into())) + // Measured: `452 + r * (32 ±0) + s * (1 ±0)` + // Estimated: `11717` + // Minimum execution time: 37_130_000 picoseconds. + Weight::from_parts(38_578_842, 11717) + // Standard Error: 20_037 + .saturating_add(Weight::from_parts(43_833, 0).saturating_mul(r.into())) + // Standard Error: 18 + .saturating_add(Weight::from_parts(1_837, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -166,16 +167,27 @@ impl WeightInfo for SubstrateWeight { /// Proof: CompanyRegistry Registries (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) /// The range of component `r` is `[1, 8]`. /// The range of component `s` is `[2, 8194]`. - fn set_registered_entity(r: u32, s: u32, ) -> Weight { + fn set_registered_entity(_r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `406 + r * (32 ±0) + s * (1 ±0)` // Estimated: `11716` - // Minimum execution time: 26_109_000 picoseconds. - Weight::from_parts(27_675_938, 11716) - // Standard Error: 13_707 - .saturating_add(Weight::from_parts(6_976, 0).saturating_mul(r.into())) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_074, 0).saturating_mul(s.into())) + // Minimum execution time: 25_669_000 picoseconds. + Weight::from_parts(28_812_042, 11716) + // Standard Error: 25 + .saturating_add(Weight::from_parts(1_092, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: CompanyRegistry EntityOwner (r:1 w:0) + /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: CompanyRegistry Requests (r:1 w:1) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) + fn request_entity_unregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `434` + // Estimated: `11717` + // Minimum execution time: 25_559_000 picoseconds. + Weight::from_parts(26_300_000, 11717) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -190,17 +202,17 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `235 + r * (32 ±0)` // Estimated: `1806` - // Minimum execution time: 18_876_000 picoseconds. - Weight::from_parts(19_483_330, 1806) - // Standard Error: 69_679 - .saturating_add(Weight::from_parts(384_797, 0).saturating_mul(r.into())) + // Minimum execution time: 18_625_000 picoseconds. + Weight::from_parts(19_253_901, 1806) + // Standard Error: 9_859 + .saturating_add(Weight::from_parts(114_870, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: CompanyRegistry NextEntityId (r:1 w:1) /// Proof: CompanyRegistry NextEntityId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: Balances Reserves (r:1 w:1) /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) /// Storage: System Account (r:1 w:1) @@ -213,18 +225,18 @@ impl WeightInfo for () { fn request_entity(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `316` - // Estimated: `11716` - // Minimum execution time: 61_807_000 picoseconds. - Weight::from_parts(64_763_447, 11716) - // Standard Error: 115 - .saturating_add(Weight::from_parts(412, 0).saturating_mul(s.into())) + // Estimated: `11717` + // Minimum execution time: 60_375_000 picoseconds. + Weight::from_parts(62_809_913, 11717) + // Standard Error: 49 + .saturating_add(Weight::from_parts(580, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } /// Storage: CompanyRegistry EntityOwner (r:1 w:0) /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: Balances Reserves (r:1 w:1) /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) /// Storage: System Account (r:1 w:1) @@ -232,29 +244,29 @@ impl WeightInfo for () { /// The range of component `s` is `[2, 8194]`. fn request_registration(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `593 + s * (1 ±0)` - // Estimated: `11716` - // Minimum execution time: 84_531_000 picoseconds. - Weight::from_parts(88_087_918, 11716) - // Standard Error: 63 - .saturating_add(Weight::from_parts(1_008, 0).saturating_mul(s.into())) + // Measured: `594 + s * (1 ±0)` + // Estimated: `11717` + // Minimum execution time: 82_357_000 picoseconds. + Weight::from_parts(85_982_329, 11717) + // Standard Error: 62 + .saturating_add(Weight::from_parts(1_060, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: CompanyRegistry EntityOwner (r:1 w:0) /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: Balances Reserves (r:1 w:1) /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) /// Storage: System Account (r:1 w:1) /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn cancel_request() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `11716` - // Minimum execution time: 61_646_000 picoseconds. - Weight::from_parts(62_619_000, 11716) + // Measured: `694` + // Estimated: `11717` + // Minimum execution time: 59_584_000 picoseconds. + Weight::from_parts(60_044_000, 11717) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -273,15 +285,15 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `712 + r * (32 ±0)` // Estimated: `11716` - // Minimum execution time: 60_505_000 picoseconds. - Weight::from_parts(63_352_987, 11716) + // Minimum execution time: 59_503_000 picoseconds. + Weight::from_parts(61_339_873, 11716) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: CompanyRegistry Registrars (r:1 w:0) /// Proof: CompanyRegistry Registrars (max_values: Some(1), max_size: Some(321), added: 816, mode: MaxEncodedLen) /// Storage: CompanyRegistry Requests (r:1 w:1) - /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) /// Storage: CompanyRegistry EntityOwner (r:1 w:0) /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) /// Storage: CompanyRegistry Registries (r:1 w:1) @@ -290,14 +302,14 @@ impl WeightInfo for () { /// The range of component `s` is `[2, 8194]`. fn register_entity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `451 + r * (32 ±0) + s * (1 ±0)` - // Estimated: `11716` - // Minimum execution time: 37_541_000 picoseconds. - Weight::from_parts(39_476_882, 11716) - // Standard Error: 19_642 - .saturating_add(Weight::from_parts(11_047, 0).saturating_mul(r.into())) - // Standard Error: 17 - .saturating_add(Weight::from_parts(1_753, 0).saturating_mul(s.into())) + // Measured: `452 + r * (32 ±0) + s * (1 ±0)` + // Estimated: `11717` + // Minimum execution time: 37_130_000 picoseconds. + Weight::from_parts(38_578_842, 11717) + // Standard Error: 20_037 + .saturating_add(Weight::from_parts(43_833, 0).saturating_mul(r.into())) + // Standard Error: 18 + .saturating_add(Weight::from_parts(1_837, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -307,16 +319,27 @@ impl WeightInfo for () { /// Proof: CompanyRegistry Registries (max_values: None, max_size: Some(8251), added: 10726, mode: MaxEncodedLen) /// The range of component `r` is `[1, 8]`. /// The range of component `s` is `[2, 8194]`. - fn set_registered_entity(r: u32, s: u32, ) -> Weight { + fn set_registered_entity(_r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `406 + r * (32 ±0) + s * (1 ±0)` // Estimated: `11716` - // Minimum execution time: 26_109_000 picoseconds. - Weight::from_parts(27_675_938, 11716) - // Standard Error: 13_707 - .saturating_add(Weight::from_parts(6_976, 0).saturating_mul(r.into())) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_074, 0).saturating_mul(s.into())) + // Minimum execution time: 25_669_000 picoseconds. + Weight::from_parts(28_812_042, 11716) + // Standard Error: 25 + .saturating_add(Weight::from_parts(1_092, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: CompanyRegistry EntityOwner (r:1 w:0) + /// Proof: CompanyRegistry EntityOwner (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: CompanyRegistry Requests (r:1 w:1) + /// Proof: CompanyRegistry Requests (max_values: None, max_size: Some(8252), added: 10727, mode: MaxEncodedLen) + fn request_entity_unregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `434` + // Estimated: `11717` + // Minimum execution time: 25_559_000 picoseconds. + Weight::from_parts(26_300_000, 11717) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) }