Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Support jsonParsed address lookup table accounts (backport #26723) #28134

Merged
merged 2 commits into from
Oct 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions account-decoder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ lazy_static = "1.4.0"
serde = "1.0.138"
serde_derive = "1.0.103"
serde_json = "1.0.81"
solana-address-lookup-table-program = { path = "../programs/address-lookup-table", version = "=1.14.4" }
solana-config-program = { path = "../programs/config", version = "=1.14.4" }
solana-sdk = { path = "../sdk", version = "=1.14.4" }
solana-vote-program = { path = "../programs/vote", version = "=1.14.4" }
Expand Down
1 change: 1 addition & 0 deletions account-decoder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ extern crate lazy_static;
extern crate serde_derive;

pub mod parse_account_data;
pub mod parse_address_lookup_table;
pub mod parse_bpf_loader;
pub mod parse_config;
pub mod parse_nonce;
Expand Down
10 changes: 10 additions & 0 deletions account-decoder/src/parse_account_data.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use {
crate::{
parse_address_lookup_table::parse_address_lookup_table,
parse_bpf_loader::parse_bpf_upgradeable_loader,
parse_config::parse_config,
parse_nonce::parse_nonce,
Expand All @@ -16,6 +17,7 @@ use {
};

lazy_static! {
static ref ADDRESS_LOOKUP_PROGRAM_ID: Pubkey = solana_address_lookup_table_program::id();
static ref BPF_UPGRADEABLE_LOADER_PROGRAM_ID: Pubkey = solana_sdk::bpf_loader_upgradeable::id();
static ref CONFIG_PROGRAM_ID: Pubkey = solana_config_program::id();
static ref STAKE_PROGRAM_ID: Pubkey = stake::program::id();
Expand All @@ -24,6 +26,10 @@ lazy_static! {
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
pub static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableAccount> = {
let mut m = HashMap::new();
m.insert(
*ADDRESS_LOOKUP_PROGRAM_ID,
ParsableAccount::AddressLookupTable,
);
m.insert(
*BPF_UPGRADEABLE_LOADER_PROGRAM_ID,
ParsableAccount::BpfUpgradeableLoader,
Expand Down Expand Up @@ -68,6 +74,7 @@ pub struct ParsedAccount {
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ParsableAccount {
AddressLookupTable,
BpfUpgradeableLoader,
Config,
Nonce,
Expand All @@ -94,6 +101,9 @@ pub fn parse_account_data(
.ok_or(ParseAccountError::ProgramNotParsable)?;
let additional_data = additional_data.unwrap_or_default();
let parsed_json = match program_name {
ParsableAccount::AddressLookupTable => {
serde_json::to_value(parse_address_lookup_table(data)?)?
}
ParsableAccount::BpfUpgradeableLoader => {
serde_json::to_value(parse_bpf_upgradeable_loader(data)?)?
}
Expand Down
117 changes: 117 additions & 0 deletions account-decoder/src/parse_address_lookup_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use {
crate::parse_account_data::{ParsableAccount, ParseAccountError},
solana_address_lookup_table_program::state::AddressLookupTable,
solana_sdk::instruction::InstructionError,
};

pub fn parse_address_lookup_table(
data: &[u8],
) -> Result<LookupTableAccountType, ParseAccountError> {
AddressLookupTable::deserialize(data)
.map(|address_lookup_table| {
LookupTableAccountType::LookupTable(address_lookup_table.into())
})
.or_else(|err| match err {
InstructionError::UninitializedAccount => Ok(LookupTableAccountType::Uninitialized),
_ => Err(ParseAccountError::AccountNotParsable(
ParsableAccount::AddressLookupTable,
)),
})
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase", tag = "type", content = "info")]
pub enum LookupTableAccountType {
Uninitialized,
LookupTable(UiLookupTable),
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct UiLookupTable {
pub deactivation_slot: String,
pub last_extended_slot: String,
pub last_extended_slot_start_index: u8,
#[serde(skip_serializing_if = "Option::is_none")]
pub authority: Option<String>,
pub addresses: Vec<String>,
}

impl<'a> From<AddressLookupTable<'a>> for UiLookupTable {
fn from(address_lookup_table: AddressLookupTable) -> Self {
Self {
deactivation_slot: address_lookup_table.meta.deactivation_slot.to_string(),
last_extended_slot: address_lookup_table.meta.last_extended_slot.to_string(),
last_extended_slot_start_index: address_lookup_table
.meta
.last_extended_slot_start_index,
authority: address_lookup_table
.meta
.authority
.map(|authority| authority.to_string()),
addresses: address_lookup_table
.addresses
.iter()
.map(|address| address.to_string())
.collect(),
}
}
}

#[cfg(test)]
mod test {
use {
super::*,
solana_address_lookup_table_program::state::{LookupTableMeta, LOOKUP_TABLE_META_SIZE},
solana_sdk::pubkey::Pubkey,
std::borrow::Cow,
};

#[test]
fn test_parse_address_lookup_table() {
let authority = Pubkey::new_unique();
let deactivation_slot = 1;
let last_extended_slot = 2;
let last_extended_slot_start_index = 3;
let lookup_table_meta = LookupTableMeta {
deactivation_slot,
last_extended_slot,
last_extended_slot_start_index,
authority: Some(authority),
..LookupTableMeta::default()
};
let num_addresses = 42;
let mut addresses = Vec::with_capacity(num_addresses);
addresses.resize_with(num_addresses, Pubkey::new_unique);
let lookup_table = AddressLookupTable {
meta: lookup_table_meta,
addresses: Cow::Owned(addresses),
};
let lookup_table_data =
AddressLookupTable::serialize_for_tests(lookup_table.clone()).unwrap();

let parsing_result = parse_address_lookup_table(&lookup_table_data).unwrap();
if let LookupTableAccountType::LookupTable(ui_lookup_table) = parsing_result {
assert_eq!(
ui_lookup_table.deactivation_slot,
deactivation_slot.to_string()
);
assert_eq!(
ui_lookup_table.last_extended_slot,
last_extended_slot.to_string()
);
assert_eq!(
ui_lookup_table.last_extended_slot_start_index,
last_extended_slot_start_index
);
assert_eq!(ui_lookup_table.authority, Some(authority.to_string()));
assert_eq!(ui_lookup_table.addresses.len(), num_addresses);
}

assert_eq!(
parse_address_lookup_table(&[0u8; LOOKUP_TABLE_META_SIZE]).unwrap(),
LookupTableAccountType::Uninitialized
);
assert!(parse_address_lookup_table(&[]).is_err());
}
}
1 change: 1 addition & 0 deletions programs/bpf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.