Overhaul crypto (Schnorr/Ristretto, HDKD, BIP39) (#1795)

* Rijig to Ristretto

* Rebuild wasm

* adds compatibility test with the wasm module

* Add Ed25519-BIP39 support

* Bump subkey version

* Update CLI output

* New keys.

* Standard phrase/password/path keys.

* Subkey uses S-URI for secrets

* Move everything to use new HDKD crypto.

* Test fixes

* Ignore old test vector.

* fix the ^^ old test vector.

* Fix tests

* Test fixes

* Cleanups

* Fix broken key conversion logic in grandpa

CC @rphmeier

* Remove legacy Keyring usage

* Traitify `Pair`

* Replace Ed25519AuthorityId with ed25519::Public

* Expunge Ed25519AuthorityId type!

* Replace Sr25519AuthorityId with sr25519::Public

* Remove dodgy crypto type-punning conversions

* Fix some tests

* Avoid trait

* Deduplicate DeriveJunction string decode

* Remove cruft code

* Fix test

* Minor removals

* Build fix

* Subkey supports sign and verify

* Inspect works for public key URIs

* Remove more crypto type-punning

* Fix typo

* Fix tests
This commit is contained in:
Gav Wood
2019-03-13 14:08:31 +01:00
committed by GitHub
parent 17f093da13
commit d7fcf5dc9d
83 changed files with 2636 additions and 1687 deletions
+8 -11
View File
@@ -18,38 +18,35 @@
use std::collections::HashMap;
use runtime_io::twox_128;
use super::AccountId;
use parity_codec::{Encode, KeyedVec, Joiner};
use primitives::{Ed25519AuthorityId, ChangesTrieConfiguration, map};
use primitives::storage::well_known_keys;
use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys};
use runtime_primitives::traits::Block;
use primitives::ed25519::Public as AuthorityId;
/// Configuration of a general Substrate test genesis block.
pub struct GenesisConfig {
pub changes_trie_config: Option<ChangesTrieConfiguration>,
pub authorities: Vec<Ed25519AuthorityId>,
pub balances: Vec<(Ed25519AuthorityId, u64)>,
pub authorities: Vec<AuthorityId>,
pub balances: Vec<(AccountId, u64)>,
}
impl GenesisConfig {
pub fn new_simple(authorities: Vec<Ed25519AuthorityId>, balance: u64) -> Self {
Self::new(false, authorities, balance)
}
pub fn new(support_changes_trie: bool, authorities: Vec<Ed25519AuthorityId>, balance: u64) -> Self {
pub fn new(support_changes_trie: bool, authorities: Vec<AuthorityId>, endowed_accounts: Vec<AccountId>, balance: u64) -> Self {
GenesisConfig {
changes_trie_config: match support_changes_trie {
true => Some(super::changes_trie_config()),
false => None,
},
authorities: authorities.clone(),
balances: authorities.into_iter().map(|a| (a, balance)).collect(),
balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(),
}
}
pub fn genesis_map(&self) -> HashMap<Vec<u8>, Vec<u8>> {
let wasm_runtime = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm").to_vec();
let mut map: HashMap<Vec<u8>, Vec<u8>> = self.balances.iter()
.map(|&(account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance)))
.map(|&(ref account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance)))
.map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec()))
.chain(vec![
(well_known_keys::CODE.into(), wasm_runtime),
+14 -8
View File
@@ -29,7 +29,7 @@ use substrate_client::{
impl_runtime_apis,
};
use runtime_primitives::{
ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity,
ApplyResult, transaction_validity::TransactionValidity,
create_runtime_str,
traits::{
BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT,
@@ -38,7 +38,7 @@ use runtime_primitives::{
};
use runtime_version::RuntimeVersion;
pub use primitives::hash::H256;
use primitives::{Ed25519AuthorityId, OpaqueMetadata};
use primitives::{ed25519, sr25519, OpaqueMetadata};
#[cfg(any(feature = "std", test))]
use runtime_version::NativeVersion;
use inherents::{CheckInherentsResult, InherentData};
@@ -81,8 +81,8 @@ pub struct Transfer {
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Extrinsic {
AuthoritiesChange(Vec<Ed25519AuthorityId>),
Transfer(Transfer, Ed25519Signature),
AuthoritiesChange(Vec<AuthorityId>),
Transfer(Transfer, AccountSignature),
}
#[cfg(feature = "std")]
@@ -125,8 +125,14 @@ impl Extrinsic {
}
}
// The identity type used by authorities.
pub type AuthorityId = ed25519::Public;
// The signature type used by authorities.
pub type AuthoritySignature = ed25519::Signature;
/// An identifier for an account on this system.
pub type AccountId = H256;
pub type AccountId = sr25519::Public;
// The signature type used by accounts/transactions.
pub type AccountSignature = sr25519::Signature;
/// A simple hash type for all our hashing.
pub type Hash = H256;
/// The block number type used in this runtime.
@@ -134,7 +140,7 @@ pub type BlockNumber = u64;
/// Index of a transaction.
pub type Index = u64;
/// The item of a block digest.
pub type DigestItem = runtime_primitives::generic::DigestItem<H256, Ed25519AuthorityId>;
pub type DigestItem = runtime_primitives::generic::DigestItem<H256, AuthorityId, AuthoritySignature>;
/// The digest of a block.
pub type Digest = runtime_primitives::generic::Digest<DigestItem>;
/// A test block.
@@ -256,7 +262,7 @@ cfg_if! {
version()
}
fn authorities() -> Vec<Ed25519AuthorityId> {
fn authorities() -> Vec<AuthorityId> {
system::authorities()
}
@@ -347,7 +353,7 @@ cfg_if! {
version()
}
fn authorities() -> Vec<Ed25519AuthorityId> {
fn authorities() -> Vec<AuthorityId> {
system::authorities()
}
+90 -59
View File
@@ -26,8 +26,8 @@ use runtime_primitives::generic;
use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity};
use parity_codec::{KeyedVec, Encode};
use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest};
use primitives::{Ed25519AuthorityId, Blake2Hasher};
use primitives::storage::well_known_keys;
use primitives::{Blake2Hasher, storage::well_known_keys};
use primitives::ed25519::Public as AuthorityId;
const NONCE_OF: &[u8] = b"nonce:";
const BALANCE_OF: &[u8] = b"balance:";
@@ -37,7 +37,7 @@ storage_items! {
// The current block number being processed. Set by `execute_block`.
Number: b"sys:num" => required BlockNumber;
ParentHash: b"sys:pha" => required Hash;
NewAuthorities: b"sys:new_auth" => Vec<Ed25519AuthorityId>;
NewAuthorities: b"sys:new_auth" => Vec<AuthorityId>;
}
pub fn balance_of_key(who: AccountId) -> Vec<u8> {
@@ -53,7 +53,7 @@ pub fn nonce_of(who: AccountId) -> u64 {
}
/// Get authorities ar given block.
pub fn authorities() -> Vec<Ed25519AuthorityId> {
pub fn authorities() -> Vec<AuthorityId> {
let len: u32 = storage::unhashed::get(well_known_keys::AUTHORITY_COUNT)
.expect("There are always authorities in test-runtime");
(0..len)
@@ -71,6 +71,36 @@ pub fn initialise_block(header: &Header) {
}
/// Actually execute all transitioning for `block`.
pub fn polish_block(block: &mut Block) {
let header = &mut block.header;
// check transaction trie root represents the transactions.
let txs = block.extrinsics.iter().map(Encode::encode).collect::<Vec<_>>();
let txs = txs.iter().map(Vec::as_slice).collect::<Vec<_>>();
let txs_root = enumerated_trie_root::<Blake2Hasher>(&txs).into();
info_expect_equal_hash(&txs_root, &header.extrinsics_root);
header.extrinsics_root = txs_root;
// execute transactions
block.extrinsics.iter().enumerate().for_each(|(i, e)| {
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32));
execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction"));
storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX);
});
header.state_root = storage_root().into();
// check digest
let mut digest = Digest::default();
if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into(), header.number - 1) {
digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into()));
}
if let Some(new_authorities) = <NewAuthorities>::take() {
digest.push(generic::DigestItem::AuthoritiesChange(new_authorities));
}
header.digest = digest;
}
pub fn execute_block(block: Block) {
let ref header = block.header;
@@ -83,9 +113,9 @@ pub fn execute_block(block: Block) {
// execute transactions
block.extrinsics.iter().enumerate().for_each(|(i, e)| {
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32));
execute_transaction_backend(e).map_err(|_| ()).expect("Extrinsic error");
storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX);
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32));
execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction"));
storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX);
});
// check storage root.
@@ -122,7 +152,7 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity {
}
let hash = |from: &AccountId, nonce: u64| {
twox_128(&nonce.to_keyed_vec(from.as_bytes())).to_vec()
twox_128(&nonce.to_keyed_vec(&from.encode())).to_vec()
};
let requires = if tx.nonce != expected_nonce && tx.nonce > 0 {
let mut deps = Vec::new();
@@ -144,7 +174,6 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity {
}
}
/// Execute a transaction outside of the block execution function.
/// This doesn't attempt to validate anything regarding the block.
pub fn execute_transaction(utx: Extrinsic) -> ApplyResult {
@@ -225,8 +254,8 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult {
Ok(ApplyOutcome::Success)
}
fn execute_new_authorities_backend(new_authorities: &[Ed25519AuthorityId]) -> ApplyResult {
let new_authorities: Vec<Ed25519AuthorityId> = new_authorities.iter().cloned().collect();
fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult {
let new_authorities: Vec<AuthorityId> = new_authorities.iter().cloned().collect();
<NewAuthorities>::put(new_authorities);
Ok(ApplyOutcome::Success)
}
@@ -258,12 +287,11 @@ mod tests {
use runtime_io::{with_externalities, twox_128, TestExternalities};
use parity_codec::{Joiner, KeyedVec};
use keyring::Keyring;
use crate::{Header, Digest, Extrinsic, Transfer};
use substrate_test_client::{AuthorityKeyring, AccountKeyring};
use crate::{Header, Extrinsic, Transfer};
use primitives::{Blake2Hasher, map};
use primitives::storage::well_known_keys;
use substrate_executor::WasmExecutor;
use hex_literal::{hex, hex_impl};
const WASM_CODE: &'static [u8] =
include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm");
@@ -272,36 +300,34 @@ mod tests {
TestExternalities::new(map![
twox_128(b"latest").to_vec() => vec![69u8; 32],
twox_128(well_known_keys::AUTHORITY_COUNT).to_vec() => vec![].and(&3u32),
twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Alice.to_raw_public().to_vec(),
twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Bob.to_raw_public().to_vec(),
twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Charlie.to_raw_public().to_vec(),
twox_128(&Keyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Alice.to_raw_public().to_vec(),
twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Bob.to_raw_public().to_vec(),
twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Charlie.to_raw_public().to_vec(),
twox_128(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
])
}
fn construct_signed_tx(tx: Transfer) -> Extrinsic {
let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into();
let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into();
Extrinsic::Transfer(tx, signature)
}
fn block_import_works<F>(block_executor: F) where F: Fn(Block, &mut TestExternalities<Blake2Hasher>) {
let mut t = new_test_ext();
let h = Header {
parent_hash: [69u8; 32].into(),
number: 1,
state_root: hex!("e51369d0b37e4aa1383f1e7a34c2eec75f18ee6b4b199a440f4f2456906e0eb7").into(),
extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(),
digest: Digest { logs: vec![], },
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
};
let b = Block {
let mut b = Block {
header: h,
extrinsics: vec![],
};
block_executor(b, &mut t);
with_externalities(&mut new_test_ext(), || polish_block(&mut b));
block_executor(b, &mut new_test_ext());
}
#[test]
@@ -321,69 +347,74 @@ mod tests {
}
fn block_import_with_transaction_works<F>(block_executor: F) where F: Fn(Block, &mut TestExternalities<Blake2Hasher>) {
let mut t = new_test_ext();
with_externalities(&mut t, || {
assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 111);
assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 0);
});
let b = Block {
let mut b1 = Block {
header: Header {
parent_hash: [69u8; 32].into(),
number: 1,
state_root: hex!("f61a14ce70846cd6a1714bbe1b63b2ca1172df1c8c01adfd798bb08bd30dc486").into(),
extrinsics_root: hex!("198205cb7729fec8ccdc2e58571a4858586a4f305898078e0e8bee1dddea7e4b").into(),
digest: Digest { logs: vec![], },
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
},
extrinsics: vec![
construct_signed_tx(Transfer {
from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Bob.to_raw_public().into(),
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Bob.into(),
amount: 69,
nonce: 0,
})
],
};
with_externalities(&mut t, || {
execute_block(b.clone());
let mut dummy_ext = new_test_ext();
with_externalities(&mut dummy_ext, || polish_block(&mut b1));
assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 42);
assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 69);
});
let b = Block {
let mut b2 = Block {
header: Header {
parent_hash: b.header.hash(),
parent_hash: b1.header.hash(),
number: 2,
state_root: hex!("a47383d9a5d6c8c7531386abccdf512c76729a1a19c59b6c2e4f95dde419923a").into(),
extrinsics_root: hex!("041fa8971dda28745967179a9f39e3ca1a595c510682105df1cff74ae6f05e0d").into(),
digest: Digest { logs: vec![], },
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
},
extrinsics: vec![
construct_signed_tx(Transfer {
from: Keyring::Bob.to_raw_public().into(),
to: Keyring::Alice.to_raw_public().into(),
from: AccountKeyring::Bob.into(),
to: AccountKeyring::Alice.into(),
amount: 27,
nonce: 0,
}),
construct_signed_tx(Transfer {
from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Charlie.to_raw_public().into(),
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Charlie.into(),
amount: 69,
nonce: 1,
}),
],
};
block_executor(b, &mut t);
with_externalities(&mut dummy_ext, || polish_block(&mut b2));
drop(dummy_ext);
let mut t = new_test_ext();
with_externalities(&mut t, || {
assert_eq!(balance_of(AccountKeyring::Alice.into()), 111);
assert_eq!(balance_of(AccountKeyring::Bob.into()), 0);
});
assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 0);
assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 42);
assert_eq!(balance_of(Keyring::Charlie.to_raw_public().into()), 69);
block_executor(b1, &mut t);
with_externalities(&mut t, || {
assert_eq!(balance_of(AccountKeyring::Alice.into()), 42);
assert_eq!(balance_of(AccountKeyring::Bob.into()), 69);
});
block_executor(b2, &mut t);
with_externalities(&mut t, || {
assert_eq!(balance_of(AccountKeyring::Alice.into()), 0);
assert_eq!(balance_of(AccountKeyring::Bob.into()), 42);
assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69);
});
}