Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
ad44d72
Add KEY_KIND_ID to the public trait
rakanalh Feb 17, 2020
3199d1e
Use `sign_with` as implemented in BareCryptoStore
rakanalh Feb 17, 2020
25f4a5c
Implement `sign_with` in sc_keystore
rakanalh Feb 17, 2020
8cc6dfd
Fix inconsistencies, use *_KIND_ID in sp_core testing
rakanalh Feb 17, 2020
4895e80
Rename KeyKindId to CryptoTypeId
rakanalh Feb 18, 2020
42f426d
Remove pair-returning functions from BareCryptoStore trait
rakanalh Feb 19, 2020
35555ff
Define CryptoTypeId in app-crypto macros
rakanalh Feb 19, 2020
d7623c7
Add functions to get keys supported by keystore
rakanalh Feb 19, 2020
01af73e
Fix sign_with signature to include CryptoTypePublicPair
rakanalh Feb 19, 2020
97775db
Add `sign_with_any` and `sign_with_all`
rakanalh Feb 19, 2020
1ee13ac
Use keystore.sign_with in auth_discovery
rakanalh Feb 19, 2020
ccec7f5
Rename get_supported_keys -> supported_keys
rakanalh Feb 19, 2020
5f59041
Added headers to function docstrings
rakanalh Feb 19, 2020
b588f7f
Use chain instead of extending a temp vector
rakanalh Feb 19, 2020
94e45a9
Fixed some code formatting
rakanalh Feb 19, 2020
e19ecf6
Restrict size of CryptoTypeId
rakanalh Feb 19, 2020
12836f4
Implement sign_with in the trait itself
rakanalh Feb 19, 2020
d6082cc
Remove whitespace
rakanalh Feb 19, 2020
ef029eb
Use key_type also as a CryptoTypeId in app_crypto macros
rakanalh Feb 19, 2020
c9680e3
Rename `get_keys` to `keys` in BareCryptoStore
rakanalh Feb 20, 2020
9dd7929
Remove usage of key_pair funcs in tests
rakanalh Feb 20, 2020
4d0b81b
Adjust docstring for *_CYPTO_ID constants
rakanalh Feb 20, 2020
0956ef7
Fix failures
rakanalh Feb 20, 2020
02f7099
Simplify mapping on keys
rakanalh Feb 20, 2020
79290de
Remove one let
rakanalh Feb 20, 2020
1ff324b
Merge remote-tracking branch 'upstream/master' into sign_with
rakanalh Feb 20, 2020
6a06530
Fixed typo
rakanalh Feb 20, 2020
6c37161
PR feedback
rakanalh Feb 20, 2020
ea81fba
remove whitespace
rakanalh Feb 20, 2020
118a53c
Zip keys and signatures
rakanalh Feb 20, 2020
eaa1c80
Use into_iter & remove cloned
rakanalh Feb 20, 2020
bf42dec
Pass index to MissingSignature
rakanalh Feb 20, 2020
17dd9a2
Use typed errors instead of strings for BareCryptoStore
rakanalh Feb 20, 2020
25c9bdd
Implement Debug for trait error
rakanalh Feb 20, 2020
b6de5e6
Use hashsets for better performance for supported_keys
rakanalh Feb 21, 2020
6cad7b9
Make sure keys are inserted into the keystore
rakanalh Feb 21, 2020
87e13fa
Make sign_with_all return type consistent with `sign_with`
rakanalh Feb 21, 2020
a7bfe13
Rename Error to BareCryptoStoreError
rakanalh Feb 21, 2020
7d38383
Rename CRYPT_TYPE_ID -> CRYPTO_ID
rakanalh Feb 21, 2020
321f16c
Remove unnecessary CRYPTO_ID declaration in Public trait
rakanalh Feb 21, 2020
69f474e
Convert pub key to CryptoTypePublicPair
rakanalh Feb 21, 2020
164d16b
Fix use
rakanalh Feb 21, 2020
c120f12
Fix code style
rakanalh Feb 21, 2020
fe8cf28
Implement From on CryptoTypePublicPair in app_crypto macros
rakanalh Feb 21, 2020
19c7499
Change CryptoTypePublicPair to a struct
rakanalh Feb 26, 2020
499c1bb
Implement Display on CryptoTypePublicPair
rakanalh Feb 26, 2020
b42af41
Pass CryptoTypePublicPair to MissingSignature error
rakanalh Feb 26, 2020
fc40b1e
Adjust docs according to function signature
rakanalh Feb 26, 2020
bca2c90
Unify keys implementation
rakanalh Feb 26, 2020
79b7e23
Fix RPC author tests
rakanalh Feb 26, 2020
31ae7ce
Fix stackoverflow
rakanalh Feb 26, 2020
6696aa0
Merge remote-tracking branch 'upstream/master' into sign_with
rakanalh Feb 26, 2020
5de1d04
Tabify spaces
rakanalh Mar 13, 2020
47f6c08
Pass KeyTypeId to error for easier debugging
rakanalh Mar 13, 2020
1674645
Fix asserts
rakanalh Mar 13, 2020
94651fa
Use ToHex to format public key
rakanalh Mar 13, 2020
c71646a
Use constants from sp_core
rakanalh Mar 13, 2020
46d6f23
Rename testing KeyTypeId constants
rakanalh Mar 13, 2020
f4d231e
Merge remote-tracking branch 'upstream/master' into sign_with
rakanalh Mar 13, 2020
bc0880b
Please compiler
rakanalh Mar 13, 2020
c8b721c
Restore KeyTypeId names
rakanalh Mar 13, 2020
fbfd23b
Use BareCryptoStoreError instead of String
rakanalh Mar 13, 2020
cac19ad
Document return value
rakanalh Mar 13, 2020
d5f4c4b
Fix borrow check
rakanalh Mar 13, 2020
c007d13
Convert to hashset internally
rakanalh Mar 20, 2020
9874c96
WIP - iter_keys
rakanalh Mar 20, 2020
f6be826
Return raw_public_keys
rakanalh Mar 20, 2020
0c012e7
Address PR feedback
rakanalh Mar 23, 2020
145d876
Merge remote-tracking branch 'upstream/master' into sign_with
rakanalh Mar 23, 2020
9e80c07
Address PR Feedback
rakanalh Mar 23, 2020
7b92399
Fix hexdisplay import error
rakanalh Mar 23, 2020
7908f71
Update primitives/core/src/traits.rs
bkchr Mar 23, 2020
5f9ad09
Merge remote-tracking branch 'upstream/master' into sign_with2
rakanalh Mar 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/authority-discovery/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ pub enum Error {
EncodingDecodingScale(codec::Error),
/// Failed to parse a libp2p multi address.
ParsingMultiaddress(libp2p::core::multiaddr::Error),
/// Failed to map signature to public key
Comment thread
rakanalh marked this conversation as resolved.
Outdated
PublicKeyToSignatureMaping,
Comment thread
rakanalh marked this conversation as resolved.
Outdated
}
37 changes: 18 additions & 19 deletions client/authority-discovery/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ use sc_client_api::blockchain::HeaderBackend;
use sc_network::specialization::NetworkSpecialization;
use sc_network::{DhtEvent, ExHashT, NetworkStateInfo};
use sp_authority_discovery::{AuthorityDiscoveryApi, AuthorityId, AuthoritySignature, AuthorityPair};
use sp_core::crypto::{key_types, Pair};
use sp_core::sr25519;
use sp_core::crypto::{key_types, CryptoTypePublicPair, Pair, Public};
use sp_core::traits::BareCryptoStorePtr;
use sp_runtime::{traits::Block as BlockT, generic::BlockId};
use sp_api::ProvideRuntimeApi;
Expand Down Expand Up @@ -211,10 +212,23 @@ where
.encode(&mut serialized_addresses)
.map_err(Error::EncodingProto)?;

