Add Memcmp filter constructor and deprecate fields (#29923)
* Deprecate Memcmp inner fields * Add Memcmp::new * Replace some literal construction * Add convert_to_raw_bytes method and use * Make convert_to_raw_bytes fallible * Allow literal matches for complex cases
This commit is contained in:
parent
d6fbf3fb17
commit
e39153df51
|
@ -133,18 +133,35 @@ pub enum MemcmpEncodedBytes {
|
||||||
#[serde(into = "RpcMemcmp", from = "RpcMemcmp")]
|
#[serde(into = "RpcMemcmp", from = "RpcMemcmp")]
|
||||||
pub struct Memcmp {
|
pub struct Memcmp {
|
||||||
/// Data offset to begin match
|
/// 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,
|
pub offset: usize,
|
||||||
/// Bytes, encoded with specified encoding, or default Binary
|
/// 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,
|
pub bytes: MemcmpEncodedBytes,
|
||||||
/// Optional encoding specification
|
/// Optional encoding specification
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
since = "1.11.2",
|
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<MemcmpEncoding>,
|
pub encoding: Option<MemcmpEncoding>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memcmp {
|
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<u8>) -> Self {
|
pub fn new_raw_bytes(offset: usize, bytes: Vec<u8>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
offset,
|
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 {
|
pub fn bytes_match(&self, data: &[u8]) -> bool {
|
||||||
match self.bytes() {
|
match self.bytes() {
|
||||||
Some(bytes) => {
|
Some(bytes) => {
|
||||||
|
|
|
@ -4421,11 +4421,10 @@ impl RpcClient {
|
||||||
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
||||||
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
||||||
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||||
/// let memcmp = RpcFilterType::Memcmp(Memcmp {
|
/// let memcmp = RpcFilterType::Memcmp(Memcmp::new(
|
||||||
/// offset: 0,
|
/// 0, // offset
|
||||||
/// bytes: MemcmpEncodedBytes::Base64(base64_bytes.to_string()),
|
/// MemcmpEncodedBytes::Base64(base64_bytes.to_string()), // encoded bytes
|
||||||
/// encoding: None,
|
/// ));
|
||||||
/// });
|
|
||||||
/// let config = RpcProgramAccountsConfig {
|
/// let config = RpcProgramAccountsConfig {
|
||||||
/// filters: Some(vec![
|
/// filters: Some(vec![
|
||||||
/// RpcFilterType::DataSize(128),
|
/// RpcFilterType::DataSize(128),
|
||||||
|
|
|
@ -3600,11 +3600,10 @@ impl RpcClient {
|
||||||
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
||||||
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
|
||||||
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
/// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||||
/// let memcmp = RpcFilterType::Memcmp(Memcmp {
|
/// let memcmp = RpcFilterType::Memcmp(Memcmp::new(
|
||||||
/// offset: 0,
|
/// 0, // offset
|
||||||
/// bytes: MemcmpEncodedBytes::Base64(base64_bytes.to_string()),
|
/// MemcmpEncodedBytes::Base64(base64_bytes.to_string()), // encoded bytes
|
||||||
/// encoding: None,
|
/// ));
|
||||||
/// });
|
|
||||||
/// let config = RpcProgramAccountsConfig {
|
/// let config = RpcProgramAccountsConfig {
|
||||||
/// filters: Some(vec![
|
/// filters: Some(vec![
|
||||||
/// RpcFilterType::DataSize(128),
|
/// RpcFilterType::DataSize(128),
|
||||||
|
|
|
@ -2174,20 +2174,9 @@ impl JsonRpcRequestProcessor {
|
||||||
fn optimize_filters(filters: &mut [RpcFilterType]) {
|
fn optimize_filters(filters: &mut [RpcFilterType]) {
|
||||||
filters.iter_mut().for_each(|filter_type| {
|
filters.iter_mut().for_each(|filter_type| {
|
||||||
if let RpcFilterType::Memcmp(compare) = filter_type {
|
if let RpcFilterType::Memcmp(compare) = filter_type {
|
||||||
use MemcmpEncodedBytes::*;
|
if let Err(err) = compare.convert_to_raw_bytes() {
|
||||||
match &compare.bytes {
|
// All filters should have been previously verified
|
||||||
#[allow(deprecated)]
|
warn!("Invalid filter: bytes could not be decoded, {err}");
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -2338,6 +2327,7 @@ fn get_spl_token_owner_filter(program_id: &Pubkey, filters: &[RpcFilterType]) ->
|
||||||
for filter in filters {
|
for filter in filters {
|
||||||
match filter {
|
match filter {
|
||||||
RpcFilterType::DataSize(size) => data_size_filter = Some(*size),
|
RpcFilterType::DataSize(size) => data_size_filter = Some(*size),
|
||||||
|
#[allow(deprecated)]
|
||||||
RpcFilterType::Memcmp(Memcmp {
|
RpcFilterType::Memcmp(Memcmp {
|
||||||
offset,
|
offset,
|
||||||
bytes: MemcmpEncodedBytes::Bytes(bytes),
|
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() => {
|
}) if *offset == account_packed_len && *program_id == inline_spl_token_2022::id() => {
|
||||||
memcmp_filter = Some(bytes)
|
memcmp_filter = Some(bytes)
|
||||||
}
|
}
|
||||||
|
#[allow(deprecated)]
|
||||||
RpcFilterType::Memcmp(Memcmp {
|
RpcFilterType::Memcmp(Memcmp {
|
||||||
offset,
|
offset,
|
||||||
bytes: MemcmpEncodedBytes::Bytes(bytes),
|
bytes: MemcmpEncodedBytes::Bytes(bytes),
|
||||||
|
@ -2394,6 +2385,7 @@ fn get_spl_token_mint_filter(program_id: &Pubkey, filters: &[RpcFilterType]) ->
|
||||||
for filter in filters {
|
for filter in filters {
|
||||||
match filter {
|
match filter {
|
||||||
RpcFilterType::DataSize(size) => data_size_filter = Some(*size),
|
RpcFilterType::DataSize(size) => data_size_filter = Some(*size),
|
||||||
|
#[allow(deprecated)]
|
||||||
RpcFilterType::Memcmp(Memcmp {
|
RpcFilterType::Memcmp(Memcmp {
|
||||||
offset,
|
offset,
|
||||||
bytes: MemcmpEncodedBytes::Bytes(bytes),
|
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() => {
|
}) if *offset == account_packed_len && *program_id == inline_spl_token_2022::id() => {
|
||||||
memcmp_filter = Some(bytes)
|
memcmp_filter = Some(bytes)
|
||||||
}
|
}
|
||||||
|
#[allow(deprecated)]
|
||||||
RpcFilterType::Memcmp(Memcmp {
|
RpcFilterType::Memcmp(Memcmp {
|
||||||
offset,
|
offset,
|
||||||
bytes: MemcmpEncodedBytes::Bytes(bytes),
|
bytes: MemcmpEncodedBytes::Bytes(bytes),
|
||||||
|
@ -6531,22 +6524,16 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rpc_verify_filter() {
|
fn test_rpc_verify_filter() {
|
||||||
#[allow(deprecated)]
|
let filter = RpcFilterType::Memcmp(Memcmp::new(
|
||||||
let filter = RpcFilterType::Memcmp(Memcmp {
|
0, // offset
|
||||||
offset: 0,
|
MemcmpEncodedBytes::Base58("13LeFbG6m2EP1fqCj9k66fcXsoTHMMtgr7c78AivUrYD".to_string()), // encoded bytes
|
||||||
bytes: MemcmpEncodedBytes::Base58(
|
));
|
||||||
"13LeFbG6m2EP1fqCj9k66fcXsoTHMMtgr7c78AivUrYD".to_string(),
|
|
||||||
),
|
|
||||||
encoding: None,
|
|
||||||
});
|
|
||||||
assert_eq!(verify_filter(&filter), Ok(()));
|
assert_eq!(verify_filter(&filter), Ok(()));
|
||||||
// Invalid base-58
|
// Invalid base-58
|
||||||
#[allow(deprecated)]
|
let filter = RpcFilterType::Memcmp(Memcmp::new(
|
||||||
let filter = RpcFilterType::Memcmp(Memcmp {
|
0, // offset
|
||||||
offset: 0,
|
MemcmpEncodedBytes::Base58("III".to_string()), // encoded bytes
|
||||||
bytes: MemcmpEncodedBytes::Base58("III".to_string()),
|
));
|
||||||
encoding: None,
|
|
||||||
});
|
|
||||||
assert!(verify_filter(&filter).is_err());
|
assert!(verify_filter(&filter).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue