1use polkadot_sdk::frame_support::{
2 migrations::VersionedMigration, traits::UncheckedOnRuntimeUpgrade, weights::Weight,
3};
4
5use crate::{Config, Pallet};
6
7pub mod v4 {
8 use super::*;
9 use crate::{Agent, Agents};
10 use scale_info::prelude::vec::Vec;
11
12 pub mod storage {
13 use codec::{Decode, Encode, MaxEncodedLen};
14 use polkadot_sdk::frame_support::{storage_alias, DebugNoBound, Identity};
15 use polkadot_sdk::polkadot_sdk_frame::prelude::BlockNumberFor;
16 use polkadot_sdk::sp_runtime::{BoundedVec, Percent};
17 use scale_info::TypeInfo;
18
19 use crate::AccountIdOf;
20
21 #[derive(DebugNoBound, Encode, Decode, MaxEncodedLen, TypeInfo)]
22 #[scale_info(skip_type_params(T))]
23 pub struct Agent<T: crate::Config> {
24 pub key: AccountIdOf<T>,
25 pub name: BoundedVec<u8, T::MaxAgentNameLengthConstraint>,
26 pub url: BoundedVec<u8, T::MaxAgentUrlLengthConstraint>,
27 pub metadata: BoundedVec<u8, T::MaxAgentMetadataLengthConstraint>,
28 pub weight_penalty_factor: Percent,
29 pub registration_block: BlockNumberFor<T>,
30 pub fees: crate::fee::ValidatorFee<T>,
31 }
32
33 #[storage_alias]
34 pub type Agents<T: crate::Config> =
35 StorageMap<crate::Pallet<T>, Identity, AccountIdOf<T>, Agent<T>>;
36 }
37
38 pub type Migration<T, W> = VersionedMigration<3, 4, MigrateToV4<T>, Pallet<T>, W>;
39 pub struct MigrateToV4<T>(core::marker::PhantomData<T>);
40 impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV4<T> {
41 fn on_runtime_upgrade() -> Weight {
42 let old_agents = storage::Agents::<T>::iter().collect::<Vec<_>>();
43 let _ = storage::Agents::<T>::clear(u32::MAX, None);
44
45 for (id, old_agent) in old_agents {
46 Agents::<T>::insert(
47 id,
48 Agent {
49 key: old_agent.key,
50 name: old_agent.name,
51 url: old_agent.url,
52 metadata: old_agent.metadata,
53 registration_block: old_agent.registration_block,
54 weight_penalty_factor: old_agent.weight_penalty_factor,
55 fees: old_agent.fees,
56 last_update_block: old_agent.registration_block,
57 },
58 )
59 }
60
61 Weight::zero()
62 }
63 }
64}
65
66pub mod v5 {
67 use pallet_torus0_api::NamespacePath;
68 use polkadot_sdk::{
69 frame_support::{migrations::VersionedMigration, traits::UncheckedOnRuntimeUpgrade},
70 sp_tracing::{error, info},
71 sp_weights::Weight,
72 };
73
74 use crate::{
75 burn::BurnConfiguration, namespace::NamespaceOwnership, Agents, BurnConfig, Config, Pallet,
76 };
77
78 pub mod storage {
79 use polkadot_sdk::frame_support::{pallet_prelude::*, storage_alias};
80
81 use crate::AccountIdOf;
82
83 #[storage_alias]
84 pub type Namespaces<T: crate::Config> = StorageDoubleMap<
85 crate::Pallet<T>,
86 Blake2_128Concat,
87 AccountIdOf<T>,
88 Blake2_128Concat,
89 pallet_torus0_api::NamespacePath,
90 crate::namespace::NamespaceMetadata<T>,
91 >;
92
93 #[storage_alias]
94 pub type NamespaceCount<T: crate::Config> =
95 StorageMap<crate::Pallet<T>, Blake2_128Concat, AccountIdOf<T>, u32, ValueQuery>;
96 }
97
98 pub type Migration<T, W> = VersionedMigration<4, 5, MigrateToV5<T>, Pallet<T>, W>;
99 pub struct MigrateToV5<T>(core::marker::PhantomData<T>);
100
101 impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV5<T> {
102 fn on_runtime_upgrade() -> Weight {
103 BurnConfig::<T>::set(BurnConfiguration {
104 min_burn: 15000000000000000000, max_burn: 1000000000000000000000, max_registrations_per_interval: 16,
107 ..BurnConfig::<T>::get()
108 });
109
110 let _ = storage::Namespaces::<T>::clear(u32::MAX, None);
111 let _ = storage::NamespaceCount::<T>::clear(u32::MAX, None);
112
113 let path = NamespacePath::agent_root();
114 #[allow(deprecated)]
115 if let Err(err) =
116 crate::namespace::create_namespace0::<T>(NamespaceOwnership::System, path, false)
117 {
118 error!("failed to create root agent namespace: {err:?}");
119 return Weight::default();
120 }
121
122 info!("created root agent namespace");
123
124 for (id, agent) in Agents::<T>::iter() {
125 let old_name = agent.name.clone();
126 let Ok(agent_name) = core::str::from_utf8(&agent.name) else {
127 error!("agent name is not utf-8: {:?}", agent.name);
128 continue;
129 };
130
131 let agent_name = agent_name.trim().to_ascii_lowercase().replace(' ', "-");
132
133 let Ok(bounded_name) = agent_name.as_bytes().to_vec().try_into() else {
134 error!("cannot lower case agent {agent_name:?}");
135 continue;
136 };
137
138 let path = match NamespacePath::new_agent_root(agent_name.as_bytes()) {
139 Ok(path) => path,
140 Err(err) => {
141 error!("cannot create path for agent {agent_name:?}: {err:?}");
142 continue;
143 }
144 };
145
146 Agents::<T>::mutate_extant(id.clone(), |agent| {
147 agent.name = bounded_name;
148 });
149
150 #[allow(deprecated)]
151 if let Err(err) = crate::namespace::create_namespace0::<T>(
152 NamespaceOwnership::Account(id.clone()),
153 path.clone(),
154 false,
155 ) {
156 error!("cannot create namespace for agent {agent_name:?}: {err:?}");
157
158 Agents::<T>::mutate_extant(id.clone(), |agent| {
159 agent.name = old_name;
160 });
161 } else {
162 info!("created namespace entry for agent {agent_name:?}: {path:?}");
163 }
164 }
165
166 Weight::default()
167 }
168 }
169}