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}