Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
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
Next Next commit
Refactor as_sub to make things clearer.
- `as_sub` becomes `as_alternative`
- `as_sub_limited` becomes `as_derivative`
- `as_alternative` and `as_derivative` generate a mutually exclusive set of accounts.
  • Loading branch information
gavofyork committed Jun 25, 2020
commit 532c73517f51ac836af26ee1218ab375c5562ca4
4 changes: 2 additions & 2 deletions frame/proxy/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,15 @@ fn filtering_works() {
Balances::mutate_account(&sub_id, |a| a.free = 1000);
let inner = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));

let call = Box::new(Call::Utility(UtilityCall::as_sub(0, inner.clone())));
let call = Box::new(Call::Utility(UtilityCall::as_derivative(0, inner.clone())));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));

let call = Box::new(Call::Utility(UtilityCall::as_limited_sub(0, inner.clone())));
let call = Box::new(Call::Utility(UtilityCall::as_alternative(0, inner.clone())));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(())));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
Expand Down
8 changes: 4 additions & 4 deletions frame/utility/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ benchmarks! {
let caller = account("caller", 0, SEED);
}: _(RawOrigin::Signed(caller), calls)

as_sub {
as_derivative {
let u in 0 .. 1000;
let caller = account("caller", u, SEED);
let call = Box::new(frame_system::Call::remark(vec![]).into());
}: _(RawOrigin::Signed(caller), u as u16, call)

as_limited_sub {
as_alternative {
let u in 0 .. 1000;
let caller = account("caller", u, SEED);
let call = Box::new(frame_system::Call::remark(vec![]).into());
Expand All @@ -61,8 +61,8 @@ mod tests {
fn test_benchmarks() {
new_test_ext().execute_with(|| {
assert_ok!(test_benchmark_batch::<Test>());
assert_ok!(test_benchmark_as_sub::<Test>());
assert_ok!(test_benchmark_as_limited_sub::<Test>());
assert_ok!(test_benchmark_as_derivative::<Test>());
assert_ok!(test_benchmark_as_alternative::<Test>());
});
}
}
33 changes: 24 additions & 9 deletions frame/utility/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@
//! corresponding `set_storage`s, for efficient multiple payouts with just a single signature
//! verify, or in combination with one of the other two dispatch functionality.
//! - Pseudonymal dispatch: A stateless operation, allowing a signed origin to execute a call from
//! an alternative signed origin. Each account has 2**16 possible "pseudonyms" (alternative
//! an alternative signed origin. Each account has 2 * 2**16 possible "pseudonyms" (alternative
//! account IDs) and these can be stacked. This can be useful as a key management tool, where you
//! need multiple distinct accounts (e.g. as controllers for many staking accounts), but where
//! it's perfectly fine to have each of them controlled by the same underlying keypair.
//! it's perfectly fine to have each of them controlled by the same underlying keypair. There
//! exist two sets of these pseudonymous accounts: *alternative* IDs (`as_alternative`) and *sub
//! account* IDs (`as_derivative`). The only difference between then is that *alternative*
//! accounts are, for the purposes of proxy filtering, considered a re-authentication and not a
//! direct "derivative" and thus are *not* hampered with the origin's filters.
//!
//! ## Interface
//!
Expand All @@ -42,7 +46,8 @@
//! * `batch` - Dispatch multiple calls from the sender's origin.
//!
//! #### For pseudonymal dispatch
//! * `as_sub` - Dispatch a call from a secondary ("sub") signed origin.
//! * `as_derivative` - Dispatch a call from a derivative signed origin.
//! * `as_alternative` - Dispatch a call from a alternative signed origin.
//!
//! [`Call`]: ./enum.Call.html
//! [`Trait`]: ./trait.Trait.html
Expand Down Expand Up @@ -159,7 +164,9 @@ decl_module! {
///
/// NOTE: If you need to ensure that any account-based filtering is honored (i.e. because
/// you expect `proxy` to have been used prior in the call stack and you want it to apply to
/// any sub-accounts), then use `as_limited_sub` instead.
/// any sub-accounts), then use `as_derivative` instead.
///
/// NOTE: Prior to version *12, this was called `as_derivative`.
///
/// The dispatch origin for this call must be _Signed_.
///
Expand All @@ -171,11 +178,11 @@ decl_module! {
call.get_dispatch_info().weight.saturating_add(3_000_000),
call.get_dispatch_info().class,
)]
fn as_sub(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult {
fn as_alternative(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult {
let who = ensure_signed(origin)?;

// This is a freshly authenticated new account, the origin restrictions doesn't apply.
let pseudonym = Self::sub_account_id(who, index);
let pseudonym = Self::alt_account_id(who, index);
call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into())
.map(|_| ()).map_err(|e| e.error)
}
Expand All @@ -187,7 +194,9 @@ decl_module! {
///
/// NOTE: If you need to ensure that any account-based filtering is not honored (i.e.
/// because you expect `proxy` to have been used prior in the call stack and you do not want
/// the call restrictions to apply to any sub-accounts), then use `as_sub` instead.
/// the call restrictions to apply to any sub-accounts), then use `as_alternative` instead.
///
/// NOTE: Prior to version *12, this was called `as_limited_sub`.
///
/// The dispatch origin for this call must be _Signed_.
///
Expand All @@ -199,7 +208,7 @@ decl_module! {
call.get_dispatch_info().weight.saturating_add(3_000_000),
call.get_dispatch_info().class,
)]
fn as_limited_sub(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult {
fn as_derivative(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult {
let mut origin = origin;
let who = ensure_signed(origin.clone())?;
let pseudonym = Self::sub_account_id(who, index);
Expand All @@ -211,8 +220,14 @@ decl_module! {

impl<T: Trait> Module<T> {
/// Derive a sub-account ID from the owner account and the sub-account index.
pub fn sub_account_id(who: T::AccountId, index: u16) -> T::AccountId {
pub fn alt_account_id(who: T::AccountId, index: u16) -> T::AccountId {
let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256);
T::AccountId::decode(&mut &entropy[..]).unwrap_or_default()
}

/// Derive an alt-account ID from the owner account and the sub-account index.
pub fn sub_account_id(who: T::AccountId, index: u16) -> T::AccountId {
let entropy = (b"modlpy/utililsba", who, index).using_encoded(blake2_256);
T::AccountId::decode(&mut &entropy[..]).unwrap_or_default()
}
}
10 changes: 5 additions & 5 deletions frame/utility/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,16 @@ fn expect_event<E: Into<TestEvent>>(e: E) {
}

#[test]
fn as_sub_works() {
fn as_derivative_works() {
new_test_ext().execute_with(|| {
let sub_1_0 = Utility::sub_account_id(1, 0);
assert_ok!(Balances::transfer(Origin::signed(1), sub_1_0, 5));
assert_noop!(Utility::as_sub(
assert_noop!(Utility::as_derivative(
Origin::signed(1),
1,
Box::new(Call::Balances(BalancesCall::transfer(6, 3))),
), BalancesError::<Test, _>::InsufficientBalance);
assert_ok!(Utility::as_sub(
assert_ok!(Utility::as_derivative(
Origin::signed(1),
0,
Box::new(Call::Balances(BalancesCall::transfer(2, 3))),
Expand All @@ -158,9 +158,9 @@ fn as_sub_works() {
}

#[test]
fn as_sub_filters() {
fn as_derivative_filters() {
new_test_ext().execute_with(|| {
assert_noop!(Utility::as_sub(
assert_noop!(Utility::as_derivative(
Origin::signed(1),
1,
Box::new(Call::System(frame_system::Call::remark(vec![]))),
Expand Down