Skip to content

Commit 8bc0975

Browse files
committed
address feedback
Signed-off-by: Alexandru Gheorghe <[email protected]>
1 parent 03fcc46 commit 8bc0975

File tree

2 files changed

+43
-103
lines changed
  • substrate
    • client/rpc-api/src/statement
    • primitives/statement-store/src

2 files changed

+43
-103
lines changed

substrate/client/rpc-api/src/statement/mod.rs

Lines changed: 10 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -32,67 +32,22 @@ pub enum TopicFilter {
3232
/// Matches all topics.
3333
Any,
3434
/// Matches only statements including all of the given topics.
35-
/// Bytes are expected to be a 32-byte topic.
35+
/// Bytes are expected to be a 32-byte topic. Up to `4` topics can be provided.
3636
MatchAll(Vec<Bytes>),
37-
}
38-
39-
/// Filter for querying statements with different decryption key identifiers.
40-
#[derive(Debug, Clone, Serialize, Deserialize)]
41-
#[serde(rename_all = "camelCase")]
42-
pub enum DecryptionKeyIdFilter {
43-
/// Matches any statement regardless of their decryption key identifier.
44-
Any,
45-
/// Match only statements without a decryption key identifier.
46-
NoDecryptionKey,
47-
/// Match only statements with the provided decryption key identifier.
48-
/// Bytes are expected to be a 32-byte key identifier.
49-
Matches(Bytes),
50-
}
51-
52-
/// Filter for querying statements with different submitters.
53-
#[derive(Debug, Clone, Serialize, Deserialize)]
54-
#[serde(rename_all = "camelCase")]
55-
pub enum SubmitterFilter {
56-
/// Matches any statement regardless of their owner identifier.
57-
Any,
58-
/// Match only statements with the provided owner identifier.
59-
/// Bytes are expected to be a 32-byte owner identifier.
60-
Matches(Bytes),
61-
}
62-
63-
/// Cursor for paginated statement queries.
64-
#[derive(Debug, Clone, Serialize, Deserialize)]
65-
pub enum PageCursor {
66-
// No more pages
67-
End,
68-
// Cursor to fetch the next page, opaque to the client.
69-
NextPage(Bytes),
70-
}
71-
72-
#[derive(Debug, Clone, Serialize, Deserialize)]
73-
#[serde(rename_all = "camelCase")]
74-
pub struct GetStatementsResponse {
75-
/// SCALE-encoded statements matching the query.
76-
pub encoded_statements: Vec<Bytes>,
77-
/// Cursor for the next page, or `End` if there are no further pages.
78-
pub next_page: PageCursor,
37+
/// Matches statements including any of the given topics.
38+
/// Bytes are expected to be a 32-byte topic. Up to `128` topics can be provided.
39+
MatchAny(Vec<Bytes>),
7940
}
8041

