diff --git a/finality-aleph/src/network/manager/compatibility.rs b/finality-aleph/src/network/manager/compatibility.rs index 8e40afac4e..8d489d34d6 100644 --- a/finality-aleph/src/network/manager/compatibility.rs +++ b/finality-aleph/src/network/manager/compatibility.rs @@ -130,34 +130,107 @@ impl Display for Error { #[cfg(test)] mod test { + use std::sync::Arc; + use codec::{Decode, Encode}; + use sp_keystore::testing::KeyStore; use super::{DiscoveryMessage, VersionedAuthentication}; use crate::{ + crypto::AuthorityVerifier, network::{ manager::{compatibility::MAX_AUTHENTICATION_SIZE, SessionHandler}, - mock::{crypto_basics, MockMultiaddress, MockNetworkIdentity}, + mock::MockMultiaddress, NetworkIdentity, }, - SessionId, Version, + nodes::testing::new_pen, + tcp_network::{testing::new_identity, TcpMultiaddress}, + NodeIndex, SessionId, Version, }; - #[tokio::test] - async fn correctly_decodes_v1() { - let crypto_basics = crypto_basics(1).await; - let handler = SessionHandler::new( - Some(crypto_basics.0[0].clone()), - crypto_basics.1.clone(), - SessionId(43), - MockNetworkIdentity::new().identity().0, + /// Session Handler used for generating versioned authentication in `raw_authentication_v1` + async fn handler() -> SessionHandler { + let mnemonic = "ring cool spatial rookie need wing opinion pond fork garbage more april"; + let external_addresses = vec![ + String::from("addr1"), + String::from("addr2"), + String::from("addr3"), + ]; + + let keystore = Arc::new(KeyStore::new()); + let pen = new_pen(mnemonic, keystore).await; + let identity = new_identity( + external_addresses.into_iter().map(String::from).collect(), + pen.authority_id(), + ); + + SessionHandler::new( + Some((NodeIndex(21), pen)), + AuthorityVerifier::new(vec![]), + SessionId(37), + identity.identity().0, ) .await - .unwrap(); + .unwrap() + } + + /// Versioned authentication for authority with: + /// external_addresses: [String::from("addr1"), String::from("addr2"), String::from("addr3")] + /// derived from mnemonic "ring cool spatial rookie need wing opinion pond fork garbage more april" + /// for node index 21 and session id 37 + /// encoded at version of Aleph Node from r-8.0 + fn raw_authentication_v1() -> Vec { + vec![ + 1, 0, 192, 0, 1, 12, 50, 40, 192, 239, 72, 72, 119, 156, 76, 37, 212, 220, 76, 165, 39, + 73, 20, 89, 77, 66, 171, 174, 61, 31, 254, 137, 186, 1, 7, 141, 187, 219, 20, 97, 100, + 100, 114, 49, 50, 40, 192, 239, 72, 72, 119, 156, 76, 37, 212, 220, 76, 165, 39, 73, + 20, 89, 77, 66, 171, 174, 61, 31, 254, 137, 186, 1, 7, 141, 187, 219, 20, 97, 100, 100, + 114, 50, 50, 40, 192, 239, 72, 72, 119, 156, 76, 37, 212, 220, 76, 165, 39, 73, 20, 89, + 77, 66, 171, 174, 61, 31, 254, 137, 186, 1, 7, 141, 187, 219, 20, 97, 100, 100, 114, + 51, 21, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 166, 39, 166, 74, 57, 190, 80, 240, 169, 85, + 240, 126, 250, 119, 54, 24, 244, 91, 199, 127, 32, 78, 52, 98, 159, 182, 227, 170, 251, + 49, 47, 89, 13, 171, 79, 190, 220, 22, 65, 254, 25, 115, 232, 103, 177, 252, 161, 222, + 74, 18, 216, 213, 105, 220, 223, 247, 221, 85, 31, 146, 177, 96, 254, 9, + ] + } + + #[tokio::test] + async fn correcly_encodes_v1_to_bytes() { + let handler = handler().await; + let raw = raw_authentication_v1(); + + let authentication_v1 = VersionedAuthentication::V1(DiscoveryMessage::Authentication( + handler.authentication().unwrap(), + )); + + assert_eq!(authentication_v1.encode(), raw); + } + + #[tokio::test] + async fn correcly_decodes_v1_from_bytes() { + let handler = handler().await; + let raw = raw_authentication_v1(); + let authentication_v1 = VersionedAuthentication::V1(DiscoveryMessage::Authentication( handler.authentication().unwrap(), )); + + let decoded = VersionedAuthentication::decode(&mut raw.as_slice()); + + assert_eq!(decoded, Ok(authentication_v1)); + } + + #[tokio::test] + async fn correctly_decodes_v1_roundtrip() { + let handler = handler().await; + + let authentication_v1 = VersionedAuthentication::V1(DiscoveryMessage::Authentication( + handler.authentication().unwrap(), + )); + let encoded = authentication_v1.encode(); let decoded = VersionedAuthentication::decode(&mut encoded.as_slice()); + assert_eq!(decoded, Ok(authentication_v1)) } diff --git a/finality-aleph/src/nodes/mod.rs b/finality-aleph/src/nodes/mod.rs index fb36090eea..d9e6d52e74 100644 --- a/finality-aleph/src/nodes/mod.rs +++ b/finality-aleph/src/nodes/mod.rs @@ -29,6 +29,11 @@ use crate::{ JustificationNotification, Metrics, MillisecsPerBlock, SessionPeriod, }; +#[cfg(test)] +pub mod testing { + pub use super::validator_node::new_pen; +} + /// Max amount of tries we can not update a finalized block number before we will clear requests queue const MAX_ATTEMPTS: u32 = 5; diff --git a/finality-aleph/src/nodes/validator_node.rs b/finality-aleph/src/nodes/validator_node.rs index b6ed7b619b..6576ac2449 100644 --- a/finality-aleph/src/nodes/validator_node.rs +++ b/finality-aleph/src/nodes/validator_node.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use std::{marker::PhantomData, sync::Arc}; use bip39::{Language, Mnemonic, MnemonicType}; use futures::channel::oneshot; @@ -6,6 +6,7 @@ use log::{debug, error}; use sc_client_api::Backend; use sc_network::ExHashT; use sp_consensus::SelectChain; +use sp_keystore::CryptoStore; use sp_runtime::traits::Block; use crate::{ @@ -26,6 +27,16 @@ use crate::{ AlephConfig, }; +pub async fn new_pen(mnemonic: &str, keystore: Arc) -> AuthorityPen { + let validator_peer_id = keystore + .ed25519_generate_new(KEY_TYPE, Some(mnemonic)) + .await + .expect("generating a key should work"); + AuthorityPen::new_with_key_type(validator_peer_id.into(), keystore, KEY_TYPE) + .await + .expect("we just generated this key so everything should work") +} + pub async fn run_validator_node(aleph_config: AlephConfig) where B: Block, @@ -55,21 +66,15 @@ where // We generate the phrase manually to only save the key in RAM, we don't want to have these // relatively low-importance keys getting spammed around the absolutely crucial Aleph keys. // The interface of `ed25519_generate_new` only allows to save in RAM by providing a mnemonic. - let validator_peer_id = keystore - .ed25519_generate_new( - KEY_TYPE, - Some(Mnemonic::new(MnemonicType::Words12, Language::English).phrase()), - ) - .await - .expect("generating a key should work"); - let network_authority_pen = - AuthorityPen::new_with_key_type(validator_peer_id.into(), keystore.clone(), KEY_TYPE) - .await - .expect("we just generated this key so everything should work"); + let network_authority_pen = new_pen( + Mnemonic::new(MnemonicType::Words12, Language::English).phrase(), + keystore.clone(), + ) + .await; let (dialer, listener, network_identity) = new_tcp_network( ("0.0.0.0", validator_port), external_addresses, - validator_peer_id.into(), + network_authority_pen.authority_id(), ) .await .expect("we should have working networking"); diff --git a/finality-aleph/src/tcp_network.rs b/finality-aleph/src/tcp_network.rs index dd2ee8ef5b..e338344d18 100644 --- a/finality-aleph/src/tcp_network.rs +++ b/finality-aleph/src/tcp_network.rs @@ -127,6 +127,21 @@ impl NetworkIdentity for TcpNetworkIdentity { } } +impl TcpNetworkIdentity { + fn new(external_addresses: Vec, peer_id: AuthorityId) -> TcpNetworkIdentity { + TcpNetworkIdentity { + addresses: external_addresses + .into_iter() + .map(|address| TcpMultiaddress { + peer_id: peer_id.clone(), + address, + }) + .collect(), + peer_id, + } + } +} + /// Create a new tcp network, including an identity that can be used for constructing /// authentications for other peers. pub async fn new_tcp_network( @@ -139,15 +154,21 @@ pub async fn new_tcp_network( impl NetworkIdentity, )> { let listener = TcpListener::bind(listening_addresses).await?; - let identity = TcpNetworkIdentity { - addresses: external_addresses - .into_iter() - .map(|address| TcpMultiaddress { - peer_id: peer_id.clone(), - address, - }) - .collect(), - peer_id, - }; + let identity = TcpNetworkIdentity::new(external_addresses, peer_id); Ok((TcpDialer {}, listener, identity)) } + +#[cfg(test)] +pub mod testing { + use aleph_primitives::AuthorityId; + + use super::{TcpMultiaddress, TcpNetworkIdentity}; + use crate::network::NetworkIdentity; + + pub fn new_identity( + external_addresses: Vec, + peer_id: AuthorityId, + ) -> impl NetworkIdentity { + TcpNetworkIdentity::new(external_addresses, peer_id) + } +}