Skip to content

Commit 2bf2f71

Browse files
authored
[AHM] Use MultiSignature to allow allow ED25519 keys in Multisig (#936)
The simple multisig that we introduced in #929 assumes SR25519 keys. This change now also makes it possible to use ED25519 keys and ECDSA. Video Tut on how to use it https://drive.google.com/file/d/1D5g_EYKMs73XE6lFlU62xOYLEBMp-yb6/view?usp=sharing PS: Also fixing one proxy test. --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
1 parent bf7ba60 commit 2bf2f71

File tree

4 files changed

+135
-56
lines changed

4 files changed

+135
-56
lines changed

integration-tests/ahm/src/proxy/basic_still_works.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,6 @@ impl AhMigrationCheck for ProxyBasicWorks {
179179
}
180180

181181
for ((delegatee, delegator), permissions) in pre_and_post.iter() {
182-
// Assert storage "Proxy::Proxies::ah_post::correct"
183-
let (entry, _) = pallet_proxy::Proxies::<AssetHubRuntime>::get(delegator);
184-
if entry.is_empty() {
185-
defensive!("Storage entry must exist");
186-
}
187-
188-
let maybe_delay =
189-
entry.iter().find(|proxy| proxy.delegate == *delegatee).map(|proxy| proxy.delay);
190-
191182
let delegatee =
192183
pallet_ah_migrator::Pallet::<AssetHubRuntime>::translate_account_rc_to_ah(
193184
delegatee.clone(),
@@ -196,6 +187,14 @@ impl AhMigrationCheck for ProxyBasicWorks {
196187
pallet_ah_migrator::Pallet::<AssetHubRuntime>::translate_account_rc_to_ah(
197188
delegator.clone(),
198189
);
190+
191+
// Assert storage "Proxy::Proxies::ah_post::correct"
192+
let (entry, _) = pallet_proxy::Proxies::<AssetHubRuntime>::get(&delegator);
193+
assert!(!entry.is_empty(), "Proxies must exist");
194+
195+
let maybe_delay =
196+
entry.iter().find(|proxy| proxy.delegate == delegatee).map(|proxy| proxy.delay);
197+
199198
Self::check_proxy(&delegatee, &delegator, permissions, maybe_delay.unwrap_or(0));
200199
}
201200
}

pallets/rc-migrator/src/lib.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ use runtime_parachains::{
103103
};
104104
use sp_core::{crypto::Ss58Codec, H256};
105105
use sp_runtime::{
106-
traits::{BadOrigin, BlockNumberProvider, Dispatchable, Hash, One, Zero},
106+
traits::{BadOrigin, BlockNumberProvider, Dispatchable, Hash, IdentifyAccount, One, Zero},
107107
AccountId32, Saturating,
108108
};
109109
use sp_std::prelude::*;
@@ -628,7 +628,7 @@ pub mod pallet {
628628
type AhUmpQueuePriorityPattern: Get<(BlockNumberFor<Self>, BlockNumberFor<Self>)>;
629629

630630
/// Members of a multisig that can be submit unsigned txs and act as the manager.
631-
type MultisigMembers: Get<Vec<sp_core::sr25519::Public>>;
631+
type MultisigMembers: Get<Vec<AccountId32>>;
632632

633633
/// Threshold of `MultisigMembers`.
634634
type MultisigThreshold: Get<u32>;
@@ -1315,7 +1315,7 @@ pub mod pallet {
13151315
pub fn vote_manager_multisig(
13161316
origin: OriginFor<T>,
13171317
payload: Box<ManagerMultisigVote<T>>,
1318-
_sig: sp_core::sr25519::Signature,
1318+
_sig: sp_runtime::MultiSignature,
13191319
) -> DispatchResult {
13201320
let _ = ensure_none(origin);
13211321

@@ -1364,14 +1364,14 @@ pub mod pallet {
13641364
)]
13651365
#[scale_info(skip_type_params(T))]
13661366
pub struct ManagerMultisigVote<T: Config> {
1367-
who: sp_core::sr25519::Public,
1367+
who: sp_runtime::MultiSigner,
13681368
call: <T as Config>::RuntimeCall,
13691369
round: u32,
13701370
}
13711371

13721372
impl<T: Config> ManagerMultisigVote<T> {
13731373
pub fn new(
1374-
who: sp_core::sr25519::Public,
1374+
who: sp_runtime::MultiSigner,
13751375
call: <T as Config>::RuntimeCall,
13761376
round: u32,
13771377
) -> Self {
@@ -1389,7 +1389,7 @@ pub mod pallet {
13891389
_,
13901390
Twox64Concat,
13911391
<T as Config>::RuntimeCall,
1392-
Vec<sp_core::sr25519::Public>,
1392+
Vec<sp_runtime::MultiSigner>,
13931393
ValueQuery,
13941394
>;
13951395
#[pallet::storage]
@@ -1402,18 +1402,20 @@ pub mod pallet {
14021402
fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
14031403
use sp_runtime::traits::Verify;
14041404
if let Call::vote_manager_multisig { payload, sig } = call {
1405-
if !T::MultisigMembers::get().contains(&payload.who) {
1405+
let account = payload.who.clone().into_account();
1406+
1407+
if !T::MultisigMembers::get().contains(&account) {
14061408
return InvalidTransaction::BadSigner.into()
14071409
}
1408-
if !sig.verify(&payload.encode_with_bytes_wrapper()[..], &payload.who) {
1410+
if !sig.verify(&payload.encode_with_bytes_wrapper()[..], &account) {
14091411
return InvalidTransaction::BadProof.into()
14101412
}
14111413
if ManagerMultisigRound::<T>::get() != payload.round {
14121414
return InvalidTransaction::Stale.into()
14131415
}
14141416
ValidTransaction::with_tag_prefix("AhmMultisig")
14151417
.priority(sp_runtime::traits::Bounded::max_value())
1416-
.and_provides(vec![("ahm_multi", payload.who).encode()])
1418+
.and_provides(vec![("ahm_multi", account).encode()])
14171419
.propagate(true)
14181420
.longevity(30)
14191421
.build()

pallets/rc-migrator/src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ mod xcm_batch_tests {
749749

750750
// Add messages to multiple batches
751751
batch.push(TestMessage::new(10));
752-
batch.push(TestMessage::new((MAX_XCM_SIZE - 1) as usize));
752+
batch.push(TestMessage::new((MAX_XCM_SIZE - 4) as usize)); // -4 for length prefix
753753
batch.push(TestMessage::new(10));
754754

755755
assert_eq!(batch.len(), 3);

relay/kusama/src/lib.rs

Lines changed: 115 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ use frame_support::{
5252
traits::{
5353
fungible::HoldConsideration,
5454
tokens::{imbalance::ResolveTo, UnityOrOuterConversion},
55-
ConstU32, ConstU8, ConstUint, Currency, EitherOf, EitherOfDiverse, EnsureOrigin,
56-
EnsureOriginWithArg, Equals, FromContains, InstanceFilter, KeyOwnerProofSystem,
57-
LinearStoragePrice, OnUnbalanced, PrivilegeCmp, ProcessMessage, ProcessMessageError,
58-
WithdrawReasons,
55+
ConstU32, ConstU8, ConstUint, Currency, DefensiveResult, EitherOf, EitherOfDiverse,
56+
EnsureOrigin, EnsureOriginWithArg, Equals, FromContains, InstanceFilter,
57+
KeyOwnerProofSystem, LinearStoragePrice, OnUnbalanced, PrivilegeCmp, ProcessMessage,
58+
ProcessMessageError, WithdrawReasons,
5959
},
6060
weights::{
6161
constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS},
@@ -125,8 +125,8 @@ use sp_runtime::{
125125
Get, IdentityLookup, Keccak256, OpaqueKeys, SaturatedConversion, Saturating, Verify,
126126
},
127127
transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
128-
ApplyExtrinsicResult, FixedU128, KeyTypeId, OpaqueValue, Perbill, Percent, Permill,
129-
RuntimeDebug,
128+
AccountId32, ApplyExtrinsicResult, FixedU128, KeyTypeId, OpaqueValue, Perbill, Percent,
129+
Permill, RuntimeDebug,
130130
};
131131
use sp_staking::{EraIndex, SessionIndex};
132132
#[cfg(any(feature = "std", test))]
@@ -1908,11 +1908,14 @@ const AH_MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
19081908
polkadot_primitives::MAX_POV_SIZE as u64,
19091909
);
19101910

1911-
fn multisig_members() -> Vec<sp_core::sr25519::Public> {
1912-
use sp_core::{crypto::Ss58Codec, ByteArray};
1911+
fn multisig_members() -> Vec<AccountId32> {
1912+
use sp_core::crypto::Ss58Codec;
19131913
let addresses = if cfg!(test) {
19141914
vec![
1915-
"HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F", // Alice
1915+
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", // Alice SR25519
1916+
"5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TTpu", // Alice ED25519
1917+
"5C7C2Z5sWbytvHpuLTvzKunnnRwQxft1jiqrLD5rhucQ5S9X", /* Alice ECDSA Address (not SS58
1918+
* Public Key) */
19161919
"FoQJpPyadYccjavVdTWxpxU7rUEaYhfLCPwXgkfD6Zat9QP", // Bob
19171920
"Fr4NzY1udSFFLzb2R3qxVQkwz9cZraWkyfH4h3mVVk7BK7P", // Charlie
19181921
"DfnTB4z7eUvYRqcGtTpFsLC69o6tvBSC1pEv8vWPZFtCkaK", // Dave
@@ -1943,9 +1946,7 @@ fn multisig_members() -> Vec<sp_core::sr25519::Public> {
19431946

19441947
addresses
19451948
.into_iter()
1946-
.filter_map(|ss| sp_runtime::AccountId32::from_ss58check(ss).ok())
1947-
.map(|acc32| acc32.to_raw_vec())
1948-
.filter_map(|bytes| sp_core::sr25519::Public::from_slice(&bytes).ok())
1949+
.filter_map(|ss| sp_runtime::AccountId32::from_ss58check(ss).defensive_ok())
19491950
.collect()
19501951
}
19511952

@@ -1959,7 +1960,7 @@ parameter_types! {
19591960
pub const XcmResponseTimeout: BlockNumber = 30 * DAYS;
19601961
pub const AhUmpQueuePriorityPattern: (BlockNumber, BlockNumber) = (18, 2);
19611962

1962-
pub MultisigMembers: Vec<sp_core::sr25519::Public> = multisig_members();
1963+
pub MultisigMembers: Vec<AccountId32> = multisig_members();
19631964

19641965
}
19651966

@@ -2484,8 +2485,10 @@ mod benches {
24842485

24852486
fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
24862487
let origin = Location::new(0, [Parachain(1000)]);
2487-
let target =
2488-
Location::new(0, [Parachain(1000), AccountId32 { id: [128u8; 32], network: None }]);
2488+
let target = Location::new(
2489+
0,
2490+
[Parachain(1000), Junction::AccountId32 { id: [128u8; 32], network: None }],
2491+
);
24892492
Ok((origin, target))
24902493
}
24912494
}
@@ -3231,12 +3234,15 @@ mod ahm_multisig {
32313234
use pallet_rc_migrator::ManagerMultisigVote;
32323235
use sp_core::Pair;
32333236
use sp_io::TestExternalities;
3234-
use sp_runtime::traits::{Dispatchable, ValidateUnsigned};
3237+
use sp_runtime::{
3238+
traits::{Dispatchable, ValidateUnsigned},
3239+
MultiSignature, MultiSigner,
3240+
};
32353241

32363242
#[test]
32373243
fn all_ss58s_decode() {
32383244
// ensure all non-dev account ids we have are valid ss58s
3239-
assert_eq!(MultisigMembers::get().len(), 14);
3245+
assert_eq!(MultisigMembers::get().len(), 16);
32403246
}
32413247

32423248
#[test]
@@ -3257,11 +3263,15 @@ mod ahm_multisig {
32573263
{
32583264
// Ferdie is not part of the multisig, will get rejected on validate
32593265
let ferdie = sp_keyring::Sr25519Keyring::Ferdie.pair();
3260-
let payload = ManagerMultisigVote::new(ferdie.public(), runtime_call.clone(), 0);
3266+
let payload = ManagerMultisigVote::new(
3267+
MultiSigner::Sr25519(ferdie.public()),
3268+
runtime_call.clone(),
3269+
0,
3270+
);
32613271
let sig = ferdie.sign(payload.encode_with_bytes_wrapper().as_ref());
32623272
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
32633273
payload: Box::new(payload),
3264-
sig,
3274+
sig: MultiSignature::Sr25519(sig),
32653275
};
32663276
assert!(pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
32673277
TransactionSource::External,
@@ -3274,30 +3284,37 @@ mod ahm_multisig {
32743284
// Alice signs a wrong message, rejected
32753285
let alice = sp_keyring::Sr25519Keyring::Alice.pair();
32763286
let payload = ManagerMultisigVote::new(
3277-
sp_keyring::Sr25519Keyring::Bob.pair().public(),
3287+
MultiSigner::Sr25519(sp_keyring::Sr25519Keyring::Bob.pair().public()),
32783288
runtime_call.clone(),
32793289
0,
32803290
);
32813291
let sig = alice.sign(payload.encode_with_bytes_wrapper().as_ref());
32823292
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
32833293
payload: Box::new(payload),
3284-
sig,
3294+
sig: MultiSignature::Sr25519(sig),
32853295
};
3286-
assert!(pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
3287-
TransactionSource::External,
3288-
&call
3289-
)
3290-
.is_err());
3296+
assert!(
3297+
pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
3298+
TransactionSource::External,
3299+
&call
3300+
)
3301+
.is_err(),
3302+
"Alice signs a wrong message, rejected"
3303+
);
32913304
}
32923305

32933306
let alice_sig_for_first_round = {
32943307
// Alice signs, not executed yet
32953308
let alice = sp_keyring::Sr25519Keyring::Alice.pair();
3296-
let payload = ManagerMultisigVote::new(alice.public(), runtime_call.clone(), 0);
3309+
let payload = ManagerMultisigVote::new(
3310+
MultiSigner::Sr25519(alice.public()),
3311+
runtime_call.clone(),
3312+
0,
3313+
);
32973314
let sig = alice.sign(payload.encode_with_bytes_wrapper().as_ref());
32983315
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
32993316
payload: Box::new(payload),
3300-
sig,
3317+
sig: MultiSignature::Sr25519(sig),
33013318
};
33023319

33033320
assert!(pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
@@ -3312,17 +3329,71 @@ mod ahm_multisig {
33123329
1
33133330
);
33143331

3315-
sig
3332+
MultiSignature::Sr25519(sig)
33163333
};
33173334

3335+
frame_support::hypothetically!({
3336+
// Alice ED25519 signs
3337+
let alice = sp_keyring::Ed25519Keyring::Alice.pair();
3338+
let payload = ManagerMultisigVote::new(
3339+
MultiSigner::Ed25519(sp_keyring::Ed25519Keyring::Alice.pair().public()),
3340+
runtime_call.clone(),
3341+
0,
3342+
);
3343+
let sig = alice.sign(payload.encode_with_bytes_wrapper().as_ref());
3344+
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
3345+
payload: Box::new(payload),
3346+
sig: MultiSignature::Ed25519(sig),
3347+
};
3348+
assert!(
3349+
pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
3350+
TransactionSource::External,
3351+
&call
3352+
)
3353+
.is_ok(),
3354+
"Alice ED25519 signs"
3355+
);
3356+
});
3357+
3358+
frame_support::hypothetically!({
3359+
// Alice ECDSA Address signs
3360+
let seed = hex_literal::hex!(
3361+
"cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"
3362+
);
3363+
let alice = sp_application_crypto::ecdsa::Pair::from_seed_slice(&seed).unwrap();
3364+
let payload = ManagerMultisigVote::new(
3365+
MultiSigner::Ecdsa(alice.public()),
3366+
runtime_call.clone(),
3367+
0,
3368+
);
3369+
3370+
let sig = alice.sign(payload.encode_with_bytes_wrapper().as_ref());
3371+
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
3372+
payload: Box::new(payload),
3373+
sig: MultiSignature::Ecdsa(sig),
3374+
};
3375+
assert!(
3376+
pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
3377+
TransactionSource::External,
3378+
&call
3379+
)
3380+
.is_ok(),
3381+
"Alice ECDSA Address signs"
3382+
);
3383+
});
3384+
33183385
{
33193386
// Bob signs, still waiting
33203387
let bob = sp_keyring::Sr25519Keyring::Bob.pair();
3321-
let payload = ManagerMultisigVote::new(bob.public(), runtime_call.clone(), 0);
3388+
let payload = ManagerMultisigVote::new(
3389+
MultiSigner::Sr25519(bob.public()),
3390+
runtime_call.clone(),
3391+
0,
3392+
);
33223393
let sig = bob.sign(payload.encode_with_bytes_wrapper().as_ref());
33233394
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
33243395
payload: Box::new(payload),
3325-
sig,
3396+
sig: MultiSignature::Sr25519(sig),
33263397
};
33273398
assert!(pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
33283399
TransactionSource::External,
@@ -3340,12 +3411,15 @@ mod ahm_multisig {
33403411
{
33413412
// charlie signs something else, stored but not used.
33423413
let charlie = sp_keyring::Sr25519Keyring::Charlie.pair();
3343-
let payload =
3344-
ManagerMultisigVote::new(charlie.public(), other_runtime_call.clone(), 0);
3414+
let payload = ManagerMultisigVote::new(
3415+
MultiSigner::Sr25519(charlie.public()),
3416+
other_runtime_call.clone(),
3417+
0,
3418+
);
33453419
let sig = charlie.sign(payload.encode_with_bytes_wrapper().as_ref());
33463420
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
33473421
payload: Box::new(payload),
3348-
sig,
3422+
sig: MultiSignature::Sr25519(sig),
33493423
};
33503424
assert!(pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
33513425
TransactionSource::External,
@@ -3372,11 +3446,15 @@ mod ahm_multisig {
33723446
{
33733447
// eve signs, dispatched
33743448
let eve = sp_keyring::Sr25519Keyring::Eve.pair();
3375-
let payload = ManagerMultisigVote::new(eve.public(), runtime_call.clone(), 0);
3449+
let payload = ManagerMultisigVote::new(
3450+
MultiSigner::Sr25519(eve.public()),
3451+
runtime_call.clone(),
3452+
0,
3453+
);
33763454
let sig = eve.sign(payload.encode_with_bytes_wrapper().as_ref());
33773455
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
33783456
payload: Box::new(payload),
3379-
sig,
3457+
sig: MultiSignature::Sr25519(sig),
33803458
};
33813459
assert!(pallet_rc_migrator::Pallet::<Runtime>::validate_unsigned(
33823460
TransactionSource::External,
@@ -3400,7 +3478,7 @@ mod ahm_multisig {
34003478
// Alice's signature from first round cannot be re-used
34013479
let call = pallet_rc_migrator::Call::<Runtime>::vote_manager_multisig {
34023480
payload: Box::new(ManagerMultisigVote::new(
3403-
sp_keyring::Sr25519Keyring::Alice.pair().public(),
3481+
MultiSigner::Sr25519(sp_keyring::Sr25519Keyring::Alice.pair().public()),
34043482
runtime_call.clone(),
34053483
0,
34063484
)),

0 commit comments

Comments
 (0)