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}