sp_statement_store/
runtime_api.rs1use crate::{Hash, Statement, Topic};
21use alloc::vec::Vec;
22use codec::{Decode, Encode};
23use scale_info::TypeInfo;
24use sp_runtime_interface::{
25 pass_by::{
26 AllocateAndReturnByCodec, PassFatPointerAndDecode, PassFatPointerAndDecodeSlice,
27 PassPointerAndRead, PassPointerAndReadCopy, ReturnAs,
28 },
29 runtime_interface,
30};
31use Debug;
32
33#[cfg(feature = "std")]
34use sp_externalities::ExternalitiesExt;
35
36#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, Debug, TypeInfo)]
40pub enum StatementSource {
41 Chain,
43 Network,
45 Local,
47}
48
49impl StatementSource {
50 pub fn can_be_resubmitted(&self) -> bool {
53 match self {
54 StatementSource::Chain | StatementSource::Local => true,
55 StatementSource::Network => false,
56 }
57 }
58}
59
60#[cfg(feature = "std")]
61sp_externalities::decl_extension! {
62 pub struct StatementStoreExt(std::sync::Arc<dyn crate::StatementStore>);
64}
65
66#[cfg(feature = "std")]
68impl StatementStoreExt {
69 pub fn new(store: std::sync::Arc<dyn crate::StatementStore>) -> Self {
71 Self(store)
72 }
73}
74
75#[derive(Debug, Eq, PartialEq, Clone, Copy, Encode, Decode)]
77pub enum SubmitResult {
78 OkNew = 0,
80 OkKnown = 1,
82 Bad = 2,
84 NotAvailable = 3,
86 Full = 4,
88}
89
90impl TryFrom<u8> for SubmitResult {
91 type Error = ();
92 fn try_from(value: u8) -> Result<Self, Self::Error> {
93 match value {
94 0 => Ok(SubmitResult::OkNew),
95 1 => Ok(SubmitResult::OkKnown),
96 2 => Ok(SubmitResult::Bad),
97 3 => Ok(SubmitResult::NotAvailable),
98 4 => Ok(SubmitResult::Full),
99 _ => Err(()),
100 }
101 }
102}
103
104impl From<SubmitResult> for u8 {
105 fn from(value: SubmitResult) -> Self {
106 value as u8
107 }
108}
109
110#[cfg(feature = "std")]
112pub type HostFunctions = (statement_store::HostFunctions,);
113
114#[runtime_interface]
116pub trait StatementStore {
117 fn submit_statement(
120 &mut self,
121 statement: PassFatPointerAndDecode<Statement>,
122 ) -> ReturnAs<SubmitResult, u8> {
123 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
124 match store.submit(statement, StatementSource::Chain) {
125 crate::SubmitResult::New => SubmitResult::OkNew,
126 crate::SubmitResult::Known => SubmitResult::OkKnown,
127 crate::SubmitResult::Rejected(_) => SubmitResult::Full,
128 crate::SubmitResult::KnownExpired => SubmitResult::Bad,
131 crate::SubmitResult::Invalid(_) => SubmitResult::Bad,
132 crate::SubmitResult::InternalError(_) => SubmitResult::Bad,
133 }
134 } else {
135 SubmitResult::NotAvailable
136 }
137 }
138
139 fn statements(&mut self) -> AllocateAndReturnByCodec<Vec<(Hash, Statement)>> {
141 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
142 store.statements().unwrap_or_default()
143 } else {
144 Vec::default()
145 }
146 }
147
148 fn broadcasts(
151 &mut self,
152 match_all_topics: PassFatPointerAndDecodeSlice<&[Topic]>,
153 ) -> AllocateAndReturnByCodec<Vec<Vec<u8>>> {
154 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
155 store.broadcasts(match_all_topics).unwrap_or_default()
156 } else {
157 Vec::default()
158 }
159 }
160
161 fn posted(
165 &mut self,
166 match_all_topics: PassFatPointerAndDecodeSlice<&[Topic]>,
167 dest: PassPointerAndReadCopy<[u8; 32], 32>,
168 ) -> AllocateAndReturnByCodec<Vec<Vec<u8>>> {
169 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
170 store.posted(match_all_topics, dest).unwrap_or_default()
171 } else {
172 Vec::default()
173 }
174 }
175
176 fn posted_clear(
179 &mut self,
180 match_all_topics: PassFatPointerAndDecodeSlice<&[Topic]>,
181 dest: PassPointerAndReadCopy<[u8; 32], 32>,
182 ) -> AllocateAndReturnByCodec<Vec<Vec<u8>>> {
183 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
184 store.posted_clear(match_all_topics, dest).unwrap_or_default()
185 } else {
186 Vec::default()
187 }
188 }
189
190 fn remove(&mut self, hash: PassPointerAndRead<&Hash, 32>) {
192 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
193 store.remove(hash).unwrap_or_default()
194 }
195 }
196
197 fn remove_by(&mut self, who: PassPointerAndReadCopy<[u8; 32], 32>) {
199 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
200 let _ = store.remove_by(who);
201 }
202 }
203}