Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Verify signature and session index during apply phase of im-online. #3418

Merged
merged 4 commits into from
Aug 16, 2019
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
43 changes: 39 additions & 4 deletions core/sr-primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,14 @@ pub trait SignedExtension:
fn additional_signed(&self) -> Result<Self::AdditionalSigned, &'static str>;

/// Validate a signed transaction for the transaction queue.
///
/// This function can be called frequently by the transaction queue,
/// to obtain transaction validity against current state.
/// It should perform all checks that determine a valid transaction,
/// that can pay for it's execution and quickly eliminate ones
/// that are stale or incorrect.
///
/// Make sure to perform the same checks in `pre_dispatch` function.
fn validate(
&self,
_who: &Self::AccountId,
Expand All @@ -885,6 +893,13 @@ pub trait SignedExtension:
}

/// Do any pre-flight stuff for a signed transaction.
///
/// Note this function by default delegates to `validate`, so that
/// all checks performed for the transaction queue are also performed during
/// the dispatch phase (applying the extrinsic).
///
/// If you ever override this function, you need to make sure to always
/// perform the same validation as in `validate`.
fn pre_dispatch(
self,
who: &Self::AccountId,
Expand All @@ -895,16 +910,31 @@ pub trait SignedExtension:
self.validate(who, call, info, len).map(|_| Self::Pre::default())
}

/// Validate an unsigned transaction for the transaction queue. Normally the default
/// implementation is fine since `ValidateUnsigned` is a better way of recognising and
/// validating unsigned transactions.
/// Validate an unsigned transaction for the transaction queue.
///
/// Normally the default implementation is fine since `ValidateUnsigned`
/// is a better way of recognising and validating unsigned transactions.
///
/// This function can be called frequently by the transaction queue,
/// to obtain transaction validity against current state.
/// It should perform all checks that determine a valid unsigned transaction,
/// and quickly eliminate ones that are stale or incorrect.
///
/// Make sure to perform the same checks in `pre_dispatch_unsigned` function.
fn validate_unsigned(
_call: &Self::Call,
_info: DispatchInfo,
_len: usize,
) -> Result<ValidTransaction, DispatchError> { Ok(Default::default()) }

/// Do any pre-flight stuff for a unsigned transaction.
///
/// Note this function by default delegates to `validate_unsigned`, so that
/// all checks performed for the transaction queue are also performed during
/// the dispatch phase (applying the extrinsic).
///
/// If you ever override this function, you need to make sure to always
/// perform the same validation as in `validate_unsigned`.
fn pre_dispatch_unsigned(
call: &Self::Call,
info: DispatchInfo,
Expand Down Expand Up @@ -1095,7 +1125,12 @@ pub trait RuntimeApiInfo {
const VERSION: u32;
}

/// Something that can validate unsigned extrinsics.
/// Something that can validate unsigned extrinsics for the transaction pool.
///
/// Note that any checks done here are only used for determining the validity of
/// the transaction for the transaction pool.
/// During block execution phase one need to perform the same checks anyway,
/// since this function is not being called.
pub trait ValidateUnsigned {
/// The call to validate
type Call;
Expand Down
2 changes: 1 addition & 1 deletion node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 144,
impl_version: 144,
impl_version: 145,
apis: RUNTIME_API_VERSIONS,
};

Expand Down
10 changes: 8 additions & 2 deletions srml/im-online/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ use rstd::prelude::*;
use session::SessionIndex;
use sr_io::Printable;
use srml_support::{
StorageValue, decl_module, decl_event, decl_storage, StorageDoubleMap, print,
StorageValue, decl_module, decl_event, decl_storage, StorageDoubleMap, print, ensure
};
use system::ensure_none;
use app_crypto::RuntimeAppPublic;
Expand Down Expand Up @@ -206,18 +206,24 @@ decl_module! {
fn heartbeat(
origin,
heartbeat: Heartbeat<T::BlockNumber>,
_signature: AuthoritySignature
signature: AuthoritySignature
) {
ensure_none(origin)?;

let current_session = <session::Module<T>>::current_index();
ensure!(current_session == heartbeat.session_index, "Outdated hearbeat received.");
let exists = <ReceivedHeartbeats>::exists(
&current_session,
&heartbeat.authority_index
);
let keys = Keys::get();
let public = keys.get(heartbeat.authority_index as usize);
if let (true, Some(public)) = (!exists, public) {
let signature_valid = heartbeat.using_encoded(|encoded_heartbeat| {
public.verify(&encoded_heartbeat, &signature)
});
ensure!(signature_valid, "Invalid hearbeat signature.");

Self::deposit_event(Event::HeartbeatReceived(public.clone()));

let network_state = heartbeat.network_state.encode();
Expand Down