sawtooth_sdk/processor/handler.rs
1/*
2 * Copyright 2017 Bitwise IO, Inc.
3 * Copyright 2019 Cargill Incorporated
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * -----------------------------------------------------------------------------
17 */
18
19#![allow(unknown_lints)]
20
21extern crate protobuf;
22extern crate rand;
23extern crate zmq;
24
25use std::collections::HashMap;
26use std::error::Error as StdError;
27
28use crate::messages::processor::TpProcessRequest;
29use crate::messaging::stream::ReceiveError;
30use crate::messaging::stream::SendError;
31
32#[derive(Debug)]
33pub enum ApplyError {
34 /// Returned for an Invalid Transaction.
35 InvalidTransaction(String),
36 /// Returned when an internal error occurs during transaction processing.
37 InternalError(String),
38}
39
40impl std::error::Error for ApplyError {}
41
42impl std::fmt::Display for ApplyError {
43 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
44 match *self {
45 ApplyError::InvalidTransaction(ref s) => write!(f, "InvalidTransaction: {}", s),
46 ApplyError::InternalError(ref s) => write!(f, "InternalError: {}", s),
47 }
48 }
49}
50
51#[derive(Debug)]
52pub enum ContextError {
53 /// Returned for an authorization error
54 AuthorizationError(String),
55 /// Returned when a error occurs due to missing info in a response
56 ResponseAttributeError(String),
57 /// Returned when there is an issues setting receipt data or events.
58 TransactionReceiptError(String),
59 /// Returned when a ProtobufError is returned during serializing
60 SerializationError(Box<dyn StdError>),
61 /// Returned when an error is returned when sending a message
62 SendError(Box<dyn StdError>),
63 /// Returned when an error is returned when sending a message
64 ReceiveError(Box<dyn StdError>),
65}
66
67impl std::error::Error for ContextError {
68 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
69 match self {
70 ContextError::SerializationError(err) => Some(&**err),
71 ContextError::SendError(err) => Some(&**err),
72 ContextError::ReceiveError(err) => Some(&**err),
73 _ => None,
74 }
75 }
76}
77
78impl std::fmt::Display for ContextError {
79 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
80 match *self {
81 ContextError::AuthorizationError(ref s) => write!(f, "AuthorizationError: {}", s),
82 ContextError::ResponseAttributeError(ref s) => {
83 write!(f, "ResponseAttributeError: {}", s)
84 }
85 ContextError::TransactionReceiptError(ref s) => {
86 write!(f, "TransactionReceiptError: {}", s)
87 }
88 ContextError::SerializationError(ref err) => write!(f, "SerializationError: {}", err),
89 ContextError::SendError(ref err) => write!(f, "SendError: {}", err),
90 ContextError::ReceiveError(ref err) => write!(f, "ReceiveError: {}", err),
91 }
92 }
93}
94
95impl From<ContextError> for ApplyError {
96 fn from(context_error: ContextError) -> Self {
97 match context_error {
98 ContextError::TransactionReceiptError(..) => {
99 ApplyError::InternalError(format!("{}", context_error))
100 }
101 _ => ApplyError::InvalidTransaction(format!("{}", context_error)),
102 }
103 }
104}
105
106impl From<protobuf::ProtobufError> for ContextError {
107 fn from(e: protobuf::ProtobufError) -> Self {
108 ContextError::SerializationError(Box::new(e))
109 }
110}
111
112impl From<SendError> for ContextError {
113 fn from(e: SendError) -> Self {
114 ContextError::SendError(Box::new(e))
115 }
116}
117
118impl From<ReceiveError> for ContextError {
119 fn from(e: ReceiveError) -> Self {
120 ContextError::ReceiveError(Box::new(e))
121 }
122}
123
124pub trait TransactionContext {
125 #[deprecated(
126 since = "0.3.0",
127 note = "please use `get_state_entry` or `get_state_entries` instead"
128 )]
129 /// get_state queries the validator state for data at each of the
130 /// addresses in the given list. The addresses that have been set
131 /// are returned. get_state is deprecated, please use get_state_entry or get_state_entries
132 /// instead
133 ///
134 /// # Arguments
135 ///
136 /// * `addresses` - the addresses to fetch
137 fn get_state(&self, addresses: &[String]) -> Result<Vec<(String, Vec<u8>)>, ContextError> {
138 self.get_state_entries(addresses)
139 }
140
141 /// get_state_entry queries the validator state for data at the
142 /// address given. If the address is set, the data is returned.
143 ///
144 /// # Arguments
145 ///
146 /// * `address` - the address to fetch
147 fn get_state_entry(&self, address: &str) -> Result<Option<Vec<u8>>, ContextError> {
148 Ok(self
149 .get_state_entries(&[address.to_string()])?
150 .into_iter()
151 .map(|(_, val)| val)
152 .next())
153 }
154
155 /// get_state_entries queries the validator state for data at each of the
156 /// addresses in the given list. The addresses that have been set
157 /// are returned.
158 ///
159 /// # Arguments
160 ///
161 /// * `addresses` - the addresses to fetch
162 fn get_state_entries(
163 &self,
164 addresses: &[String],
165 ) -> Result<Vec<(String, Vec<u8>)>, ContextError>;
166
167 #[deprecated(
168 since = "0.3.0",
169 note = "please use `set_state_entry` or `set_state_entries` instead"
170 )]
171 /// set_state requests that each address in the provided map be
172 /// set in validator state to its corresponding value. set_state is deprecated, please use
173 /// set_state_entry to set_state_entries instead
174 ///
175 /// # Arguments
176 ///
177 /// * `entries` - entries are a hashmap where the key is an address and value is the data
178 fn set_state(&self, entries: HashMap<String, Vec<u8>>) -> Result<(), ContextError> {
179 let state_entries: Vec<(String, Vec<u8>)> = entries.into_iter().collect();
180 self.set_state_entries(state_entries)
181 }
182
183 /// set_state_entry requests that the provided address is set in the validator state to its
184 /// corresponding value.
185 ///
186 /// # Arguments
187 ///
188 /// * `address` - address of where to store the data
189 /// * `data` - payload is the data to store at the address
190 fn set_state_entry(&self, address: String, data: Vec<u8>) -> Result<(), ContextError> {
191 self.set_state_entries(vec![(address, data)])
192 }
193
194 /// set_state_entries requests that each address in the provided map be
195 /// set in validator state to its corresponding value.
196 ///
197 /// # Arguments
198 ///
199 /// * `entries` - entries are a hashmap where the key is an address and value is the data
200 fn set_state_entries(&self, entries: Vec<(String, Vec<u8>)>) -> Result<(), ContextError>;
201
202 /// delete_state requests that each of the provided addresses be unset
203 /// in validator state. A list of successfully deleted addresses is returned.
204 /// delete_state is deprecated, please use delete_state_entry to delete_state_entries instead
205 ///
206 /// # Arguments
207 ///
208 /// * `addresses` - the addresses to delete
209 #[deprecated(
210 since = "0.3.0",
211 note = "please use `delete_state_entry` or `delete_state_entries` instead"
212 )]
213 fn delete_state(&self, addresses: &[String]) -> Result<Vec<String>, ContextError> {
214 self.delete_state_entries(addresses)
215 }
216
217 /// delete_state_entry requests that the provided address be unset
218 /// in validator state. A list of successfully deleted addresses
219 /// is returned.
220 ///
221 /// # Arguments
222 ///
223 /// * `address` - the address to delete
224 fn delete_state_entry(&self, address: &str) -> Result<Option<String>, ContextError> {
225 Ok(self
226 .delete_state_entries(&[address.to_string()])?
227 .into_iter()
228 .next())
229 }
230
231 /// delete_state_entries requests that each of the provided addresses be unset
232 /// in validator state. A list of successfully deleted addresses
233 /// is returned.
234 ///
235 /// # Arguments
236 ///
237 /// * `addresses` - the addresses to delete
238 fn delete_state_entries(&self, addresses: &[String]) -> Result<Vec<String>, ContextError>;
239
240 /// add_receipt_data adds a blob to the execution result for this transaction
241 ///
242 /// # Arguments
243 ///
244 /// * `data` - the data to add
245 fn add_receipt_data(&self, data: &[u8]) -> Result<(), ContextError>;
246
247 /// add_event adds a new event to the execution result for this transaction.
248 ///
249 /// # Arguments
250 ///
251 /// * `event_type` - This is used to subscribe to events. It should be globally unique and
252 /// describe what, in general, has occured.
253 /// * `attributes` - Additional information about the event that is transparent to the
254 /// validator. Attributes can be used by subscribers to filter the type of events
255 /// they receive.
256 /// * `data` - Additional information about the event that is opaque to the validator.
257 fn add_event(
258 &self,
259 event_type: String,
260 attributes: Vec<(String, String)>,
261 data: &[u8],
262 ) -> Result<(), ContextError>;
263}
264
265pub trait TransactionHandler {
266 /// TransactionHandler that defines the business logic for a new transaction family.
267 /// The family_name, family_versions, and namespaces functions are
268 /// used by the processor to route processing requests to the handler.
269
270 /// family_name should return the name of the transaction family that this
271 /// handler can process, e.g. "intkey"
272 fn family_name(&self) -> String;
273
274 /// family_versions should return a list of versions this transaction
275 /// family handler can process, e.g. ["1.0"]
276 fn family_versions(&self) -> Vec<String>;
277
278 /// namespaces should return a list containing all the handler's
279 /// namespaces, e.g. ["abcdef"]
280 fn namespaces(&self) -> Vec<String>;
281
282 /// Apply is the single method where all the business logic for a
283 /// transaction family is defined. The method will be called by the
284 /// transaction processor upon receiving a TpProcessRequest that the
285 /// handler understands and will pass in the TpProcessRequest and an
286 /// initialized instance of the Context type.
287 fn apply(
288 &self,
289 request: &TpProcessRequest,
290 context: &mut dyn TransactionContext,
291 ) -> Result<(), ApplyError>;
292}