Skip to content

Commit 0cda88b

Browse files
authored
Merge pull request #162 from bifrost-platform/feature-tx-extension
feat: create CheckBlockedOrigin tx extension
2 parents c462041 + 52562bd commit 0cda88b

File tree

9 files changed

+171
-12
lines changed

9 files changed

+171
-12
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pallets/bfc-utility/src/pallet/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub mod pallet {
3636
pub enum Error<T> {
3737
/// The given amount is too low to process.
3838
AmountTooLow,
39+
/// The account is already blocked.
40+
AccountAlreadyBlocked,
41+
/// The account is not blocked.
42+
AccountNotBlocked,
3943
}
4044

4145
#[pallet::event]
@@ -56,6 +60,16 @@ pub mod pallet {
5660
/// Storage for proposal index. Whenever proposal is accepted, index will be increased.
5761
pub type ProposalIndex<T: Config> = StorageValue<_, PropIndex, ValueQuery>;
5862

63+
#[pallet::storage]
64+
#[pallet::unbounded]
65+
pub type BlockedAccounts<T: Config> = StorageValue<_, Vec<T::AccountId>, ValueQuery>;
66+
67+
impl<T: Config> Pallet<T> {
68+
pub fn is_blocked_account(account: &T::AccountId) -> bool {
69+
BlockedAccounts::<T>::get().contains(account)
70+
}
71+
}
72+
5973
#[pallet::hooks]
6074
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
6175
fn on_runtime_upgrade() -> Weight {
@@ -124,5 +138,35 @@ pub mod pallet {
124138

125139
Ok(().into())
126140
}
141+
142+
#[pallet::call_index(2)]
143+
#[pallet::weight((T::DbWeight::get().writes(1), DispatchClass::Operational,))]
144+
/// Add an account to the blocked accounts list.
145+
pub fn add_blocked_account(
146+
origin: OriginFor<T>,
147+
account: T::AccountId,
148+
) -> DispatchResultWithPostInfo {
149+
ensure_root(origin)?;
150+
ensure!(!Self::is_blocked_account(&account), Error::<T>::AccountAlreadyBlocked);
151+
let mut blocked_accounts = BlockedAccounts::<T>::get();
152+
blocked_accounts.push(account);
153+
BlockedAccounts::<T>::put(blocked_accounts);
154+
Ok(().into())
155+
}
156+
157+
#[pallet::call_index(3)]
158+
#[pallet::weight((T::DbWeight::get().writes(1), DispatchClass::Operational,))]
159+
/// Remove an account from the blocked accounts list.
160+
pub fn remove_blocked_account(
161+
origin: OriginFor<T>,
162+
account: T::AccountId,
163+
) -> DispatchResultWithPostInfo {
164+
ensure_root(origin)?;
165+
ensure!(Self::is_blocked_account(&account), Error::<T>::AccountNotBlocked);
166+
let mut blocked_accounts = BlockedAccounts::<T>::get();
167+
blocked_accounts.retain(|a| a != &account);
168+
BlockedAccounts::<T>::put(blocked_accounts);
169+
Ok(().into())
170+
}
127171
}
128172
}

runtime/common/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ repository = { workspace = true }
1010

1111
[dependencies]
1212
parity-scale-codec = { workspace = true }
13+
scale-info = { workspace = true }
1314
ethereum = { workspace = true }
1415

1516
# Substrate
@@ -18,16 +19,19 @@ frame-support = { workspace = true }
1819
sp-core = { workspace = true }
1920
sp-runtime = { workspace = true }
2021
sp-std = { workspace = true }
22+
pallet-bfc-utility = { workspace = true }
2123

2224
[features]
2325
default = ["std"]
2426
std = [
27+
"scale-info/std",
2528
"ethereum/std",
2629
"parity-scale-codec/std",
2730
"frame-system/std",
2831
"frame-support/std",
2932
"sp-core/std",
3033
"sp-runtime/std",
3134
"sp-std/std",
35+
"pallet-bfc-utility/std",
3236
]
3337
try-runtime = ["frame-support/try-runtime"]

runtime/common/src/extensions.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use frame_support::pallet_prelude::{TransactionSource, TransactionValidityError};
2+
use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode};
3+
use scale_info::TypeInfo;
4+
5+
use sp_core::H160;
6+
use sp_runtime::{
7+
traits::{AsSystemOriginSigner, DispatchInfoOf, Dispatchable, TransactionExtension},
8+
Weight,
9+
};
10+
use sp_std::{
11+
fmt::{Debug, Formatter},
12+
marker::PhantomData,
13+
};
14+
15+
/// Transaction extension that blocks extrinsics from specific origins
16+
#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo, DecodeWithMemTracking)]
17+
#[scale_info(skip_type_params(T))]
18+
#[codec(encode_bound())]
19+
#[codec(decode_bound())]
20+
pub struct CheckBlockedOrigin<T, Call>(PhantomData<(T, Call)>);
21+
22+
impl<T, Call> Debug for CheckBlockedOrigin<T, Call> {
23+
fn fmt(&self, f: &mut Formatter) -> sp_std::fmt::Result {
24+
write!(f, "CheckBlockedOrigin")
25+
}
26+
}
27+
28+
impl<T, Call> Default for CheckBlockedOrigin<T, Call> {
29+
fn default() -> Self {
30+
Self::new()
31+
}
32+
}
33+
34+
impl<T, Call> CheckBlockedOrigin<T, Call> {
35+
pub fn new() -> Self {
36+
Self(PhantomData)
37+
}
38+
}
39+
40+
impl<T, Call> TransactionExtension<Call> for CheckBlockedOrigin<T, Call>
41+
where
42+
T: frame_system::Config + Send + Sync,
43+
T::AccountId: From<H160>,
44+
T: pallet_bfc_utility::Config,
45+
Call: Dispatchable + Clone + Eq + TypeInfo + Send + Sync + 'static,
46+
<Call as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<T::AccountId>,
47+
{
48+
const IDENTIFIER: &'static str = "CheckBlockedOrigin";
49+
type Implicit = ();
50+
type Pre = ();
51+
type Val = ();
52+
53+
fn weight(&self, _call: &Call) -> Weight {
54+
Weight::zero()
55+
}
56+
57+
fn validate(
58+
&self,
59+
origin: <Call as Dispatchable>::RuntimeOrigin,
60+
_call: &Call,
61+
_info: &DispatchInfoOf<Call>,
62+
_len: usize,
63+
_self_implicit: Self::Implicit,
64+
_inherited_implication: &impl Encode,
65+
_source: TransactionSource,
66+
) -> Result<
67+
(
68+
sp_runtime::transaction_validity::ValidTransaction,
69+
Self::Val,
70+
<Call as Dispatchable>::RuntimeOrigin,
71+
),
72+
TransactionValidityError,
73+
> {
74+
if let Some(who) = origin.as_system_origin_signer() {
75+
if pallet_bfc_utility::Pallet::<T>::is_blocked_account(who) {
76+
return Err(TransactionValidityError::Invalid(
77+
sp_runtime::transaction_validity::InvalidTransaction::BadSigner,
78+
));
79+
}
80+
}
81+
Ok((sp_runtime::transaction_validity::ValidTransaction::default(), (), origin))
82+
}
83+
84+
fn prepare(
85+
self,
86+
_val: Self::Val,
87+
_origin: &<Call as Dispatchable>::RuntimeOrigin,
88+
_call: &Call,
89+
_info: &DispatchInfoOf<Call>,
90+
_len: usize,
91+
) -> Result<Self::Pre, TransactionValidityError> {
92+
Ok(())
93+
}
94+
}

