@@ -19,13 +19,28 @@ pub fn compile_instruction_without_data(
1919 key_map : & KeyMap ,
2020 instruction : & Instruction ,
2121) -> CompiledInstructionWithoutData {
22+ let program_id_index = key_map
23+ . position ( & instruction. program_id )
24+ . or_panic_with ( MolluskError :: ProgramIdNotMapped ( & instruction. program_id ) ) ;
25+
26+ let program_id_index = u8:: try_from ( program_id_index)
27+ . or_panic_with ( MolluskError :: AccountIndexOverflow ( program_id_index) ) ;
28+
29+ let accounts: Vec < u8 > = instruction
30+ . accounts
31+ . iter ( )
32+ . map ( |account_meta| {
33+ let index = key_map
34+ . position ( & account_meta. pubkey )
35+ . or_panic_with ( MolluskError :: AccountMissing ( & account_meta. pubkey ) ) ;
36+
37+ u8:: try_from ( index) . or_panic_with ( MolluskError :: AccountIndexOverflow ( index) )
38+ } )
39+ . collect ( ) ;
40+
2241 CompiledInstructionWithoutData {
23- program_id_index : key_map. position ( & instruction. program_id ) . unwrap ( ) as u8 ,
24- accounts : instruction
25- . accounts
26- . iter ( )
27- . map ( |account_meta| key_map. position ( & account_meta. pubkey ) . unwrap ( ) as u8 )
28- . collect ( ) ,
42+ program_id_index,
43+ accounts,
2944 }
3045}
3146
@@ -381,4 +396,76 @@ mod tests {
381396 let acc = result. iter ( ) . find ( |( pk, _) | pk == & account1) . unwrap ( ) ;
382397 assert_eq ! ( acc. 1 . lamports( ) , 100 ) ;
383398 }
399+
400+ #[ test]
401+ fn test_compile_instruction_without_data_deterministic ( ) {
402+ let program_id = Pubkey :: new_unique ( ) ;
403+ let account1 = Pubkey :: new_unique ( ) ;
404+ let account2 = Pubkey :: new_unique ( ) ;
405+ let account3 = Pubkey :: new_unique ( ) ;
406+
407+ let instruction = test_instruction ( program_id, & [ account1, account2, account3] ) ;
408+
409+ let key_map1 = KeyMap :: compile_from_instruction ( & instruction) ;
410+ let compiled1 = compile_instruction_without_data ( & key_map1, & instruction) ;
411+
412+ let key_map2 = KeyMap :: compile_from_instruction ( & instruction) ;
413+ let compiled2 = compile_instruction_without_data ( & key_map2, & instruction) ;
414+
415+ assert_eq ! ( compiled1. program_id_index, compiled2. program_id_index) ;
416+ assert_eq ! ( compiled1. accounts, compiled2. accounts) ;
417+ }
418+
419+ #[ test]
420+ #[ should_panic( expected = "Account index exceeds maximum of 255" ) ]
421+ fn test_compile_instruction_without_data_account_index_overflow ( ) {
422+ let mut key_map = KeyMap :: default ( ) ;
423+
424+ for _ in 0 ..256 {
425+ let pubkey = Pubkey :: new_unique ( ) ;
426+ key_map. add_program ( pubkey) ;
427+ }
428+
429+ let program_id = Pubkey :: new_unique ( ) ;
430+ key_map. add_program ( program_id) ;
431+
432+ let instruction = Instruction :: new_with_bytes ( program_id, & [ ] , vec ! [ ] ) ;
433+
434+ let _ = compile_instruction_without_data ( & key_map, & instruction) ;
435+ }
436+
437+ #[ test]
438+ #[ should_panic( expected = "Program ID required by the instruction is not mapped" ) ]
439+ fn test_compile_instruction_without_data_missing_program_id ( ) {
440+ let program_id = Pubkey :: new_unique ( ) ;
441+ let account1 = Pubkey :: new_unique ( ) ;
442+ let instruction = test_instruction ( program_id, & [ account1] ) ;
443+
444+ let mut key_map = KeyMap :: default ( ) ;
445+ key_map. add_account ( & AccountMeta :: new ( account1, false ) ) ;
446+
447+ let _ = compile_instruction_without_data ( & key_map, & instruction) ;
448+ }
449+
450+ #[ test]
451+ #[ should_panic( expected = "An account required by the instruction was not provided" ) ]
452+ fn test_compile_instruction_without_data_missing_account ( ) {
453+ let program_id = Pubkey :: new_unique ( ) ;
454+ let account1 = Pubkey :: new_unique ( ) ;
455+ let account_missing = Pubkey :: new_unique ( ) ;
456+ let instruction = Instruction :: new_with_bytes (
457+ program_id,
458+ & [ ] ,
459+ vec ! [
460+ AccountMeta :: new( account1, false ) ,
461+ AccountMeta :: new( account_missing, false ) ,
462+ ] ,
463+ ) ;
464+
465+ let mut key_map = KeyMap :: default ( ) ;
466+ key_map. add_program ( program_id) ;
467+ key_map. add_account ( & AccountMeta :: new ( account1, false ) ) ;
468+
469+ let _ = compile_instruction_without_data ( & key_map, & instruction) ;
470+ }
384471}
0 commit comments