Update Rpc filters to support token-2022 (#24541)

* Add TokenAccountState rpc_filter

* Use a method on RpcFliterType instead of helper
This commit is contained in:
Tyera Eulberg 2022-04-20 21:18:12 -04:00 committed by GitHub
parent 96d977fd05
commit b42f34a7b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 38 deletions

1
Cargo.lock generated
View File

@ -4608,6 +4608,7 @@ dependencies = [
"solana-transaction-status", "solana-transaction-status",
"solana-version", "solana-version",
"solana-vote-program", "solana-vote-program",
"spl-token-2022",
"thiserror", "thiserror",
"tokio", "tokio",
"tokio-stream", "tokio-stream",

View File

@ -48,6 +48,7 @@ solana-streamer = { path = "../streamer", version = "=1.11.0" }
solana-transaction-status = { path = "../transaction-status", version = "=1.11.0" } solana-transaction-status = { path = "../transaction-status", version = "=1.11.0" }
solana-version = { path = "../version", version = "=1.11.0" } solana-version = { path = "../version", version = "=1.11.0" }
solana-vote-program = { path = "../programs/vote", version = "=1.11.0" } solana-vote-program = { path = "../programs/vote", version = "=1.11.0" }
spl-token-2022 = { version = "=0.2.0", features = ["no-entrypoint"] }
thiserror = "1.0" thiserror = "1.0"
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1.8" tokio-stream = "0.1.8"

View File

@ -1,5 +1,10 @@
#![allow(deprecated)] #![allow(deprecated)]
use {std::borrow::Cow, thiserror::Error}; use {
solana_sdk::account::{AccountSharedData, ReadableAccount},
spl_token_2022::{generic_token_account::GenericTokenAccount, state::Account},
std::borrow::Cow,
thiserror::Error,
};
const MAX_DATA_SIZE: usize = 128; const MAX_DATA_SIZE: usize = 128;
const MAX_DATA_BASE58_SIZE: usize = 175; const MAX_DATA_BASE58_SIZE: usize = 175;
@ -10,6 +15,7 @@ const MAX_DATA_BASE64_SIZE: usize = 172;
pub enum RpcFilterType { pub enum RpcFilterType {
DataSize(u64), DataSize(u64),
Memcmp(Memcmp), Memcmp(Memcmp),
TokenAccountState,
} }
impl RpcFilterType { impl RpcFilterType {
@ -68,6 +74,15 @@ impl RpcFilterType {
} }
} }
} }
RpcFilterType::TokenAccountState => Ok(()),
}
}
pub fn allows(&self, account: &AccountSharedData) -> bool {
match self {
RpcFilterType::DataSize(size) => account.data().len() as u64 == *size,
RpcFilterType::Memcmp(compare) => compare.bytes_match(account.data()),
RpcFilterType::TokenAccountState => Account::valid_account_data(account.data()),
} }
} }
} }

View File

