webb-tools / gadget

A framework for building modular AVS and Tangle Blueprints: https://docs.tangle.tools/developers/blueprints.
https://tangle.tools
MIT License
5 stars 1 forks source link

Gadget SDK - Keystore Module #155

Closed shekohex closed 1 month ago

shekohex commented 1 month ago

Overview

Every gadget would definitely need access to some sort of key management, like signing transactions and signing messages over network.

A Keystore should be exposed as a trait with default implementations that could be utilized as required, so we split the keystore into a frontend and a backend, with a trait that sits in between.

Possible Backends:

  1. in Memory Keystore (useful for testing)
  2. File-based Keystore
  3. AWS KMS based Keystore
  4. GCP CKM based Keystore …etc.

Keystore backend trait design

pub trait KeystoreBackend {
    /// Generate a new sr25519 key pair with an optional seed.
    ///
    /// Returns an `sr25519::Public` key of the generated key pair or an `Err` if
    /// something failed during key generation.
    fn sr25519_generate_new(
        &self,
        seed: Option<&str>,
    ) -> Result<sr25519::Public, Error>;
    /// Generate an sr25519 signature for a given message.
    ///
    /// Receives an [`sr25519::Public`] key to be able to map
    /// them to a private key that exists in the keystore.
    ///
    /// Returns an [`sr25519::Signature`] or `None` in case the given 
    /// `public` doesn't exist in the keystore.
    /// An `Err` will be returned if generating the signature itself failed.
    fn sr25519_sign(
        &self,
        public: &sr25519::Public,
        msg: &[u8],
    ) -> Result<Option<sr25519::Signature>, Error>;
    /// Generate a new ed25519 key pair with an optional seed.
    ///
    /// Returns an `ed25519::Public` key of the generated key pair or an `Err` if
    /// something failed during key generation.
    fn ed25519_generate_new(
        &self,
        seed: Option<&str>,
    ) -> Result<ed25519::Public, Error>;
    /// Generate an ed25519 signature for a given message.
    ///
    /// Receives an [`ed25519::Public`] key to be able to map
    /// it to a private key that exists in the keystore.
    ///
    /// Returns an [`ed25519::Signature`] or `None` in case the given 
    /// `public` doesn't exist in the keystore.
    /// An `Err` will be returned if generating the signature itself failed.
    fn ed25519_sign(
        &self,
        public: &ed25519::Public,
        msg: &[u8],
    ) -> Result<Option<ed25519::Signature>, Error>;
    /// Generate a new ecdsa key pair with an optional seed.
    ///
    /// Returns an `ecdsa::Public` key of the generated key pair or an `Err` if
    /// something failed during key generation.
    fn ecdsa_generate_new(
        &self,
        seed: Option<&str>,
    ) -> Result<ecdsa::Public, Error>;
    /// Generate an ecdsa signature for a given message.
    ///
    /// Receives an [`ecdsa::Public`] key to be able to map
    /// it to a private key that exists in the keystore.
    ///
    /// Returns an [`ecdsa::Signature`] or `None` in case the given 
    /// `public` doesn't exist in the keystore.
    /// An `Err` will be returned if generating the signature itself failed.
    fn ecdsa_sign(
        &self,
        public: &ecdsa::Public,
        msg: &[u8],
    ) -> Result<Option<ecdsa::Signature>, Error>;
    /// Generate a new bls381 key pair with an optional seed.
    ///
    /// Returns an `bls381::Public` key of the generated key pair or an `Err` if
    /// something failed during key generation.
    fn bls381_generate_new(
        &self,
        seed: Option<&str>,
    ) -> Result<bls381::Public, Error>;
    /// Generate an bls381 signature for a given message.
    ///
    /// Receives an [`bls381::Public`] key to be able to map
    /// it to a private key that exists in the keystore.
    ///
    /// Returns an [`bls381::Signature`] or `None` in case the given 
    /// `public` doesn't exist in the keystore.
    /// An `Err` will be returned if generating the signature itself failed.
    fn bls381_sign(
        &self,
        public: &bls381::Public,
        msg: &[u8],
    ) -> Result<Option<bls381::Signature>, Error>;
    /// Checks if the private key for the given public key exist.
    ///
    /// Returns `true` if the private key could be found.
    fn has_key(&self, public: &[u8]) -> bool;
    /// Returns the Keypair for the given [`sr25519::Public`] if it does exist, otherwise returns `None`.
    /// An `Err` will be returned if finding the key operation itself failed.
    fn expose_sr25519_pair(&self, public: &sr25519::Public) -> Result<Option<sr25519::Pair>, Error>;
    /// Returns the Keypair for the given [`ecdsa::Public`] if it does exist, otherwise returns `None`.
    /// An `Err` will be returned if finding the key operation itself failed.
    fn expose_ecdsa_pair(&self, public: &ecdsa::Public) -> Result<Option<ecdsa::Pair>, Error>;
    /// Returns the Keypair for the given [`ed25519::Public`] if it does exist, otherwise returns `None`.
    /// An `Err` will be returned if finding the key operation itself failed.
    fn expose_ed25519_pair(&self, public: &ed25519::Public) -> Result<Option<ed25519::Pair>, Error>;
    /// Returns the Keypair for the given [`bls381::Public`] if it does exist, otherwise returns `None`.
    /// An `Err` will be returned if finding the key operation itself failed.
    fn expose_bls381_pair(&self, public: &bls381::Public) -> Result<Option<bls381::Pair>, Error>;
}

Constraints

  1. This new Keystore should not directly depend on sp- or sc- crates, instead we could have a Substrate Keystore backend behind a feature flag.
  2. For each backend implemented, we should keep it behind a feature flag (the mem backend is enabled by default).