soil_statement_store/
runtime_api.rs1use crate::{Hash, Statement, Topic};
10use alloc::vec::Vec;
11use codec::{Decode, Encode};
12use scale_info::TypeInfo;
13use subsoil::runtime_interface::{
14 pass_by::{
15 AllocateAndReturnByCodec, PassFatPointerAndDecode, PassFatPointerAndDecodeSlice,
16 PassPointerAndRead, PassPointerAndReadCopy, ReturnAs,
17 },
18 runtime_interface,
19};
20use Debug;
21
22#[cfg(feature = "std")]
23use subsoil::externalities::ExternalitiesExt;
24
25#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, Debug, TypeInfo)]
29pub enum StatementSource {
30 Chain,
32 Network,
34 Local,
36}
37
38impl StatementSource {
39 pub fn can_be_resubmitted(&self) -> bool {
42 match self {
43 StatementSource::Chain | StatementSource::Local => true,
44 StatementSource::Network => false,
45 }
46 }
47}
48
49#[cfg(feature = "std")]
50subsoil::decl_extension! {
51 pub struct StatementStoreExt(std::sync::Arc<dyn crate::StatementStore>);
53}
54
55#[cfg(feature = "std")]
57impl StatementStoreExt {
58 pub fn new(store: std::sync::Arc<dyn crate::StatementStore>) -> Self {
60 Self(store)
61 }
62}
63
64#[derive(Debug, Eq, PartialEq, Clone, Copy, Encode, Decode)]
66pub enum SubmitResult {
67 OkNew = 0,
69 OkKnown = 1,
71 Bad = 2,
73 NotAvailable = 3,
75 Full = 4,
77}
78
79impl TryFrom<u8> for SubmitResult {
80 type Error = ();
81 fn try_from(value: u8) -> Result<Self, Self::Error> {
82 match value {
83 0 => Ok(SubmitResult::OkNew),
84 1 => Ok(SubmitResult::OkKnown),
85 2 => Ok(SubmitResult::Bad),
86 3 => Ok(SubmitResult::NotAvailable),
87 4 => Ok(SubmitResult::Full),
88 _ => Err(()),
89 }
90 }
91}
92
93impl From<SubmitResult> for u8 {
94 fn from(value: SubmitResult) -> Self {
95 value as u8
96 }
97}
98
99#[cfg(feature = "std")]
101pub type HostFunctions = (statement_store::HostFunctions,);
102
103#[runtime_interface]
105pub trait StatementStore {
106 fn submit_statement(
109 &mut self,
110 statement: PassFatPointerAndDecode<Statement>,
111 ) -> ReturnAs<SubmitResult, u8> {
112 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
113 match store.submit(statement, StatementSource::Chain) {
114 crate::SubmitResult::New => SubmitResult::OkNew,
115 crate::SubmitResult::Known => SubmitResult::OkKnown,
116 crate::SubmitResult::Rejected(_) => SubmitResult::Full,
117 crate::SubmitResult::KnownExpired => SubmitResult::Bad,
120 crate::SubmitResult::Invalid(_) => SubmitResult::Bad,
121 crate::SubmitResult::InternalError(_) => SubmitResult::Bad,
122 }
123 } else {
124 SubmitResult::NotAvailable
125 }
126 }
127
128 fn statements(&mut self) -> AllocateAndReturnByCodec<Vec<(Hash, Statement)>> {
130 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
131 store.statements().unwrap_or_default()
132 } else {
133 Vec::default()
134 }
135 }
136
137 fn broadcasts(
140 &mut self,
141 match_all_topics: PassFatPointerAndDecodeSlice<&[Topic]>,
142 ) -> AllocateAndReturnByCodec<Vec<Vec<u8>>> {
143 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
144 store.broadcasts(match_all_topics).unwrap_or_default()
145 } else {
146 Vec::default()
147 }
148 }
149
150 fn posted(
154 &mut self,
155 match_all_topics: PassFatPointerAndDecodeSlice<&[Topic]>,
156 dest: PassPointerAndReadCopy<[u8; 32], 32>,
157 ) -> AllocateAndReturnByCodec<Vec<Vec<u8>>> {
158 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
159 store.posted(match_all_topics, dest).unwrap_or_default()
160 } else {
161 Vec::default()
162 }
163 }
164
165 fn posted_clear(
168 &mut self,
169 match_all_topics: PassFatPointerAndDecodeSlice<&[Topic]>,
170 dest: PassPointerAndReadCopy<[u8; 32], 32>,
171 ) -> AllocateAndReturnByCodec<Vec<Vec<u8>>> {
172 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
173 store.posted_clear(match_all_topics, dest).unwrap_or_default()
174 } else {
175 Vec::default()
176 }
177 }
178
179 fn remove(&mut self, hash: PassPointerAndRead<&Hash, 32>) {
181 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
182 store.remove(hash).unwrap_or_default()
183 }
184 }
185
186 fn remove_by(&mut self, who: PassPointerAndReadCopy<[u8; 32], 32>) {
188 if let Some(StatementStoreExt(store)) = self.extension::<StatementStoreExt>() {
189 let _ = store.remove_by(who);
190 }
191 }
192}