for key in self.get_priv_keys_within_authority_set()?.into_iter() {
let signature = key.sign(&serialized_addresses);
let keys: Vec<CryptoTypePublicPair> = self.get_own_public_keys_within_authority_set()?
.into_iter()
.map(|k| (sr25519::SR25519_CRYPTO_ID, k.to_raw_vec()))
Comment thread
rakanalh marked this conversation as resolved.
Outdated
.collect();

let signatures = self.key_store
.read()
Comment thread
rakanalh marked this conversation as resolved.
Outdated
.sign_with_all(
key_types::AUTHORITY_DISCOVERY,
keys.clone(),
serialized_addresses.as_slice()
);

for (index, signature) in signatures.iter().enumerate() {
Comment thread
rakanalh marked this conversation as resolved.
Outdated
let mut signed_addresses = vec![];
let key = keys.get(index).ok_or(Error::PublicKeyToSignatureMaping)?;

schema::SignedAuthorityAddresses {
addresses: serialized_addresses.clone(),
signature: signature.encode(),
Expand All @@ -223,7 +237,7 @@ where
.map_err(Error::EncodingProto)?;

self.network.put_value(
hash_authority_id(key.public().as_ref())?,
hash_authority_id(key.1.as_ref())?,
signed_addresses,
);
}
Expand Down Expand Up @@ -347,21 +361,6 @@ where
Ok(())
}

/// Retrieve all local authority discovery private keys that are within the current authority
/// set.
fn get_priv_keys_within_authority_set(&mut self) -> Result<Vec<AuthorityPair>> {
let keys = self.get_own_public_keys_within_authority_set()?
.into_iter()
.map(std::convert::Into::into)
.filter_map(|pub_key| {
self.key_store.read().sr25519_key_pair(key_types::AUTHORITY_DISCOVERY, &pub_key)
})
.map(std::convert::Into::into)
.collect();

Ok(keys)
}

/// Retrieve our public keys within the current authority set.
//
// A node might have multiple authority discovery keys within its keystore, e.g. an old one and
Expand Down
89 changes: 79 additions & 10 deletions client/keystore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
use std::{collections::HashMap, path::PathBuf, fs::{self, File}, io::{self, Write}, sync::Arc};

use sp_core::{
crypto::{KeyTypeId, Pair as PairT, Public, IsWrappedBy, Protected}, traits::BareCryptoStore,
crypto::{IsWrappedBy, CryptoTypePublicPair, KeyTypeId, Pair as PairT, Protected, Public},
traits::BareCryptoStore,
};

use sp_application_crypto::{AppKey, AppPublic, AppPair, ed25519, sr25519};
Expand Down Expand Up @@ -276,11 +277,87 @@ impl Store {
buf.push(key_type + key.as_str());
Some(buf)
}

/// Signs a message with the private key that matches
/// the public key passed.
fn _sign_with(
Comment thread
rakanalh marked this conversation as resolved.
Outdated
&self,
id: KeyTypeId,
key: &CryptoTypePublicPair,
msg: &[u8],
) -> std::result::Result<Vec<u8>, String> {
Comment thread
gnunicorn marked this conversation as resolved.
Outdated
Comment thread
rakanalh marked this conversation as resolved.
Outdated
match key.0 {
ed25519::ED25519_CRYPTO_ID => {
let pub_key = ed25519::Public::from_slice(key.1.as_slice());
let key_pair: ed25519::Pair = self
.key_pair_by_type::<ed25519::Pair>(&pub_key, id)
.map(Into::into)
Comment thread
rakanalh marked this conversation as resolved.
Outdated
.map_err(|e| e.to_string())?;
return Ok(<[u8; 64]>::from(key_pair.sign(msg)).to_vec());
Comment thread
rakanalh marked this conversation as resolved.
Outdated
}
sr25519::SR25519_CRYPTO_ID => {
let pub_key = sr25519::Public::from_slice(key.1.as_slice());
let key_pair: sr25519::Pair = self
.key_pair_by_type::<sr25519::Pair>(&pub_key, id)
.map(Into::into)
Comment thread
rakanalh marked this conversation as resolved.
Outdated
.map_err(|e| e.to_string())?;
return Ok(<[u8; 64]>::from(key_pair.sign(msg)).to_vec());
Comment thread
rakanalh marked this conversation as resolved.
Outdated
}
_ => Err(String::from("Key kind invalid"))
Comment thread
rakanalh marked this conversation as resolved.
Outdated
}
}
}