runtime/common/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22

33
mod apis;
44
mod self_contained_call;
5+
6+
pub mod extensions;

runtime/common/src/self_contained_call.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,26 @@ macro_rules! impl_self_contained_call {
1515
}
1616

1717
fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
18-
match self {
19-
RuntimeCall::Ethereum(call) => call.check_self_contained(),
20-
_ => None,
21-
}
22-
}
18+
match self {
19+
RuntimeCall::Ethereum(call) => {
20+
match call.check_self_contained()? {
21+
Ok(signer) => {
22+
let signer_account: AccountId = signer.into();
23+
if pallet_bfc_utility::Pallet::<Runtime>::is_blocked_account(&signer_account) {
24+
return Some(Err(TransactionValidityError::Invalid(
25+
sp_runtime::transaction_validity::InvalidTransaction::BadSigner,
26+
)));
27+
}
28+
Some(Ok(signer))
29+
},
30+
Err(error) => {
31+
Some(Err(error))
32+
}
33+
}
34+
},
35+
_ => None,
36+
}
37+
}
2338

2439
fn validate_self_contained(
2540
&self,

runtime/dev/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
9999

100100
/// The `TransactionExtension` to the basic transaction logic.
101101
pub type TxExtension = (
102+
bifrost_common_runtime::extensions::CheckBlockedOrigin<Runtime, RuntimeCall>,
102103
frame_system::CheckNonZeroSender<Runtime>,
103104
frame_system::CheckSpecVersion<Runtime>,
104105
frame_system::CheckTxVersion<Runtime>,
@@ -156,7 +157,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
156157
// The version of the authorship interface.
157158
authoring_version: 1,
158159
// The version of the runtime spec.
159-
spec_version: 414,
160+
spec_version: 415,
160161
// The version of the implementation of the spec.
161162
impl_version: 1,
162163
// A list of supported runtime APIs along with their versions.

runtime/mainnet/src/lib.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
9999

100100
/// The `TransactionExtension` to the basic transaction logic.
101101
pub type TxExtension = (
102+
bifrost_common_runtime::extensions::CheckBlockedOrigin<Runtime, RuntimeCall>,
102103
frame_system::CheckNonZeroSender<Runtime>,
103104
frame_system::CheckSpecVersion<Runtime>,
104105
frame_system::CheckTxVersion<Runtime>,
@@ -116,12 +117,7 @@ pub type UncheckedExtrinsic =
116117
fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
117118

118119
/// All migrations executed on runtime upgrade as a nested tuple of types implementing `OnRuntimeUpgrade`.
119-
type Migrations = (
120-
pallet_session::migrations::v1::MigrateV0ToV1<
121-
Runtime,
122-
pallet_session::migrations::v1::InitOffenceSeverity<Runtime>,
123-
>,
124-
);
120+
type Migrations = ();
125121

126122
/// Executive: handles dispatch to the various modules.
127123
pub type Executive = frame_executive::Executive<

runtime/testnet/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
9999

100100
/// The `TransactionExtension` to the basic transaction logic.
101101
pub type TxExtension = (
102+
bifrost_common_runtime::extensions::CheckBlockedOrigin<Runtime, RuntimeCall>,
102103
frame_system::CheckNonZeroSender<Runtime>,
103104
frame_system::CheckSpecVersion<Runtime>,
104105
frame_system::CheckTxVersion<Runtime>,

0 commit comments

Comments
 (0)