Skip to content

Commit 5d79e22

Browse files
fix(namespaces): prevent de-registering root (#117)
This patch prevents a registered agent from de-registering the agent entry (`agent.<name>`) through the `delete_namespace` extrinsic.
1 parent e75b350 commit 5d79e22

File tree

15 files changed

+396
-36
lines changed

15 files changed

+396
-36
lines changed

flake.lock

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node/src/cli/eth.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(clippy::result_large_err)]
2+
13
use std::{
24
collections::BTreeMap,
35
path::PathBuf,

node/src/command/benchmarking.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,6 @@ pub fn inherent_benchmark_data() -> Result<InherentData> {
171171
let timestamp = sp_timestamp::InherentDataProvider::new(d.into());
172172

173173
futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data))
174-
.map_err(|e| format!("creating inherent data: {:?}", e))?;
174+
.map_err(|e| format!("creating inherent data: {e:?}"))?;
175175
Ok(inherent_data)
176176
}

node/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(clippy::result_large_err)]
12
//! The Torus node implementation.
23
34
mod chain_spec;

node/src/service.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1515
// See the License for the specific language governing permissions and
1616
// limitations under the License.
17+
#![allow(clippy::result_large_err)]
1718

1819
use std::{pin::Pin, sync::Arc, time::Duration};
1920