8142
/// Substrate statement RPC API
8243
#[rpc(client, server)]
8344
pub trait StatementApi2 {
84-
/// Return statements that match the provided filters, with pagination.
45+
/// Subscribe to new statements that match the provided filters.
8546
///
8647
/// # Parameters
8748
///
8849
/// - `topic_filter` — Which topics to match. Use `TopicFilter::Any` to match all topics, or
8950
/// `TopicFilter::MatchAll(vec)` to match statements that include all provided topics.
90-
/// - `key_filter` — Filter by decryption key identifier. Use `DecryptionKeyIdFilter::Any` to
91-
/// ignore the decryption key, `NoDecryptionKey` to select statements without a decryption
92-
/// key, or `Matches(id)` to select statements with the given key id.
93-
/// - `submitter_filter` — Filter by statement submitter. Use `SubmitterFilter::Any` to match
94-
/// any owner identifier or `SubmitterFilter::Matches(owner)` to restrict to a specific owner
95-
/// identifier.
9651
/// - `next_page` — Optional pagination cursor. Pass `None` to request the first page. When a
9752
/// previous response contained a `PageCursor::NextPage(bytes)`, pass that wrapped in
9853
/// `Some(...)` to fetch the next page. The server will return `PageCursor::End` when there
@@ -103,42 +58,17 @@ pub trait StatementApi2 {
10358
///
10459
/// # Returns
10560
///
106-
/// Returns `RpcResult<GetStatementsResponse>` on success.
107-
/// - `GetStatementsResponse.encoded_statements` contains a Vec of SCALE-encoded statements as
108-
/// `Bytes`.
109-
/// - `GetStatementsResponse.next_page` indicates whether more pages are available (an
110-
/// opaque cursor) or `End` if the result set is exhausted.
111-
#[method(name = "statement_getStatements")]
112-
fn get_statements(
113-
&self,
114-
topic_filter: TopicFilter,
115-
key_filter: DecryptionKeyIdFilter,
116-
submitter_filter: SubmitterFilter,
117-
next_page: Option<PageCursor>,
118-
limit: Option<u32>,
119-
) -> RpcResult<GetStatementsResponse>;
120-
121-
/// Subscribe to new statements that match the provided filters.
122-
///
123-
/// # Parameters
124-
///
125-
/// See `get_statements` for parameter descriptions.
126-
///
127-
/// # Returns
128-
///
12961
/// Returns a stream of SCALE-encoded statements as `Bytes`.
62+
/// When a subscription is initiated the endpoint will immediately return the matching
63+
/// statements already in the store. Subsequent matching statements will be pushed to the client
64+
/// as they are added to the store.
13065
#[subscription(
13166
name = "statement_subscribeStatement" => "statement_statement",
13267
unsubscribe = "statement_unsubscribeStatement",
13368
item = Bytes,
13469
with_extensions,
13570
)]
136-
fn subscribe_statement(
137-
&self,
138-
topic_filter: TopicFilter,
139-
key_filter: DecryptionKeyIdFilter,
140-
submitter_filter: SubmitterFilter,
141-
);
71+
fn subscribe_statement(&self, topic_filter: TopicFilter);
14272

