Skip to content

A0-1820: implement substrate specific verifier for sync protocol #864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion finality-aleph/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn verify(authority: &AuthorityId, message: &[u8], signature: &Signature) ->

/// Holds the public authority keys for a session allowing for verification of messages from that
/// session.
#[derive(Clone)]
#[derive(PartialEq, Clone, Debug)]
pub struct AuthorityVerifier {
authorities: Vec<AuthorityId>,
}
Expand Down
67 changes: 7 additions & 60 deletions finality-aleph/src/nodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,23 @@ mod validator_node;

use std::{future::Future, sync::Arc};

use aleph_primitives::{AuthorityId, SessionAuthorityData};
use codec::Encode;
use log::warn;
pub use nonvalidator_node::run_nonvalidator_node;
use sc_client_api::Backend;
use sc_network::NetworkService;
use sc_network_common::ExHashT;
use sp_runtime::{
traits::{Block, Header, NumberFor},
RuntimeAppPublic,
};
use sp_runtime::traits::{Block, Header, NumberFor};
pub use validator_node::run_validator_node;

use crate::{
crypto::AuthorityVerifier,
finalization::AlephFinalizer,
justification::{
AlephJustification, JustificationHandler, JustificationRequestSchedulerImpl, SessionInfo,
SessionInfoProvider, Verifier,
JustificationHandler, JustificationRequestSchedulerImpl, SessionInfo, SessionInfoProvider,
},
last_block_of_session, mpsc,
mpsc::UnboundedSender,
session_id_from_block_num,
session_map::ReadOnlySessionMap,
sync::SessionVerifier,
BlockchainBackend, JustificationNotification, Metrics, MillisecsPerBlock, SessionPeriod,
};

