Refactor key management (#3296)

* Add Call type to extensible transactions.

Cleanup some naming

* Merge Resource and BlockExhausted into just Exhausted

* Fix

* Another fix

* Call

* Some fixes

* Fix srml tests.

* Fix all tests.

* Refactor crypto so each application of it has its own type.

* Introduce new AuthorityProvider API into Aura

This will eventually allow for dynamic determination of authority
keys and avoid having to set them directly on CLI.

* Introduce authority determinator for Babe.

Experiment with modular consensus API.

* Work in progress to introduce KeyTypeId and avoid polluting API
with validator IDs

* Finish up drafting imonline

* Rework offchain workers API.

* Rework API implementation.

* Make it compile for wasm, simplify app_crypto.

* Fix compilation of im-online.

* Fix compilation of im-online.

* Fix more compilation errors.

* Make it compile.

* Fixing tests.

* Rewrite `keystore`

* Fix session tests

* Bring back `TryFrom`'s'

* Fix `srml-grandpa`

* Fix `srml-aura`

* Fix consensus babe

* More fixes

* Make service generate keys from dev_seed

* Build fixes

* Remove offchain tests

* More fixes and cleanups

* Fixes finality grandpa

* Fix `consensus-aura`

* Fix cli

* Fix `node-cli`

* Fix chain_spec builder

* Fix doc tests

* Add authority getter for grandpa.

* Test fix

* Fixes

* Make keystore accessible from the runtime

* Move app crypto to its own crate

* Update `Cargo.lock`

* Make the crypto stuff usable from the runtime

* Adds some runtime crypto tests

* Use last finalized block for grandpa authority

* Fix warning

* Adds `SessionKeys` runtime api

* Remove `FinalityPair` and `ConsensusPair`

* Minor governance tweaks to get it inline with docs.

* Make the governance be up to date with the docs.

* Build fixes.

* Generate the inital session keys

* Failing keystore is a hard error

* Make babe work again

* Fix grandpa

* Fix tests

* Disable `keystore` in consensus critical stuff

* Build fix.

* ImOnline supports multiple authorities at once.

* Update core/application-crypto/src/ed25519.rs

* Merge branch 'master' into gav-in-progress

* Remove unneeded code for now.

* Some `session` testing

* Support querying the public keys

* Cleanup offchain

* Remove warnings

* More cleanup

* Apply suggestions from code review

Co-Authored-By: Benjamin Kampmann <ben.kampmann@googlemail.com>

* More cleanups

* JSONRPC API for setting keys.

Also, rename traits::KeyStore* -> traits::BareCryptoStore*

* Bad merge

* Fix integration tests

* Fix test build

* Test fix

* Fixes

* Warnings

* Another warning

* Bump version.
This commit is contained in:
Gavin Wood
2019-08-07 20:47:48 +02:00
committed by GitHub
parent a6a6779f01
commit 1a524b8207
160 changed files with 4467 additions and 2769 deletions
+55 -52
View File
@@ -30,8 +30,10 @@ use substrate_bip39::mini_secret_from_entropy;
#[cfg(feature = "std")]
use bip39::{Mnemonic, Language, MnemonicType};
#[cfg(feature = "std")]
use crate::crypto::{Pair as TraitPair, DeriveJunction, Infallible, SecretStringError, Derive, Ss58Codec};
use crate::crypto::{key_types, KeyTypeId, Public as TraitPublic, TypedKey, UncheckedFrom};
use crate::crypto::{
Pair as TraitPair, DeriveJunction, Infallible, SecretStringError, Ss58Codec
};
use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}};
use crate::hash::{H256, H512};
use codec::{Encode, Decode};
@@ -56,19 +58,13 @@ pub struct Pair(Keypair);
impl Clone for Pair {
fn clone(&self) -> Self {
Pair(schnorrkel::Keypair {
public: self.0.public.clone(),
public: self.0.public,
secret: schnorrkel::SecretKey::from_bytes(&self.0.secret.to_bytes()[..])
.expect("key is always the correct size; qed")
})
}
}
impl AsRef<Public> for Public {
fn as_ref(&self) -> &Public {
&self
}
}
impl AsRef<[u8; 32]> for Public {
fn as_ref(&self) -> &[u8; 32] {
&self.0
@@ -99,6 +95,20 @@ impl From<Public> for H256 {
}
}
impl rstd::convert::TryFrom<&[u8]> for Public {
type Error = ();
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
if data.len() == 32 {
let mut inner = [0u8; 32];
inner.copy_from_slice(data);
Ok(Public(inner))
} else {
Err(())
}
}
}
impl UncheckedFrom<[u8; 32]> for Public {
fn unchecked_from(x: [u8; 32]) -> Self {
Public::from_raw(x)
@@ -112,15 +122,15 @@ impl UncheckedFrom<H256> for Public {
}
#[cfg(feature = "std")]
impl ::std::fmt::Display for Public {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl std::fmt::Display for Public {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.to_ss58check())
}
}
#[cfg(feature = "std")]
impl ::std::fmt::Debug for Public {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl std::fmt::Debug for Public {
fn fmt(&self, f: &mut std::fmt::Formatter) -> ::std::fmt::Result {
let s = self.to_ss58check();
write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8])
}
@@ -142,8 +152,8 @@ impl<'de> Deserialize<'de> for Public {
}
#[cfg(feature = "std")]
impl ::std::hash::Hash for Public {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
impl std::hash::Hash for Public {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
@@ -154,6 +164,20 @@ impl ::std::hash::Hash for Public {
#[derive(Encode, Decode)]
pub struct Signature(pub [u8; 64]);
impl rstd::convert::TryFrom<&[u8]> for Signature {
type Error = ();
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
if data.len() == 64 {
let mut inner = [0u8; 64];
inner.copy_from_slice(data);
Ok(Signature(inner))
} else {
Err(())
}
}
}
impl Clone for Signature {
fn clone(&self) -> Self {
let mut r = [0u8; 64];
@@ -170,7 +194,7 @@ impl Default for Signature {
impl PartialEq for Signature {
fn eq(&self, b: &Self) -> bool {
&self.0[..] == &b.0[..]
self.0[..] == b.0[..]
}
}
@@ -268,11 +292,11 @@ impl Signature {
}
}
#[cfg(feature = "std")]
impl Derive for Public {
/// Derive a child key from a series of given junctions.
///
/// `None` if there are any hard junctions in there.
#[cfg(feature = "std")]
fn derive<Iter: Iterator<Item=DeriveJunction>>(&self, path: Iter) -> Option<Public> {
let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?;
for j in path {
@@ -318,24 +342,6 @@ impl TraitPublic for Public {
r.copy_from_slice(data);
Public(r)
}
/// Return a `Vec<u8>` filled with raw data.
#[cfg(feature = "std")]
fn to_raw_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
/// Return a slice filled with raw data.
fn as_slice(&self) -> &[u8] {
&self.0
}
}
#[cfg(feature = "std")]
impl AsRef<Pair> for Pair {
fn as_ref(&self) -> &Pair {
&self
}
}
#[cfg(feature = "std")]
@@ -475,20 +481,15 @@ impl TraitPair for Pair {
}
/// Verify a signature on a message. Returns true if the signature is good.
fn verify<P: AsRef<Self::Public>, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool {
// Match both schnorrkel 0.1.1 and 0.8.0+ signatures, supporting both wallets
// that have not been upgraded and those that have. To swap to 0.8.0 only,
// create `schnorrkel::Signature` and pass that into `verify_simple`
match PublicKey::from_bytes(pubkey.as_ref().as_slice()) {
Ok(pk) => pk.verify_simple_preaudit_deprecated(
SIGNING_CTX, message.as_ref(), &sig.as_ref(),
).is_ok(),
Err(_) => false,
}
fn verify<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool {
Self::verify_weak(&sig.0[..], message, pubkey)
}
/// Verify a signature on a message. Returns true if the signature is good.
fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool {
// Match both schnorrkel 0.1.1 and 0.8.0+ signatures, supporting both wallets
// that have not been upgraded and those that have. To swap to 0.8.0 only,
// create `schnorrkel::Signature` and pass that into `verify_simple`
match PublicKey::from_bytes(pubkey.as_ref()) {
Ok(pk) => pk.verify_simple_preaudit_deprecated(
SIGNING_CTX, message.as_ref(), &sig,
@@ -518,17 +519,19 @@ impl Pair {
}
}
impl TypedKey for Public {
const KEY_TYPE: KeyTypeId = key_types::SR25519;
impl CryptoType for Public {
#[cfg(feature="std")]
type Pair = Pair;
}
impl TypedKey for Signature {
const KEY_TYPE: KeyTypeId = key_types::SR25519;
impl CryptoType for Signature {
#[cfg(feature="std")]
type Pair = Pair;
}
#[cfg(feature = "std")]
impl TypedKey for Pair {
const KEY_TYPE: KeyTypeId = key_types::SR25519;
impl CryptoType for Pair {
type Pair = Pair;
}
#[cfg(test)]
@@ -713,6 +716,6 @@ mod test {
let js_signature = Signature::from_raw(hex!(
"28a854d54903e056f89581c691c1f7d2ff39f8f896c9e9c22475e60902cc2b3547199e0e91fa32902028f2ca2355e8cdd16cfe19ba5e8b658c94aa80f3b81a00"
));
assert!(Pair::verify(&js_signature, b"SUBSTRATE", public));
assert!(Pair::verify(&js_signature, b"SUBSTRATE", &public));
}
}