Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
2 changes: 2 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,7 @@ where
.saturating_sub(1);
let era = Era::mortal(period, current_block);
let extra = (
frame_system::CheckNonZeroSender::<Runtime>::new(),
frame_system::CheckSpecVersion::<Runtime>::new(),
frame_system::CheckTxVersion::<Runtime>::new(),
frame_system::CheckGenesis::<Runtime>::new(),
Expand Down Expand Up @@ -1322,6 +1323,7 @@ pub type BlockId = generic::BlockId<Block>;
///
/// [`sign`]: <../../testing/src/keyring.rs.html>
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckTxVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
Expand Down
100 changes: 100 additions & 0 deletions frame/system/src/extensions/check_non_zero_sender.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// This file is part of Substrate.

// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::Config;
use codec::{Decode, Encode};
use frame_support::weights::DispatchInfo;
use scale_info::TypeInfo;
use sp_runtime::{
traits::{DispatchInfoOf, Dispatchable, SignedExtension},
transaction_validity::{
InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
},
};
use sp_std::{marker::PhantomData, prelude::*};

/// Check to ensure that the sender is not the zero address.
#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
#[scale_info(skip_type_params(T))]
pub struct CheckNonZeroSender<T: Config + Send + Sync>(PhantomData<T>);

impl<T: Config + Send + Sync> sp_std::fmt::Debug for CheckNonZeroSender<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckNonZeroSender")
}

#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}

impl<T: Config + Send + Sync> CheckNonZeroSender<T> {
/// Create new `SignedExtension` to check runtime version.
pub fn new() -> Self {
Self(sp_std::marker::PhantomData)
}
}

impl<T: Config + Send + Sync> SignedExtension for CheckNonZeroSender<T>
where
T::Call: Dispatchable<Info = DispatchInfo>,
{
type AccountId = T::AccountId;
type Call = T::Call;
type AdditionalSigned = ();
type Pre = ();
const IDENTIFIER: &'static str = "CheckNonZero";
Comment thread
gavofyork marked this conversation as resolved.
Outdated

fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
Ok(())
}

fn validate(
&self,
who: &Self::AccountId,
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> TransactionValidity {
if who.using_encoded(|d| d.into_iter().all(|x| *x == 0)) {
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner))
}
Ok(ValidTransaction::default())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{new_test_ext, Test, CALL};
use frame_support::{assert_noop, assert_ok};

#[test]
fn zero_account_ban_works() {
new_test_ext().execute_with(|| {
let info = DispatchInfo::default();
let len = 0_usize;
assert_noop!(
CheckNonZeroSender::<Test>::new().validate(&0, CALL, &info, len),
InvalidTransaction::BadSigner
);
assert_ok!(CheckNonZeroSender::<Test>::new().validate(&1, CALL, &info, len),);
Comment thread
shawntabrizi marked this conversation as resolved.
Outdated
})
}
}
1 change: 1 addition & 0 deletions frame/system/src/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

pub mod check_genesis;
pub mod check_mortality;
pub mod check_non_zero_sender;
pub mod check_nonce;
pub mod check_spec_version;
pub mod check_tx_version;
Expand Down
3 changes: 2 additions & 1 deletion frame/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ mod tests;
pub mod weights;

pub use extensions::{
check_genesis::CheckGenesis, check_mortality::CheckMortality, check_nonce::CheckNonce,
check_genesis::CheckGenesis, check_mortality::CheckMortality,
check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce,
check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion,
check_weight::CheckWeight,
};
Expand Down
3 changes: 3 additions & 0 deletions primitives/runtime/src/transaction_validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ pub enum InvalidTransaction {
/// A transaction with a mandatory dispatch. This is invalid; only inherent extrinsics are
/// allowed to have mandatory dispatches.
MandatoryDispatch,
/// The sending address is disabled or known to be invalid.
BadSigner,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will require that clients update before.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it is not a hard requirement, aka we don't break authoring. We will just get a failure on validate_block when trying to decode the return value.

}

impl InvalidTransaction {
Expand Down Expand Up @@ -109,6 +111,7 @@ impl From<InvalidTransaction> for &'static str {
InvalidTransaction::MandatoryDispatch =>
"Transaction dispatch is mandatory; transactions may not have mandatory dispatches.",
InvalidTransaction::Custom(_) => "InvalidTransaction custom error",
InvalidTransaction::BadSigner => "Invalid signing address",
}
}
}
Expand Down