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
+2 -162
View File
@@ -16,11 +16,12 @@
//! Offchain workers types
use crate::crypto;
use codec::{Encode, Decode};
use rstd::prelude::{Vec, Box};
use rstd::convert::TryFrom;
pub use crate::crypto::KeyTypeId;
/// A type of supported crypto.
#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
@@ -58,81 +59,6 @@ impl From<StorageKind> for u32 {
}
}
/// A type of supported crypto.
#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
#[repr(C)]
pub enum CryptoKind {
/// SR25519 crypto (Schnorrkel)
Sr25519 = crypto::key_types::SR25519 as isize,
/// ED25519 crypto (Edwards)
Ed25519 = crypto::key_types::ED25519 as isize,
}
impl TryFrom<u32> for CryptoKind {
type Error = ();
fn try_from(kind: u32) -> Result<Self, Self::Error> {
match kind {
e if e == CryptoKind::Sr25519 as isize as u32 => Ok(CryptoKind::Sr25519),
e if e == CryptoKind::Ed25519 as isize as u32 => Ok(CryptoKind::Ed25519),
_ => Err(()),
}
}
}
impl From<CryptoKind> for u32 {
fn from(c: CryptoKind) -> Self {
c as isize as u32
}
}
/// Key to use in the offchain worker crypto api.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum CryptoKey {
/// Use a key from the offchain workers local storage.
LocalKey {
/// The id of the key.
id: u16,
/// The kind of the key.
kind: CryptoKind,
},
/// Use the key the block authoring algorithm uses.
AuthorityKey,
/// Use the key the finality gadget uses.
FgAuthorityKey,
}
impl TryFrom<u64> for CryptoKey {
type Error = ();
fn try_from(key: u64) -> Result<Self, Self::Error> {
match key & 0xFF {
0 => {
let id = (key >> 8 & 0xFFFF) as u16;
let kind = CryptoKind::try_from((key >> 32) as u32)?;
Ok(CryptoKey::LocalKey { id, kind })
}
1 => Ok(CryptoKey::AuthorityKey),
2 => Ok(CryptoKey::FgAuthorityKey),
_ => Err(()),
}
}
}
impl From<CryptoKey> for u64 {
fn from(key: CryptoKey) -> u64 {
match key {
CryptoKey::LocalKey { id, kind } => {
((kind as u64) << 32) | ((id as u64) << 8)
}
CryptoKey::AuthorityKey => 1,
CryptoKey::FgAuthorityKey => 2,
}
}
}
/// Opaque type for offchain http requests.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "std", derive(Debug))]
@@ -314,45 +240,6 @@ pub trait Externalities {
/// Returns information about the local node's network state.
fn network_state(&self) -> Result<OpaqueNetworkState, ()>;
/// Create new key(pair) for signing/encryption/decryption.
///
/// Returns an error if given crypto kind is not supported.
fn new_crypto_key(&mut self, crypto: CryptoKind) -> Result<CryptoKey, ()>;
/// Returns the locally configured authority public key, if available.
fn pubkey(&self, key: CryptoKey) -> Result<Vec<u8>, ()>;
/// Encrypt a piece of data using given crypto key.
///
/// If `key` is `None`, it will attempt to use current authority key of `CryptoKind`.
///
/// Returns an error if `key` is not available or does not exist,
/// or the expected `CryptoKind` does not match.
fn encrypt(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
/// Decrypt a piece of data using given crypto key.
///
/// If `key` is `None`, it will attempt to use current authority key of `CryptoKind`.
///
/// Returns an error if data cannot be decrypted or the `key` is not available or does not exist,
/// or the expected `CryptoKind` does not match.
fn decrypt(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
/// Sign a piece of data using given crypto key.
///
/// If `key` is `None`, it will attempt to use current authority key of `CryptoKind`.
///
/// Returns an error if `key` is not available or does not exist,
/// or the expected `CryptoKind` does not match.
fn sign(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
/// Verifies that `signature` for `msg` matches given `key`.
///
/// Returns an `Ok` with `true` in case it does, `false` in case it doesn't.
/// Returns an error in case the key is not available or does not exist or the parameters
/// lengths are incorrect or `CryptoKind` does not match.
fn verify(&mut self, key: CryptoKey, msg: &[u8], signature: &[u8]) -> Result<bool, ()>;
/// Returns current UNIX timestamp (in millis)
fn timestamp(&mut self) -> Timestamp;
@@ -466,34 +353,10 @@ impl<T: Externalities + ?Sized> Externalities for Box<T> {
(&mut **self).submit_transaction(ex)
}
fn new_crypto_key(&mut self, crypto: CryptoKind) -> Result<CryptoKey, ()> {
(&mut **self).new_crypto_key(crypto)
}
fn encrypt(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).encrypt(key, data)
}
fn network_state(&self) -> Result<OpaqueNetworkState, ()> {
(& **self).network_state()
}
fn pubkey(&self, key: CryptoKey) -> Result<Vec<u8>, ()> {
(&**self).pubkey(key)
}
fn decrypt(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).decrypt(key, data)
}
fn sign(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).sign(key, data)
}
fn verify(&mut self, key: CryptoKey, msg: &[u8], signature: &[u8]) -> Result<bool, ()> {
(&mut **self).verify(key, msg, signature)
}
fn timestamp(&mut self) -> Timestamp {
(&mut **self).timestamp()
}
@@ -571,27 +434,4 @@ mod tests {
assert_eq!(t.sub(Duration::from_millis(10)), Timestamp(0));
assert_eq!(t.diff(&Timestamp(3)), Duration(2));
}
#[test]
fn crypto_key_to_from_u64() {
let key = CryptoKey::AuthorityKey;
let uint: u64 = key.clone().into();
let key2 = CryptoKey::try_from(uint).unwrap();
assert_eq!(key, key2);
let key = CryptoKey::FgAuthorityKey;
let uint: u64 = key.clone().into();
let key2 = CryptoKey::try_from(uint).unwrap();
assert_eq!(key, key2);
let key = CryptoKey::LocalKey { id: 0, kind: CryptoKind::Ed25519 };
let uint: u64 = key.clone().into();
let key2 = CryptoKey::try_from(uint).unwrap();
assert_eq!(key, key2);
let key = CryptoKey::LocalKey { id: 10, kind: CryptoKind::Sr25519 };
let uint: u64 = key.clone().into();
let key2 = CryptoKey::try_from(uint).unwrap();
assert_eq!(key, key2);
}
}