Deprecate ValidateUnsigned and prevent duplicate heartbeats (#3975)

* Add pre-dispatch checks for ValidateUnsigned

* Deprecate ValidateUnsigned.

* Bump specversion.

* Fix test.
This commit is contained in:
Tomasz Drwięga
2019-11-03 11:52:08 +01:00
committed by Gavin Wood
parent 45e79d617b
commit 69c4e2f7f0
7 changed files with 75 additions and 24 deletions
+7 -10
View File
@@ -88,7 +88,7 @@ use sr_staking_primitives::{
offence::{ReportOffence, Offence, Kind},
};
use support::{
decl_module, decl_event, decl_storage, print, ensure, Parameter, debug
decl_module, decl_event, decl_storage, print, Parameter, debug
};
use system::ensure_none;
use system::offchain::SubmitUnsignedTransaction;
@@ -243,24 +243,20 @@ decl_module! {
fn heartbeat(
origin,
heartbeat: Heartbeat<T::BlockNumber>,
signature: <T::AuthorityId as RuntimeAppPublic>::Signature
// since signature verification is done in `validate_unsigned`
// we can skip doing it here again.
_signature: <T::AuthorityId as RuntimeAppPublic>::Signature
) {
ensure_none(origin)?;
let current_session = <session::Module<T>>::current_index();
ensure!(current_session == heartbeat.session_index, "Outdated heartbeat received.");
let exists = <ReceivedHeartbeats>::exists(
&current_session,
&heartbeat.authority_index
);
let keys = Keys::<T>::get();
let maybe_public = keys.get(heartbeat.authority_index as usize);
if let (false, Some(public)) = (exists, maybe_public) {
let signature_valid = heartbeat.using_encoded(|encoded_heartbeat| {
public.verify(&encoded_heartbeat, &signature)
});
ensure!(signature_valid, "Invalid heartbeat signature.");
let public = keys.get(heartbeat.authority_index as usize);
if let (false, Some(public)) = (exists, public) {
Self::deposit_event(Event::<T>::HeartbeatReceived(public.clone()));
let network_state = heartbeat.network_state.encode();
@@ -563,6 +559,7 @@ impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> {
}
}
#[allow(deprecated)]
impl<T: Trait> support::unsigned::ValidateUnsigned for Module<T> {
type Call = Call<T>;
+7 -2
View File
@@ -103,6 +103,9 @@ fn heartbeat(
authority_index: u32,
id: UintAuthorityId,
) -> dispatch::Result {
#[allow(deprecated)]
use support::unsigned::ValidateUnsigned;
let heartbeat = Heartbeat {
block_number,
network_state: OpaqueNetworkState {
@@ -114,6 +117,8 @@ fn heartbeat(
};
let signature = id.sign(&heartbeat.encode()).unwrap();
#[allow(deprecated)] // Allow ValidateUnsigned
ImOnline::pre_dispatch(&crate::Call::heartbeat(heartbeat.clone(), signature.clone()))?;
ImOnline::heartbeat(
Origin::system(system::RawOrigin::None),
heartbeat,
@@ -170,8 +175,8 @@ fn late_heartbeat_should_fail() {
assert_eq!(Session::validators(), vec![1, 2, 3]);
// when
assert_noop!(heartbeat(1, 3, 0, 1.into()), "Outdated heartbeat received.");
assert_noop!(heartbeat(1, 1, 0, 1.into()), "Outdated heartbeat received.");
assert_noop!(heartbeat(1, 3, 0, 1.into()), "Transaction is outdated");
assert_noop!(heartbeat(1, 1, 0, 1.into()), "Transaction is outdated");
});
}