14373
/// Submit a SCALE-encoded statement.
14474
///
@@ -151,7 +81,7 @@ pub trait StatementApi2 {
15181

15282
/// Substrate statement RPC API
15383
#[rpc(client, server)]
154-
#[deprecated(since = "0.0.0", note = "Please use StatementApi2 instead")]
84+
#[deprecated(since = "0.0.0", note = "Please use StatementApi2 instead, will be removed soon.")]
15585
pub trait StatementApi {
15686
/// Return all statements, SCALE-encoded.
15787
#[method(name = "statement_dump", with_extensions)]

substrate/primitives/statement-store/src/lib.rs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ pub enum Field {
150150
AuthenticityProof(Proof) = 0,
151151
/// An identifier for the key that `Data` field may be decrypted with.
152152
DecryptionKey(DecryptionKey) = 1,
153-
/// Priority when competing with other messages from the same sender.
154-
Priority(u32) = 2,
153+
/// Expiry of the statement.
154+
Expiry(u64) = 2,
155155
/// Account channel to use. Only one message per `(account, channel)` pair is allowed.
156156
Channel(Channel) = 3,
157157
/// First statement topic.
@@ -180,6 +180,7 @@ pub struct Statement {
180180
/// Proof used for authorizing the statement.
181181
proof: Option<Proof>,
182182
/// An identifier for the key that `Data` field may be decrypted with.
183+
#[deprecated(note = "Experimental feature, may be removed in future releases")]
183184
decryption_key: Option<DecryptionKey>,
184185
/// Used for identifying a distinct communication channel, only a message per channel is
185186
/// stored.
@@ -192,16 +193,25 @@ pub struct Statement {
192193
/// in the account quota. In that case, other statements from the same account with the lowest
193194
/// priority might be removed.
194195
channel: Option<Channel>,
195-
/// Message priority, if any, used for determining which statements to keep when over quota.
196-
/// Statements with higher priority are kept over those with lower priority.
197-
priority: Option<u32>,
196+
/// Message priority, used for determining which statements to keep.
197+
///
198+
/// The the most significant 32 bits represents the expiration timestamp (in seconds since
199+
/// UNIX epoch) after which the statement gets removed. These ensure that statements with a
200+
/// higher expiration time have a higher priority.
201+
/// The lower 32 bits represents an arbitrary sequence number used to order statements with the
202+
/// same expiration time.
203+
///
204+
/// Higher values indicate a higher priority.
205+
/// This is used in two case:
206+
/// 1) When an account exceeds its quota and some statements need to be removed. Statements
207+
/// with the lowest priority are removed first.
208+
/// 2) When multiple statements are submitted on the same channel, the one with the highest
209+
/// priority replaces the one with the same channel.
210+
expiry: u64,
198211
/// Number of topics present.
199212
num_topics: u8,
200213
/// Topics, used for querying and filtering statements.
201214
topics: [Topic; MAX_TOPICS],
202-
/// A Unix timestamp (in milliseconds) after which the statement is considered expired and it
203-
/// will be cleaned up from the store.
204-
expires_at_ms: u64,
205215
/// Statement data.
206216
data: Option<Vec<u8>>,
207217
}
@@ -222,7 +232,7 @@ impl Decode for Statement {
222232
match field {
223233
Field::AuthenticityProof(p) => statement.set_proof(p),
224234
Field::DecryptionKey(key) => statement.set_decryption_key(key),
225-
Field::Priority(p) => statement.set_priority(p),
235+
Field::Expiry(p) => statement.set_expiry(p),
226236
Field::Channel(c) => statement.set_channel(c),
227237
Field::Topic1(t) => statement.set_topic(0, t),
228238
Field::Topic2(t) => statement.set_topic(1, t),
@@ -445,8 +455,8 @@ impl Statement {
445455
}
446456

447457
/// Get priority, if any.
448-
pub fn priority(&self) -> Option<u32> {
449-
self.priority
458+
pub fn expiry(&self) -> u64 {
459+
self.expiry
450460
}
451461

452462
/// Return encoded fields that can be signed to construct or verify a proof
@@ -464,9 +474,9 @@ impl Statement {
464474
self.proof = Some(proof)
465475
}
466476

467-
/// Set statement priority.
468-
pub fn set_priority(&mut self, priority: u32) {
469-
self.priority = Some(priority)
477+
/// Set statement expiry.
478+
pub fn set_expiry(&mut self, expiry: u64) {
479+
self.expiry = expiry;
470480
}
471481

472482
/// Set statement channel.
@@ -495,9 +505,9 @@ impl Statement {
495505
fn encoded(&self, for_signing: bool) -> Vec<u8> {
496506
// Encoding matches that of Vec<Field>. Basically this just means accepting that there
497507
// will be a prefix of vector length.
498-
let num_fields = if !for_signing && self.proof.is_some() { 1 } else { 0 } +
508+
// Expiry field is always present.
509+
let num_fields = if !for_signing && self.proof.is_some() { 2 } else { 1 } +
499510
if self.decryption_key.is_some() { 1 } else { 0 } +
500-
if self.priority.is_some() { 1 } else { 0 } +
501511
if self.channel.is_some() { 1 } else { 0 } +
502512
if self.data.is_some() { 1 } else { 0 } +
503513
self.num_topics as u32;
@@ -519,10 +529,10 @@ impl Statement {
519529
1u8.encode_to(&mut output);
520530
decryption_key.encode_to(&mut output);
521531
}
522-
if let Some(priority) = &self.priority {
523-
2u8.encode_to(&mut output);
524-
priority.encode_to(&mut output);
525-
}
532+
533+
2u8.encode_to(&mut output);
534+
self.expiry().encode_to(&mut output);
535+
526536
if let Some(channel) = &self.channel {
527537
3u8.encode_to(&mut output);
528538
channel.encode_to(&mut output);
@@ -594,7 +604,7 @@ mod test {
594604
let fields = vec![
595605
Field::AuthenticityProof(proof.clone()),
596606
Field::DecryptionKey(decryption_key),
597-
Field::Priority(priority),
607+
Field::Expiry(priority),
598608
Field::Channel(channel),
599609
Field::Topic1(topic1),
600610
Field::Topic2(topic2),
@@ -616,7 +626,7 @@ mod test {
616626
let priority = 999;
617627

618628
let fields = vec![
619-
Field::Priority(priority),
629+
Field::Expiry(priority),
620630
Field::Topic1(topic1),
621631
Field::Topic1(topic1),
622632
Field::Topic2(topic2),
@@ -626,7 +636,7 @@ mod test {
626636
assert!(Statement::decode(&mut fields.as_slice()).is_err());
627637

628638
let fields =
629-
vec![Field::Topic1(topic1), Field::Priority(priority), Field::Topic2(topic2)].encode();
639+
vec![Field::Topic1(topic1), Field::Expiry(priority), Field::Topic2(topic2)].encode();
630640

631641
assert!(Statement::decode(&mut fields.as_slice()).is_err());
632642
}

0 commit comments

Comments
 (0)