Expand All @@ -38,52 +31,6 @@ pub mod testing {
/// Max amount of tries we can not update a finalized block number before we will clear requests queue
const MAX_ATTEMPTS: u32 = 5;

struct JustificationVerifier {
authority_verifier: AuthorityVerifier,
emergency_signer: Option<AuthorityId>,
}

impl From<SessionAuthorityData> for JustificationVerifier {
fn from(authority_data: SessionAuthorityData) -> Self {
JustificationVerifier {
authority_verifier: AuthorityVerifier::new(authority_data.authorities().to_vec()),
emergency_signer: authority_data.emergency_finalizer().clone(),
}
}
}

impl<B: Block> Verifier<B> for JustificationVerifier {
fn verify(&self, justification: &AlephJustification, hash: B::Hash) -> bool {
use AlephJustification::*;
let encoded_hash = hash.encode();
match justification {
CommitteeMultisignature(multisignature) => match self
.authority_verifier
.is_complete(&encoded_hash, multisignature)
{
true => true,
false => {
warn!(target: "aleph-justification", "Bad multisignature for block hash #{:?} {:?}", hash, multisignature);
false
}
},
EmergencySignature(signature) => match &self.emergency_signer {
Some(emergency_signer) => match emergency_signer.verify(&encoded_hash, signature) {
true => true,
false => {
warn!(target: "aleph-justification", "Bad emergency signature for block hash #{:?} {:?}", hash, signature);
false
}
},
None => {
warn!(target: "aleph-justification", "Received emergency signature for block with hash #{:?}, which has no emergency signer defined.", hash);
false
}
},
}
}
}

struct JustificationParams<B: Block, H: ExHashT, C, BB> {
pub network: Arc<NetworkService<B, H>>,
pub client: Arc<C>,
Expand All @@ -110,10 +57,10 @@ impl SessionInfoProviderImpl {
}

#[async_trait::async_trait]
impl<B: Block> SessionInfoProvider<B, JustificationVerifier> for SessionInfoProviderImpl {
async fn for_block_num(&self, number: NumberFor<B>) -> SessionInfo<B, JustificationVerifier> {
let current_session = session_id_from_block_num::<B>(number, self.session_period);
let last_block_height = last_block_of_session::<B>(current_session, self.session_period);
impl<B: Block> SessionInfoProvider<B, SessionVerifier> for SessionInfoProviderImpl {
async fn for_block_num(&self, number: NumberFor<B>) -> SessionInfo<B, SessionVerifier> {
let current_session = session_id_from_block_num(number, self.session_period);
let last_block_height = last_block_of_session(current_session, self.session_period);
let verifier = self
.session_authorities
.get(current_session)
Expand Down
9 changes: 5 additions & 4 deletions finality-aleph/src/party/impls.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{marker::PhantomData, sync::Arc};

use sc_client_api::Backend;
use sp_runtime::traits::{Block as BlockT, NumberFor, SaturatedConversion};
use sp_runtime::traits::{Block as BlockT, NumberFor};

use crate::{
party::traits::{Block, ChainState, SessionInfo},
session::{first_block_of_session, last_block_of_session, session_id_from_block_num},
ClientForAleph, SessionId, SessionPeriod,
};

Expand Down Expand Up @@ -44,14 +45,14 @@ impl SessionInfoImpl {

impl<B: BlockT> SessionInfo<B> for SessionInfoImpl {
fn session_id_from_block_num(&self, n: NumberFor<B>) -> SessionId {
SessionId(n.saturated_into::<u32>() / self.session_period.0)
session_id_from_block_num(n, self.session_period)
}

fn last_block_of_session(&self, session_id: SessionId) -> NumberFor<B> {
((session_id.0 + 1) * self.session_period.0 - 1).into()
last_block_of_session(session_id, self.session_period)
}

fn first_block_of_session(&self, session_id: SessionId) -> NumberFor<B> {
(session_id.0 * self.session_period.0).into()
first_block_of_session(session_id, self.session_period)
}
}
15 changes: 9 additions & 6 deletions finality-aleph/src/party/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use crate::{
manager::AuthorityTask,
traits::{Block, ChainState, NodeSessionManager, SessionInfo, SyncState},
},
AuthorityId, NodeIndex, SessionId,
session::{first_block_of_session, last_block_of_session, session_id_from_block_num},
AuthorityId, NodeIndex, SessionId, SessionPeriod,
};

type AMutex<T> = Arc<Mutex<T>>;
Expand Down Expand Up @@ -183,25 +184,27 @@ impl NodeSessionManager for Arc<MockNodeSessionManager> {
}

pub struct MockSessionInfo {
pub session_period: u32,
pub session_period: SessionPeriod,
}

impl MockSessionInfo {
pub fn new(session_period: u32) -> Self {
Self { session_period }
Self {
session_period: SessionPeriod(session_period),
}
}
}

impl SessionInfo<SimpleBlock> for MockSessionInfo {
fn session_id_from_block_num(&self, n: u32) -> SessionId {
SessionId(n / self.session_period)
session_id_from_block_num(n, self.session_period)
}

fn last_block_of_session(&self, session_id: SessionId) -> u32 {
(session_id.0 + 1) * self.session_period - 1
last_block_of_session(session_id, self.session_period)
}

fn first_block_of_session(&self, session_id: SessionId) -> u32 {
session_id.0 * self.session_period
first_block_of_session(session_id, self.session_period)
}
}
39 changes: 30 additions & 9 deletions finality-aleph/src/session.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use codec::{Decode, Encode};
use sp_runtime::{traits::Block, SaturatedConversion};
use sp_runtime::{
traits::{AtLeast32BitUnsigned, Block},
SaturatedConversion,
};

use crate::NumberFor;

Expand All @@ -12,8 +15,8 @@ pub struct SessionBoundaries<B: Block> {
impl<B: Block> SessionBoundaries<B> {
pub fn new(session_id: SessionId, period: SessionPeriod) -> Self {
SessionBoundaries {
first_block: first_block_of_session::<B>(session_id, period),
last_block: last_block_of_session::<B>(session_id, period),
first_block: first_block_of_session(session_id, period),
last_block: last_block_of_session(session_id, period),
}
}

Expand All @@ -26,22 +29,40 @@ impl<B: Block> SessionBoundaries<B> {
}
}

pub fn first_block_of_session<B: Block>(
pub fn first_block_of_session<N: AtLeast32BitUnsigned>(
session_id: SessionId,
period: SessionPeriod,
) -> NumberFor<B> {
) -> N {
(session_id.0 * period.0).into()
}

pub fn last_block_of_session<B: Block>(
pub fn last_block_of_session<N: AtLeast32BitUnsigned>(
session_id: SessionId,
period: SessionPeriod,
) -> NumberFor<B> {
) -> N {
((session_id.0 + 1) * period.0 - 1).into()
}

pub fn session_id_from_block_num<B: Block>(num: NumberFor<B>, period: SessionPeriod) -> SessionId {
SessionId(num.saturated_into::<u32>() / period.0)
pub fn session_id_from_block_num<N: AtLeast32BitUnsigned>(
num: N,
period: SessionPeriod,
) -> SessionId {
SessionId((num / period.0.into()).saturated_into())
}

#[cfg(test)]
pub mod testing {
use aleph_primitives::SessionAuthorityData;
use sp_runtime::testing::UintAuthorityId;

pub fn authority_data(from: u64, to: u64) -> SessionAuthorityData {
SessionAuthorityData::new(
(from..to)
.map(|id| UintAuthorityId(id).to_public_key())
.collect(),
None,
)
}
}

#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd, Encode, Decode)]
Expand Down
18 changes: 4 additions & 14 deletions finality-aleph/src/session_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,15 @@ where
}

async fn update_session(&mut self, session_id: SessionId, period: SessionPeriod) {
let first_block = first_block_of_session::<B>(session_id, period);
let first_block = first_block_of_session(session_id, period);
self.handle_first_block_of_session(first_block, session_id)
.await;
}

fn catch_up_boundaries(&self, period: SessionPeriod) -> (SessionId, SessionId) {
let last_finalized = self.finality_notificator.last_finalized();

let current_session = session_id_from_block_num::<B>(last_finalized, period);
let current_session = session_id_from_block_num(last_finalized, period);
let starting_session = SessionId(current_session.0.saturating_sub(PRUNING_THRESHOLD));

(starting_session, current_session)
Expand All @@ -343,7 +343,7 @@ where
let last_finalized = header.number();
trace!(target: "aleph-session-updater", "got FinalityNotification about #{:?}", last_finalized);

let session_id = session_id_from_block_num::<B>(*last_finalized, period);
let session_id = session_id_from_block_num(*last_finalized, period);

if last_updated >= session_id {
continue;
Expand All @@ -366,15 +366,14 @@ mod tests {
use sc_block_builder::BlockBuilderProvider;
use sc_utils::mpsc::tracing_unbounded;
use sp_consensus::BlockOrigin;
use sp_runtime::testing::UintAuthorityId;
use substrate_test_runtime_client::{
ClientBlockImportExt, DefaultTestClientBuilderExt, TestClient, TestClientBuilder,
TestClientBuilderExt,
};
use tokio::sync::oneshot::error::TryRecvError;

use super::*;
use crate::testing::mocks::TBlock;
use crate::{session::testing::authority_data, testing::mocks::TBlock};

struct MockProvider {
pub session_map: HashMap<NumberFor<TBlock>, SessionAuthorityData>,
Expand Down Expand Up @@ -432,15 +431,6 @@ mod tests {
}
}

fn authority_data(from: u64, to: u64) -> SessionAuthorityData {
SessionAuthorityData::new(
(from..to)
.map(|id| UintAuthorityId(id).to_public_key())
.collect(),
None,
)
}

fn n_new_blocks(client: &mut Arc<TestClient>, n: u64) -> Vec<TBlock> {
(0..n)
.map(|_| {
Expand Down
4 changes: 3 additions & 1 deletion finality-aleph/src/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ mod substrate;
mod task_queue;
mod ticker;

pub use substrate::SessionVerifier;

const LOG_TARGET: &str = "aleph-block-sync";

/// The identifier of a block, the least amount of knowledge we can have about a block.
Expand Down Expand Up @@ -50,7 +52,7 @@ pub trait Verifier<J: Justification> {

/// Verifies the raw justification and returns a full justification if successful, otherwise an
/// error.
fn verify(&self, justification: J::Unverified) -> Result<J, Self::Error>;
fn verify(&mut self, justification: J::Unverified) -> Result<J, Self::Error>;
}

/// A facility for finalizing blocks using justifications.
Expand Down
4 changes: 4 additions & 0 deletions finality-aleph/src/sync/substrate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ use crate::{
mod chain_status;
mod finalizer;
mod status_notifier;
mod verification;

pub use verification::SessionVerifier;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BlockId<H: SubstrateHeader<Number = BlockNumber>> {
hash: H::Hash,
number: H::Number,
}

/// An identifier uniquely specifying a block and its height.
impl<SH: SubstrateHeader<Number = BlockNumber>> Hash for BlockId<SH> {
fn hash<H>(&self, state: &mut H)
where
Expand Down
Loading