|
3 | 3 | use { |
4 | 4 | crate::{ |
5 | 5 | check_id, |
| 6 | + error::AddressLookupTableError, |
6 | 7 | instruction::AddressLookupTableInstruction, |
7 | 8 | state::{ |
8 | 9 | AddressLookupTable, ProgramState, LOOKUP_TABLE_MAX_ADDRESSES, LOOKUP_TABLE_META_SIZE, |
@@ -342,6 +343,37 @@ fn process_extend_lookup_table( |
342 | 343 | ) |
343 | 344 | }; |
344 | 345 |
|
| 346 | + // [Core BPF]: |
| 347 | + // When a builtin program attempts to write to an executable or read-only |
| 348 | + // account, it will be immediately rejected by the `TransactionContext`. |
| 349 | + // For more information, see https://github.com/solana-program/config/pull/21. |
| 350 | + // |
| 351 | + // However, in the case of the Address Lookup Table program's |
| 352 | + // `ExtendLookupTable` instruction, since the processor rejects any |
| 353 | + // zero-length "new keys" vectors, and will gladly append the same keys |
| 354 | + // again to the table, the issue here is slightly different than the linked |
| 355 | + // PR. |
| 356 | + // |
| 357 | + // The builtin version of the Address Lookup Table program will throw |
| 358 | + // when it attempts to overwrite the metadata, while the BPF version will |
| 359 | + // continue. In the case where an executable or read-only lookup table |
| 360 | + // account is provided, and some other requirement below is violated |
| 361 | + // (ie. no payer or system program accounts provided, payer is not a |
| 362 | + // signer, payer has insufficent balance, etc.), the BPF version will throw |
| 363 | + // based on one of those violations, rather than throwing immediately when |
| 364 | + // it encounters the executable or read-only lookup table account. |
| 365 | + // |
| 366 | + // In order to maximize backwards compatibility between the BPF version and |
| 367 | + // its original builtin, we add this check from `TransactionContext` to the |
| 368 | + // program directly, to throw even when the data being written is the same |
| 369 | + // same as what's currently in the account. |
| 370 | + // |
| 371 | + // Since the account can never be executable and also owned by the ALT |
| 372 | + // program, we'll just focus on readonly. |
| 373 | + if !lookup_table_info.is_writable { |
| 374 | + return Err(AddressLookupTableError::ReadonlyDataModified.into()); |
| 375 | + } |
| 376 | + |
345 | 377 | AddressLookupTable::overwrite_meta_data( |
346 | 378 | &mut lookup_table_info.try_borrow_mut_data()?[..], |
347 | 379 | lookup_table_meta, |
@@ -419,6 +451,7 @@ fn process_deactivate_lookup_table(program_id: &Pubkey, accounts: &[AccountInfo] |
419 | 451 | }; |
420 | 452 |
|
421 | 453 | let clock = <Clock as Sysvar>::get()?; |
| 454 | + |
422 | 455 | lookup_table_meta.deactivation_slot = clock.slot; |
423 | 456 |
|
424 | 457 | AddressLookupTable::overwrite_meta_data( |
|
0 commit comments