From 65b78a0443f965abb213d9657683a08aad88e6eb Mon Sep 17 00:00:00 2001 From: nol4lej Date: Sun, 8 Mar 2026 02:40:43 -0300 Subject: [PATCH 1/3] feat: add error for disallowing Substrate-native signature schemes in chain links --- frame/account-mapping/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frame/account-mapping/src/lib.rs b/frame/account-mapping/src/lib.rs index c600d02f..19e8f093 100644 --- a/frame/account-mapping/src/lib.rs +++ b/frame/account-mapping/src/lib.rs @@ -367,6 +367,9 @@ pub mod pallet { CommitmentMismatch, /// The ZK proof for a private link dispatch is invalid. InvalidProof, + /// Attempted to register a Substrate-native signature scheme as a chain link scheme. + /// Chain links are exclusively for external, non-Substrate ecosystems. + SubstrateNativeSchemeNotAllowed, } // ────────────────────────────────────────────── @@ -386,6 +389,14 @@ pub mod pallet { scheme: SignatureScheme, ) -> DispatchResult { ensure_root(origin)?; + // Chain links are exclusively for external, non-Substrate-native ecosystems. + // Substrate accounts are already self-proving via their AccountId32; linking + // them with a chain link is meaningless and would create a confusing identity + // model. See SignatureScheme::is_for_external_chain() for the invariant. + ensure!( + scheme.is_for_external_chain(), + Error::::SubstrateNativeSchemeNotAllowed + ); SupportedChains::::insert(chain_id, scheme.clone()); Self::deposit_event(Event::SupportedChainAdded { chain_id, scheme }); Ok(()) From 5e71db9ad7161e6e7527a2542a86dd408a0749c8 Mon Sep 17 00:00:00 2001 From: nol4lej Date: Sun, 8 Mar 2026 02:40:57 -0300 Subject: [PATCH 2/3] feat: enhance ChainId and SignatureScheme documentation for clarity on external signing schemes --- frame/account-mapping/src/types.rs | 41 +++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/frame/account-mapping/src/types.rs b/frame/account-mapping/src/types.rs index d0c68b3b..f59417aa 100644 --- a/frame/account-mapping/src/types.rs +++ b/frame/account-mapping/src/types.rs @@ -12,7 +12,24 @@ pub const MAX_WHITELIST_SIZE: u32 = 20; /// Maximum length for metadata strings (bio, avatar CID, etc.). pub const MAX_METADATA_LEN: u32 = 128; +/// Opaque chain identifier used as storage key for cross-chain links. +/// +/// The `u32` namespace is split into two ranges using the high bit (bit 31): +/// +/// | Bit 31 | Range | Standard | Examples | +/// |--------|-------|----------|---------| +/// | `0` | `0x0000_0000 – 0x7FFF_FFFF` | EIP-155 (EVM chain IDs) | Ethereum = 1, Polygon = 137 | +/// | `1` | `0x8000_0000 – 0xFFFF_FFFF` | SLIP-0044 (HD wallet coin types) | Bitcoin = `0x8000_0000`, Solana = `0x8000_01F5` | +/// +/// Use `SLIP0044_NAMESPACE | ` to build SLIP-0044 identifiers. +/// Canonical constants for well-known chains are defined in `protocol-core`. +/// Governance MUST follow this convention when registering chains via `add_supported_chain`. pub type ChainId = u32; + +/// Bitmask to set bit 31, placing a coin type in the SLIP-0044 namespace. +/// Example: `SLIP0044_NAMESPACE | 0` = Bitcoin, `SLIP0044_NAMESPACE | 501` = Solana. +pub const SLIP0044_NAMESPACE: u32 = 0x8000_0000; + pub type ExternalAddr = BoundedVec>; #[derive( @@ -27,13 +44,35 @@ pub type ExternalAddr = BoundedVec>; scale_codec::DecodeWithMemTracking )] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +/// Signature verification scheme used to prove ownership of a cross-chain wallet. +/// +/// # Design invariant +/// +/// Every variant MUST represent an **external, non-Substrate-native** signing scheme. +/// Substrate-native schemes (Sr25519, Ed25519-Substrate, etc.) MUST NOT be added here +/// because an `AccountId32` is already self-proving in the Substrate key model — no +/// cross-chain proof of ownership is required or meaningful. `add_supported_chain` +/// enforces this invariant at the governance call level via `is_for_external_chain()`. pub enum SignatureScheme { /// Ethereum-style EIP-191 (ECDSA over Keccak256). Eip191, - /// Solana-style Ed25519 (raw signature of the message). + /// Solana-style raw Ed25519 (not the Substrate Ed25519 wrapper). Ed25519, } +impl SignatureScheme { + /// Returns `true` if this scheme belongs to a non-Substrate-native ecosystem. + /// + /// All current variants are external. Any future variant for a Substrate-native + /// scheme MUST return `false` here so that `add_supported_chain` rejects it. + pub fn is_for_external_chain(&self) -> bool { + match self { + SignatureScheme::Eip191 => true, + SignatureScheme::Ed25519 => true, + } + } +} + #[derive( Encode, Decode, From 8f8a3b5868c0a16f3c7f42c98e8cea37bd9da502 Mon Sep 17 00:00:00 2001 From: nol4lej Date: Sun, 8 Mar 2026 02:41:27 -0300 Subject: [PATCH 3/3] feat: update version to 0.2.0 in Cargo.toml for pallet-account-mapping --- frame/account-mapping/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/account-mapping/Cargo.toml b/frame/account-mapping/Cargo.toml index 73c81834..819b48bd 100644 --- a/frame/account-mapping/Cargo.toml +++ b/frame/account-mapping/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-account-mapping" -version = "0.1.0" +version = "0.2.0" license = "Apache-2.0" description = "Stateful mapping between Substrate AccountId32 and EVM H160 addresses, with alias registration and multichain identity support." authors = { workspace = true }