generate_solution_type!() { /* proc-macro */ }
Expand description

Re-export the solution generation macro. Generates a struct to store the election result in a small/compact way. This can encode a structure which is the equivalent of a sp_npos_elections::Assignment<_>.

The following data types can be configured by the macro.

  • The identifier of the voter. This can be any type that supports parity-scale-codec’s compact encoding.
  • The identifier of the target. This can be any type that supports parity-scale-codec’s compact encoding.
  • The accuracy of the ratios. This must be one of the PerThing types defined in sp-arithmetic.
  • The maximum number of voters. This must be of type Get<u32>. Check https://github.com/paritytech/substrate/issues/10866 for more details. This is used to bound the struct, by leveraging the fact that votes1.len() < votes2.len() < ... < votesn.len() (the details of the struct is explained further below). We know that sum_i votes_i.len() <= MaxVoters, and we know that the maximum size of the struct would be achieved if all voters fall in the last bucket. One can also check the tests and more specifically max_encoded_len_exact for a concrete example.

Moreover, the maximum number of edges per voter (distribution per assignment) also need to be specified. Attempting to convert from/to an assignment with more distributions will fail.

For example, the following generates a public struct with name TestSolution with u16 voter type, u8 target type and Perbill accuracy with maximum of 4 edges per voter.

generate_solution_type!(pub struct TestSolution::<
    VoterIndex = u16,
    TargetIndex = u8,
    Accuracy = Perbill,
    MaxVoters = ConstU32::<10>,
>(4));

The output of this macro will roughly look like:

struct TestSolution {
	voters1: vec![(u16 /* voter */, u8 /* target */)]
	voters2: vec![
		(u16 /* voter */, [u8 /* first target*/, Perbill /* proportion for first target */], u8 /* last target */)
	]
	voters3: vec![
		(u16 /* voter */,  [
			(u8 /* first target*/, Perbill /* proportion for first target */ ),
			(u8 /* second target */, Perbill /* proportion for second target*/)
		], u8 /* last target */)
		],
	voters4: ...,
}

impl NposSolution for TestSolution {};
impl Solution for TestSolution {};

The given struct provides function to convert from/to Assignment as part of frame_election_provider_support::NposSolution trait:

  • fn from_assignment<..>(..)
  • fn into_assignment<..>(..)

Compact Encoding

The generated struct is by default deriving both Encode and Decode. This is okay but could lead to many 0s in the solution. If prefixed with #[compact], then a custom compact encoding for numbers will be used, similar to how parity-scale-codec’s Compact works.

generate_solution_type!(
    #[compact]
    pub struct TestSolutionCompact::<
         VoterIndex = u16,
         TargetIndex = u8,
         Accuracy = Perbill,
         MaxVoters = ConstU32::<10>,
    >(8)
);