github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/src/state/identity_view.rs (about)

     1  /*
     2   * Copyright 2018 Intel Corporation
     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 std::iter::repeat;
    19  
    20  use crypto::digest::Digest;
    21  use crypto::sha2::Sha256;
    22  use protobuf;
    23  
    24  use proto::identity::Policy;
    25  use proto::identity::PolicyList;
    26  use proto::identity::Role;
    27  use proto::identity::RoleList;
    28  
    29  use state::StateDatabaseError;
    30  use state::StateReader;
    31  
    32  /// The namespace for storage
    33  const POLICY_NS: &str = "00001d00";
    34  const ROLE_NS: &str = "00001d01";
    35  const MAX_KEY_PARTS: usize = 4;
    36  
    37  #[derive(Debug)]
    38  pub enum IdentityViewError {
    39      StateDatabaseError(StateDatabaseError),
    40      EncodingError(protobuf::ProtobufError),
    41  
    42      UnknownError,
    43  }
    44  
    45  impl From<StateDatabaseError> for IdentityViewError {
    46      fn from(err: StateDatabaseError) -> Self {
    47          IdentityViewError::StateDatabaseError(err)
    48      }
    49  }
    50  
    51  impl From<protobuf::ProtobufError> for IdentityViewError {
    52      fn from(err: protobuf::ProtobufError) -> Self {
    53          IdentityViewError::EncodingError(err)
    54      }
    55  }
    56  
    57  /// Provides a view into global state which translates Role and Policy names
    58  /// into the corresponding addresses, and returns the deserialized values from
    59  /// state.
    60  pub struct IdentityView<R>
    61  where
    62      R: StateReader,
    63  {
    64      state_reader: R,
    65  }
    66  
    67  impl<R> IdentityView<R>
    68  where
    69      R: StateReader,
    70  {
    71      /// Creates an IdentityView from a given StateReader.
    72      pub fn new(state_reader: R) -> Self {
    73          IdentityView { state_reader }
    74      }
    75  
    76      /// Returns a single Role by name, if it exists.
    77      pub fn get_role(&self, name: &str) -> Result<Option<Role>, IdentityViewError> {
    78          self.get_identity_value::<Role, RoleList>(name, &role_address(name))
    79      }
    80  
    81      /// Returns all of the Roles under the Identity namespace
    82      pub fn get_roles(&self) -> Result<Vec<Role>, IdentityViewError> {
    83          self.get_identity_value_list::<Role, RoleList>(ROLE_NS)
    84      }
    85  
    86      /// Returns a single Policy by name, if it exists.
    87      pub fn get_policy(&self, name: &str) -> Result<Option<Policy>, IdentityViewError> {
    88          self.get_identity_value::<Policy, PolicyList>(name, &policy_address(name))
    89      }
    90  
    91      /// Returns all of the Policies under the Identity namespace
    92      pub fn get_policies(&self) -> Result<Vec<Policy>, IdentityViewError> {
    93          self.get_identity_value_list::<Policy, PolicyList>(POLICY_NS)
    94      }
    95  
    96      fn get_identity_value<I, L>(
    97          &self,
    98          name: &str,
    99          address: &str,
   100      ) -> Result<Option<I>, IdentityViewError>
   101      where
   102          I: Named,
   103          L: ProtobufList<I>,
   104      {
   105          if !self.state_reader.contains(&address)? {
   106              return Ok(None);
   107          }
   108  
   109          self.state_reader
   110              .get(&address)
   111              .map_err(IdentityViewError::StateDatabaseError)
   112              .and_then(|bytes_opt| {
   113                  Ok(if let Some(bytes) = bytes_opt {
   114                      Some(protobuf::parse_from_bytes::<L>(&bytes)?)
   115                  } else {
   116                      None
   117                  })
   118              })
   119              .and_then(|list_opt| {
   120                  if let Some(list) = list_opt {
   121                      for item in list.values() {
   122                          if item.name() == name {
   123                              return Ok(Some(item.clone()));
   124                          }
   125                      }
   126                  }
   127                  // We didn't find the item, so return None
   128                  Ok(None)
   129              })
   130      }
   131  
   132      fn get_identity_value_list<I, L>(&self, prefix: &str) -> Result<Vec<I>, IdentityViewError>
   133      where
   134          I: Named,
   135          L: ProtobufList<I>,
   136      {
   137          let mut res = Vec::new();
   138          for state_value in self.state_reader.leaves(Some(prefix))? {
   139              let (_, bytes) = state_value?;
   140              let item_list = protobuf::parse_from_bytes::<L>(&bytes)?;
   141              for item in item_list.values() {
   142                  res.push(item.clone());
   143              }
   144          }
   145          res.sort_by(|a, b| a.name().cmp(b.name()));
   146          Ok(res)
   147      }
   148  }
   149  
   150  trait ProtobufList<T>: protobuf::Message {
   151      fn values(&self) -> &[T];
   152  }
   153  
   154  impl ProtobufList<Role> for RoleList {
   155      fn values(&self) -> &[Role] {
   156          self.get_roles()
   157      }
   158  }
   159  
   160  impl ProtobufList<Policy> for PolicyList {
   161      fn values(&self) -> &[Policy] {
   162          self.get_policies()
   163      }
   164  }
   165  
   166  trait Named: Clone {
   167      fn name(&self) -> &str;
   168  }
   169  
   170  impl Named for Role {
   171      fn name(&self) -> &str {
   172          self.get_name()
   173      }
   174  }
   175  
   176  impl Named for Policy {
   177      fn name(&self) -> &str {
   178          self.get_name()
   179      }
   180  }
   181  
   182  fn role_address(name: &str) -> String {
   183      let mut address = String::new();
   184      address.push_str(ROLE_NS);
   185      address.push_str(&name.splitn(MAX_KEY_PARTS, ".")
   186          .chain(repeat(""))
   187          .enumerate()
   188          .map(|(i, part)| short_hash(part, if i == 0 { 14 } else { 16 }))
   189          .take(MAX_KEY_PARTS)
   190          .collect::<Vec<_>>()
   191          .join(""));
   192  
   193      address
   194  }
   195  
   196  fn policy_address(name: &str) -> String {
   197      let mut address = String::new();
   198      address.push_str(POLICY_NS);
   199      address.push_str(&short_hash(name, 62));
   200      address
   201  }
   202  
   203  fn short_hash(s: &str, length: usize) -> String {
   204      let mut sha = Sha256::new();
   205      sha.input(s.as_bytes());
   206      sha.result_str()[..length].to_string()
   207  }
   208  
   209  #[cfg(test)]
   210  mod tests {
   211      use super::*;
   212      use proto::identity::Policy;
   213      use proto::identity::PolicyList;
   214      use proto::identity::Policy_Entry;
   215      use proto::identity::Policy_EntryType;
   216      use proto::identity::Role;
   217      use proto::identity::RoleList;
   218  
   219      use protobuf;
   220      use protobuf::Message;
   221      use state::StateDatabaseError;
   222      use state::StateReader;
   223      use std::collections::HashMap;
   224  
   225      #[test]
   226      fn addressing() {
   227          // These addresses were generated using the legacy python code
   228          assert_eq!(
   229              "00001d01e0d7826133ad07e3b0c44298fc1c14e3b0c44298fc1c14e3b0c44298fc1c14",
   230              &role_address("MY_ROLE")
   231          );
   232          assert_eq!(
   233              "00001d00237e86847d59b61cd902a533a1c9701327ed992dfe7ec1996ffc84bc8f0b4e",
   234              &policy_address("MY_POLICY")
   235          );
   236      }
   237  
   238      #[test]
   239      fn no_roles() {
   240          let mock_reader = MockStateReader::new(vec![]);
   241          let identity_view = IdentityView::new(mock_reader);
   242  
   243          assert_eq!(None, identity_view.get_role("my_role").unwrap());
   244          let expect_empty: Vec<Role> = vec![];
   245          assert_eq!(expect_empty, identity_view.get_roles().unwrap());
   246      }
   247  
   248      #[test]
   249      fn get_role_by_name() {
   250          let mock_reader = MockStateReader::new(vec![
   251              role_entry("role1", "some_policy"),
   252              role_entry("role2", "some_other_policy"),
   253          ]);
   254          let identity_view = IdentityView::new(mock_reader);
   255  
   256          assert_eq!(
   257              Some(role("role2", "some_other_policy")),
   258              identity_view.get_role("role2").unwrap()
   259          );
   260      }
   261  
   262      #[test]
   263      fn get_roles() {
   264          let mock_reader = MockStateReader::new(vec![
   265              role_entry("role1", "some_policy"),
   266              role_entry("role2", "some_other_policy"),
   267          ]);
   268          let identity_view = IdentityView::new(mock_reader);
   269  
   270          assert_eq!(
   271              vec![
   272                  role("role1", "some_policy"),
   273                  role("role2", "some_other_policy"),
   274              ],
   275              identity_view.get_roles().unwrap()
   276          );
   277      }
   278  
   279      #[test]
   280      fn no_policies() {
   281          let mock_reader = MockStateReader::new(vec![]);
   282          let identity_view = IdentityView::new(mock_reader);
   283  
   284          assert_eq!(None, identity_view.get_policy("my_policy").unwrap());
   285          let expect_empty: Vec<Policy> = vec![];
   286          assert_eq!(expect_empty, identity_view.get_policies().unwrap());
   287      }
   288  
   289      #[test]
   290      fn get_policy_by_name() {
   291          let mock_reader = MockStateReader::new(vec![
   292              policy_entry("policy1", &["some_pubkey"]),
   293              policy_entry("policy2", &["some_other_pubkey"]),
   294          ]);
   295          let identity_view = IdentityView::new(mock_reader);
   296  
   297          assert_eq!(
   298              Some(policy("policy2", &["some_other_pubkey"])),
   299              identity_view.get_policy("policy2").unwrap()
   300          );
   301      }
   302  
   303      #[test]
   304      fn get_policies() {
   305          let mock_reader = MockStateReader::new(vec![
   306              policy_entry("policy1", &["some_pubkey"]),
   307              policy_entry("policy2", &["some_other_pubkey"]),
   308          ]);
   309          let identity_view = IdentityView::new(mock_reader);
   310  
   311          assert_eq!(
   312              vec![
   313                  policy("policy1", &["some_pubkey"]),
   314                  policy("policy2", &["some_other_pubkey"]),
   315              ],
   316              identity_view.get_policies().unwrap()
   317          );
   318      }
   319  
   320      fn role(name: &str, policy_name: &str) -> Role {
   321          let mut role = Role::new();
   322          role.set_name(name.to_string());
   323          role.set_policy_name(policy_name.to_string());
   324  
   325          role
   326      }
   327  
   328      fn role_entry(name: &str, policy_name: &str) -> (String, Vec<u8>) {
   329          let role = role(name, policy_name);
   330          let mut role_list = RoleList::new();
   331          role_list.set_roles(protobuf::RepeatedField::from_slice(&[role]));
   332  
   333          (
   334              role_address(name),
   335              role_list
   336                  .write_to_bytes()
   337                  .expect("Unable to serialize role"),
   338          )
   339      }
   340  
   341      fn policy(name: &str, permits: &[&str]) -> Policy {
   342          let mut policy = Policy::new();
   343  
   344          policy.set_name(name.to_string());
   345          policy.set_entries(protobuf::RepeatedField::from_vec(
   346              permits
   347                  .iter()
   348                  .map(|key| {
   349                      let mut entry = Policy_Entry::new();
   350                      entry.set_field_type(Policy_EntryType::PERMIT_KEY);
   351                      entry.set_key(key.to_string());
   352                      entry
   353                  })
   354                  .collect(),
   355          ));
   356  
   357          policy
   358      }
   359  
   360      fn policy_entry(name: &str, permits: &[&str]) -> (String, Vec<u8>) {
   361          let policy = policy(name, permits);
   362          let mut policy_list = PolicyList::new();
   363          policy_list.set_policies(protobuf::RepeatedField::from_slice(&[policy]));
   364  
   365          (
   366              policy_address(name),
   367              policy_list
   368                  .write_to_bytes()
   369                  .expect("Unable to serialize policy"),
   370          )
   371      }
   372  
   373      struct MockStateReader {
   374          state: HashMap<String, Vec<u8>>,
   375      }
   376  
   377      impl MockStateReader {
   378          fn new(values: Vec<(String, Vec<u8>)>) -> Self {
   379              MockStateReader {
   380                  state: values.into_iter().collect(),
   381              }
   382          }
   383      }
   384  
   385      impl StateReader for MockStateReader {
   386          fn get(&self, address: &str) -> Result<Option<Vec<u8>>, StateDatabaseError> {
   387              Ok(self.state.get(address).cloned())
   388          }
   389  
   390          fn contains(&self, address: &str) -> Result<bool, StateDatabaseError> {
   391              Ok(self.state.contains_key(address))
   392          }
   393  
   394          fn leaves(
   395              &self,
   396              prefix: Option<&str>,
   397          ) -> Result<
   398              Box<Iterator<Item = Result<(String, Vec<u8>), StateDatabaseError>>>,
   399              StateDatabaseError,
   400          > {
   401              let iterable: Vec<_> = self.state
   402                  .iter()
   403                  .filter(|(key, _)| key.starts_with(prefix.unwrap_or("")))
   404                  .map(|(key, value)| Ok((key.clone().to_string(), value.clone())))
   405                  .collect();
   406  
   407              Ok(Box::new(iterable.into_iter()))
   408          }
   409      }
   410  }