From 9de9e8d30b47266efb4d484ae0dc441fdd42886f Mon Sep 17 00:00:00 2001
From: tuxmain <tuxmain@zettascript.org>
Date: Sat, 28 May 2022 17:48:44 +0200
Subject: [PATCH] fix(duniter-primitives): stricter idty name validation

---
 Cargo.lock                    | 12 +++++++++
 primitives/duniter/Cargo.toml | 51 +++++++++++++++++++++++++++++++++++
 primitives/duniter/src/lib.rs | 48 +++++++++++++++++++++++++++++++++
 runtime/common/Cargo.toml     |  2 ++
 runtime/common/src/lib.rs     |  2 +-
 5 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 primitives/duniter/Cargo.toml
 create mode 100644 primitives/duniter/src/lib.rs

diff --git a/Cargo.lock b/Cargo.lock
index 01a4067c6..02bf066e0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -827,6 +827,7 @@ dependencies = [
 name = "common-runtime"
 version = "0.8.0-dev"
 dependencies = [
+ "duniter-primitives",
  "frame-support",
  "frame-system",
  "log",
@@ -1347,6 +1348,17 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "duniter-primitives"
+version = "3.0.0"
+dependencies = [
+ "frame-support",
+ "parity-scale-codec",
+ "scale-info",
+ "sp-runtime",
+ "sp-std",
+]
+
 [[package]]
 name = "dyn-clonable"
 version = "0.9.0"
diff --git a/primitives/duniter/Cargo.toml b/primitives/duniter/Cargo.toml
new file mode 100644
index 000000000..18ccc04f9
--- /dev/null
+++ b/primitives/duniter/Cargo.toml
@@ -0,0 +1,51 @@
+[package]
+authors = ['librelois <c@elo.tf>']
+description = 'primitives for duniter runtime.'
+edition = '2018'
+homepage = 'https://substrate.dev'
+license = 'AGPL-3.0'
+name = 'duniter-primitives'
+readme = 'README.md'
+repository = 'https://git.duniter.org/nodes/rust/duniter-v2s'
+version = '3.0.0'
+
+[features]
+default = ['std']
+std = [
+    'codec/std',
+    'frame-support/std',
+	'sp-runtime/std',
+	'sp-std/std',
+]
+try-runtime = ['frame-support/try-runtime']
+
+[dependencies]
+
+# substrate
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.3.1'
+
+[dependencies.frame-support]
+default-features = false
+git = 'https://github.com/librelois/substrate.git'
+branch = 'duniter-monthly-2022-02'
+
+[dependencies.sp-runtime]
+default-features = false
+git = 'https://github.com/librelois/substrate.git'
+branch = 'duniter-monthly-2022-02'
+
+[dependencies.sp-std]
+default-features = false
+git = 'https://github.com/librelois/substrate.git'
+branch = 'duniter-monthly-2022-02'
+
+### DOC ###
+
+[package.metadata.docs.rs]
+targets = ['x86_64-unknown-linux-gnu']
diff --git a/primitives/duniter/src/lib.rs b/primitives/duniter/src/lib.rs
new file mode 100644
index 000000000..916c97a4d
--- /dev/null
+++ b/primitives/duniter/src/lib.rs
@@ -0,0 +1,48 @@
+// Copyright 2021 Axiom-Team
+//
+// This file is part of Substrate-Libre-Currency.
+//
+// Substrate-Libre-Currency is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, version 3 of the License.
+//
+// Substrate-Libre-Currency is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+/// Bound length; forbid trailing or double spaces; accept only ascii alphanumeric or punctuation or space
+pub fn validate_idty_name(idty_name: &[u8]) -> bool {
+    idty_name.len() >= 3
+        && idty_name.len() <= 64
+        && idty_name[0] != 32
+        && idty_name[idty_name.len() - 1] != 32
+        && idty_name
+            .iter()
+            .all(|c| c.is_ascii_alphanumeric() || c.is_ascii_punctuation() || *c == 32)
+        && idty_name
+            .iter()
+            .zip(idty_name.iter().skip(1))
+            .all(|(c1, c2)| *c1 != 32 || *c2 != 32)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_validate_idty_name() {
+        assert!(validate_idty_name(b"B0b"));
+        assert!(validate_idty_name(b"lorem ipsum dolor-sit_amet."));
+        assert!(!validate_idty_name(b" space"));
+        assert!(!validate_idty_name(b"space "));
+        assert!(!validate_idty_name(b"double  space"));
+        assert!(!validate_idty_name("non-ascii🌵".as_bytes()));
+        assert!(!validate_idty_name("ÄŸune".as_bytes()));
+    }
+}
diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml
index 0cceb7f4a..1e9fc156a 100644
--- a/runtime/common/Cargo.toml
+++ b/runtime/common/Cargo.toml
@@ -20,6 +20,7 @@ runtime-benchmarks = [
 ]
 std = [
     'codec/std',
+    'duniter-primitives/std',
     'frame-support/std',
     'frame-system/std',
 	'log/std',
@@ -43,6 +44,7 @@ std = [
 ]
 
 [dependencies]
+duniter-primitives = { path = '../../primitives/duniter', default-features = false }
 pallet-authority-members = { path = '../../pallets/authority-members', default-features = false }
 pallet-certification = { path = '../../pallets/certification', default-features = false }
 pallet-duniter-account = { path = '../../pallets/duniter-account', default-features = false }
diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs
index d06efc221..3e4d998de 100644
--- a/runtime/common/src/lib.rs
+++ b/runtime/common/src/lib.rs
@@ -84,6 +84,6 @@ impl<Runtime: pallet_babe::Config> frame_support::pallet_prelude::Get<u64>
 pub struct IdtyNameValidatorImpl;
 impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorImpl {
     fn validate(idty_name: &pallet_identity::IdtyName) -> bool {
-        idty_name.0.len() >= 3 && idty_name.0.len() <= 64
+        duniter_primitives::validate_idty_name(&idty_name.0)
     }
 }
-- 
GitLab