diff --git a/Cargo.lock b/Cargo.lock index 453265ef65..3aef483bab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4608,6 +4608,7 @@ dependencies = [ "solana-transaction-status", "solana-version", "solana-vote-program", + "spl-token-2022", "thiserror", "tokio", "tokio-stream", diff --git a/client/Cargo.toml b/client/Cargo.toml index 5469b49ac0..7dc255af9d 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -48,6 +48,7 @@ solana-streamer = { path = "../streamer", version = "=1.11.0" } solana-transaction-status = { path = "../transaction-status", version = "=1.11.0" } solana-version = { path = "../version", 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" tokio = { version = "1", features = ["full"] } tokio-stream = "0.1.8" diff --git a/client/src/rpc_filter.rs b/client/src/rpc_filter.rs index a13b53f89c..f11de58ae4 100644 --- a/client/src/rpc_filter.rs +++ b/client/src/rpc_filter.rs @@ -1,5 +1,10 @@ #![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_BASE58_SIZE: usize = 175; @@ -10,6 +15,7 @@ const MAX_DATA_BASE64_SIZE: usize = 172; pub enum RpcFilterType { DataSize(u64), Memcmp(Memcmp), + TokenAccountState, } 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()), } } } diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 087d9ae2e6..2b169b28f8 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -3252,6 +3252,7 @@ dependencies = [ "solana-transaction-status", "solana-version", "solana-vote-program", + "spl-token-2022", "thiserror", "tokio", "tokio-stream", diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index 0124e4d436..77efabbd92 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -1898,10 +1898,9 @@ impl JsonRpcRequestProcessor { ) -> RpcCustomResult> { optimize_filters(&mut filters); let filter_closure = |account: &AccountSharedData| { - filters.iter().all(|filter_type| match filter_type { - RpcFilterType::DataSize(size) => account.data().len() as u64 == *size, - RpcFilterType::Memcmp(compare) => compare.bytes_match(account.data()), - }) + filters + .iter() + .all(|filter_type| filter_type.allows(account)) }; if self .config @@ -1954,9 +1953,7 @@ impl JsonRpcRequestProcessor { // later updates. We include the redundant filters here to avoid returning these accounts. // // Filter on Token Account state - filters.push(RpcFilterType::DataSize( - TokenAccount::get_packed_len() as u64 - )); + filters.push(RpcFilterType::TokenAccountState); // Filter on Owner address filters.push(RpcFilterType::Memcmp(Memcmp { offset: SPL_TOKEN_ACCOUNT_OWNER_OFFSET, @@ -1979,14 +1976,9 @@ impl JsonRpcRequestProcessor { &IndexKey::SplTokenOwner(*owner_key), |account| { account.owner() == program_id - && filters.iter().all(|filter_type| match filter_type { - RpcFilterType::DataSize(size) => { - account.data().len() as u64 == *size - } - RpcFilterType::Memcmp(compare) => { - compare.bytes_match(account.data()) - } - }) + && filters + .iter() + .all(|filter_type| filter_type.allows(account)) }, &ScanConfig::default(), bank.byte_limit_for_scans(), @@ -2013,9 +2005,7 @@ impl JsonRpcRequestProcessor { // updates. We include the redundant filters here to avoid returning these accounts. // // Filter on Token Account state - filters.push(RpcFilterType::DataSize( - TokenAccount::get_packed_len() as u64 - )); + filters.push(RpcFilterType::TokenAccountState); // Filter on Mint address filters.push(RpcFilterType::Memcmp(Memcmp { offset: SPL_TOKEN_ACCOUNT_MINT_OFFSET, @@ -2037,14 +2027,9 @@ impl JsonRpcRequestProcessor { &IndexKey::SplTokenMint(*mint_key), |account| { account.owner() == program_id - && filters.iter().all(|filter_type| match filter_type { - RpcFilterType::DataSize(size) => { - account.data().len() as u64 == *size - } - RpcFilterType::Memcmp(compare) => { - compare.bytes_match(account.data()) - } - }) + && filters + .iter() + .all(|filter_type| filter_type.allows(account)) }, &ScanConfig::default(), bank.byte_limit_for_scans(), diff --git a/rpc/src/rpc_subscriptions.rs b/rpc/src/rpc_subscriptions.rs index 57e0dcacaf..1710c5f107 100644 --- a/rpc/src/rpc_subscriptions.rs +++ b/rpc/src/rpc_subscriptions.rs @@ -15,13 +15,10 @@ use { rayon::prelude::*, serde::Serialize, solana_account_decoder::{parse_token::is_known_spl_token_id, UiAccount, UiAccountEncoding}, - solana_client::{ - rpc_filter::RpcFilterType, - rpc_response::{ - ProcessedSignatureResult, ReceivedSignatureResult, Response, RpcBlockUpdate, - RpcBlockUpdateError, RpcKeyedAccount, RpcLogsResponse, RpcResponseContext, - RpcSignatureResult, RpcVote, SlotInfo, SlotUpdate, - }, + solana_client::rpc_response::{ + ProcessedSignatureResult, ReceivedSignatureResult, Response, RpcBlockUpdate, + RpcBlockUpdateError, RpcKeyedAccount, RpcLogsResponse, RpcResponseContext, + RpcSignatureResult, RpcVote, SlotInfo, SlotUpdate, }, solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path}, solana_measure::measure::Measure, @@ -400,10 +397,9 @@ fn filter_program_results( let encoding = params.encoding; let filters = params.filters.clone(); let keyed_accounts = accounts.into_iter().filter(move |(_, account)| { - filters.iter().all(|filter_type| match filter_type { - RpcFilterType::DataSize(size) => account.data().len() as u64 == *size, - RpcFilterType::Memcmp(compare) => compare.bytes_match(account.data()), - }) + filters + .iter() + .all(|filter_type| filter_type.allows(account)) }); let accounts: Box> = if is_known_spl_token_id(¶ms.pubkey)