Add runtime support for address table lookups (#22223)

* Add support for address table lookups in runtime

* feedback

* feedback
This commit is contained in:
Justin Starry
2022-01-07 11:59:09 +08:00
committed by GitHub
parent 08e64c88ed
commit 52d12cc802
16 changed files with 568 additions and 69 deletions

View File

@ -22,7 +22,7 @@ use {
pub enum SanitizedMessage {
/// Sanitized legacy message
Legacy(LegacyMessage),
/// Sanitized version #0 message with mapped addresses
/// Sanitized version #0 message with dynamically loaded addresses
V0(v0::LoadedMessage),
}
@ -130,7 +130,7 @@ impl SanitizedMessage {
})
}
/// Iterator of all account keys referenced in this message, included mapped keys.
/// Iterator of all account keys referenced in this message, including dynamically loaded keys.
pub fn account_keys_iter(&self) -> Box<dyn Iterator<Item = &Pubkey> + '_> {
match self {
Self::Legacy(message) => Box::new(message.account_keys.iter()),
@ -138,7 +138,7 @@ impl SanitizedMessage {
}
}
/// Length of all account keys referenced in this message, included mapped keys.
/// Length of all account keys referenced in this message, including dynamically loaded keys.
pub fn account_keys_len(&self) -> usize {
match self {
Self::Legacy(message) => message.account_keys.len(),
@ -257,11 +257,11 @@ impl SanitizedMessage {
/// Return the number of readonly accounts loaded by this message.
pub fn num_readonly_accounts(&self) -> usize {
let mapped_readonly_addresses = self
let loaded_readonly_addresses = self
.loaded_lookup_table_addresses()
.map(|keys| keys.readonly.len())
.unwrap_or_default();
mapped_readonly_addresses
loaded_readonly_addresses
.saturating_add(usize::from(self.header().num_readonly_signed_accounts))
.saturating_add(usize::from(self.header().num_readonly_unsigned_accounts))
}

View File

@ -43,21 +43,28 @@ impl VersionedMessage {
}
}
pub fn unmapped_keys(self) -> Vec<Pubkey> {
pub fn static_account_keys(&self) -> &[Pubkey] {
match self {
Self::Legacy(message) => &message.account_keys,
Self::V0(message) => &message.account_keys,
}
}
pub fn into_static_account_keys(self) -> Vec<Pubkey> {
match self {
Self::Legacy(message) => message.account_keys,
Self::V0(message) => message.account_keys,
}
}
pub fn unmapped_keys_iter(&self) -> impl Iterator<Item = &Pubkey> {
pub fn static_account_keys_iter(&self) -> impl Iterator<Item = &Pubkey> {
match self {
Self::Legacy(message) => message.account_keys.iter(),
Self::V0(message) => message.account_keys.iter(),
}
}
pub fn unmapped_keys_len(&self) -> usize {
pub fn static_account_keys_len(&self) -> usize {
match self {
Self::Legacy(message) => message.account_keys.len(),
Self::V0(message) => message.account_keys.len(),

View File

@ -34,6 +34,19 @@ pub struct LoadedAddresses {
pub readonly: Vec<Pubkey>,
}
impl FromIterator<LoadedAddresses> for LoadedAddresses {
fn from_iter<T: IntoIterator<Item = LoadedAddresses>>(iter: T) -> Self {
let (writable, readonly): (Vec<Vec<Pubkey>>, Vec<Vec<Pubkey>>) = iter
.into_iter()
.map(|addresses| (addresses.writable, addresses.readonly))
.unzip();
LoadedAddresses {
writable: writable.into_iter().flatten().collect(),
readonly: readonly.into_iter().flatten().collect(),
}
}
}
impl LoadedMessage {
/// Returns an iterator of account key segments. The ordering of segments
/// affects how account indexes from compiled instructions are resolved and
@ -68,8 +81,9 @@ impl LoadedMessage {
}
/// Returns the address of the account at the specified index of the list of
/// message account keys constructed from unmapped keys, followed by mapped
/// writable addresses, and lastly the list of mapped readonly addresses.
/// message account keys constructed from static keys, followed by dynamically
/// loaded writable addresses, and lastly the list of dynamically loaded
/// readonly addresses.
pub fn get_account_key(&self, mut index: usize) -> Option<&Pubkey> {
for key_segment in self.account_keys_segment_iter() {
if index < key_segment.len() {
@ -88,8 +102,8 @@ impl LoadedMessage {
let num_account_keys = self.message.account_keys.len();
let num_signed_accounts = usize::from(header.num_required_signatures);
if key_index >= num_account_keys {
let mapped_addresses_index = key_index.saturating_sub(num_account_keys);
mapped_addresses_index < self.loaded_addresses.writable.len()
let loaded_addresses_index = key_index.saturating_sub(num_account_keys);
loaded_addresses_index < self.loaded_addresses.writable.len()
} else if key_index >= num_signed_accounts {
let num_unsigned_accounts = num_account_keys.saturating_sub(num_signed_accounts);
let num_writable_unsigned_accounts = num_unsigned_accounts