pallets/emission0/src/distribute.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,11 @@ impl<T: Config> ConsensusMemberInput<T> {
204204

205205
let validator_permit = total_stake >= min_validator_stake && !weights.is_empty();
206206

207-
let weights = validator_permit
208-
.then(|| Self::prepare_weights(weights, &agent_id))
209-
.unwrap_or_default();
207+
let weights = if validator_permit {
208+
Self::prepare_weights(weights, &agent_id)
209+
} else {
210+
Default::default()
211+
};
210212

211213
ConsensusMemberInput {
212214
registered: <T::Torus>::is_agent_registered(&agent_id)

pallets/torus0/api/src/lib.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ impl NamespacePath {
8282
NamespacePath(b"agent".to_vec().try_into().unwrap())
8383
}
8484

85+
/// Create a new root agent namespace path from the agent name
86+
pub fn new_agent_root(agent_name: &[u8]) -> Result<Self, &'static str> {
87+
let namespace_path: Vec<_> = [NAMESPACE_AGENT_PREFIX, agent_name].concat();
88+
Self::new_agent(&namespace_path)
89+
}
90+
8591
/// Create a new namespace path from bytes with validation
8692
pub fn new_agent(bytes: &[u8]) -> Result<Self, &'static str> {
8793
if bytes.is_empty() {
@@ -192,6 +198,19 @@ impl NamespacePath {
192198

193199
parents
194200
}
201+
202+
/// Wether the namespace is an agent root path: "agent.<name>".
203+
pub fn is_agent_root(&self) -> bool {
204+
if self.depth() != 2 {
205+
return false;
206+
}
207+
208+
if let Some(root) = self.segments().next() {
209+
root == b"agent"
210+
} else {
211+
false
212+
}
213+
}
195214
}
196215

197216
impl Debug for NamespacePath {
@@ -293,4 +312,47 @@ mod tests {
293312
assert_eq!(parents[1].as_bytes(), b"agent.alice");
294313
assert_eq!(parents[2].as_bytes(), b"agent");
295314
}
315+
316+
#[test]
317+
fn test_is_agent_root() {
318+
let agent_alice = NamespacePath::new_agent(b"agent.alice").unwrap();
319+
assert!(agent_alice.is_agent_root());
320+
321+
let agent_bob = NamespacePath::new_agent(b"agent.bob").unwrap();
322+
assert!(agent_bob.is_agent_root());
323+
324+
let deeper = NamespacePath::new_agent(b"agent.alice.memory").unwrap();
325+
assert!(!deeper.is_agent_root());
326+
327+
let just_agent = NamespacePath::agent_root();
328+
assert!(!just_agent.is_agent_root());
329+
}
330+
331+
#[test]
332+
fn test_new_agent_root() {
333+
let alice_root = NamespacePath::new_agent_root(b"alice").unwrap();
334+
assert_eq!(alice_root.as_bytes(), b"agent.alice");
335+
assert!(alice_root.is_agent_root());
336+
337+
let bob_root = NamespacePath::new_agent_root(b"bob").unwrap();
338+
assert_eq!(bob_root.as_bytes(), b"agent.bob");
339+
assert!(bob_root.is_agent_root());
340+
341+
assert!(NamespacePath::new_agent_root(b"alice123").is_ok());
342+
assert!(NamespacePath::new_agent_root(b"alice-test").is_ok());
343+
assert!(NamespacePath::new_agent_root(b"alice_test").is_ok());
344+
345+
assert!(
346+
NamespacePath::new_agent_root(b"Alice").is_err(),
347+
"uppercase should fail"
348+
);
349+
assert!(
350+
NamespacePath::new_agent_root(b"alice!").is_err(),
351+
"special chars should fail"
352+
);
353+
assert!(
354+
NamespacePath::new_agent_root(b"").is_err(),
355+
"empty name should fail"
356+
);
357+
}
296358
}

pallets/torus0/src/agent.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use codec::{Decode, Encode, MaxEncodedLen};
22
use pallet_emission0_api::Emission0Api;
33
use pallet_governance_api::GovernanceApi;
4-
use pallet_torus0_api::{NamespacePath, NAMESPACE_AGENT_PREFIX};
4+
use pallet_torus0_api::NamespacePath;
55
use polkadot_sdk::{
66
frame_election_provider_support::Get,
77
frame_support::{
@@ -78,8 +78,7 @@ pub fn register<T: crate::Config>(
7878
crate::Error::<T>::TooManyAgentRegistrationsThisInterval
7979
);
8080

81-
let namespace_path: Vec<_> = [NAMESPACE_AGENT_PREFIX, &name].concat();
82-
let namespace_path = NamespacePath::new_agent(&namespace_path).map_err(|err| {
81+
let namespace_path = NamespacePath::new_agent_root(&name).map_err(|err| {
8382
warn!("{agent_key:?} tried using invalid name: {err:?}");
8483
crate::Error::<T>::InvalidNamespacePath
8584
})?;
@@ -140,8 +139,7 @@ pub fn unregister<T: crate::Config>(agent_key: AccountIdOf<T>) -> DispatchResult
140139

141140
let agent = crate::Agents::<T>::get(&agent_key).ok_or(crate::Error::<T>::AgentDoesNotExist)?;
142141

143-
let namespace_path: Vec<_> = [NAMESPACE_AGENT_PREFIX, &agent.name].concat();
144-
let namespace_path = NamespacePath::new_agent(&namespace_path)
142+
let namespace_path = NamespacePath::new_agent_root(&agent.name)
145143
.map_err(|_| crate::Error::<T>::InvalidNamespacePath)?;
146144
crate::namespace::delete_namespace::<T>(
147145
crate::namespace::NamespaceOwnership::Account(agent_key.clone()),

pallets/torus0/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,8 @@ pub mod pallet {
390390
NamespacePath::new_agent(&path).map_err(|_| Error::<T>::InvalidNamespacePath)?;
391391

392392
ensure!(
393-
!T::Permission0::is_delegating_namespace(&owner, &namespace_path),
394-
Error::<T>::NamespaceBeingDelegated
393+
!namespace_path.is_agent_root(),
394+
Error::<T>::InvalidNamespacePath
395395
);
396396

397397
namespace::delete_namespace::<T>(NamespaceOwnership::Account(owner), namespace_path)

pallets/torus0/src/migrations.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub mod v4 {
6464
}
6565

6666
pub mod v5 {
67-
use pallet_torus0_api::{NamespacePath, NAMESPACE_AGENT_PREFIX};
67+
use pallet_torus0_api::NamespacePath;
6868
use polkadot_sdk::{
6969
frame_support::{migrations::VersionedMigration, traits::UncheckedOnRuntimeUpgrade},
7070
sp_tracing::{error, info},
@@ -138,15 +138,10 @@ pub mod v5 {
138138
continue;
139139
};
140140

141-
let path: polkadot_sdk::sp_std::vec::Vec<_> =
142-
[NAMESPACE_AGENT_PREFIX, agent_name.as_bytes()].concat();
143-
let path = match NamespacePath::new_agent(&path) {
141+
let path = match NamespacePath::new_agent_root(agent_name.as_bytes()) {
144142
Ok(path) => path,
145143
Err(err) => {
146-
error!(
147-
"cannot create path for agent {agent_name:?} ({:?}): {err:?}",
148-
core::str::from_utf8(&path)
149-
);
144+
error!("cannot create path for agent {agent_name:?}: {err:?}");
150145
continue;
151146
}
152147
};

0 commit comments

Comments
 (0)