mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 04:41:02 +00:00
contracts: Make Origin information available (#13708)
* contracts: allow root calls * contracts: update ContractOrigin * contracts: test allow root calls * contracts: rustfmt * contracts: test root caller traps * contracts: add Caller enum * contracts: improve some comments * contracts: improve some comments * contracts: format code with +nightly * contracts: fix failing tests * contracts: improve charte instantiate call when root origin * contract: refactor common, call and instantiate inputs * contracts: fix some failing test * contracts: trap caller when there is no account id * Update frame/contracts/src/lib.rs Co-authored-by: PG Herveou <pgherveou@gmail.com> * Update frame/contracts/src/exec.rs Co-authored-by: PG Herveou <pgherveou@gmail.com> * contracts: make `into_deposit` return zero when the origin is root * contracts: cargo fmt * contracts: charging and terminating tests refactored * contracts: improved errors * contracts: refactor & merge ContractOrigin cand Caller enums * Update frame/contracts/src/lib.rs Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * contracts: apply suggested pr changes * contracts: rename Caller to Origin * contracts: refactor run fn * contracts: cr improvements * contracts: allow root to use delegate call * contracts: add caller_is_root weight * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * contracts: add caller_is_root benchmarking * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * contracts: add caller_is_root benchmarking * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * contracts: add some minor improvements * contracts: make caller_is_root runtime fn unstable * contracts: fix failing wasm test * contracts: update benchmarking for origin_is_root * contracts: improve seal_caller_is_root benchmarking * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * contracts: add small pr improvements * contracts: fix broken tests after master merge * contracts: acknowledge the default storage deposit limit * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * contracts: move origin to CommonInput * contracts: add some extra tests * contracts: move ensure origin logic inside invokable::run_guarded * contracts: add minor improvements * contracts: fix caller_is_root benchmarking * contracts: improve function description * Update frame/contracts/src/lib.rs Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * Update frame/contracts/src/lib.rs Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * contracts: improve function description --------- Co-authored-by: parity-processbot <> Co-authored-by: PG Herveou <pgherveou@gmail.com> Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
|
||||
use crate::{
|
||||
storage::{ContractInfo, DepositAccount},
|
||||
BalanceOf, Config, Error, Inspect, Pallet, System,
|
||||
BalanceOf, Config, Error, Inspect, Origin, Pallet, System,
|
||||
};
|
||||
use codec::Encode;
|
||||
use frame_support::{
|
||||
@@ -352,12 +352,21 @@ where
|
||||
///
|
||||
/// This tries to [`Ext::check_limit`] on `origin` and fails if this is not possible.
|
||||
pub fn new(
|
||||
origin: &T::AccountId,
|
||||
origin: &Origin<T>,
|
||||
limit: Option<BalanceOf<T>>,
|
||||
min_leftover: BalanceOf<T>,
|
||||
) -> Result<Self, DispatchError> {
|
||||
let limit = E::check_limit(origin, limit, min_leftover)?;
|
||||
Ok(Self { limit, ..Default::default() })
|
||||
// Check the limit only if the origin is not root.
|
||||
return match origin {
|
||||
Origin::Root => Ok(Self {
|
||||
limit: limit.unwrap_or(T::DefaultDepositLimit::get()),
|
||||
..Default::default()
|
||||
}),
|
||||
Origin::Signed(o) => {
|
||||
let limit = E::check_limit(o, limit, min_leftover)?;
|
||||
Ok(Self { limit, ..Default::default() })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// The total amount of deposit that should change hands as result of the execution
|
||||
@@ -366,7 +375,13 @@ where
|
||||
///
|
||||
/// This drops the root meter in order to make sure it is only called when the whole
|
||||
/// execution did finish.
|
||||
pub fn try_into_deposit(self, origin: &T::AccountId) -> Result<DepositOf<T>, DispatchError> {
|
||||
|
||||
pub fn try_into_deposit(self, origin: &Origin<T>) -> Result<DepositOf<T>, DispatchError> {
|
||||
// Only refund or charge deposit if the origin is not root.
|
||||
let origin = match origin {
|
||||
Origin::Root => return Ok(Deposit::Charge(Zero::zero())),
|
||||
Origin::Signed(o) => o,
|
||||
};
|
||||
for charge in self.charges.iter().filter(|c| matches!(c.amount, Deposit::Refund(_))) {
|
||||
E::charge(origin, &charge.deposit_account, &charge.amount, charge.terminated)?;
|
||||
}
|
||||
@@ -625,6 +640,12 @@ mod tests {
|
||||
TestExtTestValue::mutate(|ext| ext.clear())
|
||||
}
|
||||
|
||||
struct ChargingTestCase {
|
||||
origin: Origin<Test>,
|
||||
deposit: DepositOf<Test>,
|
||||
expected: TestExt,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StorageInfo {
|
||||
bytes: u32,
|
||||
@@ -650,7 +671,7 @@ mod tests {
|
||||
fn new_reserves_balance_works() {
|
||||
clear_ext();
|
||||
|
||||
TestMeter::new(&ALICE, Some(1_000), 0).unwrap();
|
||||
TestMeter::new(&Origin::from_account_id(ALICE), Some(1_000), 0).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
TestExtTestValue::get(),
|
||||
@@ -665,7 +686,7 @@ mod tests {
|
||||
fn empty_charge_works() {
|
||||
clear_ext();
|
||||
|
||||
let mut meter = TestMeter::new(&ALICE, Some(1_000), 0).unwrap();
|
||||
let mut meter = TestMeter::new(&Origin::from_account_id(ALICE), Some(1_000), 0).unwrap();
|
||||
assert_eq!(meter.available(), 1_000);
|
||||
|
||||
// an empty charge does not create a `Charge` entry
|
||||
@@ -684,118 +705,158 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn charging_works() {
|
||||
clear_ext();
|
||||
let test_cases = vec![
|
||||
ChargingTestCase {
|
||||
origin: Origin::<Test>::from_account_id(ALICE),
|
||||
deposit: Deposit::Refund(28),
|
||||
expected: TestExt {
|
||||
limit_checks: vec![LimitCheck { origin: ALICE, limit: 100, min_leftover: 0 }],
|
||||
charges: vec![
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(CHARLIE),
|
||||
amount: Deposit::Refund(10),
|
||||
terminated: false,
|
||||
},
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(CHARLIE),
|
||||
amount: Deposit::Refund(20),
|
||||
terminated: false,
|
||||
},
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(BOB),
|
||||
amount: Deposit::Charge(2),
|
||||
terminated: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
ChargingTestCase {
|
||||
origin: Origin::<Test>::Root,
|
||||
deposit: Deposit::Charge(0),
|
||||
expected: TestExt { limit_checks: vec![], charges: vec![] },
|
||||
},
|
||||
];
|
||||
|
||||
let mut meter = TestMeter::new(&ALICE, Some(100), 0).unwrap();
|
||||
assert_eq!(meter.available(), 100);
|
||||
for test_case in test_cases {
|
||||
clear_ext();
|
||||
|
||||
let mut nested0_info =
|
||||
new_info(StorageInfo { bytes: 100, items: 5, bytes_deposit: 100, items_deposit: 10 });
|
||||
let mut nested0 = meter.nested(BalanceOf::<Test>::zero());
|
||||
nested0.charge(&Diff {
|
||||
bytes_added: 108,
|
||||
bytes_removed: 5,
|
||||
items_added: 1,
|
||||
items_removed: 2,
|
||||
});
|
||||
nested0.charge(&Diff { bytes_removed: 99, ..Default::default() });
|
||||
let mut meter = TestMeter::new(&test_case.origin, Some(100), 0).unwrap();
|
||||
assert_eq!(meter.available(), 100);
|
||||
|
||||
let mut nested1_info =
|
||||
new_info(StorageInfo { bytes: 100, items: 10, bytes_deposit: 100, items_deposit: 20 });
|
||||
let mut nested1 = nested0.nested(BalanceOf::<Test>::zero());
|
||||
nested1.charge(&Diff { items_removed: 5, ..Default::default() });
|
||||
nested0.absorb(nested1, DepositAccount(CHARLIE), Some(&mut nested1_info));
|
||||
let mut nested0_info = new_info(StorageInfo {
|
||||
bytes: 100,
|
||||
items: 5,
|
||||
bytes_deposit: 100,
|
||||
items_deposit: 10,
|
||||
});
|
||||
let mut nested0 = meter.nested(BalanceOf::<Test>::zero());
|
||||
nested0.charge(&Diff {
|
||||
bytes_added: 108,
|
||||
bytes_removed: 5,
|
||||
items_added: 1,
|
||||
items_removed: 2,
|
||||
});
|
||||
nested0.charge(&Diff { bytes_removed: 99, ..Default::default() });
|
||||
|
||||
let mut nested2_info =
|
||||
new_info(StorageInfo { bytes: 100, items: 7, bytes_deposit: 100, items_deposit: 20 });
|
||||
let mut nested2 = nested0.nested(BalanceOf::<Test>::zero());
|
||||
nested2.charge(&Diff { items_removed: 7, ..Default::default() });
|
||||
nested0.absorb(nested2, DepositAccount(CHARLIE), Some(&mut nested2_info));
|
||||
let mut nested1_info = new_info(StorageInfo {
|
||||
bytes: 100,
|
||||
items: 10,
|
||||
bytes_deposit: 100,
|
||||
items_deposit: 20,
|
||||
});
|
||||
let mut nested1 = nested0.nested(BalanceOf::<Test>::zero());
|
||||
nested1.charge(&Diff { items_removed: 5, ..Default::default() });
|
||||
nested0.absorb(nested1, DepositAccount(CHARLIE), Some(&mut nested1_info));
|
||||
|
||||
nested0.enforce_limit(Some(&mut nested0_info)).unwrap();
|
||||
meter.absorb(nested0, DepositAccount(BOB), Some(&mut nested0_info));
|
||||
let mut nested2_info = new_info(StorageInfo {
|
||||
bytes: 100,
|
||||
items: 7,
|
||||
bytes_deposit: 100,
|
||||
items_deposit: 20,
|
||||
});
|
||||
let mut nested2 = nested0.nested(BalanceOf::<Test>::zero());
|
||||
nested2.charge(&Diff { items_removed: 7, ..Default::default() });
|
||||
nested0.absorb(nested2, DepositAccount(CHARLIE), Some(&mut nested2_info));
|
||||
|
||||
meter.try_into_deposit(&ALICE).unwrap();
|
||||
nested0.enforce_limit(Some(&mut nested0_info)).unwrap();
|
||||
meter.absorb(nested0, DepositAccount(BOB), Some(&mut nested0_info));
|
||||
|
||||
assert_eq!(nested0_info.extra_deposit(), 112);
|
||||
assert_eq!(nested1_info.extra_deposit(), 110);
|
||||
assert_eq!(nested2_info.extra_deposit(), 100);
|
||||
assert_eq!(meter.try_into_deposit(&test_case.origin).unwrap(), test_case.deposit);
|
||||
|
||||
assert_eq!(
|
||||
TestExtTestValue::get(),
|
||||
TestExt {
|
||||
limit_checks: vec![LimitCheck { origin: ALICE, limit: 100, min_leftover: 0 }],
|
||||
charges: vec![
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(CHARLIE),
|
||||
amount: Deposit::Refund(10),
|
||||
terminated: false
|
||||
},
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(CHARLIE),
|
||||
amount: Deposit::Refund(20),
|
||||
terminated: false
|
||||
},
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(BOB),
|
||||
amount: Deposit::Charge(2),
|
||||
terminated: false
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert_eq!(nested0_info.extra_deposit(), 112);
|
||||
assert_eq!(nested1_info.extra_deposit(), 110);
|
||||
assert_eq!(nested2_info.extra_deposit(), 100);
|
||||
|
||||
assert_eq!(TestExtTestValue::get(), test_case.expected)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn termination_works() {
|
||||
clear_ext();
|
||||
let test_cases = vec![
|
||||
ChargingTestCase {
|
||||
origin: Origin::<Test>::from_account_id(ALICE),
|
||||
deposit: Deposit::Refund(107),
|
||||
expected: TestExt {
|
||||
limit_checks: vec![LimitCheck { origin: ALICE, limit: 1_000, min_leftover: 0 }],
|
||||
charges: vec![
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(CHARLIE),
|
||||
amount: Deposit::Refund(119),
|
||||
terminated: true,
|
||||
},
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(BOB),
|
||||
amount: Deposit::Charge(12),
|
||||
terminated: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
ChargingTestCase {
|
||||
origin: Origin::<Test>::Root,
|
||||
deposit: Deposit::Charge(0),
|
||||
expected: TestExt { limit_checks: vec![], charges: vec![] },
|
||||
},
|
||||
];
|
||||
|
||||
let mut meter = TestMeter::new(&ALICE, Some(1_000), 0).unwrap();
|
||||
assert_eq!(meter.available(), 1_000);
|
||||
for test_case in test_cases {
|
||||
clear_ext();
|
||||
|
||||
let mut nested0 = meter.nested(BalanceOf::<Test>::zero());
|
||||
nested0.charge(&Diff {
|
||||
bytes_added: 5,
|
||||
bytes_removed: 1,
|
||||
items_added: 3,
|
||||
items_removed: 1,
|
||||
});
|
||||
nested0.charge(&Diff { items_added: 2, ..Default::default() });
|
||||
let mut meter = TestMeter::new(&test_case.origin, Some(1_000), 0).unwrap();
|
||||
assert_eq!(meter.available(), 1_000);
|
||||
|
||||
let mut nested1_info =
|
||||
new_info(StorageInfo { bytes: 100, items: 10, bytes_deposit: 100, items_deposit: 20 });
|
||||
let mut nested1 = nested0.nested(BalanceOf::<Test>::zero());
|
||||
nested1.charge(&Diff { items_removed: 5, ..Default::default() });
|
||||
nested1.charge(&Diff { bytes_added: 20, ..Default::default() });
|
||||
nested1.terminate(&nested1_info);
|
||||
nested0.enforce_limit(Some(&mut nested1_info)).unwrap();
|
||||
nested0.absorb(nested1, DepositAccount(CHARLIE), None);
|
||||
let mut nested0 = meter.nested(BalanceOf::<Test>::zero());
|
||||
nested0.charge(&Diff {
|
||||
bytes_added: 5,
|
||||
bytes_removed: 1,
|
||||
items_added: 3,
|
||||
items_removed: 1,
|
||||
});
|
||||
nested0.charge(&Diff { items_added: 2, ..Default::default() });
|
||||
|
||||
meter.absorb(nested0, DepositAccount(BOB), None);
|
||||
meter.try_into_deposit(&ALICE).unwrap();
|
||||
let mut nested1_info = new_info(StorageInfo {
|
||||
bytes: 100,
|
||||
items: 10,
|
||||
bytes_deposit: 100,
|
||||
items_deposit: 20,
|
||||
});
|
||||
let mut nested1 = nested0.nested(BalanceOf::<Test>::zero());
|
||||
nested1.charge(&Diff { items_removed: 5, ..Default::default() });
|
||||
nested1.charge(&Diff { bytes_added: 20, ..Default::default() });
|
||||
nested1.terminate(&nested1_info);
|
||||
nested0.enforce_limit(Some(&mut nested1_info)).unwrap();
|
||||
nested0.absorb(nested1, DepositAccount(CHARLIE), None);
|
||||
|
||||
assert_eq!(
|
||||
TestExtTestValue::get(),
|
||||
TestExt {
|
||||
limit_checks: vec![LimitCheck { origin: ALICE, limit: 1_000, min_leftover: 0 }],
|
||||
charges: vec![
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(CHARLIE),
|
||||
amount: Deposit::Refund(119),
|
||||
terminated: true
|
||||
},
|
||||
Charge {
|
||||
origin: ALICE,
|
||||
contract: DepositAccount(BOB),
|
||||
amount: Deposit::Charge(12),
|
||||
terminated: false
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
meter.absorb(nested0, DepositAccount(BOB), None);
|
||||
assert_eq!(meter.try_into_deposit(&test_case.origin).unwrap(), test_case.deposit);
|
||||
|
||||
assert_eq!(TestExtTestValue::get(), test_case.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user