Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MESH-2209 multisig improvements part 4 #1697

Merged
389 changes: 358 additions & 31 deletions integration/tests/multisig_permissions.rs

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions pallets/common/src/traits/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ pub trait WeightInfo {
fn accept_multisig_signer() -> Weight;
fn add_multisig_signers(signers: u32) -> Weight;
fn remove_multisig_signers(signers: u32) -> Weight;
fn add_multisig_signers_via_creator(signers: u32) -> Weight;
fn remove_multisig_signers_via_creator(signers: u32) -> Weight;
fn add_multisig_signers_via_admin(signers: u32) -> Weight;
fn remove_multisig_signers_via_admin(signers: u32) -> Weight;
fn change_sigs_required() -> Weight;
fn make_multisig_secondary() -> Weight;
fn make_multisig_primary() -> Weight;
fn change_sigs_required_via_creator() -> Weight;
fn remove_creator_controls() -> Weight;
fn change_sigs_required_via_admin() -> Weight;
fn add_admin() -> Weight;
fn remove_admin_via_admin() -> Weight;
fn remove_payer() -> Weight;
fn remove_payer_via_payer() -> Weight;
fn create_join_identity() -> Weight;
fn approve_join_identity() -> Weight;
fn join_identity() -> Weight;
}

/// This trait is used to add a signer to a multisig and enable unlinking multisig from an identity
Expand Down
114 changes: 84 additions & 30 deletions pallets/multisig/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ fn generate_multisig_with_extra_signers<T: Config + TestUtilsFn<AccountIdOf<T>>>
caller.origin.clone().into(),
signers.clone(),
num_of_signers_required.into(),
None,
)
.unwrap();
Ok((multisig, signers, users))
Expand All @@ -84,6 +85,30 @@ pub type MultisigSetupResult<T, AccountId, MaxSigners> = (
RawOrigin<AccountId>,
);

fn init_admin<T: Config + TestUtilsFn<AccountIdOf<T>>>(multisig: &T::AccountId, admin: &User<T>) {
let multisig_origin = RawOrigin::Signed(multisig.clone());
let admin_did = admin.did.expect("Admin must have a DID");
MultiSig::<T>::add_admin(multisig_origin.into(), admin_did).unwrap();
}

fn init_join_identity<T: Config + TestUtilsFn<AccountIdOf<T>>>(
multisig: &T::AccountId,
admin: &User<T>,
) -> u64 {
let multisig_origin = RawOrigin::Signed(multisig.clone());
let admin_did = admin.did.expect("Admin must have a DID");
Identity::<T>::leave_identity_as_key(multisig_origin.into()).unwrap();
let signatory = Signatory::Account(multisig.clone());
let auth_id = Identity::<T>::add_auth(
admin_did,
signatory,
AuthorizationData::JoinIdentity(Permissions::empty()),
None,
)
.unwrap();
auth_id
}

