sp_statement_store/store_api.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18pub use crate::runtime_api::StatementSource;
19use crate::{Hash, Statement, Topic};
20
21/// Statement store error.
22#[derive(Debug, Clone, Eq, PartialEq, thiserror::Error)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub enum Error {
25 /// Database error.
26 #[error("Database error: {0:?}")]
27 Db(String),
28 /// Error decoding statement structure.
29 #[error("Error decoding statement: {0:?}")]
30 Decode(String),
31 /// Error making runtime call.
32 #[error("Error calling into the runtime")]
33 Runtime,
34}
35
36/// Reason why a statement was rejected from the store.
37#[derive(Debug, Clone, Eq, PartialEq)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39#[cfg_attr(feature = "serde", serde(tag = "reason", rename_all = "camelCase"))]
40pub enum RejectionReason {
41 /// Statement data exceeds the maximum allowed size for the account.
42 DataTooLarge {
43 /// The size of the submitted statement data.
44 submitted_size: usize,
45 /// Still available data size for the account.
46 available_size: usize,
47 },
48 /// Attempting to replace a channel message with lower or equal priority.
49 ChannelPriorityTooLow {
50 /// The priority of the submitted statement.
51 submitted_priority: u32,
52 /// The minimum priority of the existing channel message.
53 min_priority: u32,
54 },
55 /// Account reached its statement limit and submitted priority is too low to evict existing.
56 AccountFull {
57 /// The priority of the submitted statement.
58 submitted_priority: u32,
59 /// The minimum priority of the existing statement.
60 min_priority: u32,
61 },
62 /// The global statement store is full and cannot accept new statements.
63 StoreFull,
64}
65
66/// Reason why a statement failed validation.
67#[derive(Debug, Clone, Eq, PartialEq)]
68#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
69#[cfg_attr(feature = "serde", serde(tag = "reason", rename_all = "camelCase"))]
70pub enum InvalidReason {
71 /// Statement has no proof.
72 NoProof,
73 /// Proof validation failed.
74 BadProof,
75 /// Statement exceeds max allowed statement size.
76 EncodingTooLarge {
77 /// The size of the submitted statement encoding.
78 submitted_size: usize,
79 /// The maximum allowed size.
80 max_size: usize,
81 },
82}
83
84/// Statement submission outcome
85#[derive(Debug, Clone, Eq, PartialEq)]
86#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
87#[cfg_attr(feature = "serde", serde(tag = "status", rename_all = "camelCase"))]
88pub enum SubmitResult {
89 /// Statement was accepted as new.
90 New,
91 /// Statement was already known.
92 Known,
93 /// Statement was already known but has expired.
94 KnownExpired,
95 /// Statement was rejected because the store is full or priority is too low.
96 Rejected(RejectionReason),
97 /// Statement failed validation.
98 Invalid(InvalidReason),
99 /// Internal store error.
100 InternalError(Error),
101}
102
103/// Result type for `Error`
104pub type Result<T> = std::result::Result<T, Error>;
105
106/// Decision returned by the filter used in [`StatementStore::statements_by_hashes`].
107#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108pub enum FilterDecision {
109 /// Skip this statement, continue to next.
110 Skip,
111 /// Take this statement, continue to next.
112 Take,
113 /// Stop iteration, return collected statements.
114 Abort,
115}
116
117/// Statement store API.
118pub trait StatementStore: Send + Sync {
119 /// Return all statements.
120 fn statements(&self) -> Result<Vec<(Hash, Statement)>>;
121
122 /// Return recent statements and clear the internal index.
123 ///
124 /// This consumes and clears the recently received statements,
125 /// allowing new statements to be collected from this point forward.
126 fn take_recent_statements(&self) -> Result<Vec<(Hash, Statement)>>;
127
128 /// Get statement by hash.
129 fn statement(&self, hash: &Hash) -> Result<Option<Statement>>;
130
131 /// Check if statement exists in the store
132 ///
133 /// Fast index check without accessing the DB.
134 fn has_statement(&self, hash: &Hash) -> bool;
135
136 /// Return all statement hashes.
137 fn statement_hashes(&self) -> Vec<Hash>;
138
139 /// Fetch statements by their hashes with a filter callback.
140 ///
141 /// The callback receives (hash, encoded_bytes, decoded_statement) and returns:
142 /// - `Skip`: ignore this statement, continue to next
143 /// - `Take`: include this statement in the result, continue to next
144 /// - `Abort`: stop iteration, return collected statements so far
145 ///
146 /// Returns (statements, number_of_hashes_processed).
147 fn statements_by_hashes(
148 &self,
149 hashes: &[Hash],
150 filter: &mut dyn FnMut(&Hash, &[u8], &Statement) -> FilterDecision,
151 ) -> Result<(Vec<(Hash, Statement)>, usize)>;
152
153 /// Return the data of all known statements which include all topics and have no `DecryptionKey`
154 /// field.
155 fn broadcasts(&self, match_all_topics: &[Topic]) -> Result<Vec<Vec<u8>>>;
156
157 /// Return the data of all known statements whose decryption key is identified as `dest` (this
158 /// will generally be the public key or a hash thereof for symmetric ciphers, or a hash of the
159 /// private key for symmetric ciphers).
160 fn posted(&self, match_all_topics: &[Topic], dest: [u8; 32]) -> Result<Vec<Vec<u8>>>;
161
162 /// Return the decrypted data of all known statements whose decryption key is identified as
163 /// `dest`. The key must be available to the client.
164 fn posted_clear(&self, match_all_topics: &[Topic], dest: [u8; 32]) -> Result<Vec<Vec<u8>>>;
165
166 /// Return all known statements which include all topics and have no `DecryptionKey`
167 /// field.
168 fn broadcasts_stmt(&self, match_all_topics: &[Topic]) -> Result<Vec<Vec<u8>>>;
169
170 /// Return all known statements whose decryption key is identified as `dest` (this
171 /// will generally be the public key or a hash thereof for symmetric ciphers, or a hash of the
172 /// private key for symmetric ciphers).
173 fn posted_stmt(&self, match_all_topics: &[Topic], dest: [u8; 32]) -> Result<Vec<Vec<u8>>>;
174
175 /// Return the statement and the decrypted data of all known statements whose decryption key is
176 /// identified as `dest`. The key must be available to the client.
177 ///
178 /// The result is for each statement: the SCALE-encoded statement concatenated to the
179 /// decrypted data.
180 fn posted_clear_stmt(&self, match_all_topics: &[Topic], dest: [u8; 32])
181 -> Result<Vec<Vec<u8>>>;
182
183 /// Submit a statement.
184 fn submit(&self, statement: Statement, source: StatementSource) -> SubmitResult;
185
186 /// Remove a statement from the store.
187 fn remove(&self, hash: &Hash) -> Result<()>;
188
189 /// Remove all statements authored by `who`.
190 fn remove_by(&self, who: [u8; 32]) -> Result<()>;
191}