Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
move justification verification to sync folder
  • Loading branch information
maciejnems committed Jan 13, 2023
commit fc19a316da4290731c5274cef87133bf596d9c21
63 changes: 5 additions & 58 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,8 +57,8 @@ 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> {
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
Expand Down
2 changes: 2 additions & 0 deletions 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
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
3 changes: 3 additions & 0 deletions finality-aleph/src/sync/substrate/verification/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod verifier;

pub use verifier::SessionVerifier;
90 changes: 90 additions & 0 deletions finality-aleph/src/sync/substrate/verification/verifier.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use std::fmt::{Display, Error as FmtError, Formatter};

use aleph_primitives::SessionAuthorityData;
use codec::Encode;
use log::warn;
use sp_runtime::{traits::Block as BlockT, RuntimeAppPublic};

use crate::{
crypto::AuthorityVerifier,
justification::{AlephJustification, Verifier as LegacyVerifier},
AuthorityId,
};

/// A justification verifier within a single session.
#[derive(Clone, PartialEq, Debug)]
pub struct SessionVerifier {
authority_verifier: AuthorityVerifier,
emergency_signer: Option<AuthorityId>,
}

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

/// Ways in which a justification can be wrong.
#[derive(Debug, PartialEq, Eq)]
pub enum SessionVerificationError {
BadMultisignature,
BadEmergencySignature,
NoEmergencySigner,
}

impl Display for SessionVerificationError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
use SessionVerificationError::*;
match self {
BadMultisignature => write!(f, "bad multisignature"),
BadEmergencySignature => write!(f, "bad emergency signature"),
NoEmergencySigner => write!(f, "no emergency signer defined"),
}
}
}

impl SessionVerifier {
/// Verifies the correctness of a justification for supplied bytes.
pub fn verify_bytes(
&self,
justification: &AlephJustification,
bytes: Vec<u8>,
) -> Result<(), SessionVerificationError> {
use AlephJustification::*;
use SessionVerificationError::*;
match justification {
CommitteeMultisignature(multisignature) => {
match self.authority_verifier.is_complete(&bytes, multisignature) {
true => Ok(()),
false => Err(BadMultisignature),
}
}
EmergencySignature(signature) => match self
.emergency_signer
.as_ref()
.ok_or(NoEmergencySigner)?
.verify(&bytes, signature)
{
true => Ok(()),
false => Err(BadEmergencySignature),
},
}
}
}

// This shouldn't be necessary after we remove the legacy justification sync. Then we can also
// rewrite the implementation above and make it simpler.
impl<B: BlockT> LegacyVerifier<B> for SessionVerifier {
fn verify(&self, justification: &AlephJustification, hash: B::Hash) -> bool {
match self.verify_bytes(justification, hash.encode()) {
Ok(()) => true,
Err(e) => {
warn!(target: "aleph-justification", "Bad justification for block {:?}: {}", hash, e);
false
}
}
}
}