Skip to main content

pallet_auto_id/
lib.rs

1// Copyright (C) 2023 Subspace Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// 	http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Pallet AutoID
17
18#![cfg_attr(not(feature = "std"), no_std)]
19// TODO: Remove once FRAME macros stop generating `.clone()` calls on `Copy` types with user spans
20#![expect(clippy::clone_on_copy, reason = "Comes from Substrate")]
21
22#[cfg(feature = "runtime-benchmarks")]
23mod benchmarking;
24#[cfg(test)]
25mod tests;
26pub mod weights;
27
28extern crate alloc;
29
30#[cfg(not(feature = "std"))]
31use alloc::collections::BTreeSet;
32#[cfg(not(feature = "std"))]
33use alloc::vec::Vec;
34use frame_support::dispatch::{DispatchResult, DispatchResultWithPostInfo};
35use frame_support::ensure;
36use frame_support::traits::Time;
37use frame_support::weights::Weight;
38pub use pallet::*;
39use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode};
40use scale_info::TypeInfo;
41use sp_auto_id::auto_id_runtime_interface::{decode_tbs_certificate, verify_signature};
42use sp_auto_id::{DerVec, SignatureVerificationRequest, Validity};
43use sp_core::{H256, U256, blake2_256};
44#[cfg(feature = "std")]
45use std::collections::BTreeSet;
46use subspace_runtime_primitives::Moment;
47pub use weights::WeightInfo;
48
49/// Unique AutoId identifier.
50pub type Identifier = H256;
51
52/// Serial issued by the subject.
53pub type Serial = U256;
54
55/// X509 certificate.
56#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
57pub struct X509Certificate {
58    /// Issuer identifier of this certificate.
59    pub issuer_id: Option<Identifier>,
60    /// Serial number for this certificate
61    pub serial: U256,
62    /// Subject common name of the certificate.
63    pub subject_common_name: Vec<u8>,
64    /// Der encoded certificate's subject's public key info.
65    pub subject_public_key_info: DerVec,
66    /// Validity of the certificate
67    pub validity: Validity,
68    /// Der encoded full X509 certificate.
69    pub raw: DerVec,
70    /// A list of all certificate serials issues by the subject.
71    /// Serial of root certificate is included as well.
72    pub issued_serials: BTreeSet<Serial>,
73    /// Certificate action nonce.
74    pub nonce: U256,
75}
76
77/// Certificate associated with AutoId.
78#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
79pub enum Certificate {
80    X509(X509Certificate),
81}
82
83impl Certificate {
84    /// Returns the subject distinguished name.
85    #[cfg(test)]
86    fn subject_common_name(&self) -> Vec<u8> {
87        match self {
88            Certificate::X509(cert) => cert.subject_common_name.clone(),
89        }
90    }
91
92    /// Returns the subject public key info.
93    fn subject_public_key_info(&self) -> DerVec {
94        match self {
95            Certificate::X509(cert) => cert.subject_public_key_info.clone(),
96        }
97    }
98
99    fn issue_certificate_serial<T: Config>(&mut self, serial: U256) -> DispatchResult {
100        match self {
101            Certificate::X509(cert) => {
102                ensure!(
103                    !cert.issued_serials.contains(&serial),
104                    Error::<T>::CertificateSerialAlreadyIssued
105                );
106                cert.issued_serials.insert(serial);
107                Ok(())
108            }
109        }
110    }
111
112    fn issuer_id(&self) -> Option<Identifier> {
113        match self {
114            Certificate::X509(cert) => cert.issuer_id,
115        }
116    }
117
118    fn serial(&self) -> Serial {
119        match self {
120            Certificate::X509(cert) => cert.serial,
121        }
122    }
123
124    fn issued_serials(&self) -> BTreeSet<Serial> {
125        match self {
126            Certificate::X509(cert) => cert.issued_serials.clone(),
127        }
128    }
129
130    /// Checks if the certificate is valid at this time.
131    pub(crate) fn is_valid_at(&self, time: Moment) -> bool {
132        match self {
133            Certificate::X509(cert) => cert.validity.is_valid_at(time),
134        }
135    }
136
137    /// Deterministically derives an identifier from the certificate.
138    ///
139    /// The identifier is derived by hashing the subject common name of the certificate.
140    /// If the certificate is a leaf certificate, the issuer identifier is combined with the subject common name.
141    fn derive_identifier(&self) -> Identifier {
142        match &self {
143            Certificate::X509(cert) => {
144                if let Some(issuer_id) = cert.issuer_id {
145                    let mut data = issuer_id.to_fixed_bytes().to_vec();
146
147                    data.extend_from_slice(cert.subject_common_name.as_ref());
148
149                    blake2_256(&data).into()
150                } else {
151                    // Root certificate
152                    blake2_256(cert.subject_common_name.as_ref()).into()
153                }
154            }
155        }
156    }
157
158    fn nonce(&self) -> U256 {
159        match self {
160            Certificate::X509(cert) => cert.nonce,
161        }
162    }
163
164    fn inc_nonce<T: Config>(&mut self) -> DispatchResult {
165        match self {
166            Certificate::X509(cert) => {
167                cert.nonce = cert
168                    .nonce
169                    .checked_add(U256::one())
170                    .ok_or(Error::<T>::NonceOverflow)?;
171                Ok(())
172            }
173        }
174    }
175}
176
177/// A representation of AutoId
178#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
179pub struct AutoId {
180    /// Certificate associated with this AutoId.
181    pub certificate: Certificate,
182}
183
184/// Type holds X509 certificate details used to register an AutoId.
185#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone, DecodeWithMemTracking)]
186pub enum RegisterAutoIdX509 {
187    Root {
188        certificate: DerVec,
189        signature_algorithm: DerVec,
190        signature: Vec<u8>,
191    },
192    Leaf {
193        issuer_id: Identifier,
194        certificate: DerVec,
195        signature_algorithm: DerVec,
196        signature: Vec<u8>,
197    },
198}
199
200/// Request to renew AutoId.
201#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone, DecodeWithMemTracking)]
202pub enum RenewAutoId {
203    X509(RenewX509Certificate),
204}
205
206/// Type holds X509 certificate details used to renew.
207#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone, DecodeWithMemTracking)]
208pub struct RenewX509Certificate {
209    issuer_id: Option<Identifier>,
210    certificate: DerVec,
211    signature_algorithm: DerVec,
212    signature: Vec<u8>,
213}
214
215/// Signature holds algorithm used and the signature value.
216#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone, DecodeWithMemTracking)]
217pub struct Signature {
218    pub signature_algorithm: DerVec,
219    pub value: Vec<u8>,
220}
221
222/// Request to register a new AutoId.
223#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone, DecodeWithMemTracking)]
224pub enum RegisterAutoId {
225    X509(RegisterAutoIdX509),
226}
227
228/// Specific action type taken by the subject of the Certificate.
229#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
230pub enum CertificateActionType {
231    RevokeCertificate,
232    DeactivateAutoId,
233}
234
235/// Signing data used to verify the certificate action.
236#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
237pub struct CertificateAction {
238    /// On which AutoId the action is taken.
239    pub id: Identifier,
240    /// Current nonce of the certificate.
241    pub nonce: U256,
242    /// Type of action taken.
243    pub action_type: CertificateActionType,
244}
245
246#[frame_support::pallet]
247mod pallet {
248    use super::*;
249    use crate::weights::WeightInfo;
250    use crate::{AutoId, Identifier, RegisterAutoId, Serial, Signature};
251    use frame_support::pallet_prelude::*;
252    use frame_support::traits::Time;
253    use frame_system::pallet_prelude::*;
254
255    #[pallet::config]
256    pub trait Config: frame_system::Config<RuntimeEvent: From<Event<Self>>> {
257        type Time: Time<Moment = subspace_runtime_primitives::Moment>;
258        type Weights: WeightInfo;
259    }
260
261    #[pallet::pallet]
262    #[pallet::without_storage_info]
263    pub struct Pallet<T>(_);
264
265    /// Stores the auto id identifier against an AutoId.
266    #[pallet::storage]
267    pub(super) type AutoIds<T> = StorageMap<_, Identity, Identifier, AutoId, OptionQuery>;
268
269    /// Stores list of revoked certificates.
270    ///
271    /// It maps the issuer's identifier to the list of revoked serial numbers of certificates. Before accepting
272    /// the certificate, external entities should check if the certificate or its issuer has been revoked.
273    #[pallet::storage]
274    pub(super) type CertificateRevocationList<T> =
275        StorageMap<_, Identity, Identifier, BTreeSet<Serial>, OptionQuery>;
276
277    #[pallet::error]
278    pub enum Error<T> {
279        /// Issuer auto id does not exist.
280        UnknownIssuer,
281        /// Unknown AutoId identifier.
282        UnknownAutoId,
283        /// Certificate is invalid,
284        InvalidCertificate,
285        /// Invalid signature.
286        InvalidSignature,
287        /// Certificate serial already issued.
288        CertificateSerialAlreadyIssued,
289        /// Certificate expired.
290        ExpiredCertificate,
291        /// Certificate revoked.
292        CertificateRevoked,
293        /// Certificate already revoked.
294        CertificateAlreadyRevoked,
295        /// Nonce overflow.
296        NonceOverflow,
297        /// Identifier already exists.
298        AutoIdIdentifierAlreadyExists,
299        /// Identifier mismatch.
300        AutoIdIdentifierMismatch,
301        /// Public key mismatch.
302        PublicKeyMismatch,
303    }
304
305    #[pallet::event]
306    #[pallet::generate_deposit(pub (super) fn deposit_event)]
307    pub enum Event<T: Config> {
308        /// Emits when a new AutoId is registered.
309        NewAutoIdRegistered(Identifier),
310        /// Emits when a Certificate associated with AutoId is revoked.
311        CertificateRevoked(Identifier),
312        /// Emits when an AutoId is deactivated.
313        AutoIdDeactivated(Identifier),
314        /// Emits when an AutoId is renewed.
315        AutoIdRenewed(Identifier),
316    }
317
318    #[pallet::call]
319    impl<T: Config> Pallet<T> {
320        /// Registers a new AutoId after validating the provided certificate.
321        #[pallet::call_index(0)]
322        #[pallet::weight(Pallet::<T>::max_register_auto_id_weight())]
323        pub fn register_auto_id(
324            origin: OriginFor<T>,
325            req: RegisterAutoId,
326        ) -> DispatchResultWithPostInfo {
327            ensure_signed(origin)?;
328            Self::do_register_auto_id(req)
329        }
330
331        /// Revokes a certificate associated with given AutoId.
332        ///
333        /// The signature is verified against the issuer's public key.
334        #[pallet::call_index(1)]
335        #[pallet::weight(Pallet::<T>::max_revoke_auto_id_weight())]
336        pub fn revoke_certificate(
337            origin: OriginFor<T>,
338            auto_id_identifier: Identifier,
339            signature: Signature,
340        ) -> DispatchResultWithPostInfo {
341            ensure_signed(origin)?;
342            Self::do_revoke_certificate(auto_id_identifier, signature)
343        }
344
345        /// Deactivates a given AutoId.
346        #[pallet::call_index(2)]
347        #[pallet::weight(<T as Config>::Weights::deactivate_auto_id())]
348        pub fn deactivate_auto_id(
349            origin: OriginFor<T>,
350            auto_id_identifier: Identifier,
351            signature: Signature,
352        ) -> DispatchResult {
353            ensure_signed(origin)?;
354            Self::do_deactivate_auto_id(auto_id_identifier, signature)?;
355            Ok(())
356        }
357
358        /// Renews a given AutoId.
359        #[pallet::call_index(3)]
360        #[pallet::weight(Pallet::<T>::max_renew_auto_id_weight())]
361        pub fn renew_auto_id(
362            origin: OriginFor<T>,
363            auto_id_identifier: Identifier,
364            req: RenewAutoId,
365        ) -> DispatchResultWithPostInfo {
366            ensure_signed(origin)?;
367            Self::do_renew_auto_id_certificate(auto_id_identifier, req)
368        }
369    }
370}
371
372impl<T: Config> Pallet<T> {
373    pub(crate) fn do_register_auto_id(req: RegisterAutoId) -> DispatchResultWithPostInfo {
374        let current_time = T::Time::now();
375        let (certificate, weight) = match req {
376            RegisterAutoId::X509(x509_req) => match x509_req {
377                RegisterAutoIdX509::Root {
378                    certificate,
379                    signature_algorithm,
380                    signature,
381                } => {
382                    let tbs_certificate = decode_tbs_certificate(certificate.clone())
383                        .ok_or(Error::<T>::InvalidCertificate)?;
384                    let req = SignatureVerificationRequest {
385                        public_key_info: tbs_certificate.subject_public_key_info.clone(),
386                        signature_algorithm,
387                        data: certificate.0.clone(),
388                        signature,
389                    };
390                    verify_signature(req).ok_or(Error::<T>::InvalidSignature)?;
391
392                    ensure!(
393                        tbs_certificate.validity.is_valid_at(current_time),
394                        Error::<T>::ExpiredCertificate
395                    );
396
397                    (
398                        Certificate::X509(X509Certificate {
399                            issuer_id: None,
400                            serial: tbs_certificate.serial,
401                            subject_common_name: tbs_certificate.subject_common_name,
402                            subject_public_key_info: tbs_certificate.subject_public_key_info,
403                            validity: tbs_certificate.validity,
404                            raw: certificate,
405                            issued_serials: BTreeSet::from([tbs_certificate.serial]),
406                            nonce: U256::zero(),
407                        }),
408                        T::Weights::register_issuer_auto_id(),
409                    )
410                }
411                RegisterAutoIdX509::Leaf {
412                    issuer_id,
413                    certificate,
414                    signature_algorithm,
415                    signature,
416                } => {
417                    let mut issuer_auto_id =
418                        AutoIds::<T>::get(issuer_id).ok_or(Error::<T>::UnknownIssuer)?;
419                    let issuer_public_key_info =
420                        issuer_auto_id.certificate.subject_public_key_info();
421
422                    ensure!(
423                        issuer_auto_id.certificate.is_valid_at(current_time),
424                        Error::<T>::ExpiredCertificate
425                    );
426
427                    let tbs_certificate = decode_tbs_certificate(certificate.clone())
428                        .ok_or(Error::<T>::InvalidCertificate)?;
429
430                    let req = SignatureVerificationRequest {
431                        public_key_info: issuer_public_key_info,
432                        signature_algorithm,
433                        data: certificate.0.clone(),
434                        signature,
435                    };
436                    verify_signature(req).ok_or(Error::<T>::InvalidSignature)?;
437                    ensure!(
438                        tbs_certificate.validity.is_valid_at(current_time),
439                        Error::<T>::ExpiredCertificate
440                    );
441
442                    ensure!(
443                        !CertificateRevocationList::<T>::get(issuer_id).is_some_and(|serials| {
444                            serials.iter().any(|s| {
445                                *s == issuer_auto_id.certificate.serial()
446                                    || *s == tbs_certificate.serial
447                            })
448                        }),
449                        Error::<T>::CertificateRevoked
450                    );
451
452                    issuer_auto_id
453                        .certificate
454                        .issue_certificate_serial::<T>(tbs_certificate.serial)?;
455
456                    AutoIds::<T>::insert(issuer_id, issuer_auto_id);
457
458                    (
459                        Certificate::X509(X509Certificate {
460                            issuer_id: Some(issuer_id),
461                            serial: tbs_certificate.serial,
462                            subject_common_name: tbs_certificate.subject_common_name,
463                            subject_public_key_info: tbs_certificate.subject_public_key_info,
464                            validity: tbs_certificate.validity,
465                            raw: certificate,
466                            issued_serials: BTreeSet::from([tbs_certificate.serial]),
467                            nonce: U256::zero(),
468                        }),
469                        T::Weights::register_leaf_auto_id(),
470                    )
471                }
472            },
473        };
474
475        let auto_id_identifier = certificate.derive_identifier();
476        let auto_id = AutoId { certificate };
477
478        ensure!(
479            !AutoIds::<T>::contains_key(auto_id_identifier),
480            Error::<T>::AutoIdIdentifierAlreadyExists
481        );
482
483        AutoIds::<T>::insert(auto_id_identifier, auto_id);
484
485        Self::deposit_event(Event::<T>::NewAutoIdRegistered(auto_id_identifier));
486        Ok(Some(weight).into())
487    }
488
489    fn do_renew_auto_id_certificate(
490        auto_id_identifier: Identifier,
491        req: RenewAutoId,
492    ) -> DispatchResultWithPostInfo {
493        let current_time = T::Time::now();
494        let auto_id = AutoIds::<T>::get(auto_id_identifier).ok_or(Error::<T>::UnknownAutoId)?;
495        let RenewAutoId::X509(req) = req;
496        let tbs_certificate = decode_tbs_certificate(req.certificate.clone())
497            .ok_or(Error::<T>::InvalidCertificate)?;
498
499        let (issuer_public_key_info, weight) = match req.issuer_id {
500            None => {
501                // revoke old certificate serial
502                CertificateRevocationList::<T>::mutate(auto_id_identifier, |serials| {
503                    serials
504                        .get_or_insert_with(BTreeSet::new)
505                        .insert(auto_id.certificate.serial());
506                });
507                (
508                    auto_id.certificate.subject_public_key_info(),
509                    T::Weights::renew_issuer_auto_id(),
510                )
511            }
512            Some(issuer_id) => {
513                let mut issuer_auto_id =
514                    AutoIds::<T>::get(issuer_id).ok_or(Error::<T>::UnknownIssuer)?;
515                let issuer_public_key_info = issuer_auto_id.certificate.subject_public_key_info();
516                ensure!(
517                    issuer_auto_id.certificate.is_valid_at(current_time),
518                    Error::<T>::ExpiredCertificate
519                );
520                ensure!(
521                    !CertificateRevocationList::<T>::get(issuer_id).is_some_and(|serials| {
522                        serials.iter().any(|s| {
523                            *s == issuer_auto_id.certificate.serial()
524                                || *s == tbs_certificate.serial
525                        })
526                    }),
527                    Error::<T>::CertificateRevoked
528                );
529
530                issuer_auto_id
531                    .certificate
532                    .issue_certificate_serial::<T>(tbs_certificate.serial)?;
533
534                // revoke old certificate serial
535                CertificateRevocationList::<T>::mutate(issuer_id, |serials| {
536                    serials
537                        .get_or_insert_with(BTreeSet::new)
538                        .insert(auto_id.certificate.serial());
539                });
540
541                AutoIds::<T>::insert(issuer_id, issuer_auto_id);
542                (issuer_public_key_info, T::Weights::renew_leaf_auto_id())
543            }
544        };
545
546        let signature_req = SignatureVerificationRequest {
547            public_key_info: issuer_public_key_info,
548            signature_algorithm: req.signature_algorithm,
549            data: req.certificate.0.clone(),
550            signature: req.signature,
551        };
552        verify_signature(signature_req).ok_or(Error::<T>::InvalidSignature)?;
553        ensure!(
554            tbs_certificate.validity.is_valid_at(current_time),
555            Error::<T>::ExpiredCertificate
556        );
557
558        ensure!(
559            auto_id.certificate.subject_public_key_info()
560                == tbs_certificate.subject_public_key_info,
561            Error::<T>::PublicKeyMismatch
562        );
563
564        let updated_certificate = Certificate::X509(X509Certificate {
565            issuer_id: req.issuer_id,
566            serial: tbs_certificate.serial,
567            subject_common_name: tbs_certificate.subject_common_name,
568            subject_public_key_info: tbs_certificate.subject_public_key_info,
569            validity: tbs_certificate.validity,
570            raw: req.certificate,
571            issued_serials: auto_id.certificate.issued_serials(),
572            nonce: auto_id.certificate.nonce(),
573        });
574
575        ensure!(
576            auto_id_identifier == updated_certificate.derive_identifier(),
577            Error::<T>::AutoIdIdentifierMismatch
578        );
579
580        let updated_auto_id = AutoId {
581            certificate: updated_certificate,
582        };
583
584        AutoIds::<T>::insert(auto_id_identifier, updated_auto_id);
585
586        Self::deposit_event(Event::<T>::AutoIdRenewed(auto_id_identifier));
587        Ok(Some(weight).into())
588    }
589
590    fn do_verify_signature(
591        auto_id: &AutoId,
592        signing_data: CertificateAction,
593        signature: Signature,
594    ) -> DispatchResult {
595        let Signature {
596            signature_algorithm,
597            value: signature,
598        } = signature;
599        let req = SignatureVerificationRequest {
600            public_key_info: auto_id.certificate.subject_public_key_info(),
601            signature_algorithm,
602            data: signing_data.encode(),
603            signature,
604        };
605
606        verify_signature(req).ok_or(Error::<T>::InvalidSignature)?;
607        Ok(())
608    }
609
610    fn do_revoke_certificate(
611        auto_id_identifier: Identifier,
612        signature: Signature,
613    ) -> DispatchResultWithPostInfo {
614        let auto_id = AutoIds::<T>::get(auto_id_identifier).ok_or(Error::<T>::UnknownAutoId)?;
615
616        let (issuer_id, mut issuer_auto_id, weight) = match auto_id.certificate.issuer_id() {
617            Some(issuer_id) => (
618                issuer_id,
619                AutoIds::<T>::get(issuer_id).ok_or(Error::<T>::UnknownIssuer)?,
620                T::Weights::revoke_leaf_auto_id(),
621            ),
622            // self revoke
623            None => (
624                auto_id_identifier,
625                auto_id.clone(),
626                T::Weights::revoke_issuer_auto_id(),
627            ),
628        };
629
630        ensure!(
631            !CertificateRevocationList::<T>::get(issuer_id).is_some_and(|serials| {
632                serials.iter().any(|s| {
633                    *s == auto_id.certificate.serial() || *s == issuer_auto_id.certificate.serial()
634                })
635            }),
636            Error::<T>::CertificateAlreadyRevoked
637        );
638
639        Self::do_verify_signature(
640            &issuer_auto_id,
641            CertificateAction {
642                id: auto_id_identifier,
643                nonce: issuer_auto_id.certificate.nonce(),
644                action_type: CertificateActionType::RevokeCertificate,
645            },
646            signature,
647        )?;
648
649        CertificateRevocationList::<T>::mutate(issuer_id, |serials| {
650            serials
651                .get_or_insert_with(BTreeSet::new)
652                .insert(auto_id.certificate.serial());
653        });
654
655        issuer_auto_id.certificate.inc_nonce::<T>()?;
656        AutoIds::<T>::insert(issuer_id, issuer_auto_id);
657
658        Self::deposit_event(Event::<T>::CertificateRevoked(auto_id_identifier));
659        Ok(Some(weight).into())
660    }
661
662    fn do_deactivate_auto_id(
663        auto_id_identifier: Identifier,
664        signature: Signature,
665    ) -> DispatchResult {
666        let auto_id = AutoIds::<T>::get(auto_id_identifier).ok_or(Error::<T>::UnknownIssuer)?;
667        Self::do_verify_signature(
668            &auto_id,
669            CertificateAction {
670                id: auto_id_identifier,
671                nonce: auto_id.certificate.nonce(),
672                action_type: CertificateActionType::DeactivateAutoId,
673            },
674            signature,
675        )?;
676
677        // TODO: remove all the AutoIds registered using leaf certificates if this is the issuer.
678        AutoIds::<T>::remove(auto_id_identifier);
679
680        Self::deposit_event(Event::<T>::AutoIdDeactivated(auto_id_identifier));
681        Ok(())
682    }
683
684    fn max_register_auto_id_weight() -> Weight {
685        T::Weights::register_issuer_auto_id().max(T::Weights::register_leaf_auto_id())
686    }
687
688    fn max_revoke_auto_id_weight() -> Weight {
689        T::Weights::revoke_issuer_auto_id().max(T::Weights::revoke_leaf_auto_id())
690    }
691
692    fn max_renew_auto_id_weight() -> Weight {
693        T::Weights::renew_issuer_auto_id().max(T::Weights::renew_leaf_auto_id())
694    }
695}