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 }