@@ -483,7 +483,13 @@ use {
483483 solana_svm_log_collector:: LogCollector ,
484484 solana_svm_timings:: ExecuteTimings ,
485485 solana_transaction_context:: { InstructionAccount , TransactionContext } ,
486- std:: { cell:: RefCell , collections:: HashSet , iter:: once, rc:: Rc , sync:: Arc } ,
486+ std:: {
487+ cell:: RefCell ,
488+ collections:: { HashMap , HashSet } ,
489+ iter:: once,
490+ rc:: Rc ,
491+ sync:: Arc ,
492+ } ,
487493} ;
488494#[ cfg( feature = "inner-instructions" ) ]
489495use {
@@ -772,6 +778,44 @@ impl Mollusk {
772778 }
773779 }
774780
781+ // Determine the accounts to fallback to during account compilation.
782+ fn get_account_fallbacks < ' a > (
783+ & self ,
784+ all_program_ids : impl Iterator < Item = & ' a Pubkey > ,
785+ all_instructions : impl Iterator < Item = & ' a Instruction > ,
786+ accounts : & [ ( Pubkey , Account ) ] ,
787+ ) -> HashMap < Pubkey , Account > {
788+ // Use a HashSet for fast lookups.
789+ let account_keys: HashSet < & Pubkey > = accounts. iter ( ) . map ( |( key, _) | key) . collect ( ) ;
790+
791+ let mut fallbacks = HashMap :: new ( ) ;
792+
793+ // Top-level target programs.
794+ all_program_ids. for_each ( |program_id| {
795+ if !account_keys. contains ( program_id) {
796+ // Fallback to a stub.
797+ fallbacks. insert (
798+ * program_id,
799+ Account {
800+ owner : self . get_loader_key ( program_id) ,
801+ executable : true ,
802+ ..Default :: default ( )
803+ } ,
804+ ) ;
805+ }
806+ } ) ;
807+
808+ // Instructions sysvar.
809+ if !account_keys. contains ( & solana_instructions_sysvar:: ID ) {
810+ // Fallback to the actual implementation of the sysvar.
811+ let ( ix_sysvar_id, ix_sysvar_acct) =
812+ crate :: instructions_sysvar:: keyed_account ( all_instructions) ;
813+ fallbacks. insert ( ix_sysvar_id, ix_sysvar_acct) ;
814+ }
815+
816+ fallbacks
817+ }
818+
775819 #[ cfg( feature = "inner-instructions" ) ]
776820 fn deconstruct_transaction (
777821 transaction_context : & mut TransactionContext ,
@@ -958,17 +1002,20 @@ impl Mollusk {
9581002 ) -> InstructionResult {
9591003 const INDEX : usize = 0 ;
9601004
961- let loader_key = self . get_loader_key ( & instruction. program_id ) ;
1005+ let fallback_accounts = self . get_account_fallbacks (
1006+ std:: iter:: once ( & instruction. program_id ) ,
1007+ std:: iter:: once ( instruction) ,
1008+ accounts,
1009+ ) ;
9621010
9631011 let CompiledAccounts {
9641012 program_id_index,
9651013 instruction_accounts,
9661014 transaction_accounts,
9671015 } = crate :: compile_accounts:: compile_accounts (
968- INDEX ,
969- std:: iter:: once ( instruction) ,
1016+ instruction,
9701017 accounts. iter ( ) ,
971- loader_key ,
1018+ & fallback_accounts ,
9721019 ) ;
9731020
9741021 self . process_instruction_inner (
@@ -1001,18 +1048,21 @@ impl Mollusk {
10011048 ..Default :: default ( )
10021049 } ;
10031050
1004- for ( index, instruction) in instructions. iter ( ) . enumerate ( ) {
1005- let loader_key = self . get_loader_key ( & instruction. program_id ) ;
1051+ let fallback_accounts = self . get_account_fallbacks (
1052+ instructions. iter ( ) . map ( |ix| & ix. program_id ) ,
1053+ instructions. iter ( ) ,
1054+ accounts,
1055+ ) ;
10061056
1057+ for ( index, instruction) in instructions. iter ( ) . enumerate ( ) {
10071058 let CompiledAccounts {
10081059 program_id_index,
10091060 instruction_accounts,
10101061 transaction_accounts,
10111062 } = crate :: compile_accounts:: compile_accounts (
1012- index,
1013- instructions. iter ( ) ,
1063+ instruction,
10141064 accounts. iter ( ) ,
1015- loader_key ,
1065+ & fallback_accounts ,
10161066 ) ;
10171067
10181068 let this_result = self . process_instruction_inner (
@@ -1064,17 +1114,20 @@ impl Mollusk {
10641114 ) -> InstructionResult {
10651115 const INDEX : usize = 0 ;
10661116
1067- let loader_key = self . get_loader_key ( & instruction. program_id ) ;
1117+ let fallback_accounts = self . get_account_fallbacks (
1118+ std:: iter:: once ( & instruction. program_id ) ,
1119+ std:: iter:: once ( instruction) ,
1120+ accounts,
1121+ ) ;
10681122
10691123 let CompiledAccounts {
10701124 program_id_index,
10711125 instruction_accounts,
10721126 transaction_accounts,
10731127 } = crate :: compile_accounts:: compile_accounts (
1074- INDEX ,
1075- std:: iter:: once ( instruction) ,
1128+ instruction,
10761129 accounts. iter ( ) ,
1077- loader_key ,
1130+ & fallback_accounts ,
10781131 ) ;
10791132
10801133 let result = self . process_instruction_inner (
@@ -1127,19 +1180,23 @@ impl Mollusk {
11271180 ..Default :: default ( )
11281181 } ;
11291182
1183+ let fallback_accounts = self . get_account_fallbacks (
1184+ instructions. iter ( ) . map ( |( ix, _) | & ix. program_id ) ,
1185+ instructions. iter ( ) . map ( |( ix, _) | * ix) ,
1186+ accounts,
1187+ ) ;
1188+
11301189 for ( index, ( instruction, checks) ) in instructions. iter ( ) . enumerate ( ) {
1131- let loader_key = self . get_loader_key ( & instruction. program_id ) ;
11321190 let accounts = & composite_result. resulting_accounts ;
11331191
11341192 let CompiledAccounts {
11351193 program_id_index,
11361194 instruction_accounts,
11371195 transaction_accounts,
11381196 } = crate :: compile_accounts:: compile_accounts (
1139- index,
1140- instructions. iter ( ) . map ( |( ix, _) | * ix) ,
1197+ instruction,
11411198 accounts. iter ( ) ,
1142- loader_key ,
1199+ & fallback_accounts ,
11431200 ) ;
11441201
11451202 let this_result = self . process_instruction_inner (
0 commit comments