Refactors the offchain worker api (#3150)

* Update offchain primitives.

* Update offchain worker.

* Update im-online.

* Update service.

* Update node and node-template.

* Update runtime version.

* Fix build.

* Fix offchain worker tests.

* Generalize authority_pubkey.

* Add test.

* Update lib.rs
This commit is contained in:
David Craven
2019-07-22 11:20:57 +02:00
committed by Gavin Wood
parent 2edeef5825
commit a3d19baea3
17 changed files with 509 additions and 327 deletions
+9 -4
View File
@@ -457,7 +457,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]> + Default + Derive> Ss58Codec for T {
}
/// Trait suitable for typical cryptographic PKI key public type.
pub trait Public: TypedKey + PartialEq + Eq {
pub trait Public: AsRef<[u8]> + TypedKey + PartialEq + Eq + Clone + Send + Sync {
/// 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
@@ -476,7 +476,7 @@ pub trait Public: TypedKey + PartialEq + Eq {
///
/// For now it just specifies how to create a key from a phrase and derivation path.
#[cfg(feature = "std")]
pub trait Pair: TypedKey + Sized + 'static {
pub trait Pair: TypedKey + Sized + Clone + Send + Sync + 'static {
/// The type which is used to encode a public key.
type Public: Public + Hash;
@@ -631,7 +631,7 @@ mod tests {
use hex_literal::hex;
use super::*;
#[derive(Eq, PartialEq, Debug)]
#[derive(Clone, Eq, PartialEq, Debug)]
enum TestPair {
Generated,
GeneratedWithPhrase,
@@ -640,8 +640,13 @@ mod tests {
Seed(Vec<u8>),
}
#[derive(PartialEq, Eq, Hash)]
#[derive(Clone, PartialEq, Eq, Hash)]
struct TestPublic;
impl AsRef<[u8]> for TestPublic {
fn as_ref(&self) -> &[u8] {
&[]
}
}
impl Public for TestPublic {
fn from_slice(_bytes: &[u8]) -> Self {
Self
+83 -25
View File
@@ -87,14 +87,49 @@ impl From<CryptoKind> for u32 {
}
}
/// Opaque type for created crypto keys.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// Key to use in the offchain worker crypto api.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct CryptoKeyId(pub u16);
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 From<CryptoKeyId> for u32 {
fn from(c: CryptoKeyId) -> Self {
c.0 as u32
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,
}
}
}
@@ -279,13 +314,13 @@ pub trait Externalities {
/// Returns information about the local node's network state.
fn network_state(&self) -> Result<OpaqueNetworkState, ()>;
/// Returns the locally configured authority public key, if available.
fn authority_pubkey(&self, crypto: CryptoKind) -> Result<Vec<u8>, ()>;
/// 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<CryptoKeyId, ()>;
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.
///
@@ -293,7 +328,7 @@ pub trait Externalities {
///
/// Returns an error if `key` is not available or does not exist,
/// or the expected `CryptoKind` does not match.
fn encrypt(&mut self, key: Option<CryptoKeyId>, kind: CryptoKind, data: &[u8]) -> Result<Vec<u8>, ()>;
fn encrypt(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
/// Decrypt a piece of data using given crypto key.
///
@@ -301,7 +336,7 @@ pub trait Externalities {
///
/// 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: Option<CryptoKeyId>, kind: CryptoKind, data: &[u8]) -> Result<Vec<u8>, ()>;
fn decrypt(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
/// Sign a piece of data using given crypto key.
///
@@ -309,14 +344,14 @@ pub trait Externalities {
///
/// Returns an error if `key` is not available or does not exist,
/// or the expected `CryptoKind` does not match.
fn sign(&mut self, key: Option<CryptoKeyId>, kind: CryptoKind, data: &[u8]) -> Result<Vec<u8>, ()>;
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: Option<CryptoKeyId>, kind: CryptoKind, msg: &[u8], signature: &[u8]) -> Result<bool, ()>;
fn verify(&mut self, key: CryptoKey, msg: &[u8], signature: &[u8]) -> Result<bool, ()>;
/// Returns current UNIX timestamp (in millis)
fn timestamp(&mut self) -> Timestamp;
@@ -431,32 +466,32 @@ impl<T: Externalities + ?Sized> Externalities for Box<T> {
(&mut **self).submit_transaction(ex)
}
fn new_crypto_key(&mut self, crypto: CryptoKind) -> Result<CryptoKeyId, ()> {
fn new_crypto_key(&mut self, crypto: CryptoKind) -> Result<CryptoKey, ()> {
(&mut **self).new_crypto_key(crypto)
}
fn encrypt(&mut self, key: Option<CryptoKeyId>, kind: CryptoKind, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).encrypt(key, kind, data)
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 authority_pubkey(&self, key:CryptoKind) -> Result<Vec<u8>, ()> {
(&**self).authority_pubkey(key)
fn pubkey(&self, key: CryptoKey) -> Result<Vec<u8>, ()> {
(&**self).pubkey(key)
}
fn decrypt(&mut self, key: Option<CryptoKeyId>, kind: CryptoKind, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).decrypt(key, kind, data)
fn decrypt(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).decrypt(key, data)
}
fn sign(&mut self, key: Option<CryptoKeyId>, kind: CryptoKind, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).sign(key, kind, data)
fn sign(&mut self, key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()> {
(&mut **self).sign(key, data)
}
fn verify(&mut self, key: Option<CryptoKeyId>, kind: CryptoKind, msg: &[u8], signature: &[u8]) -> Result<bool, ()> {
(&mut **self).verify(key, kind, msg, signature)
fn verify(&mut self, key: CryptoKey, msg: &[u8], signature: &[u8]) -> Result<bool, ()> {
(&mut **self).verify(key, msg, signature)
}
fn timestamp(&mut self) -> Timestamp {
@@ -536,4 +571,27 @@ 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);
}
}