22#![ allow( clippy:: absurd_extreme_comparisons) ]
33#![ allow( clippy:: not_unsafe_ptr_arg_deref) ]
44
5- //! Tanssi Runtime fuzz target. Generates random extrinsics and some mock relay validation data (but no sudo) .
5+ //! Tanssi Runtime fuzz target. Generates random extrinsics and some pseudo-extrinsics .
66//!
7- //! Based on https://github.com/srlabs/substrate-runtime-fuzzer/blob/8d45d9960cff6f6c5aa8bf19808f84ef12b08535/node-template-fuzzer/src/main.rs
8-
9- use std:: iter;
10- use sp_state_machine:: BasicExternalities ;
11- use dancelight_runtime:: Balance ;
12- use frame_system:: Account ;
13- use dancelight_runtime:: Balances ;
14- use pallet_balances:: Holds ;
15- use pallet_balances:: TotalIssuance ;
16- use dancelight_runtime:: ParaInherent ;
17- use dancelight_runtime:: Timestamp ;
18- use sp_consensus_babe:: BABE_ENGINE_ID ;
19- use sp_consensus_babe:: digests:: PreDigest ;
20- use sp_core:: H256 ;
21- use sp_consensus_babe:: digests:: SecondaryPlainPreDigest ;
22- use primitives:: ValidationCode ;
23- use pallet_configuration:: HostConfiguration ;
24- use sp_runtime:: Saturating ;
25- use primitives:: { vstaging:: SchedulerParams } ;
26- use std:: cmp:: max;
27- use dancelight_runtime:: genesis_config_presets:: get_authority_keys_from_seed;
28- use polkadot_core_primitives:: BlockNumber ;
29- use polkadot_core_primitives:: Signature ;
30- use dancelight_runtime_constants:: time:: SLOT_DURATION ;
7+ //! Based on https://github.com/srlabs/substrate-runtime-fuzzer/blob/2a42a8b750aff0e12eb0e09b33aea9825a40595a/runtimes/kusama/src/main.rs
8+
319use {
3210 cumulus_primitives_core:: ParaId ,
3311 dancelight_runtime:: {
34- AccountId , AllPalletsWithSystem , Executive , Header , Runtime , RuntimeCall ,
35- RuntimeOrigin , UncheckedExtrinsic ,
12+ genesis_config_presets:: get_authority_keys_from_seed, AccountId , AllPalletsWithSystem ,
13+ Balance , Balances , Executive , Header , ParaInherent , Runtime , RuntimeCall , RuntimeOrigin ,
14+ Timestamp , UncheckedExtrinsic ,
3615 } ,
16+ dancelight_runtime_constants:: time:: SLOT_DURATION ,
17+ dp_container_chain_genesis_data:: ContainerChainGenesisData ,
3718 dp_core:: well_known_keys:: PARAS_HEADS_INDEX ,
3819 frame_metadata:: { v15:: RuntimeMetadataV15 , RuntimeMetadata , RuntimeMetadataPrefixed } ,
3920 frame_support:: {
4021 dispatch:: GetDispatchInfo ,
4122 pallet_prelude:: Weight ,
42- traits:: { IntegrityTest , TryState , TryStateSelect } ,
23+ traits:: { IntegrityTest , OriginTrait , TryState , TryStateSelect } ,
4324 weights:: constants:: WEIGHT_REF_TIME_PER_SECOND ,
4425 Hashable ,
4526 } ,
27+ frame_system:: Account ,
4628 nimbus_primitives:: { NimbusId , NIMBUS_ENGINE_ID } ,
29+ pallet_balances:: { Holds , TotalIssuance } ,
30+ pallet_configuration:: HostConfiguration ,
4731 parity_scale_codec:: { DecodeLimit , Encode } ,
32+ polkadot_core_primitives:: { BlockNumber , Signature } ,
33+ primitives:: { vstaging:: SchedulerParams , ValidationCode } ,
4834 sp_consensus_aura:: { Slot , AURA_ENGINE_ID } ,
49- sp_core:: { sr25519, Decode , Get , Pair , Public } ,
35+ sp_consensus_babe:: {
36+ digests:: { PreDigest , SecondaryPlainPreDigest } ,
37+ BABE_ENGINE_ID ,
38+ } ,
39+ sp_core:: { sr25519, Decode , Get , Pair , Public , H256 } ,
5040 sp_inherents:: InherentDataProvider ,
5141 sp_runtime:: {
5242 traits:: { Dispatchable , Header as HeaderT , IdentifyAccount , Verify } ,
53- Digest , DigestItem , Perbill , Storage ,
43+ Digest , DigestItem , Perbill , Saturating , Storage ,
5444 } ,
45+ sp_state_machine:: BasicExternalities ,
5546 std:: {
5647 any:: TypeId ,
5748 cell:: Cell ,
58- time:: { Duration , Instant } ,
49+ cmp:: max,
50+ iter,
5951 marker:: PhantomData ,
52+ time:: { Duration , Instant } ,
6053 } ,
61- dp_container_chain_genesis_data:: ContainerChainGenesisData ,
6254} ;
6355
6456fn recursively_find_call ( call : RuntimeCall , matches_on : fn ( RuntimeCall ) -> bool ) -> bool {
@@ -73,21 +65,14 @@ fn recursively_find_call(call: RuntimeCall, matches_on: fn(RuntimeCall) -> bool)
7365 return true ;
7466 }
7567 }
76- }
77- /*
78- else if let RuntimeCall::Lottery(pallet_lottery::Call::buy_ticket { call })
79- | RuntimeCall::Multisig(pallet_multisig::Call::as_multi_threshold_1 {
68+ } else if let RuntimeCall :: Multisig ( pallet_multisig:: Call :: as_multi_threshold_1 {
8069 call, ..
8170 } )
8271 | RuntimeCall :: Utility ( pallet_utility:: Call :: as_derivative { call, .. } )
83- | RuntimeCall::Council(pallet_collective::Call::propose {
84- proposal: call, ..
85- }) = call
72+ | RuntimeCall :: Proxy ( pallet_proxy:: Call :: proxy { call, .. } ) = call
8673 {
8774 return recursively_find_call ( * call. clone ( ) , matches_on) ;
88- }
89- */
90- else if matches_on ( call) {
75+ } else if matches_on ( call) {
9176 return true ;
9277 }
9378 false
@@ -163,9 +148,7 @@ pub fn get_from_seed<TPublic: Public + 'static>(seed: &str) -> <TPublic::Pair as
163148 . public ( )
164149}
165150
166- pub fn mock_container_chain_genesis_data (
167- para_id : ParaId ,
168- ) -> ContainerChainGenesisData {
151+ pub fn mock_container_chain_genesis_data ( para_id : ParaId ) -> ContainerChainGenesisData {
169152 ContainerChainGenesisData {
170153 storage : vec ! [ ] ,
171154 name : format ! ( "Container Chain {}" , para_id) . into ( ) ,
@@ -201,8 +184,7 @@ where
201184///
202185/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
203186pub fn template_session_keys ( account : AccountId ) -> dancelight_runtime:: SessionKeys {
204- let authority_keys =
205- get_authority_keys_from_seed ( & account. to_string ( ) , None ) ;
187+ let authority_keys = get_authority_keys_from_seed ( & account. to_string ( ) , None ) ;
206188
207189 dancelight_runtime:: SessionKeys {
208190 babe : authority_keys. babe . clone ( ) ,
@@ -230,7 +212,6 @@ pub fn invulnerables_from_seeds<S: AsRef<str>, I: Iterator<Item = S>>(
230212 . collect ( )
231213}
232214
233-
234215fn default_parachains_host_configuration (
235216) -> runtime_parachains:: configuration:: HostConfiguration < primitives:: BlockNumber > {
236217 use primitives:: {
@@ -688,9 +669,40 @@ fn fuzz_main(data: &[u8]) {
688669 //println!("data: {:?}", data);
689670 let mut extrinsic_data = data;
690671 //#[allow(deprecated)]
691- let extrinsics: Vec < ( /* lapse */ u8 , /* origin */ u8 , ExtrOrPseudo ) > = iter:: from_fn ( || {
692- DecodeLimit :: decode_with_depth_limit ( 64 , & mut extrinsic_data) . ok ( )
693- } ) . collect ( ) ;
672+ let extrinsics: Vec < ( /* lapse */ u8 , /* origin */ u8 , ExtrOrPseudo ) > =
673+ iter:: from_fn ( || DecodeLimit :: decode_with_depth_limit ( 64 , & mut extrinsic_data) . ok ( ) )
674+ . filter ( |( _, _, x) | match x {
675+ ExtrOrPseudo :: Extr ( x) => !recursively_find_call ( x. clone ( ) , |call| {
676+ // We filter out calls with Fungible(0) as they cause a debug crash
677+ matches ! ( call. clone( ) , RuntimeCall :: XcmPallet ( pallet_xcm:: Call :: execute { message, .. } )
678+ if matches!( message. as_ref( ) , staging_xcm:: VersionedXcm :: V2 ( staging_xcm:: v2:: Xcm ( msg) )
679+ if msg. iter( ) . any( |m| matches!( m, staging_xcm:: opaque:: v2:: prelude:: BuyExecution { fees: staging_xcm:: v2:: MultiAsset { fun, .. } , .. }
680+ if fun == & staging_xcm:: v2:: Fungibility :: Fungible ( 0 )
681+ )
682+ ) ) || matches!( message. as_ref( ) , staging_xcm:: VersionedXcm :: V3 ( staging_xcm:: v3:: Xcm ( msg) )
683+ if msg. iter( ) . any( |m| matches!( m, staging_xcm:: opaque:: v3:: prelude:: BuyExecution { weight_limit: staging_xcm:: opaque:: v3:: WeightLimit :: Limited ( weight) , .. }
684+ if weight. ref_time( ) <= 1
685+ ) )
686+ )
687+ )
688+ || matches ! ( call. clone( ) , RuntimeCall :: XcmPallet ( pallet_xcm:: Call :: transfer_assets_using_type_and_then { assets, ..} )
689+ if staging_xcm:: v2:: MultiAssets :: try_from( * assets. clone( ) )
690+ . map( |assets| assets. inner( ) . iter( ) . any( |a| matches!( a, staging_xcm:: v2:: MultiAsset { fun, .. }
691+ if fun == & staging_xcm:: v2:: Fungibility :: Fungible ( 0 )
692+ ) ) ) . unwrap_or( false )
693+ )
694+ || matches ! ( call. clone( ) , RuntimeCall :: System ( _) )
695+ || matches ! (
696+ & call,
697+ RuntimeCall :: Referenda ( pallet_referenda:: Call :: submit {
698+ proposal_origin: matching_origin,
699+ ..
700+ } ) if RuntimeOrigin :: from( * matching_origin. clone( ) ) . caller( ) == RuntimeOrigin :: root( ) . caller( )
701+ )
702+ } ) ,
703+ ExtrOrPseudo :: Pseudo ( x) => true ,
704+ } )
705+ . collect ( ) ;
694706
695707 if extrinsics. is_empty ( ) {
696708 return ;
@@ -736,9 +748,7 @@ fn fuzz_main(data: &[u8]) {
736748 Timestamp :: set ( RuntimeOrigin :: none ( ) , u64:: from ( block) * SLOT_DURATION ) . unwrap ( ) ;
737749
738750 Executive :: apply_extrinsic ( UncheckedExtrinsic :: new_unsigned ( RuntimeCall :: AuthorNoting (
739- pallet_author_noting:: Call :: set_latest_author_data {
740- data : ( ) ,
741- } ,
751+ pallet_author_noting:: Call :: set_latest_author_data { data : ( ) } ,
742752 ) ) )
743753 . unwrap ( )
744754 . unwrap ( ) ;
@@ -808,7 +818,6 @@ fn fuzz_main(data: &[u8]) {
808818 elapsed += now. elapsed ( ) ;
809819
810820 log:: debug!( " result: {res:?}" ) ;
811-
812821 }
813822 ExtrOrPseudo :: Pseudo ( fuzz_call) => {
814823 match fuzz_call {
@@ -828,7 +837,6 @@ fn fuzz_main(data: &[u8]) {
828837 }
829838 }
830839 }
831-
832840 }
833841
834842 finalize_block ( elapsed) ;
0 commit comments