pallet_chain_manager/
crypto.rs

1// SPDX-License-Identifier: MPL-2.0
2//
3// Part of Auguth Labs open-source softwares.
4// Built for the Substrate framework.
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at https://mozilla.org/MPL/2.0/.
9//
10// Copyright (c) 2026 Auguth Labs (OPC) Pvt Ltd, India
11
12// ===============================================================================
13// `````````````````````````````` APPLICATION CRYPTO `````````````````````````````
14// ===============================================================================
15
16//! Affidavit crypto and payload types for offchain operations used for validation,
17//! affidavit declaration, and author election
18//!
19//! Utilizes
20//! - [`AppCrypto`],
21//! - [`SignedPayload`], and
22//! - [`SigningTypes`]
23
24// ===============================================================================
25// ``````````````````````````````````` IMPORTS ```````````````````````````````````
26// ===============================================================================
27
28// --- Core / Std ---
29use core::fmt::Debug;
30
31// --- Scale-codec crates ---
32use codec::{Decode, DecodeWithMemTracking, Encode};
33use scale_info::TypeInfo;
34
35// --- FRAME System ---
36use frame_system::offchain::{AppCrypto, SignedPayload, SigningTypes};
37
38// --- Substrate primitives ---
39use sp_application_crypto::app_crypto;
40use sp_core::offchain::KeyTypeId;
41use sp_runtime::{MultiSignature, MultiSigner, RuntimeDebug};
42
43// ===============================================================================
44// ``````````````````````````````` AFFIDAVIT CRYPTO ``````````````````````````````
45// ===============================================================================
46
47// Re-export supported affidavit crypto implementations.
48//
49// The runtime or pallet configuration may choose either implementation
50// depending on desired cryptographic preferences.
51
52pub use ed25519::AffidavitCryptoEd25519;
53
54pub use sr25519::AffidavitCryptoSr25519;
55
56/// Unique application key type identifier for affidavit-related
57/// cryptography ([`crate::Config::AffidavitCrypto`]).
58///
59/// This `KeyTypeId` namespaces affidavit keys in the node's local keystore,
60/// allowing the pallet to:
61/// - Generate and rotate affidavit keys independently (see `routines`)
62/// - Recover keys via OCWs when required
63/// - Avoid collisions with other pallets or consensus keys
64///
65/// The identifier is intentionally short and fixed.
66pub const AFDT_KEY_TYPE: KeyTypeId = KeyTypeId(*b"afdt");
67
68/// sr25519-based affidavit cryptography implementation.
69pub mod sr25519 {
70    use super::*;
71
72    /// Internal application-crypto binding for sr25519 affidavit keys.
73    ///
74    /// This binds the `AFDT_KEY_TYPE` namespace to sr25519 key material
75    /// in the node keystore.
76    mod app_sr25519 {
77        use super::*;
78        use sp_application_crypto::sr25519;
79        app_crypto!(sr25519, AFDT_KEY_TYPE);
80    }
81
82    // Affidavit key pair type (sr25519).
83    //
84    // Used by offchain workers for signing affidavit- and
85    // election-related payloads.
86    sp_application_crypto::with_pair! {
87        pub type AffidavitPair = app_sr25519::Pair;
88    }
89
90    /// Affidavit signature type (sr25519).
91    pub type AffidavitSignature = app_sr25519::Signature;
92
93    /// Affidavit public key type (sr25519).
94    pub type AffidavitPublic = app_sr25519::Public;
95
96    /// Runtime crypto adapter for sr25519 affidavit keys.
97    ///
98    /// This implementation allows affidavit signatures to be verified
99    /// using `MultiSignature` while retaining a concrete sr25519
100    /// application key internally.
101    pub struct AffidavitCryptoSr25519;
102
103    impl AppCrypto<MultiSigner, MultiSignature> for AffidavitCryptoSr25519 {
104        type RuntimeAppPublic = AffidavitPublic;
105        type GenericSignature = sp_application_crypto::sr25519::Signature;
106        type GenericPublic = sp_application_crypto::sr25519::Public;
107    }
108}
109
110/// ed25519-based affidavit cryptography implementation.
111pub mod ed25519 {
112    use super::*;
113
114    /// Internal application-crypto binding for ed25519 affidavit keys.
115    ///
116    /// This binds the `AFDT_KEY_TYPE` namespace to ed25519 key material
117    /// in the node keystore.
118    mod app_ed25519 {
119        use super::*;
120        use sp_application_crypto::ed25519;
121        app_crypto!(ed25519, AFDT_KEY_TYPE);
122    }
123
124    // Affidavit key pair type (ed25519).
125    //
126    // Used by offchain workers for signing affidavit- and
127    // election-related payloads.
128    sp_application_crypto::with_pair! {
129        pub type AffidavitPair = app_ed25519::Pair;
130    }
131
132    /// Affidavit signature type (ed25519).
133    pub type AffidavitSignature = app_ed25519::Signature;
134
135    /// Affidavit public key type (ed25519).
136    pub type AffidavitPublic = app_ed25519::Public;
137
138    /// Runtime crypto adapter for ed25519 affidavit keys.
139    ///
140    /// Enables verification of affidavit signatures through
141    /// `MultiSignature` while internally using ed25519 keys.
142    pub struct AffidavitCryptoEd25519;
143
144    impl AppCrypto<MultiSigner, MultiSignature> for AffidavitCryptoEd25519 {
145        type RuntimeAppPublic = AffidavitPublic;
146        type GenericSignature = sp_application_crypto::ed25519::Signature;
147        type GenericPublic = sp_application_crypto::ed25519::Public;
148    }
149}
150
151// ===============================================================================
152// `````````````````````````````` UNSIGNED PAYLOADS ``````````````````````````````
153// ===============================================================================
154
155/// Unsigned payload for [`crate::Pallet::declare`] extrinsic.
156///
157/// - `public` is the **currently active affidavit key**, used to authorize
158///   the affidavit declaration.
159/// - `rotate` is the **next affidavit key** that will be registered and
160///   rotated in as the active key for the upcoming session.
161///
162/// The payload is signed offchain using the active affidavit key and
163/// verified on-chain via `ValidateUnsigned`.
164#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, DecodeWithMemTracking)]
165pub struct AffidavitPayload<Public, AccountId>
166where
167    Public: Debug + TypeInfo,
168    AccountId: Debug + TypeInfo,
169{
170    /// Active affidavit public key used for authorization.
171    pub public: Public,
172
173    /// Next affidavit key to be rotated in for the upcoming session.
174    pub rotate: AccountId,
175}
176
177impl<T: SigningTypes<Public = Public>, Public, AccountId> SignedPayload<T>
178    for AffidavitPayload<Public, AccountId>
179where
180    Public: Encode + Debug + TypeInfo + Clone,
181    AccountId: Encode + Debug + TypeInfo + Clone,
182{
183    fn public(&self) -> <T as SigningTypes>::Public {
184        self.public.clone()
185    }
186}
187
188/// Unsigned payload for [`crate::Pallet::validate`] extrinsic.
189///
190/// The `public` field represents the **active affidavit key** whose
191/// validity will be verified later during affidavit declaration.
192///
193/// This payload is signed offchain and authenticated on-chain
194/// via `ValidateUnsigned`.
195#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, DecodeWithMemTracking)]
196pub struct ValidatePayload<Public>
197where
198    Public: Debug + TypeInfo,
199{
200    /// Active affidavit public key to be verified.
201    pub public: Public,
202}
203
204impl<T: SigningTypes<Public = Public>, Public> SignedPayload<T> for ValidatePayload<Public>
205where
206    Public: Encode + Debug + TypeInfo + Clone,
207{
208    fn public(&self) -> <T as SigningTypes>::Public {
209        self.public.clone()
210    }
211}
212
213/// Unsigned payload for [`crate::Pallet::elect`] extrinsic.
214///
215/// The `public` field represents the **currently active affidavit key**,
216/// which was very recently rotated during the latest affidavit declaration.
217///
218/// Elections require the affidavit key that was registered for the
219/// upcoming session's affidavit window. This ensures that only authors
220/// who successfully completed affidavit declaration and key rotation
221/// are eligible to run the election.
222#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, DecodeWithMemTracking)]
223pub struct ElectionPayload<Public>
224where
225    Public: Debug + TypeInfo,
226{
227    /// Active affidavit public key authorizing election execution.
228    pub public: Public,
229}
230
231impl<T: SigningTypes<Public = Public>, Public> SignedPayload<T> for ElectionPayload<Public>
232where
233    Public: Encode + Debug + TypeInfo + Clone,
234{
235    fn public(&self) -> <T as SigningTypes>::Public {
236        self.public.clone()
237    }
238}