github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/examples/intkey_rust/src/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  use cbor;
    19  
    20  use crypto::digest::Digest;
    21  use crypto::sha2::Sha512;
    22  
    23  use std::collections::BTreeMap;
    24  use std::collections::HashMap;
    25  use std::fmt;
    26  use std::io::Cursor;
    27  
    28  use cbor::encoder::GenericEncoder;
    29  use cbor::value::Key;
    30  use cbor::value::Text;
    31  use cbor::value::Value;
    32  
    33  use sawtooth_sdk::messages::processor::TpProcessRequest;
    34  use sawtooth_sdk::processor::handler::ApplyError;
    35  use sawtooth_sdk::processor::handler::TransactionContext;
    36  use sawtooth_sdk::processor::handler::TransactionHandler;
    37  
    38  const MAX_VALUE: u32 = 4_294_967_295;
    39  const MAX_NAME_LEN: usize = 20;
    40  
    41  #[derive(Copy, Clone)]
    42  enum Verb {
    43      Set,
    44      Increment,
    45      Decrement,
    46  }
    47  
    48  impl fmt::Display for Verb {
    49      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    50          write!(
    51              f,
    52              "{}",
    53              match *self {
    54                  Verb::Set => "Verb::Set",
    55                  Verb::Increment => "Verb::Increment",
    56                  Verb::Decrement => "Verb::Decrement",
    57              }
    58          )
    59      }
    60  }
    61  
    62  fn get_intkey_prefix() -> String {
    63      let mut sha = Sha512::new();
    64      sha.input_str("intkey");
    65      sha.result_str()[..6].to_string()
    66  }
    67  
    68  struct IntkeyPayload {
    69      verb: Verb,
    70      name: String,
    71      value: u32,
    72  }
    73  
    74  impl IntkeyPayload {
    75      pub fn new(payload_data: &[u8]) -> Result<Option<IntkeyPayload>, ApplyError> {
    76          let input = Cursor::new(payload_data);
    77  
    78          let mut decoder = cbor::GenericDecoder::new(cbor::Config::default(), input);
    79          let decoder_value = decoder
    80              .value()
    81              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
    82  
    83          let c = cbor::value::Cursor::new(&decoder_value);
    84  
    85          let verb_raw: String = match c.field("Verb").text_plain() {
    86              None => {
    87                  return Err(ApplyError::InvalidTransaction(String::from(
    88                      "Verb must be 'set', 'inc', or 'dec'",
    89                  )))
    90              }
    91              Some(verb_raw) => verb_raw.clone(),
    92          };
    93  
    94          let verb = match verb_raw.as_str() {
    95              "set" => Verb::Set,
    96              "inc" => Verb::Increment,
    97              "dec" => Verb::Decrement,
    98              _ => {
    99                  return Err(ApplyError::InvalidTransaction(String::from(
   100                      "Verb must be 'set', 'inc', or 'dec'",
   101                  )))
   102              }
   103          };
   104  
   105          let value_raw = c.field("Value");
   106          let value_raw = match value_raw.value() {
   107              Some(x) => x,
   108              None => {
   109                  return Err(ApplyError::InvalidTransaction(String::from(
   110                      "Must have a value",
   111                  )))
   112              }
   113          };
   114  
   115          let value: u32 = match *value_raw {
   116              cbor::value::Value::U8(x) => u32::from(x),
   117              cbor::value::Value::U16(x) => u32::from(x),
   118              cbor::value::Value::U32(x) => x,
   119              _ => {
   120                  return Err(ApplyError::InvalidTransaction(String::from(
   121                      "Value must be an integer",
   122                  )))
   123              }
   124          };
   125  
   126          let name_raw: String = match c.field("Name").text_plain() {
   127              None => {
   128                  return Err(ApplyError::InvalidTransaction(String::from(
   129                      "Name must be a string",
   130                  )))
   131              }
   132              Some(name_raw) => name_raw.clone(),
   133          };
   134  
   135          if name_raw.len() > MAX_NAME_LEN {
   136              return Err(ApplyError::InvalidTransaction(String::from(
   137                  "Name must be equal to or less than 20 characters",
   138              )));
   139          }
   140  
   141          let intkey_payload = IntkeyPayload {
   142              verb: verb,
   143              name: name_raw,
   144              value: value,
   145          };
   146          Ok(Some(intkey_payload))
   147      }
   148  
   149      pub fn get_verb(&self) -> Verb {
   150          self.verb
   151      }
   152  
   153      pub fn get_name(&self) -> &String {
   154          &self.name
   155      }
   156  
   157      pub fn get_value(&self) -> u32 {
   158          self.value
   159      }
   160  }
   161  
   162  pub struct IntkeyState<'a> {
   163      context: &'a mut TransactionContext,
   164      get_cache: HashMap<String, BTreeMap<Key, Value>>,
   165  }
   166  
   167  impl<'a> IntkeyState<'a> {
   168      pub fn new(context: &'a mut TransactionContext) -> IntkeyState {
   169          IntkeyState {
   170              context: context,
   171              get_cache: HashMap::new(),
   172          }
   173      }
   174  
   175      fn calculate_address(name: &str) -> String {
   176          let mut sha = Sha512::new();
   177          sha.input(name.as_bytes());
   178          get_intkey_prefix() + &sha.result_str()[64..].to_string()
   179      }
   180  
   181      pub fn get(&mut self, name: &str) -> Result<Option<u32>, ApplyError> {
   182          let address = IntkeyState::calculate_address(name);
   183          let d = self.context.get_state(vec![address.clone()])?;
   184          match d {
   185              Some(packed) => {
   186                  let input = Cursor::new(packed);
   187                  let mut decoder = cbor::GenericDecoder::new(cbor::Config::default(), input);
   188                  let map_value = decoder
   189                      .value()
   190                      .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   191                  let mut map = match map_value {
   192                      Value::Map(m) => m,
   193                      _ => {
   194                          return Err(ApplyError::InternalError(String::from(
   195                              "No map returned from state",
   196                          )))
   197                      }
   198                  };
   199  
   200                  let status = match map.get(&Key::Text(Text::Text(String::from(name)))) {
   201                      Some(v) => match *v {
   202                          Value::U32(x) => Ok(Some(x)),
   203                          Value::U16(x) => Ok(Some(u32::from(x))),
   204                          Value::U8(x) => Ok(Some(u32::from(x))),
   205                          _ => Err(ApplyError::InternalError(String::from(
   206                              "Value returned from state is the wrong type.",
   207                          ))),
   208                      },
   209                      None => Ok(None),
   210                  };
   211                  self.get_cache.insert(address.clone(), map.clone());
   212                  status
   213              }
   214              None => Ok(None),
   215          }
   216      }
   217  
   218      pub fn set(&mut self, name: &str, value: u32) -> Result<(), ApplyError> {
   219          let mut map: BTreeMap<Key, Value> = match self.get_cache
   220              .get_mut(&IntkeyState::calculate_address(name))
   221          {
   222              Some(m) => m.clone(),
   223              None => BTreeMap::new(),
   224          };
   225          map.insert(Key::Text(Text::Text(String::from(name))), Value::U32(value));
   226  
   227          let mut e = GenericEncoder::new(Cursor::new(Vec::new()));
   228          e.value(&Value::Map(map))
   229              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   230  
   231          let packed = e.into_inner().into_writer().into_inner();
   232          let mut sets = HashMap::new();
   233          sets.insert(IntkeyState::calculate_address(name), packed);
   234          self.context
   235              .set_state(sets)
   236              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   237  
   238          Ok(())
   239      }
   240  }
   241  
   242  pub struct IntkeyTransactionHandler {
   243      family_name: String,
   244      family_versions: Vec<String>,
   245      namespaces: Vec<String>,
   246  }
   247  
   248  impl IntkeyTransactionHandler {
   249      pub fn new() -> IntkeyTransactionHandler {
   250          IntkeyTransactionHandler {
   251              family_name: "intkey".to_string(),
   252              family_versions: vec!["1.0".to_string()],
   253              namespaces: vec![get_intkey_prefix().to_string()],
   254          }
   255      }
   256  }
   257  
   258  impl TransactionHandler for IntkeyTransactionHandler {
   259      fn family_name(&self) -> String {
   260          self.family_name.clone()
   261      }
   262  
   263      fn family_versions(&self) -> Vec<String> {
   264          self.family_versions.clone()
   265      }
   266  
   267      fn namespaces(&self) -> Vec<String> {
   268          self.namespaces.clone()
   269      }
   270  
   271      fn apply(
   272          &self,
   273          request: &TpProcessRequest,
   274          context: &mut TransactionContext,
   275      ) -> Result<(), ApplyError> {
   276          let payload = IntkeyPayload::new(request.get_payload());
   277          let payload = match payload {
   278              Err(e) => return Err(e),
   279              Ok(payload) => payload,
   280          };
   281          let payload = match payload {
   282              Some(x) => x,
   283              None => {
   284                  return Err(ApplyError::InvalidTransaction(String::from(
   285                      "Request must contain a payload",
   286                  )))
   287              }
   288          };
   289  
   290          let mut state = IntkeyState::new(context);
   291  
   292          info!(
   293              "payload: {} {} {} {} {}",
   294              payload.get_verb(),
   295              payload.get_name(),
   296              payload.get_value(),
   297              request.get_header().get_inputs()[0],
   298              request.get_header().get_outputs()[0]
   299          );
   300  
   301          match payload.get_verb() {
   302              Verb::Set => {
   303                  match state.get(payload.get_name()) {
   304                      Ok(Some(_)) => {
   305                          return Err(ApplyError::InvalidTransaction(format!(
   306                              "{} already set",
   307                              payload.get_name()
   308                          )))
   309                      }
   310                      Ok(None) => (),
   311                      Err(err) => return Err(err),
   312                  };
   313                  state.set(&payload.get_name(), payload.get_value())
   314              }
   315              Verb::Increment => {
   316                  let orig_value: u32 = match state.get(payload.get_name()) {
   317                      Ok(Some(v)) => v,
   318                      Ok(None) => {
   319                          return Err(ApplyError::InvalidTransaction(String::from(
   320                              "inc requires a set value",
   321                          )))
   322                      }
   323                      Err(err) => return Err(err),
   324                  };
   325                  let diff = MAX_VALUE - orig_value;
   326                  if diff < payload.get_value() {
   327                      return Err(ApplyError::InvalidTransaction(String::from(
   328                          "Value is too large to inc",
   329                      )));
   330                  };
   331  
   332                  state.set(&payload.get_name(), orig_value + payload.get_value())
   333              }
   334              Verb::Decrement => {
   335                  let orig_value: u32 = match state.get(payload.get_name()) {
   336                      Ok(Some(v)) => v,
   337                      Ok(None) => {
   338                          return Err(ApplyError::InvalidTransaction(String::from(
   339                              "dec requires a set value",
   340                          )))
   341                      }
   342                      Err(err) => return Err(err),
   343                  };
   344                  if payload.get_value() > orig_value {
   345                      return Err(ApplyError::InvalidTransaction(String::from(
   346                          "Value is too large to dec",
   347                      )));
   348                  };
   349                  state.set(&payload.get_name(), orig_value - payload.get_value())
   350              }
   351          }
   352      }
   353  }