@@ -872,8 +872,19 @@ fn execute_instr(mut input: InstrContext) -> Option<InstrEffects> {
872872 let return_data = transaction_context. get_return_data ( ) . 1 . to_vec ( ) ;
873873
874874 Some ( InstrEffects {
875- custom_err : if let Err ( InstructionError :: Custom ( x) ) = result {
876- Some ( x)
875+ custom_err : if let Err ( InstructionError :: Custom ( code) ) = result {
876+ #[ cfg( feature = "core-bpf" ) ]
877+ // See comment below under `result` for special-casing of custom
878+ // errors for Core BPF programs.
879+ if program_id == & solana_sdk:: address_lookup_table:: program:: id ( ) && code == 10 {
880+ None
881+ } else if program_id == & solana_sdk:: config:: program:: id ( ) && code == 0 {
882+ None
883+ } else {
884+ Some ( code)
885+ }
886+ #[ cfg( not( feature = "core-bpf" ) ) ]
887+ Some ( code)
877888 } else {
878889 None
879890 } ,
@@ -904,6 +915,41 @@ fn execute_instr(mut input: InstrContext) -> Option<InstrEffects> {
904915 {
905916 return InstructionError :: ComputationalBudgetExceeded ;
906917 }
918+ #[ cfg( feature = "core-bpf" ) ]
919+ // Another such error case arises when a program performs a write
920+ // to an account, but the data it writes is the exact same data
921+ // that's currently stored in the account state.
922+ //
923+ // For builtins, the `TransactionContext` is invoked when any write
924+ // is performed, asking it whether or not a write is allowed,
925+ // regardless of the data being written. If the account is not
926+ // writable, it throws `InstructionError::ReadonlyDataModified`.
927+ //
928+ // For BPF programs, writes to readonly accounts are caught _after_
929+ // the VM finishes execution, when the loader inspects the
930+ // serialized input data region. If a write was performed that did
931+ // not modify serialized account state, then no error is thrown.
932+ //
933+ // As a result, Core BPF programs have been outfitted with custom
934+ // errors when `is_writable` checks fail. These errors are
935+ // special-cased below to avoid fixture mismatches.
936+ match err {
937+ InstructionError :: Custom ( code) => {
938+ if program_id == & solana_sdk:: address_lookup_table:: program:: id ( ) {
939+ // Special-cased custom error codes for the ALT program.
940+ if code == 10 {
941+ return InstructionError :: ReadonlyDataModified ;
942+ }
943+ }
944+ if program_id == & solana_sdk:: config:: program:: id ( ) {
945+ // Special-cased custom error codes for the Config program.
946+ if code == 0 {
947+ return InstructionError :: ReadonlyDataModified ;
948+ }
949+ }
950+ }
951+ _ => { }
952+ }
907953 err
908954 } ) ,
909955 modified_accounts : transaction_context
0 commit comments