Support for keyring in runtimes (#2044)

This functionality is required for #1984.

This PR enables
[`sp-keyring`](https://github.com/paritytech/polkadot-sdk/blob/21d36b7b4229c4d5225944f197918cde23fda4ea/substrate/primitives/keyring/src/sr25519.rs#L31-L40)
in `no-std` environments, allowing to generate the public key (e.g.
`AccountKeyring::Alice.public().to_ss58check()`), which can be later
used in the any of built-in [_runtime-genesis-config_
variant](https://github.com/paritytech/polkadot-sdk/blob/21d36b7b4229c4d5225944f197918cde23fda4ea/polkadot/node/service/src/chain_spec.rs#L1066-L1073).


The proposal is as follows:
- expose [`core::Pair`
trait](https://github.com/paritytech/polkadot-sdk/blob/d6f15306282e3de848a09c9aa9cba6f95a7811f0/substrate/primitives/core/src/crypto.rs#L832)
in `no-std`,
- `full_crypto` feature enables `sign` method,
- `std` feature enables `generate_with_phrase` and `generate` methods
(randomness is required),
- All other functionality, currently gated by `full_crypto` will be
available unconditionally (`no-std`):
-- `from_string`
-- `from_string_with_seed`
-- `from seed`
-- `from_seed_slice`
-- `from_phrase`
-- `derive`
-- `verify`

---

Depends on https://github.com/rust-bitcoin/rust-bip39/pull/57

---------

Co-authored-by: command-bot <>
Co-authored-by: Davide Galassi <davxy@datawok.net>
This commit is contained in:
Michal Kucharczyk
2024-03-12 12:43:31 +01:00
committed by GitHub
parent 1ead59773e
commit a756baf3b2
30 changed files with 248 additions and 233 deletions
+11 -19
View File
@@ -22,19 +22,18 @@
#[cfg(feature = "serde")]
use crate::crypto::Ss58Codec;
use crate::crypto::{
ByteArray, CryptoType, CryptoTypeId, Derive, Public as TraitPublic, UncheckedFrom, VrfPublic,
};
#[cfg(feature = "full_crypto")]
use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError, VrfSecret};
use crate::crypto::VrfSecret;
use crate::crypto::{
ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair,
Public as TraitPublic, SecretStringError, UncheckedFrom, VrfPublic,
};
#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
#[cfg(all(not(feature = "std"), feature = "serde"))]
use sp_std::alloc::{format, string::String};
use bandersnatch_vrfs::CanonicalSerialize;
#[cfg(feature = "full_crypto")]
use bandersnatch_vrfs::SecretKey;
use bandersnatch_vrfs::{CanonicalSerialize, SecretKey};
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
use scale_info::TypeInfo;
@@ -45,10 +44,8 @@ use sp_std::{vec, vec::Vec};
pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"band");
/// Context used to produce a plain signature without any VRF input/output.
#[cfg(feature = "full_crypto")]
pub const SIGNING_CTX: &[u8] = b"BandersnatchSigningContext";
#[cfg(feature = "full_crypto")]
const SEED_SERIALIZED_SIZE: usize = 32;
const PUBLIC_SERIALIZED_SIZE: usize = 33;
@@ -56,7 +53,6 @@ const SIGNATURE_SERIALIZED_SIZE: usize = 65;
const PREOUT_SERIALIZED_SIZE: usize = 33;
/// Bandersnatch public key.
#[cfg_attr(feature = "full_crypto", derive(Hash))]
#[derive(
Clone,
Copy,
@@ -69,6 +65,7 @@ const PREOUT_SERIALIZED_SIZE: usize = 33;
PassByInner,
MaxEncodedLen,
TypeInfo,
Hash,
)]
pub struct Public(pub [u8; PUBLIC_SERIALIZED_SIZE]);
@@ -116,7 +113,6 @@ impl ByteArray for Public {
impl TraitPublic for Public {}
impl CryptoType for Public {
#[cfg(feature = "full_crypto")]
type Pair = Pair;
}
@@ -154,8 +150,9 @@ impl<'de> Deserialize<'de> for Public {
///
/// The signature is created via the [`VrfSecret::vrf_sign`] using [`SIGNING_CTX`] as transcript
/// `label`.
#[cfg_attr(feature = "full_crypto", derive(Hash))]
#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo)]
#[derive(
Clone, Copy, PartialEq, Eq, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo, Hash,
)]
pub struct Signature([u8; SIGNATURE_SERIALIZED_SIZE]);
impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature {
@@ -194,7 +191,6 @@ impl ByteArray for Signature {
}
impl CryptoType for Signature {
#[cfg(feature = "full_crypto")]
type Pair = Pair;
}
@@ -211,18 +207,15 @@ impl sp_std::fmt::Debug for Signature {
}
/// The raw secret seed, which can be used to reconstruct the secret [`Pair`].
#[cfg(feature = "full_crypto")]
type Seed = [u8; SEED_SERIALIZED_SIZE];
/// Bandersnatch secret key.
#[cfg(feature = "full_crypto")]
#[derive(Clone)]
pub struct Pair {
secret: SecretKey,
seed: Seed,
}
#[cfg(feature = "full_crypto")]
impl Pair {
/// Get the key seed.
pub fn seed(&self) -> Seed {
@@ -230,7 +223,6 @@ impl Pair {
}
}
#[cfg(feature = "full_crypto")]
impl TraitPair for Pair {
type Seed = Seed;
type Public = Public;
@@ -287,6 +279,7 @@ impl TraitPair for Pair {
/// the constant label [`SIGNING_CTX`] and `data` without any additional data.
///
/// See [`vrf::VrfSignData`] for additional details.
#[cfg(feature = "full_crypto")]
fn sign(&self, data: &[u8]) -> Signature {
let data = vrf::VrfSignData::new_unchecked(SIGNING_CTX, &[data], None);
self.vrf_sign(&data).signature
@@ -305,7 +298,6 @@ impl TraitPair for Pair {
}
}
#[cfg(feature = "full_crypto")]
impl CryptoType for Pair {
type Pair = Pair;
}