github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/rust/src/processor/handler.rs (about)

     1  /*
     2   * Copyright 2017 Bitwise IO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   * -----------------------------------------------------------------------------
    16   */
    17  
    18  extern crate protobuf;
    19  extern crate rand;
    20  extern crate zmq;
    21  
    22  use protobuf::Message as M;
    23  use protobuf::RepeatedField;
    24  
    25  use std;
    26  use std::borrow::Borrow;
    27  use std::collections::HashMap;
    28  use std::error::Error as StdError;
    29  
    30  use messages::events::Event;
    31  use messages::events::Event_Attribute;
    32  use messages::processor::TpProcessRequest;
    33  use messages::state_context::*;
    34  use messages::validator::Message_MessageType;
    35  
    36  use messaging::stream::MessageSender;
    37  use messaging::stream::ReceiveError;
    38  use messaging::stream::SendError;
    39  use messaging::zmq_stream::ZmqMessageSender;
    40  
    41  use super::generate_correlation_id;
    42  
    43  #[derive(Debug)]
    44  pub enum ApplyError {
    45      /// Returned for an Invalid Transaction.
    46      InvalidTransaction(String),
    47      /// Returned when an internal error occurs during transaction processing.
    48      InternalError(String),
    49  }
    50  
    51  impl std::error::Error for ApplyError {
    52      fn description(&self) -> &str {
    53          match *self {
    54              ApplyError::InvalidTransaction(ref msg) => msg,
    55              ApplyError::InternalError(ref msg) => msg,
    56          }
    57      }
    58  
    59      fn cause(&self) -> Option<&std::error::Error> {
    60          match *self {
    61              ApplyError::InvalidTransaction(_) => None,
    62              ApplyError::InternalError(_) => None,
    63          }
    64      }
    65  }
    66  
    67  impl std::fmt::Display for ApplyError {
    68      fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    69          match *self {
    70              ApplyError::InvalidTransaction(ref s) => write!(f, "InvalidTransaction: {}", s),
    71              ApplyError::InternalError(ref s) => write!(f, "InternalError: {}", s),
    72          }
    73      }
    74  }
    75  
    76  #[derive(Debug)]
    77  pub enum ContextError {
    78      /// Returned for an authorization error
    79      AuthorizationError(String),
    80      /// Returned when a error occurs due to missing info in a response
    81      ResponseAttributeError(String),
    82      /// Returned when there is an issues setting receipt data or events.
    83      TransactionReceiptError(String),
    84      /// Returned when a ProtobufError is returned during serializing
    85      SerializationError(Box<StdError>),
    86      /// Returned when an error is returned when sending a message
    87      SendError(Box<StdError>),
    88      /// Returned when an error is returned when sending a message
    89      ReceiveError(Box<StdError>),
    90  }
    91  
    92  impl std::error::Error for ContextError {
    93      fn description(&self) -> &str {
    94          match *self {
    95              ContextError::AuthorizationError(ref msg) => msg,
    96              ContextError::ResponseAttributeError(ref msg) => msg,
    97              ContextError::TransactionReceiptError(ref msg) => msg,
    98              ContextError::SerializationError(ref err) => err.description(),
    99              ContextError::SendError(ref err) => err.description(),
   100              ContextError::ReceiveError(ref err) => err.description(),
   101          }
   102      }
   103  
   104      fn cause(&self) -> Option<&std::error::Error> {
   105          match *self {
   106              ContextError::AuthorizationError(_) => None,
   107              ContextError::ResponseAttributeError(_) => None,
   108              ContextError::TransactionReceiptError(_) => None,
   109              ContextError::SerializationError(ref err) => Some(err.borrow()),
   110              ContextError::SendError(ref err) => Some(err.borrow()),
   111              ContextError::ReceiveError(ref err) => Some(err.borrow()),
   112          }
   113      }
   114  }
   115  
   116  impl std::fmt::Display for ContextError {
   117      fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
   118          match *self {
   119              ContextError::AuthorizationError(ref s) => write!(f, "AuthorizationError: {}", s),
   120              ContextError::ResponseAttributeError(ref s) => {
   121                  write!(f, "ResponseAttributeError: {}", s)
   122              }
   123              ContextError::TransactionReceiptError(ref s) => {
   124                  write!(f, "TransactionReceiptError: {}", s)
   125              }
   126              ContextError::SerializationError(ref err) => {
   127                  write!(f, "SerializationError: {}", err.description())
   128              }
   129              ContextError::SendError(ref err) => write!(f, "SendError: {}", err.description()),
   130              ContextError::ReceiveError(ref err) => write!(f, "ReceiveError: {}", err.description()),
   131          }
   132      }
   133  }
   134  
   135  impl From<ContextError> for ApplyError {
   136      fn from(context_error: ContextError) -> Self {
   137          match context_error {
   138              ContextError::TransactionReceiptError(..) => {
   139                  ApplyError::InternalError(format!("{}", context_error))
   140              }
   141              _ => ApplyError::InvalidTransaction(format!("{}", context_error)),
   142          }
   143      }
   144  }
   145  
   146  impl From<protobuf::ProtobufError> for ContextError {
   147      fn from(e: protobuf::ProtobufError) -> Self {
   148          ContextError::SerializationError(Box::new(e))
   149      }
   150  }
   151  
   152  impl From<SendError> for ContextError {
   153      fn from(e: SendError) -> Self {
   154          ContextError::SendError(Box::new(e))
   155      }
   156  }
   157  
   158  impl From<ReceiveError> for ContextError {
   159      fn from(e: ReceiveError) -> Self {
   160          ContextError::ReceiveError(Box::new(e))
   161      }
   162  }
   163  
   164  #[derive(Clone)]
   165  pub struct TransactionContext {
   166      context_id: String,
   167      sender: ZmqMessageSender,
   168  }
   169  
   170  impl TransactionContext {
   171      /// Context provides an interface for getting, setting, and deleting
   172      /// validator state. All validator interactions by a handler should be
   173      /// through a Context instance.
   174      ///
   175      /// # Arguments
   176      ///
   177      /// * `sender` - for client grpc communication
   178      /// * `context_id` - the context_id passed in from the validator
   179      pub fn new(context_id: &str, sender: ZmqMessageSender) -> TransactionContext {
   180          TransactionContext {
   181              context_id: String::from(context_id),
   182              sender: sender,
   183          }
   184      }
   185  
   186      /// get_state queries the validator state for data at each of the
   187      /// addresses in the given list. The addresses that have been set
   188      /// are returned.
   189      ///
   190      /// # Arguments
   191      ///
   192      /// * `addresses` - the addresses to fetch
   193      pub fn get_state(&mut self, addresses: Vec<String>) -> Result<Option<Vec<u8>>, ContextError> {
   194          let mut request = TpStateGetRequest::new();
   195          request.set_context_id(self.context_id.clone());
   196          request.set_addresses(RepeatedField::from_vec(addresses.to_vec()));
   197          let serialized = request.write_to_bytes()?;
   198          let x: &[u8] = &serialized;
   199  
   200          let mut future = self.sender.send(
   201              Message_MessageType::TP_STATE_GET_REQUEST,
   202              &generate_correlation_id(),
   203              x,
   204          )?;
   205  
   206          let response: TpStateGetResponse = protobuf::parse_from_bytes(future.get()?.get_content())?;
   207          match response.get_status() {
   208              TpStateGetResponse_Status::OK => {
   209                  let entry = match response.get_entries().first() {
   210                      Some(x) => x,
   211                      None => {
   212                          return Err(ContextError::ResponseAttributeError(String::from(
   213                              "TpStateGetResponse is missing entries.",
   214                          )))
   215                      }
   216                  };
   217                  match entry.get_data().len() {
   218                      0 => Ok(None),
   219                      _ => Ok(Some(Vec::from(entry.get_data()))),
   220                  }
   221              }
   222              TpStateGetResponse_Status::AUTHORIZATION_ERROR => {
   223                  Err(ContextError::AuthorizationError(format!(
   224                      "Tried to get unauthorized address: {:?}",
   225                      addresses
   226                  )))
   227              }
   228              TpStateGetResponse_Status::STATUS_UNSET => Err(ContextError::ResponseAttributeError(
   229                  String::from("Status was not set for TpStateGetResponse"),
   230              )),
   231          }
   232      }
   233  
   234      /// set_state requests that each address in the provided map be
   235      /// set in validator state to its corresponding value.
   236      ///
   237      /// # Arguments
   238      ///
   239      /// * `address` - address of where to store the data
   240      /// * `paylaod` - payload is the data to store at the address
   241      pub fn set_state(&mut self, entries: HashMap<String, Vec<u8>>) -> Result<(), ContextError> {
   242          let state_entries: Vec<TpStateEntry> = entries
   243              .iter()
   244              .map(|(address, payload)| {
   245                  let mut entry = TpStateEntry::new();
   246                  entry.set_address(address.to_string());
   247                  entry.set_data(payload.to_vec());
   248                  entry
   249              })
   250              .collect();
   251  
   252          let mut request = TpStateSetRequest::new();
   253          request.set_context_id(self.context_id.clone());
   254          request.set_entries(RepeatedField::from_vec(state_entries.to_vec()));
   255          let serialized = request.write_to_bytes()?;
   256          let x: &[u8] = &serialized;
   257  
   258          let mut future = self.sender.send(
   259              Message_MessageType::TP_STATE_SET_REQUEST,
   260              &generate_correlation_id(),
   261              x,
   262          )?;
   263  
   264          let response: TpStateSetResponse = protobuf::parse_from_bytes(future.get()?.get_content())?;
   265          match response.get_status() {
   266              TpStateSetResponse_Status::OK => Ok(()),
   267              TpStateSetResponse_Status::AUTHORIZATION_ERROR => {
   268                  Err(ContextError::AuthorizationError(format!(
   269                      "Tried to set unauthorized address: {:?}",
   270                      state_entries
   271                  )))
   272              }
   273              TpStateSetResponse_Status::STATUS_UNSET => Err(ContextError::ResponseAttributeError(
   274                  String::from("Status was not set for TpStateSetResponse"),
   275              )),
   276          }
   277      }
   278  
   279      /// delete_state requests that each of the provided addresses be unset
   280      /// in validator state. A list of successfully deleted addresses
   281      ///  is returned.
   282      ///
   283      /// # Arguments
   284      ///
   285      /// * `addresses` - the addresses to fetch
   286      pub fn delete_state(
   287          &mut self,
   288          addresses: Vec<String>,
   289      ) -> Result<Option<Vec<String>>, ContextError> {
   290          let mut request = TpStateDeleteRequest::new();
   291          request.set_context_id(self.context_id.clone());
   292          request.set_addresses(RepeatedField::from_vec(addresses.clone()));
   293  
   294          let serialized = request.write_to_bytes()?;
   295          let x: &[u8] = &serialized;
   296  
   297          let mut future = self.sender.send(
   298              Message_MessageType::TP_STATE_DELETE_REQUEST,
   299              &generate_correlation_id(),
   300              x,
   301          )?;
   302  
   303          let response: TpStateDeleteResponse =
   304              protobuf::parse_from_bytes(future.get()?.get_content())?;
   305          match response.get_status() {
   306              TpStateDeleteResponse_Status::OK => Ok(Some(Vec::from(response.get_addresses()))),
   307              TpStateDeleteResponse_Status::AUTHORIZATION_ERROR => {
   308                  Err(ContextError::AuthorizationError(format!(
   309                      "Tried to delete unauthorized address: {:?}",
   310                      addresses
   311                  )))
   312              }
   313              TpStateDeleteResponse_Status::STATUS_UNSET => {
   314                  Err(ContextError::ResponseAttributeError(String::from(
   315                      "Status was not set for TpStateDeleteResponse",
   316                  )))
   317              }
   318          }
   319      }
   320  
   321      /// add_receipt_data adds a blob to the execution result for this transaction
   322      ///
   323      /// # Arguments
   324      ///
   325      /// * `data` - the data to add
   326      pub fn add_receipt_data(&mut self, data: &[u8]) -> Result<(), ContextError> {
   327          let mut request = TpReceiptAddDataRequest::new();
   328          request.set_context_id(self.context_id.clone());
   329          request.set_data(Vec::from(data));
   330  
   331          let serialized = request.write_to_bytes()?;
   332          let x: &[u8] = &serialized;
   333  
   334          let mut future = self.sender.send(
   335              Message_MessageType::TP_RECEIPT_ADD_DATA_REQUEST,
   336              &generate_correlation_id(),
   337              x,
   338          )?;
   339  
   340          let response: TpReceiptAddDataResponse =
   341              protobuf::parse_from_bytes(future.get()?.get_content())?;
   342          match response.get_status() {
   343              TpReceiptAddDataResponse_Status::OK => Ok(()),
   344              TpReceiptAddDataResponse_Status::ERROR => Err(ContextError::TransactionReceiptError(
   345                  format!("Failed to add receipt data {:?}", data),
   346              )),
   347              TpReceiptAddDataResponse_Status::STATUS_UNSET => {
   348                  Err(ContextError::ResponseAttributeError(String::from(
   349                      "Status was not set for TpReceiptAddDataResponse",
   350                  )))
   351              }
   352          }
   353      }
   354  
   355      /// add_event adds a new event to the execution result for this transaction.
   356      ///
   357      /// # Arguments
   358      ///
   359      /// * `event_type` -  This is used to subscribe to events. It should be globally unique and
   360      ///         describe what, in general, has occured.
   361      /// * `attributes` - Additional information about the event that is transparent to the
   362      ///          validator. Attributes can be used by subscribers to filter the type of events
   363      ///          they receive.
   364      /// * `data` - Additional information about the event that is opaque to the validator.
   365      pub fn add_event(
   366          &mut self,
   367          event_type: String,
   368          attributes: Vec<(String, String)>,
   369          data: &[u8],
   370      ) -> Result<(), ContextError> {
   371          let mut event = Event::new();
   372          event.set_event_type(event_type);
   373  
   374          let mut attributes_vec = Vec::new();
   375          for (key, value) in attributes {
   376              let mut attribute = Event_Attribute::new();
   377              attribute.set_key(key);
   378              attribute.set_value(value);
   379              attributes_vec.push(attribute);
   380          }
   381          event.set_attributes(RepeatedField::from_vec(attributes_vec));
   382          event.set_data(Vec::from(data));
   383  
   384          let mut request = TpEventAddRequest::new();
   385          request.set_context_id(self.context_id.clone());
   386          request.set_event(event.clone());
   387  
   388          let serialized = request.write_to_bytes()?;
   389          let x: &[u8] = &serialized;
   390  
   391          let mut future = self.sender.send(
   392              Message_MessageType::TP_RECEIPT_ADD_DATA_REQUEST,
   393              &generate_correlation_id(),
   394              x,
   395          )?;
   396  
   397          let response: TpEventAddResponse = protobuf::parse_from_bytes(future.get()?.get_content())?;
   398          match response.get_status() {
   399              TpEventAddResponse_Status::OK => Ok(()),
   400              TpEventAddResponse_Status::ERROR => Err(ContextError::TransactionReceiptError(
   401                  format!("Failed to add event {:?}", event),
   402              )),
   403              TpEventAddResponse_Status::STATUS_UNSET => Err(ContextError::ResponseAttributeError(
   404                  String::from("Status was not set for TpEventAddRespons"),
   405              )),
   406          }
   407      }
   408  }
   409  
   410  pub trait TransactionHandler {
   411      /// TransactionHandler that defines the business logic for a new transaction family.
   412      /// The family_name, family_versions, and namespaces functions are
   413      /// used by the processor to route processing requests to the handler.
   414  
   415      /// family_name should return the name of the transaction family that this
   416      /// handler can process, e.g. "intkey"
   417      fn family_name(&self) -> String;
   418  
   419      /// family_versions should return a list of versions this transaction
   420      /// family handler can process, e.g. ["1.0"]
   421      fn family_versions(&self) -> Vec<String>;
   422  
   423      /// namespaces should return a list containing all the handler's
   424      /// namespaces, e.g. ["abcdef"]
   425      fn namespaces(&self) -> Vec<String>;
   426  
   427      /// Apply is the single method where all the business logic for a
   428      /// transaction family is defined. The method will be called by the
   429      /// transaction processor upon receiving a TpProcessRequest that the
   430      /// handler understands and will pass in the TpProcessRequest and an
   431      /// initialized instance of the Context type.
   432      fn apply(
   433          &self,
   434          request: &TpProcessRequest,
   435          context: &mut TransactionContext,
   436      ) -> Result<(), ApplyError>;
   437  }