Lookup Table

Create Lookup Table

/// --- programs/address-lookup-table/src/processor.rs --- declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context| { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); match limited_deserialize(instruction_data)? { ProgramInstruction::CreateLookupTable { recent_slot, bump_seed, } => Processor::create_lookup_table(invoke_context, recent_slot, bump_seed), ProgramInstruction::FreezeLookupTable => Processor::freeze_lookup_table(invoke_context), ProgramInstruction::ExtendLookupTable { new_addresses } => { Processor::extend_lookup_table(invoke_context, new_addresses) } ProgramInstruction::DeactivateLookupTable => { Processor::deactivate_lookup_table(invoke_context) } ProgramInstruction::CloseLookupTable => Processor::close_lookup_table(invoke_context), } });
 
/// --- programs/address-lookup-table/src/processor.rs --- fn create_lookup_table( invoke_context: &mut InvokeContext, untrusted_recent_slot: Slot, bump_seed: u8, ) -> Result<(), InstructionError> { let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let lookup_table_account = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; let lookup_table_lamports = lookup_table_account.get_lamports(); let table_key = *lookup_table_account.get_key(); let lookup_table_owner = *lookup_table_account.get_owner(); if !invoke_context .feature_set .is_active(&feature_set::relax_authority_signer_check_for_lookup_table_creation::id()) && !lookup_table_account.get_data().is_empty() { ic_msg!(invoke_context, "Table account must not be allocated"); return Err(InstructionError::AccountAlreadyInitialized); } drop(lookup_table_account); let authority_account = instruction_context.try_borrow_instruction_account(transaction_context, 1)?; let authority_key = *authority_account.get_key(); if !invoke_context .feature_set .is_active(&feature_set::relax_authority_signer_check_for_lookup_table_creation::id()) && !authority_account.is_signer() { ic_msg!(invoke_context, "Authority account must be a signer"); return Err(InstructionError::MissingRequiredSignature); } drop(authority_account); let payer_account = instruction_context.try_borrow_instruction_account(transaction_context, 2)?; let payer_key = *payer_account.get_key(); if !payer_account.is_signer() { ic_msg!(invoke_context, "Payer account must be a signer"); return Err(InstructionError::MissingRequiredSignature); } drop(payer_account); let derivation_slot = { let slot_hashes = invoke_context.get_sysvar_cache().get_slot_hashes()?; if slot_hashes.get(&untrusted_recent_slot).is_some() { Ok(untrusted_recent_slot) } else { ic_msg!( invoke_context, "{} is not a recent slot", untrusted_recent_slot ); Err(InstructionError::InvalidInstructionData) } }?; // Use a derived address to ensure that an address table can never be // initialized more than once at the same address. let derived_table_key = Pubkey::create_program_address( &[ authority_key.as_ref(), &derivation_slot.to_le_bytes(), &[bump_seed], ], &id(), )?; if table_key != derived_table_key { ic_msg!( invoke_context, "Table address must match derived address: {}", derived_table_key ); return Err(InstructionError::InvalidArgument); } if invoke_context .feature_set .is_active(&feature_set::relax_authority_signer_check_for_lookup_table_creation::id()) && check_id(&lookup_table_owner) { return Ok(()); } let table_account_data_len = LOOKUP_TABLE_META_SIZE; let rent = invoke_context.get_sysvar_cache().get_rent()?; let required_lamports = rent .minimum_balance(table_account_data_len) .max(1) .saturating_sub(lookup_table_lamports); if required_lamports > 0 { invoke_context.native_invoke( system_instruction::transfer(&payer_key, &table_key, required_lamports).into(), &[payer_key], )?; } invoke_context.native_invoke( system_instruction::allocate(&table_key, table_account_data_len as u64).into(), &[table_key], )?; invoke_context.native_invoke( system_instruction::assign(&table_key, &id()).into(), &[table_key], )?; let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let mut lookup_table_account = instruction_context.try_borrow_instruction_account(transaction_context, 0)?; lookup_table_account.set_state(&ProgramState::LookupTable(LookupTableMeta::new( authority_key, )))?; Ok(()) }

V0 Transaction Format