Skip to content

Commit 7c851e4

Browse files
committed
Use MaxEncodedLen + test
1 parent f700f54 commit 7c851e4

3 files changed

Lines changed: 62 additions & 7 deletions

File tree

pallets/parachain-staking/src/types.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
Total,
2323
};
2424
use frame_support::pallet_prelude::*;
25-
use parity_scale_codec::{Decode, Encode};
25+
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
2626
use sp_runtime::{
2727
traits::{Saturating, Zero},
2828
Perbill, Percent, RuntimeDebug,
@@ -34,7 +34,8 @@ pub struct CountedDelegations<T: Config> {
3434
pub rewardable_delegations: Vec<Bond<T::AccountId, BalanceOf<T>>>,
3535
}
3636

37-
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
37+
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
38+
#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))]
3839
pub struct Bond<AccountId, Balance> {
3940
pub owner: AccountId,
4041
pub amount: Balance,
@@ -1101,7 +1102,7 @@ pub enum DelegatorAdded<B> {
11011102
}
11021103

11031104
#[allow(deprecated)]
1104-
#[derive(Clone, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
1105+
#[derive(Clone, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
11051106
pub enum DelegatorStatus {
11061107
/// Active with no scheduled exit
11071108
Active,

precompiles/parachain-staking/src/lib.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use frame_support::sp_runtime::Percent;
3030
use frame_support::traits::{fungible::Inspect, Get};
3131
use pallet_evm::AddressMapping;
3232
use pallet_parachain_staking::ScheduledRequest;
33+
use parity_scale_codec::{Compact, Encode};
3334
use precompile_utils::prelude::*;
3435
use sp_core::{H160, U256};
3536
use sp_runtime::traits::Dispatchable;
@@ -52,10 +53,10 @@ pub struct ParachainStakingPrecompile<Runtime>(PhantomData<Runtime>);
5253
impl<Runtime> ParachainStakingPrecompile<Runtime>
5354
where
5455
Runtime: pallet_parachain_staking::Config + pallet_evm::Config,
55-
Runtime::AccountId: Into<H160>,
56+
Runtime::AccountId: Into<H160> + MaxEncodedLen,
5657
Runtime::RuntimeCall: Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo,
5758
Runtime::RuntimeCall: From<pallet_parachain_staking::Call<Runtime>>,
58-
BalanceOf<Runtime>: TryFrom<U256> + Into<U256> + solidity::Codec,
59+
BalanceOf<Runtime>: TryFrom<U256> + Into<U256> + solidity::Codec + MaxEncodedLen,
5960
<Runtime as pallet_evm::Config>::AddressMapping: AddressMapping<Runtime::AccountId>,
6061
{
6162
// Constants
@@ -979,4 +980,29 @@ where
979980
.try_into()
980981
.map_err(|_| RevertReason::value_is_too_large("balance type").into())
981982
}
983+
984+
/// Proof-size upper bound for one read of [`pallet_parachain_staking::Pallet::delegator_state`]
985+
/// storage (`Twox64Concat` + `AccountId` key, max-sized SCALE `Delegator` value).
986+
pub(crate) fn delegator_state_storage_read_proof_size() -> usize {
987+
/// [`frame_support::Twox64Concat`] output length (bytes); Substrate storage key prefix.
988+
const TWOX64_CONCAT_PREFIX_LEN: usize = 8;
989+
let max_d =
990+
<Runtime as pallet_parachain_staking::Config>::MaxDelegationsPerDelegator::get();
991+
let delegation_compact_prefix = Compact(max_d).encode().len();
992+
let max_bonds_bytes = (max_d as usize).saturating_mul(pallet_parachain_staking::Bond::<
993+
Runtime::AccountId,
994+
BalanceOf<Runtime>,
995+
>::max_encoded_len());
996+
// Delegator Max Size = AccountId + MaxDelegationsCompact + (max_d * BondSize) + Balance + Balance + DelegatorStatus
997+
let value_max = Runtime::AccountId::max_encoded_len()
998+
.saturating_add(delegation_compact_prefix)
999+
.saturating_add(max_bonds_bytes)
1000+
.saturating_add(BalanceOf::<Runtime>::max_encoded_len())
1001+
.saturating_add(BalanceOf::<Runtime>::max_encoded_len())
1002+
.saturating_add(pallet_parachain_staking::DelegatorStatus::max_encoded_len());
1003+
// Total = TWOX64_CONCAT_PREFIX_LEN + AccountId + value_max
1004+
TWOX64_CONCAT_PREFIX_LEN
1005+
.saturating_add(Runtime::AccountId::max_encoded_len())
1006+
.saturating_add(value_max)
1007+
}
9821008
}

precompiles/parachain-staking/src/tests.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@
1515
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.
1616

1717
use crate::mock::{
18-
events, roll_to, roll_to_round_begin, set_points, ExtBuilder, PCall, ParachainStaking,
19-
Precompiles, PrecompilesValue, Runtime, RuntimeCall, RuntimeOrigin,
18+
events, roll_to, roll_to_round_begin, set_points, AccountId, ExtBuilder, PCall,
19+
ParachainStaking, Precompiles, PrecompilesValue, Runtime, RuntimeCall, RuntimeOrigin,
2020
};
21+
use crate::ParachainStakingPrecompile;
2122
use core::str::from_utf8;
2223
use fp_evm::MAX_TRANSACTION_GAS_LIMIT;
2324
use frame_support::assert_ok;
25+
use frame_support::pallet_prelude::MaxEncodedLen;
2426
use frame_support::sp_runtime::Percent;
27+
use frame_support::traits::fungible::Inspect;
2528
use pallet_evm::Call as EvmCall;
2629
use pallet_parachain_staking::Event as StakingEvent;
30+
use pallet_parachain_staking::{Bond, Config as StakingConfig, DelegatorStatus};
31+
use parity_scale_codec::{Compact, Encode};
2732
use precompile_utils::{prelude::*, testing::*};
2833
use sp_core::{H160, U256};
2934
use sp_runtime::traits::Dispatchable;
@@ -1746,3 +1751,26 @@ fn test_deprecated_solidity_selectors_are_supported() {
17461751
}
17471752
}
17481753
}
1754+
1755+
/// Mirrors the proof-size composition in [`ParachainStakingPrecompile::delegator_state_storage_read_proof_size`]
1756+
/// so this test fails if the helper drifts from the SCALE upper-bound model.
1757+
#[test]
1758+
fn delegator_state_storage_read_proof_size_matches_scale_upper_bound() {
1759+
type Bal =
1760+
<<Runtime as pallet_parachain_staking::Config>::Currency as Inspect<AccountId>>::Balance;
1761+
1762+
const TWOX64_CONCAT_PREFIX_LEN: usize = 8;
1763+
let max_d = <Runtime as StakingConfig>::MaxDelegationsPerDelegator::get();
1764+
let expected = TWOX64_CONCAT_PREFIX_LEN
1765+
.saturating_add(AccountId::max_encoded_len())
1766+
.saturating_add(AccountId::max_encoded_len())
1767+
.saturating_add(Compact(max_d).encode().len())
1768+
.saturating_add((max_d as usize).saturating_mul(Bond::<AccountId, Bal>::max_encoded_len()))
1769+
.saturating_add(Bal::max_encoded_len())
1770+
.saturating_add(Bal::max_encoded_len())
1771+
.saturating_add(DelegatorStatus::max_encoded_len());
1772+
1773+
let charged = ParachainStakingPrecompile::<Runtime>::delegator_state_storage_read_proof_size();
1774+
1775+
assert_eq!(charged, expected);
1776+
}

0 commit comments

Comments
 (0)