fn generate_multisig_for_alice_wo_accepting<T: Config + TestUtilsFn<AccountIdOf<T>>>(
total_signers: u32,
signers_required: u32,
Expand Down Expand Up @@ -126,7 +151,10 @@ pub type ProposalSetupResult<T, AccountId, Proposal, MaxSigners> = (
fn generate_multisig_and_proposal_for_alice<T: Config + TestUtilsFn<AccountIdOf<T>>>(
total_signers: u32,
signers_required: u32,
) -> Result<ProposalSetupResult<T, T::AccountId, T::Proposal, T::MaxSigners>, DispatchError> {
) -> Result<
ProposalSetupResult<T, T::AccountId, <T as Config>::Proposal, T::MaxSigners>,
DispatchError,
> {
let (alice, multisig, signers, users, _) =
generate_multisig_for_alice::<T>(total_signers, signers_required).unwrap();
let proposal_id = MultiSig::<T>::next_proposal_id(multisig.clone());
Expand All @@ -145,7 +173,10 @@ fn generate_multisig_and_proposal_for_alice<T: Config + TestUtilsFn<AccountIdOf<
fn generate_multisig_and_create_proposal<T: Config + TestUtilsFn<AccountIdOf<T>>>(
total_signers: u32,
signers_required: u32,
) -> Result<ProposalSetupResult<T, T::AccountId, T::Proposal, T::MaxSigners>, DispatchError> {
) -> Result<
ProposalSetupResult<T, T::AccountId, <T as Config>::Proposal, T::MaxSigners>,
DispatchError,
> {
let (alice, multisig, signers, users, proposal_id, proposal, ephemeral_multisig) =
generate_multisig_and_proposal_for_alice::<T>(total_signers, signers_required).unwrap();
// Use the first signer to create the proposal.
Expand Down Expand Up @@ -192,9 +223,10 @@ benchmarks! {
// Number of signers
let i in 1 .. T::MaxSigners::get() as u32;
let (alice, multisig, signers, _, _) = generate_multisig_for_alice::<T>(i, 1).unwrap();
}: _(alice.origin(), signers, i as u64)
let whole = Permissions::default();
}: _(alice.origin(), signers, i as u64, Some(whole))
verify {
assert!(CreatorDid::<T>::contains_key(multisig), "create_multisig");
assert!(PayingDid::<T>::contains_key(multisig), "create_multisig");
}

create_proposal {
Expand All @@ -215,7 +247,7 @@ benchmarks! {
let (alice, multisig, signers, users, proposal_id, proposal, ephemeral_multisig) = generate_multisig_and_create_proposal::<T>(3, 3).unwrap();
let did = alice.did.expect("Alice must have a DID");
}: {
assert!(MultiSig::<T>::execute_proposal(&multisig, proposal_id, did, Weight::MAX).is_ok());
assert!(MultiSig::<T>::execute_proposal(&multisig, proposal_id, Some(did), Weight::MAX).is_ok());
}

reject {
Expand All @@ -237,7 +269,7 @@ benchmarks! {

add_multisig_signers {
// Number of signers
let i in 1 .. T::MaxSigners::get() as u32;
let i in 1 .. (T::MaxSigners::get() - 1) as u32;

let (alice, multisig, _, _, multisig_origin) = generate_multisig_for_alice::<T>(1, 1).unwrap();
let (signers, _) = generate_signers::<T>(i as usize);
Expand All @@ -260,11 +292,12 @@ benchmarks! {
assert_number_of_signers!(1, multisig);
}

add_multisig_signers_via_creator {
add_multisig_signers_via_admin {
// Number of signers
let i in 1 .. T::MaxSigners::get() as u32;
let i in 1 .. (T::MaxSigners::get() - 1) as u32;

let (alice, multisig, _, _, _) = generate_multisig_for_alice::<T>(1, 1).unwrap();
init_admin(&multisig, &alice);
let (signers, _) = generate_signers::<T>(i as usize);
let last_signer = signers.last().cloned().unwrap();
let original_last_auth = get_last_auth_id::<T>(&last_signer);
Expand All @@ -273,11 +306,12 @@ benchmarks! {
assert!(original_last_auth < get_last_auth_id::<T>(&last_signer));
}

remove_multisig_signers_via_creator {
remove_multisig_signers_via_admin {
// Number of signers
let i in 2 .. T::MaxSigners::get() as u32;

let (alice, multisig, signers, _, _) = generate_multisig_for_alice::<T>(i, 1).unwrap();
init_admin(&multisig, &alice);
let signers_to_remove = signers[1..].to_vec().try_into().unwrap();
assert_number_of_signers!(i as u64, multisig.clone());
let ephemeral_multisig = multisig.clone();
Expand All @@ -293,26 +327,46 @@ benchmarks! {
assert!(MultiSigSignsRequired::<T>::get(&multisig) == 1);
}

make_multisig_secondary {
let (alice, multisig, _, _, _) = generate_multisig_for_alice::<T>(1, 1).unwrap();
let whole = Permissions::default();
}: _(alice.origin(), multisig.clone(), Some(whole))
verify {
assert!(Identity::<T>::is_secondary_key(alice.did(), &multisig));
}
change_sigs_required_via_admin {
let (alice, multisig, _, _, _) = generate_multisig_for_alice::<T>(2, 2).unwrap();
init_admin(&multisig, &alice);
}: _(alice.origin(), multisig, 1)

make_multisig_primary {
let (alice, multisig, _, _, _) = generate_multisig_for_alice::<T>(1, 1).unwrap();
}: _(alice.origin(), multisig.clone(), None)
verify {
assert!(Identity::<T>::get_primary_key(alice.did()) == Some(multisig));
}

change_sigs_required_via_creator {
let (alice, multisig_account, _, _, _) = generate_multisig_for_alice::<T>(2, 2).unwrap();
}: _(alice.origin(), multisig_account, 1)

remove_creator_controls {
let (alice, multisig_account, _, _, _) = generate_multisig_for_alice::<T>(2, 2).unwrap();
}: _(alice.origin(), multisig_account)
add_admin {
let (alice, multisig, _, _, multisig_origin) = generate_multisig_for_alice::<T>(2, 2).unwrap();
let did = alice.did.expect("Alice must have a DID");
}: _(multisig_origin, did)

remove_admin_via_admin {
let (alice, multisig, _, _, _) = generate_multisig_for_alice::<T>(2, 2).unwrap();
init_admin(&multisig, &alice);
}: _(alice.origin(), multisig)

remove_payer {
let (alice, multisig, _, _, multisig_origin) = generate_multisig_for_alice::<T>(2, 2).unwrap();
}: _(multisig_origin)

remove_payer_via_payer {
let (alice, multisig, _, _, _) = generate_multisig_for_alice::<T>(2, 2).unwrap();
}: _(alice.origin(), multisig)

join_identity {
let (alice, multisig, _, users, multisig_origin) = generate_multisig_for_alice::<T>(4, 3).unwrap();
let auth_id = init_join_identity(&multisig, &alice);
// The first approval creates the proposal.
MultiSig::<T>::approve_join_identity(users[0].origin().into(), multisig.clone(), auth_id).unwrap();
}: _(multisig_origin, auth_id)

create_join_identity {
let (alice, multisig, _, users, multisig_origin) = generate_multisig_for_alice::<T>(4, 3).unwrap();
let auth_id = init_join_identity(&multisig, &alice);
}: approve_join_identity(users[0].origin(), multisig, auth_id)

approve_join_identity {
let (alice, multisig, _, users, multisig_origin) = generate_multisig_for_alice::<T>(4, 3).unwrap();
let auth_id = init_join_identity(&multisig, &alice);
// The first approval creates the proposal.
MultiSig::<T>::approve_join_identity(users[0].origin().into(), multisig.clone(), auth_id).unwrap();
// The second approval call just approves.
}: approve_join_identity(users[1].origin(), multisig, auth_id)
}
Loading