mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 07:41:08 +00:00
Bound uses of Call (#11649)
* Introduce preimages module in traits * Multisize Preimages * Len not actually necessary * Tweaks to the preimage API * Fixes * Get Scheduler building with new API * Scheduler tests pass * Bounded Scheduler 🎉 * Use Agenda holes and introduce IncompleteSince to avoid need to reschedule * Tests pass with new weight system * New benchmarks * Add missing file * Drop preimage when permenantly overeight * Drop preimage when permenantly overeight * Referenda uses latest preimage API * Testing ok * Adding tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add preimage migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Remove dbg * Refactor Democracy * Refactor Democracy * Add final MEL * Remove silly maps * Fixes * Minor refactor * Formatting * Fixes * Fixes * Fixes * Update frame/preimage/src/lib.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Add migrations to Democracy * WIP Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Resolve conflicts Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Resolve conflicts" This reverts commit 734d66d69e54553471ffa54fa52e3e304dc8f106. * Undo wrong resolves... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * WIP Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * massage clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy annoyance Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy annoyance Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * add missing file * Test <Preimage as QueryPreimage> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy harassment Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove old stuff Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test <Scheduler as Anon> trait functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update pallet-ui tests Why is this needed? Should not be the case unless master is broken... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More scheduler trait test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Apply review suggestion Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Beauty fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add Scheduler test migration_v3_to_v4_works Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Merge fixup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Keep referenda benchmarks instantiatable Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new scheduler weight functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new democracy weight functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use weight compare functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update pallet-ui tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More renaming… Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More renaming… Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add comment Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Implement OnRuntimeUpgrade for scheduler::v3_to_v4 migration Put the migration into a proper `MigrateToV4` struct and implement the OnRuntimeUpgrade hooks for it. Also move the test to use that instead. This should make it easier for adding it to Polkadot. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Handle undecodable Agendas Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove trash Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new OnRuntimeUpgrade functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix BoundedSlice::truncate_from Co-authored-by: jakoblell Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix pre_upgrade hook return values Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add more error logging Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Find too large preimages in the pre_upgrade hook Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test that too large Calls in agendas are ignored Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new OnRuntimeUpgrade hooks Why did the CI not catch this?! Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * works fine - just more logs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix staking migration Causing issues on Kusama... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix UI tests No idea why this is needed. This is actually undoing an earlier change. Maybe the CI has different rustc versions!? Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove multisig's Calls (#12072) * Remove multisig's Calls * Multisig: Fix tests and re-introduce reserve logic (#12241) * Fix tests and re-introduce reserve logic * fix benches * add todo * remove irrelevant bench * [Feature] Add a migration that drains and refunds stored calls (#12313) * [Feature] Add a migration that drains and refunds stored calls * migration fixes * fixes * address review comments * consume the whole block weight * fix assertions * license header * fix interface Co-authored-by: parity-processbot <> Co-authored-by: parity-processbot <> Co-authored-by: Roman Useinov <roman.useinov@gmail.com> * Fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix multisig benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * ".git/.scripts/bench-bot.sh" pallet dev pallet_democracy * ".git/.scripts/bench-bot.sh" pallet dev pallet_scheduler * ".git/.scripts/bench-bot.sh" pallet dev pallet_preimage Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: parity-processbot <> Co-authored-by: Roman Useinov <roman.useinov@gmail.com>
This commit is contained in:
@@ -31,7 +31,7 @@ const SEED: u32 = 0;
|
||||
fn setup_multi<T: Config>(
|
||||
s: u32,
|
||||
z: u32,
|
||||
) -> Result<(Vec<T::AccountId>, OpaqueCall<T>), &'static str> {
|
||||
) -> Result<(Vec<T::AccountId>, Box<<T as Config>::RuntimeCall>), &'static str> {
|
||||
let mut signatories: Vec<T::AccountId> = Vec::new();
|
||||
for i in 0..s {
|
||||
let signatory = account("signatory", i, SEED);
|
||||
@@ -44,8 +44,7 @@ fn setup_multi<T: Config>(
|
||||
// Must first convert to runtime call type.
|
||||
let call: <T as Config>::RuntimeCall =
|
||||
frame_system::Call::<T>::remark { remark: vec![0; z as usize] }.into();
|
||||
let call_data = OpaqueCall::<T>::from_encoded(call.encode());
|
||||
Ok((signatories, call_data))
|
||||
Ok((signatories, Box::new(call)))
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
@@ -74,35 +73,15 @@ benchmarks! {
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, false, Weight::zero())
|
||||
}: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, Weight::zero())
|
||||
verify {
|
||||
assert!(Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
assert!(!Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
as_multi_create_store {
|
||||
// Signatories, need at least 2 total people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, true, Weight::zero())
|
||||
verify {
|
||||
assert!(Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
as_multi_approve {
|
||||
@@ -111,78 +90,51 @@ benchmarks! {
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi, storing for worst case
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, Weight::zero())?;
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
// Create the multi
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), Weight::zero())?;
|
||||
let caller2 = signatories2.remove(0);
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, false, Weight::zero())
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, Weight::zero())
|
||||
verify {
|
||||
let multisig = Multisigs::<T>::get(multi_account_id, call_hash).ok_or("multisig not created")?;
|
||||
assert_eq!(multisig.approvals.len(), 2);
|
||||
}
|
||||
|
||||
as_multi_approve_store {
|
||||
// Signatories, need at least 3 people (so we don't complete the multisig)
|
||||
let s in 3 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi, not storing
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), false, Weight::zero())?;
|
||||
assert!(!Calls::<T>::contains_key(call_hash));
|
||||
let caller2 = signatories2.remove(0);
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, true, Weight::zero())
|
||||
verify {
|
||||
let multisig = Multisigs::<T>::get(multi_account_id, call_hash).ok_or("multisig not created")?;
|
||||
assert_eq!(multisig.approvals.len(), 2);
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
as_multi_complete {
|
||||
// Signatories, need at least 2 people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi, storing it for worst case
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, Weight::zero())?;
|
||||
// Create the multi
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), Weight::zero())?;
|
||||
// Everyone except the first person approves
|
||||
for i in 1 .. s - 1 {
|
||||
let mut signatories_loop = signatories2.clone();
|
||||
let caller_loop = signatories_loop.remove(i as usize);
|
||||
let o = RawOrigin::Signed(caller_loop).into();
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), false, Weight::zero())?;
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), Weight::zero())?;
|
||||
}
|
||||
let caller2 = signatories2.remove(0);
|
||||
assert!(Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, false, Weight::MAX)
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, Weight::MAX)
|
||||
verify {
|
||||
assert!(!Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
}
|
||||
@@ -195,7 +147,7 @@ benchmarks! {
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
@@ -214,7 +166,7 @@ benchmarks! {
|
||||
let mut signatories2 = signatories.clone();
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi
|
||||
@@ -224,7 +176,6 @@ benchmarks! {
|
||||
signatories,
|
||||
None,
|
||||
call,
|
||||
false,
|
||||
Weight::zero()
|
||||
)?;
|
||||
let caller2 = signatories2.remove(0);
|
||||
@@ -237,45 +188,6 @@ benchmarks! {
|
||||
assert_eq!(multisig.approvals.len(), 2);
|
||||
}
|
||||
|
||||
approve_as_multi_complete {
|
||||
// Signatories, need at least 2 people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length, not a component
|
||||
let z = 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, Weight::zero())?;
|
||||
// Everyone except the first person approves
|
||||
for i in 1 .. s - 1 {
|
||||
let mut signatories_loop = signatories2.clone();
|
||||
let caller_loop = signatories_loop.remove(i as usize);
|
||||
let o = RawOrigin::Signed(caller_loop).into();
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), false, Weight::zero())?;
|
||||
}
|
||||
let caller2 = signatories2.remove(0);
|
||||
assert!(Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: approve_as_multi(
|
||||
RawOrigin::Signed(caller2),
|
||||
s as u16,
|
||||
signatories2,
|
||||
Some(timepoint),
|
||||
call_hash,
|
||||
Weight::MAX
|
||||
)
|
||||
verify {
|
||||
assert!(!Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
}
|
||||
|
||||
cancel_as_multi {
|
||||
// Signatories, need at least 2 people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
@@ -284,20 +196,18 @@ benchmarks! {
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi
|
||||
let o = RawOrigin::Signed(caller.clone()).into();
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories.clone(), None, call, true, Weight::zero())?;
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories.clone(), None, call, Weight::zero())?;
|
||||
assert!(Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: _(RawOrigin::Signed(caller), s as u16, signatories, timepoint, call_hash)
|
||||
verify {
|
||||
assert!(!Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
assert!(!Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Multisig, crate::tests::new_test_ext(), crate::tests::Test);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
mod benchmarking;
|
||||
pub mod migrations;
|
||||
mod tests;
|
||||
pub mod weights;
|
||||
|
||||
@@ -57,7 +58,7 @@ use frame_support::{
|
||||
PostDispatchInfo,
|
||||
},
|
||||
ensure,
|
||||
traits::{Currency, Get, ReservableCurrency, WrapperKeepOpaque},
|
||||
traits::{Currency, Get, ReservableCurrency},
|
||||
weights::Weight,
|
||||
RuntimeDebug,
|
||||
};
|
||||
@@ -73,6 +74,20 @@ pub use weights::WeightInfo;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
/// The log target of this pallet.
|
||||
pub const LOG_TARGET: &'static str = "runtime::multisig";
|
||||
|
||||
// syntactic sugar for logging.
|
||||
#[macro_export]
|
||||
macro_rules! log {
|
||||
($level:tt, $patter:expr $(, $values:expr)* $(,)?) => {
|
||||
log::$level!(
|
||||
target: crate::LOG_TARGET,
|
||||
concat!("[{:?}] ✍️ ", $patter), <frame_system::Pallet<T>>::block_number() $(, $values)*
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
type BalanceOf<T> =
|
||||
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||
|
||||
@@ -100,12 +115,10 @@ pub struct Multisig<BlockNumber, Balance, AccountId> {
|
||||
approvals: Vec<AccountId>,
|
||||
}
|
||||
|
||||
type OpaqueCall<T> = WrapperKeepOpaque<<T as Config>::RuntimeCall>;
|
||||
|
||||
type CallHash = [u8; 32];
|
||||
|
||||
enum CallOrHash<T: Config> {
|
||||
Call(OpaqueCall<T>, bool),
|
||||
Call(<T as Config>::RuntimeCall),
|
||||
Hash([u8; 32]),
|
||||
}
|
||||
|
||||
@@ -152,9 +165,13 @@ pub mod pallet {
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
/// The current storage version.
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store(pub(super) trait Store)]
|
||||
#[pallet::without_storage_info]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
/// The set of open multisig operations.
|
||||
@@ -168,10 +185,6 @@ pub mod pallet {
|
||||
Multisig<T::BlockNumber, BalanceOf<T>, T::AccountId>,
|
||||
>;
|
||||
|
||||
#[pallet::storage]
|
||||
pub type Calls<T: Config> =
|
||||
StorageMap<_, Identity, [u8; 32], (OpaqueCall<T>, T::AccountId, BalanceOf<T>)>;
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// Threshold must be 2 or greater.
|
||||
@@ -343,13 +356,13 @@ pub mod pallet {
|
||||
/// taken for its lifetime of `DepositBase + threshold * DepositFactor`.
|
||||
/// -------------------------------
|
||||
/// - DB Weight:
|
||||
/// - Reads: Multisig Storage, [Caller Account], Calls (if `store_call`)
|
||||
/// - Writes: Multisig Storage, [Caller Account], Calls (if `store_call`)
|
||||
/// - Reads: Multisig Storage, [Caller Account]
|
||||
/// - Writes: Multisig Storage, [Caller Account]
|
||||
/// - Plus Call Weight
|
||||
/// # </weight>
|
||||
#[pallet::weight({
|
||||
let s = other_signatories.len() as u32;
|
||||
let z = call.encoded_len() as u32;
|
||||
let z = call.using_encoded(|d| d.len()) as u32;
|
||||
|
||||
T::WeightInfo::as_multi_create(s, z)
|
||||
.max(T::WeightInfo::as_multi_create_store(s, z))
|
||||
@@ -362,8 +375,7 @@ pub mod pallet {
|
||||
threshold: u16,
|
||||
other_signatories: Vec<T::AccountId>,
|
||||
maybe_timepoint: Option<Timepoint<T::BlockNumber>>,
|
||||
call: OpaqueCall<T>,
|
||||
store_call: bool,
|
||||
call: Box<<T as Config>::RuntimeCall>,
|
||||
max_weight: Weight,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let who = ensure_signed(origin)?;
|
||||
@@ -372,7 +384,7 @@ pub mod pallet {
|
||||
threshold,
|
||||
other_signatories,
|
||||
maybe_timepoint,
|
||||
CallOrHash::Call(call, store_call),
|
||||
CallOrHash::Call(*call),
|
||||
max_weight,
|
||||
)
|
||||
}
|
||||
@@ -462,8 +474,8 @@ pub mod pallet {
|
||||
/// - Storage: removes one item.
|
||||
/// ----------------------------------
|
||||
/// - DB Weight:
|
||||
/// - Read: Multisig Storage, [Caller Account], Refund Account, Calls
|
||||
/// - Write: Multisig Storage, [Caller Account], Refund Account, Calls
|
||||
/// - Read: Multisig Storage, [Caller Account], Refund Account
|
||||
/// - Write: Multisig Storage, [Caller Account], Refund Account
|
||||
/// # </weight>
|
||||
#[pallet::weight(T::WeightInfo::cancel_as_multi(other_signatories.len() as u32))]
|
||||
pub fn cancel_as_multi(
|
||||
@@ -489,7 +501,6 @@ pub mod pallet {
|
||||
let err_amount = T::Currency::unreserve(&m.depositor, m.deposit);
|
||||
debug_assert!(err_amount.is_zero());
|
||||
<Multisigs<T>>::remove(&id, &call_hash);
|
||||
Self::clear_call(&call_hash);
|
||||
|
||||
Self::deposit_event(Event::MultisigCancelled {
|
||||
cancelling: who,
|
||||
@@ -531,13 +542,12 @@ impl<T: Config> Pallet<T> {
|
||||
let id = Self::multi_account_id(&signatories, threshold);
|
||||
|
||||
// Threshold > 1; this means it's a multi-step operation. We extract the `call_hash`.
|
||||
let (call_hash, call_len, maybe_call, store) = match call_or_hash {
|
||||
CallOrHash::Call(call, should_store) => {
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_len = call.encoded_len();
|
||||
(call_hash, call_len, Some(call), should_store)
|
||||
let (call_hash, call_len, maybe_call) = match call_or_hash {
|
||||
CallOrHash::Call(call) => {
|
||||
let (call_hash, call_len) = call.using_encoded(|d| (blake2_256(d), d.len()));
|
||||
(call_hash, call_len, Some(call))
|
||||
},
|
||||
CallOrHash::Hash(h) => (h, 0, None, false),
|
||||
CallOrHash::Hash(h) => (h, 0, None),
|
||||
};
|
||||
|
||||
// Branch on whether the operation has already started or not.
|
||||
@@ -556,13 +566,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
// We only bother fetching/decoding call if we know that we're ready to execute.
|
||||
let maybe_approved_call = if approvals >= threshold {
|
||||
Self::get_call(&call_hash, maybe_call.as_ref())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some((call, call_len)) = maybe_approved_call {
|
||||
if let Some(call) = maybe_call.filter(|_| approvals >= threshold) {
|
||||
// verify weight
|
||||
ensure!(
|
||||
call.get_dispatch_info().weight.all_lte(max_weight),
|
||||
@@ -572,7 +576,6 @@ impl<T: Config> Pallet<T> {
|
||||
// Clean up storage before executing call to avoid an possibility of reentrancy
|
||||
// attack.
|
||||
<Multisigs<T>>::remove(&id, call_hash);
|
||||
Self::clear_call(&call_hash);
|
||||
T::Currency::unreserve(&m.depositor, m.deposit);
|
||||
|
||||
let result = call.dispatch(RawOrigin::Signed(id.clone()).into());
|
||||
@@ -596,19 +599,6 @@ impl<T: Config> Pallet<T> {
|
||||
// We cannot dispatch the call now; either it isn't available, or it is, but we
|
||||
// don't have threshold approvals even with our signature.
|
||||
|
||||
// Store the call if desired.
|
||||
let stored = if let Some(data) = maybe_call.filter(|_| store) {
|
||||
Self::store_call_and_reserve(
|
||||
who.clone(),
|
||||
&call_hash,
|
||||
data,
|
||||
BalanceOf::<T>::zero(),
|
||||
)?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if let Some(pos) = maybe_pos {
|
||||
// Record approval.
|
||||
m.approvals.insert(pos, who.clone());
|
||||
@@ -622,17 +612,11 @@ impl<T: Config> Pallet<T> {
|
||||
} else {
|
||||
// If we already approved and didn't store the Call, then this was useless and
|
||||
// we report an error.
|
||||
ensure!(stored, Error::<T>::AlreadyApproved);
|
||||
Err(Error::<T>::AlreadyApproved)?
|
||||
}
|
||||
|
||||
let final_weight = if stored {
|
||||
T::WeightInfo::as_multi_approve_store(
|
||||
other_signatories_len as u32,
|
||||
call_len as u32,
|
||||
)
|
||||
} else {
|
||||
T::WeightInfo::as_multi_approve(other_signatories_len as u32, call_len as u32)
|
||||
};
|
||||
let final_weight =
|
||||
T::WeightInfo::as_multi_approve(other_signatories_len as u32, call_len as u32);
|
||||
// Call is not made, so the actual weight does not include call
|
||||
Ok(Some(final_weight).into())
|
||||
}
|
||||
@@ -643,14 +627,7 @@ impl<T: Config> Pallet<T> {
|
||||
// Just start the operation by recording it in storage.
|
||||
let deposit = T::DepositBase::get() + T::DepositFactor::get() * threshold.into();
|
||||
|
||||
// Store the call if desired.
|
||||
let stored = if let Some(data) = maybe_call.filter(|_| store) {
|
||||
Self::store_call_and_reserve(who.clone(), &call_hash, data, deposit)?;
|
||||
true
|
||||
} else {
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
false
|
||||
};
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
|
||||
<Multisigs<T>>::insert(
|
||||
&id,
|
||||
@@ -664,58 +641,13 @@ impl<T: Config> Pallet<T> {
|
||||
);
|
||||
Self::deposit_event(Event::NewMultisig { approving: who, multisig: id, call_hash });
|
||||
|
||||
let final_weight = if stored {
|
||||
T::WeightInfo::as_multi_create_store(other_signatories_len as u32, call_len as u32)
|
||||
} else {
|
||||
T::WeightInfo::as_multi_create(other_signatories_len as u32, call_len as u32)
|
||||
};
|
||||
let final_weight =
|
||||
T::WeightInfo::as_multi_create(other_signatories_len as u32, call_len as u32);
|
||||
// Call is not made, so the actual weight does not include call
|
||||
Ok(Some(final_weight).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Place a call's encoded data in storage, reserving funds as appropriate.
|
||||
///
|
||||
/// We store `data` here because storing `call` would result in needing another `.encode`.
|
||||
///
|
||||
/// Returns a `bool` indicating whether the data did end up being stored.
|
||||
fn store_call_and_reserve(
|
||||
who: T::AccountId,
|
||||
hash: &[u8; 32],
|
||||
data: OpaqueCall<T>,
|
||||
other_deposit: BalanceOf<T>,
|
||||
) -> DispatchResult {
|
||||
ensure!(!Calls::<T>::contains_key(hash), Error::<T>::AlreadyStored);
|
||||
let deposit = other_deposit +
|
||||
T::DepositBase::get() +
|
||||
T::DepositFactor::get() *
|
||||
BalanceOf::<T>::from(((data.encoded_len() + 31) / 32) as u32);
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
Calls::<T>::insert(&hash, (data, who, deposit));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempt to decode and return the call, provided by the user or from storage.
|
||||
fn get_call(
|
||||
hash: &[u8; 32],
|
||||
maybe_known: Option<&OpaqueCall<T>>,
|
||||
) -> Option<(<T as Config>::RuntimeCall, usize)> {
|
||||
maybe_known.map_or_else(
|
||||
|| {
|
||||
Calls::<T>::get(hash)
|
||||
.and_then(|(data, ..)| Some((data.try_decode()?, data.encoded_len())))
|
||||
},
|
||||
|data| Some((data.try_decode()?, data.encoded_len())),
|
||||
)
|
||||
}
|
||||
|
||||
/// Attempt to remove a call from storage, returning any deposit on it to the owner.
|
||||
fn clear_call(hash: &[u8; 32]) {
|
||||
if let Some((_, who, deposit)) = Calls::<T>::take(hash) {
|
||||
T::Currency::unreserve(&who, deposit);
|
||||
}
|
||||
}
|
||||
|
||||
/// The current `Timepoint`.
|
||||
pub fn timepoint() -> Timepoint<T::BlockNumber> {
|
||||
Timepoint {
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2019-2022 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.
|
||||
|
||||
// Migrations for Multisig Pallet
|
||||
|
||||
use super::*;
|
||||
use frame_support::{
|
||||
dispatch::GetStorageVersion,
|
||||
traits::{OnRuntimeUpgrade, WrapperKeepOpaque},
|
||||
Identity,
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
|
||||
type OpaqueCall<T> = WrapperKeepOpaque<<T as Config>::RuntimeCall>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
type Calls<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Identity,
|
||||
[u8; 32],
|
||||
(OpaqueCall<T>, <T as frame_system::Config>::AccountId, BalanceOf<T>),
|
||||
>;
|
||||
|
||||
pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
|
||||
ensure!(onchain < 1, "this migration can be deleted");
|
||||
|
||||
log!(info, "Number of calls to refund and delete: {}", Calls::<T>::iter().count());
|
||||
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let current = Pallet::<T>::current_storage_version();
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
|
||||
if onchain > 0 {
|
||||
log!(info, "MigrateToV1 should be removed");
|
||||
return T::DbWeight::get().reads(1)
|
||||
}
|
||||
|
||||
Calls::<T>::drain().for_each(|(_call_hash, (_data, caller, deposit))| {
|
||||
T::Currency::unreserve(&caller, deposit);
|
||||
});
|
||||
|
||||
current.put::<Pallet<T>>();
|
||||
|
||||
<T as frame_system::Config>::BlockWeights::get().max_block
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
ensure!(onchain < 2, "this migration needs to be removed");
|
||||
ensure!(onchain == 1, "this migration needs to be run");
|
||||
ensure!(
|
||||
Calls::<T>::iter().count() == 0,
|
||||
"there are some dangling calls that need to be destroyed and refunded"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ use sp_runtime::{
|
||||
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
type OpaqueCall = super::OpaqueCall<Test>;
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum Test where
|
||||
@@ -130,8 +129,8 @@ fn now() -> Timepoint<u64> {
|
||||
Multisig::timepoint()
|
||||
}
|
||||
|
||||
fn call_transfer(dest: u64, value: u64) -> RuntimeCall {
|
||||
RuntimeCall::Balances(BalancesCall::transfer { dest, value })
|
||||
fn call_transfer(dest: u64, value: u64) -> Box<RuntimeCall> {
|
||||
Box::new(RuntimeCall::Balances(BalancesCall::transfer { dest, value }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -144,14 +143,12 @@ fn multisig_deposit_is_taken_and_returned() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 2);
|
||||
@@ -162,8 +159,7 @@ fn multisig_deposit_is_taken_and_returned() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
@@ -171,96 +167,6 @@ fn multisig_deposit_is_taken_and_returned() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_deposit_is_taken_and_returned_with_call_storage() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2);
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(1), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 5);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
hash,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_deposit_is_taken_and_returned_with_alt_call_storage() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let multi = Multisig::multi_account_id(&[1, 2, 3][..], 3);
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(1), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
vec![2, 3],
|
||||
None,
|
||||
hash,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 1);
|
||||
assert_eq!(Balances::reserved_balance(1), 4);
|
||||
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
3,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(2), 3);
|
||||
assert_eq!(Balances::reserved_balance(2), 2);
|
||||
assert_eq!(Balances::free_balance(1), 1);
|
||||
assert_eq!(Balances::reserved_balance(1), 4);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(3),
|
||||
3,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
hash,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
assert_eq!(Balances::free_balance(2), 5);
|
||||
assert_eq!(Balances::reserved_balance(2), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_multisig_returns_deposit() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -298,8 +204,8 @@ fn timepoint_checking_works() {
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
let call = call_transfer(6, 15);
|
||||
let hash = blake2_256(&call.encode());
|
||||
|
||||
assert_noop!(
|
||||
Multisig::approve_as_multi(
|
||||
@@ -328,8 +234,7 @@ fn timepoint_checking_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::NoTimepoint,
|
||||
@@ -341,8 +246,7 @@ fn timepoint_checking_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(later),
|
||||
OpaqueCall::from_encoded(call),
|
||||
false,
|
||||
call,
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::WrongTimepoint,
|
||||
@@ -350,41 +254,6 @@ fn timepoint_checking_works() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_2_of_3_works_with_call_storing() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2);
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(1), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 0);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
hash,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_2_of_3_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -395,8 +264,7 @@ fn multisig_2_of_3_works() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
@@ -412,8 +280,7 @@ fn multisig_2_of_3_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -430,8 +297,7 @@ fn multisig_3_of_3_works() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
@@ -455,8 +321,7 @@ fn multisig_3_of_3_works() {
|
||||
3,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -492,68 +357,6 @@ fn cancel_multisig_works() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_multisig_with_call_storage_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 4);
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
3,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
hash,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_noop!(
|
||||
Multisig::cancel_as_multi(RuntimeOrigin::signed(2), 3, vec![1, 3], now(), hash),
|
||||
Error::<Test>::NotOwner,
|
||||
);
|
||||
assert_ok!(Multisig::cancel_as_multi(RuntimeOrigin::signed(1), 3, vec![2, 3], now(), hash),);
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_multisig_with_alt_call_storage_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
vec![2, 3],
|
||||
None,
|
||||
hash,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 6);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
3,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(call),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(2), 8);
|
||||
assert_ok!(Multisig::cancel_as_multi(RuntimeOrigin::signed(1), 3, vec![2, 3], now(), hash));
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
assert_eq!(Balances::free_balance(2), 10);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_2_of_3_as_multi_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -564,14 +367,12 @@ fn multisig_2_of_3_as_multi_works() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 0);
|
||||
@@ -581,8 +382,7 @@ fn multisig_2_of_3_as_multi_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -599,18 +399,15 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
|
||||
let call1 = call_transfer(6, 10);
|
||||
let call1_weight = call1.get_dispatch_info().weight;
|
||||
let data1 = call1.encode();
|
||||
let call2 = call_transfer(7, 5);
|
||||
let call2_weight = call2.get_dispatch_info().weight;
|
||||
let data2 = call2.encode();
|
||||
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data1.clone()),
|
||||
false,
|
||||
call1.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -618,8 +415,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data2.clone()),
|
||||
false,
|
||||
call2.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -627,8 +423,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
2,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data1),
|
||||
false,
|
||||
call1,
|
||||
call1_weight
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -636,8 +431,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
2,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data2),
|
||||
false,
|
||||
call2,
|
||||
call2_weight
|
||||
));
|
||||
|
||||
@@ -656,15 +450,13 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
|
||||
let call = call_transfer(6, 10);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -672,8 +464,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(multi), 5);
|
||||
@@ -683,8 +474,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -692,8 +482,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
2,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call.clone(),
|
||||
call_weight
|
||||
));
|
||||
|
||||
@@ -714,15 +503,14 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
#[test]
|
||||
fn minimum_threshold_check_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let call = call_transfer(6, 15);
|
||||
assert_noop!(
|
||||
Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
0,
|
||||
vec![2],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MinimumThreshold,
|
||||
@@ -733,8 +521,7 @@ fn minimum_threshold_check_works() {
|
||||
1,
|
||||
vec![2],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MinimumThreshold,
|
||||
@@ -745,15 +532,14 @@ fn minimum_threshold_check_works() {
|
||||
#[test]
|
||||
fn too_many_signatories_fails() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let call = call_transfer(6, 15);
|
||||
assert_noop!(
|
||||
Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3, 4],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::TooManySignatories,
|
||||
@@ -815,8 +601,8 @@ fn multisig_1_of_3_works() {
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
let call = call_transfer(6, 15);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_noop!(
|
||||
Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
@@ -834,17 +620,15 @@ fn multisig_1_of_3_works() {
|
||||
1,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MinimumThreshold,
|
||||
);
|
||||
let boxed_call = Box::new(call_transfer(6, 15));
|
||||
assert_ok!(Multisig::as_multi_threshold_1(
|
||||
RuntimeOrigin::signed(1),
|
||||
vec![2, 3],
|
||||
boxed_call
|
||||
call_transfer(6, 15)
|
||||
));
|
||||
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -871,14 +655,12 @@ fn weight_check_works() {
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let data = call.encode();
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 0);
|
||||
@@ -889,8 +671,7 @@ fn weight_check_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MaxWeightTooLow,
|
||||
@@ -911,8 +692,7 @@ fn multisig_handles_no_preimage_after_all_approve() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
@@ -944,8 +724,7 @@ fn multisig_handles_no_preimage_after_all_approve() {
|
||||
3,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
|
||||
Reference in New Issue
Block a user