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}