impl BareCryptoStore for Store {
fn get_supported_keys(&self, id: KeyTypeId, keys: Vec<CryptoTypePublicPair>) -> std::result::Result<Vec<CryptoTypePublicPair>, String> {
let ed25519_existing_keys: Vec<Vec<u8>> = self.public_keys_by_type::<ed25519::Public>(id)
.map(|keys| keys.iter().map(|k| k.to_raw_vec()).collect())
.map_err(|e| e.to_string())?;
let sr25519_existing_keys: Vec<Vec<u8>> = self.public_keys_by_type::<sr25519::Public>(id)
.map(|keys| keys.iter().map(|k| k.to_raw_vec()).collect())
.map_err(|e| e.to_string())?;

Ok(keys.iter().filter_map(|k| {
match k.0 {
sr25519::SR25519_CRYPTO_ID if sr25519_existing_keys.contains(&k.1.to_vec()) => Some(k),
ed25519::ED25519_CRYPTO_ID if ed25519_existing_keys.contains(&k.1.to_vec()) => Some(k),
_ => None
}
}).cloned().collect::<Vec<_>>())
Comment thread
gnunicorn marked this conversation as resolved.
Outdated
}

fn get_keys(&self, id: KeyTypeId) -> std::result::Result<Vec<CryptoTypePublicPair>, String> {
let ed25519_existing_keys: Vec<Vec<u8>> = self.public_keys_by_type::<ed25519::Public>(id)
.map(|keys| keys.iter().map(|k| k.to_raw_vec()).collect())
.map_err(|e| e.to_string())?;
let sr25519_existing_keys: Vec<Vec<u8>> = self.public_keys_by_type::<sr25519::Public>(id)
.map(|keys| keys.iter().map(|k| k.to_raw_vec()).collect())
.map_err(|e| e.to_string())?;

let mut keys: Vec<CryptoTypePublicPair> = vec![];
keys.extend(sr25519_existing_keys.iter()
.cloned()
.map(|k| (sr25519::SR25519_CRYPTO_ID, k)));
keys.extend(ed25519_existing_keys.iter()
.cloned()
.map(|k| (ed25519::ED25519_CRYPTO_ID, k))
.collect::<Vec<_>>());
Ok(keys)

Comment thread
rakanalh marked this conversation as resolved.
Outdated
}

fn sign_with(
&self,
id: KeyTypeId,
key: &CryptoTypePublicPair,
msg: &[u8],
) -> std::result::Result<Vec<u8>, String> {
self._sign_with(id, key, msg)
}

fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec<sr25519::Public> {
self.public_keys_by_type::<sr25519::Public>(key_type).unwrap_or_default()
self.public_keys_by_type::<sr25519::Public>(key_type)
.unwrap_or_default()
}

fn sr25519_generate_new(
Expand All @@ -296,10 +373,6 @@ impl BareCryptoStore for Store {
Ok(pair.public())
}

fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option<sr25519::Pair> {
self.key_pair_by_type::<sr25519::Pair>(pub_key, id).ok()
}

fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec<ed25519::Public> {
self.public_keys_by_type::<ed25519::Public>(key_type).unwrap_or_default()
}
Expand All @@ -317,10 +390,6 @@ impl BareCryptoStore for Store {
Ok(pair.public())
}

fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option<ed25519::Pair> {
self.key_pair_by_type::<ed25519::Pair>(pub_key, id).ok()
}

fn insert_unknown(&mut self, key_type: KeyTypeId, suri: &str, public: &[u8])
-> std::result::Result<(), ()>
{
Expand Down
4 changes: 3 additions & 1 deletion primitives/application-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub use sp_core::{self, crypto::{CryptoType, Public, Derive, IsWrappedBy, Wraps}
#[doc(hidden)]
#[cfg(feature = "full_crypto")]
pub use sp_core::crypto::{SecretStringError, DeriveJunction, Ss58Codec, Pair};
pub use sp_core::{crypto::{KeyTypeId, key_types}};
pub use sp_core::crypto::{CryptoTypeId, KeyTypeId, key_types};

#[doc(hidden)]
pub use codec;
Expand Down Expand Up @@ -271,6 +271,8 @@ macro_rules! app_crypto_public_common {
}

impl $crate::Public for Public {
const CRYPTO_TYPE_ID: $crate::CryptoTypeId = $crate::CryptoTypeId(stringify!($key_type));

fn from_slice(x: &[u8]) -> Self { Self(<$public>::from_slice(x)) }
}

Expand Down
18 changes: 16 additions & 2 deletions primitives/core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,12 @@ impl<T: Sized + AsMut<[u8]> + AsRef<[u8]> + Default + Derive> Ss58Codec for T {
}

/// Trait suitable for typical cryptographic PKI key public type.
pub trait Public: AsRef<[u8]> + AsMut<[u8]> + Default + Derive + CryptoType + PartialEq + Eq + Clone + Send + Sync {
pub trait Public:
AsRef<[u8]> + AsMut<[u8]> + Default + Derive + CryptoType + PartialEq + Eq + Clone + Send + Sync
{
/// Each implementation of Public should define its Kind identifier
Comment thread
rakanalh marked this conversation as resolved.
Outdated
const CRYPTO_TYPE_ID: CryptoTypeId;
Comment thread
rakanalh marked this conversation as resolved.
Outdated

/// A new instance from the given slice.
///
/// NOTE: No checking goes on to ensure this is a real public key. Only use it if
Expand Down Expand Up @@ -657,6 +662,8 @@ mod dummy {
impl Derive for Dummy {}

impl Public for Dummy {
const CRYPTO_TYPE_ID: CryptoTypeId = CryptoTypeId("dummy");

fn from_slice(_: &[u8]) -> Self { Self }
#[cfg(feature = "std")]
fn to_raw_vec(&self) -> Vec<u8> { vec![] }
Expand Down Expand Up @@ -882,7 +889,7 @@ pub trait CryptoType {

/// An identifier for a type of cryptographic key.
///
/// To avoid clashes with other modules when distributing your module publically, register your
/// To avoid clashes with other modules when distributing your module publicly, register your
/// `KeyTypeId` on the list here by making a PR.
///
/// Values whose first character is `_` are reserved for private use and won't conflict with any
Expand Down Expand Up @@ -918,6 +925,13 @@ impl<'a> TryFrom<&'a str> for KeyTypeId {
}
}

/// An identifier for a specific cryptographic algorithm used by a key pair
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
Comment thread
rakanalh marked this conversation as resolved.
Outdated
pub struct CryptoTypeId(pub &'static str);
Comment thread
rakanalh marked this conversation as resolved.
Outdated

/// A type alias of CryptoTypeId & a public key
pub type CryptoTypePublicPair = (CryptoTypeId, Vec<u8>);

/// Known key types; this also functions as a global registry of key types for projects wishing to
/// avoid collisions with each other.
///
Expand Down
8 changes: 7 additions & 1 deletion primitives/core/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ use crate::{hashing::blake2_256, crypto::{Pair as TraitPair, DeriveJunction, Sec
use crate::crypto::Ss58Codec;
#[cfg(feature = "std")]
use serde::{de, Serializer, Serialize, Deserializer, Deserialize};
use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive};
use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive, CryptoTypeId};
#[cfg(feature = "full_crypto")]
use secp256k1::{PublicKey, SecretKey};

/// A value which is passed along with the public key
Comment thread
rakanalh marked this conversation as resolved.
Outdated
/// to define which cryptographic algorithm that key
/// belongs to.
pub const ECDSA_CRYPTO_ID: CryptoTypeId = CryptoTypeId("ecdsa");
Comment thread
rakanalh marked this conversation as resolved.
Outdated

/// A secret seed (which is bytewise essentially equivalent to a SecretKey).
///
/// We need it as a different type because `Seed` is expected to be AsRef<[u8]>.
Expand Down Expand Up @@ -95,6 +100,7 @@ impl Public {
}

impl TraitPublic for Public {
const CRYPTO_TYPE_ID: CryptoTypeId = ECDSA_CRYPTO_ID;
Comment thread
rakanalh marked this conversation as resolved.
Outdated
/// A new instance from the given slice that should be 33 bytes long.
///
/// NOTE: No checking goes on to ensure this is a real public key. Only use it if
Expand Down
9 changes: 8 additions & 1 deletion primitives/core/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,15 @@ use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError};
use crate::crypto::Ss58Codec;
#[cfg(feature = "std")]
use serde::{de, Serializer, Serialize, Deserializer, Deserialize};
use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}};
use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive, CryptoTypeId};
use sp_runtime_interface::pass_by::PassByInner;
use sp_std::ops::Deref;

/// A value which is passed along with the public key
/// to define which cryptographic algorithm that key
/// belongs to.
pub const ED25519_CRYPTO_ID: CryptoTypeId = CryptoTypeId("ed25519");
Comment thread
rakanalh marked this conversation as resolved.
Outdated

/// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys
/// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we
/// will need it later (such as for HDKD).
Expand Down Expand Up @@ -365,6 +370,8 @@ impl Public {
}

impl TraitPublic for Public {
const CRYPTO_TYPE_ID: CryptoTypeId = ED25519_CRYPTO_ID;
Comment thread
rakanalh marked this conversation as resolved.
Outdated

/// A new instance from the given slice that should be 32 bytes long.
///
/// NOTE: No checking goes on to ensure this is a real public key. Only use it if
Expand Down
9 changes: 8 additions & 1 deletion primitives/core/src/sr25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use crate::crypto::{
#[cfg(feature = "std")]
use crate::crypto::Ss58Codec;

use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}};
use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive, CryptoTypeId};
use crate::hash::{H256, H512};
use codec::{Encode, Decode};
use sp_std::ops::Deref;
Expand All @@ -54,6 +54,11 @@ use sp_runtime_interface::pass_by::PassByInner;
#[cfg(feature = "full_crypto")]
const SIGNING_CTX: &[u8] = b"substrate";

/// A value which is passed along with the public key
/// to define which cryptographic algorithm that key
/// belongs to.
pub const SR25519_CRYPTO_ID: CryptoTypeId = CryptoTypeId("sr25519");
Comment thread
rakanalh marked this conversation as resolved.
Outdated

/// An Schnorrkel/Ristretto x25519 ("sr25519") public key.
#[cfg_attr(feature = "full_crypto", derive(Hash))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner)]
Expand Down Expand Up @@ -379,6 +384,8 @@ impl Public {
}

impl TraitPublic for Public {
const CRYPTO_TYPE_ID: CryptoTypeId = SR25519_CRYPTO_ID;
Comment thread
rakanalh marked this conversation as resolved.
Outdated

/// A new instance from the given slice that should be 32 bytes long.
///
/// NOTE: No checking goes on to ensure this is a real public key. Only use it if
Expand Down
Loading