From 71022921dbb295fc056e59191f2aed847ec574ef Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 21 Jun 2024 14:42:09 -0600 Subject: [PATCH] refactor: do not consider overflowing key patterns --- .../grpc/src/server/subscriptions/entity.rs | 12 ++++- .../grpc/src/server/subscriptions/event.rs | 52 +++++++++++++------ .../src/server/subscriptions/event_message.rs | 12 ++++- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/crates/torii/grpc/src/server/subscriptions/entity.rs b/crates/torii/grpc/src/server/subscriptions/entity.rs index da9e19451e..dc786c70b0 100644 --- a/crates/torii/grpc/src/server/subscriptions/entity.rs +++ b/crates/torii/grpc/src/server/subscriptions/entity.rs @@ -99,6 +99,12 @@ impl Service { .map_err(ParseError::FromStr)?; for (idx, sub) in subs.subscribers.read().await.iter() { + // Check if the subscriber is interested in this entity + // If we have a clause of hashed keys, then check that the id of the entity + // is in the list of hashed keys. + + // If we have a clause of keys, then check that the key pattern of the entity + // matches the key pattern of the subscriber. if let Some(proto::types::EntityKeysClause { clause_type: Some(clause) }) = &sub.keys { match clause { proto::types::entity_keys_clause::ClauseType::HashedKeys(hashed_keys) => { @@ -121,7 +127,11 @@ impl Service { .collect::, _>>() .map_err(ParseError::FromByteSliceError)?; + // if the key pattern doesnt match our subscribers key pattern, skip + // ["", "0x0"] would match with keys ["0x...", "0x0", ...] if !keys.iter().enumerate().all(|(idx, key)| { + // this is going to be None if our key pattern overflows the subscriber + // key pattern in this case we should skip let sub_key = sub_keys.get(idx); match sub_key { @@ -132,7 +142,7 @@ impl Service { key == sub_key } } - None => true, + None => false, } }) { continue; diff --git a/crates/torii/grpc/src/server/subscriptions/event.rs b/crates/torii/grpc/src/server/subscriptions/event.rs index 1b44ed7c23..33ded6e532 100644 --- a/crates/torii/grpc/src/server/subscriptions/event.rs +++ b/crates/torii/grpc/src/server/subscriptions/event.rs @@ -86,22 +86,44 @@ impl Service { .map_err(ParseError::from)?; for (idx, sub) in subs.subscribers.read().await.iter() { - // publish all updates if ids is empty or only ids that are subscribed to - if sub.keys.is_empty() || keys.starts_with(&sub.keys) { - let resp = proto::world::SubscribeEventsResponse { - event: Some(proto::types::Event { - keys: keys.iter().map(|k| k.to_bytes_be().to_vec()).collect(), - data: data.iter().map(|d| d.to_bytes_be().to_vec()).collect(), - transaction_hash: FieldElement::from_str(&event.transaction_hash) - .map_err(ParseError::from)? - .to_bytes_be() - .to_vec(), - }), - }; - - if sub.sender.send(Ok(resp)).await.is_err() { - closed_stream.push(*idx); + // if the key pattern doesnt match our subscribers key pattern, skip + // ["", "0x0"] would match with keys ["0x...", "0x0", ...] + if !keys.iter().enumerate().all(|(idx, key)| { + // this is going to be None if our key pattern overflows the subscriber key pattern + // in this case we might want to list all events with the same + // key selector so we can match them all + let sub_key = sub.keys.get(idx); + + // if we have a key in the subscriber, it must match the key in the event + // unless its empty, which is a wildcard + // if we + match sub_key { + Some(sub_key) => { + if sub_key == &FieldElement::ZERO { + true + } else { + key == sub_key + } + } + None => true, } + }) { + continue; + } + + let resp = proto::world::SubscribeEventsResponse { + event: Some(proto::types::Event { + keys: keys.iter().map(|k| k.to_bytes_be().to_vec()).collect(), + data: data.iter().map(|d| d.to_bytes_be().to_vec()).collect(), + transaction_hash: FieldElement::from_str(&event.transaction_hash) + .map_err(ParseError::from)? + .to_bytes_be() + .to_vec(), + }), + }; + + if sub.sender.send(Ok(resp)).await.is_err() { + closed_stream.push(*idx); } } diff --git a/crates/torii/grpc/src/server/subscriptions/event_message.rs b/crates/torii/grpc/src/server/subscriptions/event_message.rs index 5f44d32464..1c0724ac71 100644 --- a/crates/torii/grpc/src/server/subscriptions/event_message.rs +++ b/crates/torii/grpc/src/server/subscriptions/event_message.rs @@ -98,6 +98,12 @@ impl Service { .map_err(ParseError::FromStr)?; for (idx, sub) in subs.subscribers.read().await.iter() { + // Check if the subscriber is interested in this entity + // If we have a clause of hashed keys, then check that the id of the entity + // is in the list of hashed keys. + + // If we have a clause of keys, then check that the key pattern of the entity + // matches the key pattern of the subscriber. if let Some(proto::types::EntityKeysClause { clause_type: Some(clause) }) = &sub.keys { match clause { proto::types::entity_keys_clause::ClauseType::HashedKeys(hashed_keys) => { @@ -120,7 +126,11 @@ impl Service { .collect::, _>>() .map_err(ParseError::FromByteSliceError)?; + // if the key pattern doesnt match our subscribers key pattern, skip + // ["", "0x0"] would match with keys ["0x...", "0x0"] if !keys.iter().enumerate().all(|(idx, key)| { + // this is going to be None if our key pattern overflows the subscriber + // key pattern in this case we should skip let sub_key = sub_keys.get(idx); match sub_key { @@ -131,7 +141,7 @@ impl Service { key == sub_key } } - None => true, + None => false, } }) { continue;