mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
Enforce MaxEncodedLen impl for NposSolution (#11103)
* Fail if `MaxVoters` too small * Fixing benchmarking test, better naming of error * reverting accidental change * use fully qualified syntax no need to interate to calculate len * Fail directly if too many voters
This commit is contained in:
@@ -74,7 +74,7 @@ frame_election_provider_support::generate_solution_type!(
|
|||||||
VoterIndex = VoterIndex,
|
VoterIndex = VoterIndex,
|
||||||
TargetIndex = TargetIndex,
|
TargetIndex = TargetIndex,
|
||||||
Accuracy = PerU16,
|
Accuracy = PerU16,
|
||||||
MaxVoters = ConstU32::<20>
|
MaxVoters = ConstU32::<2_000>
|
||||||
>(16)
|
>(16)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,11 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result<TokenStream2> {
|
|||||||
for<'r> FV: Fn(&'r A) -> Option<Self::VoterIndex>,
|
for<'r> FV: Fn(&'r A) -> Option<Self::VoterIndex>,
|
||||||
for<'r> FT: Fn(&'r A) -> Option<Self::TargetIndex>,
|
for<'r> FT: Fn(&'r A) -> Option<Self::TargetIndex>,
|
||||||
{
|
{
|
||||||
|
// Make sure that the voter bound is binding.
|
||||||
|
// `assignments.len()` actually represents the number of voters
|
||||||
|
if assignments.len() as u32 > <#max_voters as _feps::Get<u32>>::get() {
|
||||||
|
return Err(_feps::Error::TooManyVoters);
|
||||||
|
}
|
||||||
let mut #struct_name: #ident = Default::default();
|
let mut #struct_name: #ident = Default::default();
|
||||||
for _feps::Assignment { who, distribution } in assignments {
|
for _feps::Assignment { who, distribution } in assignments {
|
||||||
match distribution.len() {
|
match distribution.len() {
|
||||||
@@ -134,6 +139,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result<TokenStream2> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(#struct_name)
|
Ok(#struct_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -170,12 +170,13 @@ pub mod onchain;
|
|||||||
pub mod traits;
|
pub mod traits;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{traits::Get, BoundedVec, RuntimeDebug};
|
use frame_support::{BoundedVec, RuntimeDebug};
|
||||||
use sp_runtime::traits::Bounded;
|
use sp_runtime::traits::Bounded;
|
||||||
use sp_std::{fmt::Debug, prelude::*};
|
use sp_std::{fmt::Debug, prelude::*};
|
||||||
|
|
||||||
/// Re-export the solution generation macro.
|
/// Re-export the solution generation macro.
|
||||||
pub use frame_election_provider_solution_type::generate_solution_type;
|
pub use frame_election_provider_solution_type::generate_solution_type;
|
||||||
|
pub use frame_support::traits::Get;
|
||||||
/// Re-export some type as they are used in the interface.
|
/// Re-export some type as they are used in the interface.
|
||||||
pub use sp_arithmetic::PerThing;
|
pub use sp_arithmetic::PerThing;
|
||||||
pub use sp_npos_elections::{
|
pub use sp_npos_elections::{
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ crate::generate_solution_type! {
|
|||||||
VoterIndex = u32,
|
VoterIndex = u32,
|
||||||
TargetIndex = u16,
|
TargetIndex = u16,
|
||||||
Accuracy = TestAccuracy,
|
Accuracy = TestAccuracy,
|
||||||
MaxVoters = frame_support::traits::ConstU32::<20>,
|
MaxVoters = frame_support::traits::ConstU32::<2_500>,
|
||||||
>(16)
|
>(16)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,33 @@ mod solution_type {
|
|||||||
assert!(with_compact < without_compact);
|
assert!(with_compact < without_compact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_assignment_fail_too_many_voters() {
|
||||||
|
let rng = rand::rngs::SmallRng::seed_from_u64(0);
|
||||||
|
|
||||||
|
// This will produce 24 voters..
|
||||||
|
let (voters, assignments, candidates) = generate_random_votes(10, 25, rng);
|
||||||
|
let voter_index = make_voter_fn(&voters);
|
||||||
|
let target_index = make_target_fn(&candidates);
|
||||||
|
|
||||||
|
// Limit the voters to 20..
|
||||||
|
generate_solution_type!(
|
||||||
|
pub struct InnerTestSolution::<
|
||||||
|
VoterIndex = u32,
|
||||||
|
TargetIndex = u16,
|
||||||
|
Accuracy = TestAccuracy,
|
||||||
|
MaxVoters = frame_support::traits::ConstU32::<20>,
|
||||||
|
>(16)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 24 > 20, so this should fail.
|
||||||
|
assert_eq!(
|
||||||
|
InnerTestSolution::from_assignment(&assignments, &voter_index, &target_index)
|
||||||
|
.unwrap_err(),
|
||||||
|
NposError::TooManyVoters,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn max_encoded_len_too_small() {
|
fn max_encoded_len_too_small() {
|
||||||
generate_solution_type!(
|
generate_solution_type!(
|
||||||
|
|||||||
@@ -119,12 +119,14 @@ pub enum Error {
|
|||||||
SolutionTargetOverflow,
|
SolutionTargetOverflow,
|
||||||
/// One of the index functions returned none.
|
/// One of the index functions returned none.
|
||||||
SolutionInvalidIndex,
|
SolutionInvalidIndex,
|
||||||
/// One of the page indices was invalid
|
/// One of the page indices was invalid.
|
||||||
SolutionInvalidPageIndex,
|
SolutionInvalidPageIndex,
|
||||||
/// An error occurred in some arithmetic operation.
|
/// An error occurred in some arithmetic operation.
|
||||||
ArithmeticError(&'static str),
|
ArithmeticError(&'static str),
|
||||||
/// The data provided to create support map was invalid.
|
/// The data provided to create support map was invalid.
|
||||||
InvalidSupportEdge,
|
InvalidSupportEdge,
|
||||||
|
/// The number of voters is bigger than the `MaxVoters` bound.
|
||||||
|
TooManyVoters,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type which is used in the API of this crate as a numeric weight of a vote, most often the
|
/// A type which is used in the API of this crate as a numeric weight of a vote, most often the
|
||||||
|
|||||||
Reference in New Issue
Block a user