diff --git a/rpc-client-api/src/filter.rs b/rpc-client-api/src/filter.rs index 29c85d2c4e..ef7aa12217 100644 --- a/rpc-client-api/src/filter.rs +++ b/rpc-client-api/src/filter.rs @@ -133,18 +133,35 @@ pub enum MemcmpEncodedBytes { #[serde(into = "RpcMemcmp", from = "RpcMemcmp")] pub struct Memcmp { /// Data offset to begin match + #[deprecated( + since = "1.15.0", + note = "Field will be made private in future. Please use a constructor method instead." + )] pub offset: usize, /// Bytes, encoded with specified encoding, or default Binary + #[deprecated( + since = "1.15.0", + note = "Field will be made private in future. Please use a constructor method instead." + )] pub bytes: MemcmpEncodedBytes, /// Optional encoding specification #[deprecated( since = "1.11.2", - note = "Field has no server-side effect. Specify encoding with `MemcmpEncodedBytes` variant instead." + note = "Field has no server-side effect. Specify encoding with `MemcmpEncodedBytes` variant instead. \ + Field will be made private in future. Please use a constructor method instead." )] pub encoding: Option, } impl Memcmp { + pub fn new(offset: usize, encoded_bytes: MemcmpEncodedBytes) -> Self { + Self { + offset, + bytes: encoded_bytes, + encoding: None, + } + } + pub fn new_raw_bytes(offset: usize, bytes: Vec) -> Self { Self { offset, @@ -170,6 +187,23 @@ impl Memcmp { } } + pub fn convert_to_raw_bytes(&mut self) -> Result<(), RpcFilterError> { + use MemcmpEncodedBytes::*; + match &self.bytes { + Binary(bytes) | Base58(bytes) => { + let bytes = bs58::decode(bytes).into_vec()?; + self.bytes = Bytes(bytes); + Ok(()) + } + Base64(bytes) => { + let bytes = base64::decode(bytes)?; + self.bytes = Bytes(bytes); + Ok(()) + } + _ => Ok(()), + } + } + pub fn bytes_match(&self, data: &[u8]) -> bool { match self.bytes() { Some(bytes) => { diff --git a/rpc-client/src/nonblocking/rpc_client.rs b/rpc-client/src/nonblocking/rpc_client.rs index 5f620b6124..4a55d1b69a 100644 --- a/rpc-client/src/nonblocking/rpc_client.rs +++ b/rpc-client/src/nonblocking/rpc_client.rs @@ -4421,11 +4421,10 @@ impl RpcClient { /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; - /// let memcmp = RpcFilterType::Memcmp(Memcmp { - /// offset: 0, - /// bytes: MemcmpEncodedBytes::Base64(base64_bytes.to_string()), - /// encoding: None, - /// }); + /// let memcmp = RpcFilterType::Memcmp(Memcmp::new( + /// 0, // offset + /// MemcmpEncodedBytes::Base64(base64_bytes.to_string()), // encoded bytes + /// )); /// let config = RpcProgramAccountsConfig { /// filters: Some(vec![ /// RpcFilterType::DataSize(128), diff --git a/rpc-client/src/rpc_client.rs b/rpc-client/src/rpc_client.rs index a2e957f0ab..ce6d012e69 100644 --- a/rpc-client/src/rpc_client.rs +++ b/rpc-client/src/rpc_client.rs @@ -3600,11 +3600,10 @@ impl RpcClient { /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; - /// let memcmp = RpcFilterType::Memcmp(Memcmp { - /// offset: 0, - /// bytes: MemcmpEncodedBytes::Base64(base64_bytes.to_string()), - /// encoding: None, - /// }); + /// let memcmp = RpcFilterType::Memcmp(Memcmp::new( + /// 0, // offset + /// MemcmpEncodedBytes::Base64(base64_bytes.to_string()), // encoded bytes + /// )); /// let config = RpcProgramAccountsConfig { /// filters: Some(vec![ /// RpcFilterType::DataSize(128), diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index 6e0314b0f5..d1a5e70975 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -2174,20 +2174,9 @@ impl JsonRpcRequestProcessor { fn optimize_filters(filters: &mut [RpcFilterType]) { filters.iter_mut().for_each(|filter_type| { if let RpcFilterType::Memcmp(compare) = filter_type { - use MemcmpEncodedBytes::*; - match &compare.bytes { - #[allow(deprecated)] - Binary(bytes) | Base58(bytes) => { - if let Ok(bytes) = bs58::decode(bytes).into_vec() { - compare.bytes = Bytes(bytes); - } - } - Base64(bytes) => { - if let Ok(bytes) = base64::decode(bytes) { - compare.bytes = Bytes(bytes); - } - } - _ => {} + if let Err(err) = compare.convert_to_raw_bytes() { + // All filters should have been previously verified + warn!("Invalid filter: bytes could not be decoded, {err}"); } } }) @@ -2338,6 +2327,7 @@ fn get_spl_token_owner_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> for filter in filters { match filter { RpcFilterType::DataSize(size) => data_size_filter = Some(*size), + #[allow(deprecated)] RpcFilterType::Memcmp(Memcmp { offset, bytes: MemcmpEncodedBytes::Bytes(bytes), @@ -2345,6 +2335,7 @@ fn get_spl_token_owner_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> }) if *offset == account_packed_len && *program_id == inline_spl_token_2022::id() => { memcmp_filter = Some(bytes) } + #[allow(deprecated)] RpcFilterType::Memcmp(Memcmp { offset, bytes: MemcmpEncodedBytes::Bytes(bytes), @@ -2394,6 +2385,7 @@ fn get_spl_token_mint_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> for filter in filters { match filter { RpcFilterType::DataSize(size) => data_size_filter = Some(*size), + #[allow(deprecated)] RpcFilterType::Memcmp(Memcmp { offset, bytes: MemcmpEncodedBytes::Bytes(bytes), @@ -2401,6 +2393,7 @@ fn get_spl_token_mint_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> }) if *offset == account_packed_len && *program_id == inline_spl_token_2022::id() => { memcmp_filter = Some(bytes) } + #[allow(deprecated)] RpcFilterType::Memcmp(Memcmp { offset, bytes: MemcmpEncodedBytes::Bytes(bytes), @@ -6531,22 +6524,16 @@ pub mod tests { #[test] fn test_rpc_verify_filter() { - #[allow(deprecated)] - let filter = RpcFilterType::Memcmp(Memcmp { - offset: 0, - bytes: MemcmpEncodedBytes::Base58( - "13LeFbG6m2EP1fqCj9k66fcXsoTHMMtgr7c78AivUrYD".to_string(), - ), - encoding: None, - }); + let filter = RpcFilterType::Memcmp(Memcmp::new( + 0, // offset + MemcmpEncodedBytes::Base58("13LeFbG6m2EP1fqCj9k66fcXsoTHMMtgr7c78AivUrYD".to_string()), // encoded bytes + )); assert_eq!(verify_filter(&filter), Ok(())); // Invalid base-58 - #[allow(deprecated)] - let filter = RpcFilterType::Memcmp(Memcmp { - offset: 0, - bytes: MemcmpEncodedBytes::Base58("III".to_string()), - encoding: None, - }); + let filter = RpcFilterType::Memcmp(Memcmp::new( + 0, // offset + MemcmpEncodedBytes::Base58("III".to_string()), // encoded bytes + )); assert!(verify_filter(&filter).is_err()); }