@ -3252,6 +3252,7 @@ dependencies = [
"solana-transaction-status", "solana-transaction-status",
"solana-version", "solana-version",
"solana-vote-program", "solana-vote-program",
"spl-token-2022",
"thiserror", "thiserror",
"tokio", "tokio",
"tokio-stream", "tokio-stream",

View File

@ -1898,10 +1898,9 @@ impl JsonRpcRequestProcessor {
) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> { ) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
optimize_filters(&mut filters); optimize_filters(&mut filters);
let filter_closure = |account: &AccountSharedData| { let filter_closure = |account: &AccountSharedData| {
filters.iter().all(|filter_type| match filter_type { filters
RpcFilterType::DataSize(size) => account.data().len() as u64 == *size, .iter()
RpcFilterType::Memcmp(compare) => compare.bytes_match(account.data()), .all(|filter_type| filter_type.allows(account))
})
}; };
if self if self
.config .config
@ -1954,9 +1953,7 @@ impl JsonRpcRequestProcessor {
// later updates. We include the redundant filters here to avoid returning these accounts. // later updates. We include the redundant filters here to avoid returning these accounts.
// //
// Filter on Token Account state // Filter on Token Account state
filters.push(RpcFilterType::DataSize( filters.push(RpcFilterType::TokenAccountState);
TokenAccount::get_packed_len() as u64
));
// Filter on Owner address // Filter on Owner address
filters.push(RpcFilterType::Memcmp(Memcmp { filters.push(RpcFilterType::Memcmp(Memcmp {
offset: SPL_TOKEN_ACCOUNT_OWNER_OFFSET, offset: SPL_TOKEN_ACCOUNT_OWNER_OFFSET,
@ -1979,14 +1976,9 @@ impl JsonRpcRequestProcessor {
&IndexKey::SplTokenOwner(*owner_key), &IndexKey::SplTokenOwner(*owner_key),
|account| { |account| {
account.owner() == program_id account.owner() == program_id
&& filters.iter().all(|filter_type| match filter_type { && filters
RpcFilterType::DataSize(size) => { .iter()
account.data().len() as u64 == *size .all(|filter_type| filter_type.allows(account))
}
RpcFilterType::Memcmp(compare) => {
compare.bytes_match(account.data())
}
})
}, },
&ScanConfig::default(), &ScanConfig::default(),
bank.byte_limit_for_scans(), bank.byte_limit_for_scans(),
@ -2013,9 +2005,7 @@ impl JsonRpcRequestProcessor {
// updates. We include the redundant filters here to avoid returning these accounts. // updates. We include the redundant filters here to avoid returning these accounts.
// //
// Filter on Token Account state // Filter on Token Account state
filters.push(RpcFilterType::DataSize( filters.push(RpcFilterType::TokenAccountState);
TokenAccount::get_packed_len() as u64
));
// Filter on Mint address // Filter on Mint address
filters.push(RpcFilterType::Memcmp(Memcmp { filters.push(RpcFilterType::Memcmp(Memcmp {
offset: SPL_TOKEN_ACCOUNT_MINT_OFFSET, offset: SPL_TOKEN_ACCOUNT_MINT_OFFSET,
@ -2037,14 +2027,9 @@ impl JsonRpcRequestProcessor {
&IndexKey::SplTokenMint(*mint_key), &IndexKey::SplTokenMint(*mint_key),
|account| { |account| {
account.owner() == program_id account.owner() == program_id
&& filters.iter().all(|filter_type| match filter_type { && filters
RpcFilterType::DataSize(size) => { .iter()
account.data().len() as u64 == *size .all(|filter_type| filter_type.allows(account))
}
RpcFilterType::Memcmp(compare) => {
compare.bytes_match(account.data())
}
})
}, },
&ScanConfig::default(), &ScanConfig::default(),
bank.byte_limit_for_scans(), bank.byte_limit_for_scans(),

View File

@ -15,14 +15,11 @@ use {
rayon::prelude::*, rayon::prelude::*,
serde::Serialize, serde::Serialize,
solana_account_decoder::{parse_token::is_known_spl_token_id, UiAccount, UiAccountEncoding}, solana_account_decoder::{parse_token::is_known_spl_token_id, UiAccount, UiAccountEncoding},
solana_client::{ solana_client::rpc_response::{
rpc_filter::RpcFilterType,
rpc_response::{
ProcessedSignatureResult, ReceivedSignatureResult, Response, RpcBlockUpdate, ProcessedSignatureResult, ReceivedSignatureResult, Response, RpcBlockUpdate,
RpcBlockUpdateError, RpcKeyedAccount, RpcLogsResponse, RpcResponseContext, RpcBlockUpdateError, RpcKeyedAccount, RpcLogsResponse, RpcResponseContext,
RpcSignatureResult, RpcVote, SlotInfo, SlotUpdate, RpcSignatureResult, RpcVote, SlotInfo, SlotUpdate,
}, },
},
solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path}, solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path},
solana_measure::measure::Measure, solana_measure::measure::Measure,
solana_rayon_threadlimit::get_thread_count, solana_rayon_threadlimit::get_thread_count,
@ -400,10 +397,9 @@ fn filter_program_results(
let encoding = params.encoding; let encoding = params.encoding;
let filters = params.filters.clone(); let filters = params.filters.clone();
let keyed_accounts = accounts.into_iter().filter(move |(_, account)| { let keyed_accounts = accounts.into_iter().filter(move |(_, account)| {
filters.iter().all(|filter_type| match filter_type { filters
RpcFilterType::DataSize(size) => account.data().len() as u64 == *size, .iter()
RpcFilterType::Memcmp(compare) => compare.bytes_match(account.data()), .all(|filter_type| filter_type.allows(account))
})
}); });
let accounts: Box<dyn Iterator<Item = RpcKeyedAccount>> = let accounts: Box<dyn Iterator<Item = RpcKeyedAccount>> =
if is_known_spl_token_id(&params.pubkey) if is_known_spl_token_id(&params.pubkey)