1use alloc::{
4 format,
5 string::{String, ToString},
6 vec::Vec,
7};
8
9use core::{
10 convert::TryFrom,
11 fmt::{self, Debug, Display, Formatter},
12 str::FromStr,
13};
14
15use blake2::{
16 digest::{Update, VariableOutput},
17 VarBlake2b,
18};
19#[cfg(feature = "datasize")]
20use datasize::DataSize;
21use rand::{
22 distributions::{Distribution, Standard},
23 Rng,
24};
25use serde::{de::Error as SerdeError, Deserialize, Deserializer, Serialize, Serializer};
26
27use crate::{
28 account::{self, AccountHash, ACCOUNT_HASH_LENGTH},
29 bytesrepr::{self, Error, FromBytes, ToBytes, U64_SERIALIZED_LENGTH},
30 checksummed_hex,
31 contract_wasm::ContractWasmHash,
32 contracts::{ContractHash, ContractPackageHash},
33 uref::{self, URef, URefAddr, UREF_SERIALIZED_LENGTH},
34 DeployHash, EraId, Tagged, TransferAddr, TransferFromStrError, DEPLOY_HASH_LENGTH,
35 TRANSFER_ADDR_LENGTH, UREF_ADDR_LENGTH,
36};
37
38const HASH_PREFIX: &str = "hash-";
39const DEPLOY_INFO_PREFIX: &str = "deploy-";
40const ERA_INFO_PREFIX: &str = "era-";
41const BALANCE_PREFIX: &str = "balance-";
42const BID_PREFIX: &str = "bid-";
43const WITHDRAW_PREFIX: &str = "withdraw-";
44const DICTIONARY_PREFIX: &str = "dictionary-";
45const UNBOND_PREFIX: &str = "unbond-";
46const SYSTEM_CONTRACT_REGISTRY_PREFIX: &str = "system-contract-registry-";
47const ERA_SUMMARY_PREFIX: &str = "era-summary-";
48const CHAINSPEC_REGISTRY_PREFIX: &str = "chainspec-registry-";
49const CHECKSUM_REGISTRY_PREFIX: &str = "checksum-registry-";
50
51pub const BLAKE2B_DIGEST_LENGTH: usize = 32;
53pub const KEY_HASH_LENGTH: usize = 32;
55pub const KEY_TRANSFER_LENGTH: usize = TRANSFER_ADDR_LENGTH;
57pub const KEY_DEPLOY_INFO_LENGTH: usize = DEPLOY_HASH_LENGTH;
59pub const KEY_DICTIONARY_LENGTH: usize = 32;
61pub const DICTIONARY_ITEM_KEY_MAX_LENGTH: usize = 128;
63const PADDING_BYTES: [u8; 32] = [0u8; 32];
64const KEY_ID_SERIALIZED_LENGTH: usize = 1;
65const KEY_HASH_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
67const KEY_UREF_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + UREF_SERIALIZED_LENGTH;
68const KEY_TRANSFER_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_TRANSFER_LENGTH;
69const KEY_DEPLOY_INFO_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_DEPLOY_INFO_LENGTH;
70const KEY_ERA_INFO_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + U64_SERIALIZED_LENGTH;
71const KEY_BALANCE_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + UREF_ADDR_LENGTH;
72const KEY_BID_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
73const KEY_WITHDRAW_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
74const KEY_UNBOND_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
75const KEY_DICTIONARY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_DICTIONARY_LENGTH;
76const KEY_SYSTEM_CONTRACT_REGISTRY_SERIALIZED_LENGTH: usize =
77 KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
78const KEY_ERA_SUMMARY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
79const KEY_CHAINSPEC_REGISTRY_SERIALIZED_LENGTH: usize =
80 KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
81const KEY_CHECKSUM_REGISTRY_SERIALIZED_LENGTH: usize =
82 KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
83
84pub type HashAddr = [u8; KEY_HASH_LENGTH];
86
87pub type DictionaryAddr = [u8; KEY_DICTIONARY_LENGTH];
89
90#[allow(missing_docs)]
91#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
92#[repr(u8)]
93pub enum KeyTag {
94 Account = 0,
95 Hash = 1,
96 URef = 2,
97 Transfer = 3,
98 DeployInfo = 4,
99 EraInfo = 5,
100 Balance = 6,
101 Bid = 7,
102 Withdraw = 8,
103 Dictionary = 9,
104 SystemContractRegistry = 10,
105 EraSummary = 11,
106 Unbond = 12,
107 ChainspecRegistry = 13,
108 ChecksumRegistry = 14,
109}
110
111#[repr(C)]
114#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
115#[cfg_attr(feature = "datasize", derive(DataSize))]
116pub enum Key {
117 Account(AccountHash),
119 Hash(HashAddr),
122 URef(URef),
124 Transfer(TransferAddr),
126 DeployInfo(DeployHash),
128 EraInfo(EraId),
130 Balance(URefAddr),
132 Bid(AccountHash),
134 Withdraw(AccountHash),
136 Dictionary(DictionaryAddr),
138 SystemContractRegistry,
140 EraSummary,
142 Unbond(AccountHash),
144 ChainspecRegistry,
146 ChecksumRegistry,
148}
149
150#[derive(Debug)]
152#[non_exhaustive]
153pub enum FromStrError {
154 Account(account::FromStrError),
156 Hash(String),
158 URef(uref::FromStrError),
160 Transfer(TransferFromStrError),
162 DeployInfo(String),
164 EraInfo(String),
166 Balance(String),
168 Bid(String),
170 Withdraw(String),
172 Dictionary(String),
174 SystemContractRegistry(String),
176 EraSummary(String),
178 Unbond(String),
180 ChainspecRegistry(String),
182 ChecksumRegistry(String),
184 UnknownPrefix,
186}
187
188impl From<account::FromStrError> for FromStrError {
189 fn from(error: account::FromStrError) -> Self {
190 FromStrError::Account(error)
191 }
192}
193
194impl From<TransferFromStrError> for FromStrError {
195 fn from(error: TransferFromStrError) -> Self {
196 FromStrError::Transfer(error)
197 }
198}
199
200impl From<uref::FromStrError> for FromStrError {
201 fn from(error: uref::FromStrError) -> Self {
202 FromStrError::URef(error)
203 }
204}
205
206impl Display for FromStrError {
207 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
208 match self {
209 FromStrError::Account(error) => write!(f, "account-key from string error: {}", error),
210 FromStrError::Hash(error) => write!(f, "hash-key from string error: {}", error),
211 FromStrError::URef(error) => write!(f, "uref-key from string error: {}", error),
212 FromStrError::Transfer(error) => write!(f, "transfer-key from string error: {}", error),
213 FromStrError::DeployInfo(error) => {
214 write!(f, "deploy-info-key from string error: {}", error)
215 }
216 FromStrError::EraInfo(error) => write!(f, "era-info-key from string error: {}", error),
217 FromStrError::Balance(error) => write!(f, "balance-key from string error: {}", error),
218 FromStrError::Bid(error) => write!(f, "bid-key from string error: {}", error),
219 FromStrError::Withdraw(error) => write!(f, "withdraw-key from string error: {}", error),
220 FromStrError::Dictionary(error) => {
221 write!(f, "dictionary-key from string error: {}", error)
222 }
223 FromStrError::SystemContractRegistry(error) => {
224 write!(
225 f,
226 "system-contract-registry-key from string error: {}",
227 error
228 )
229 }
230 FromStrError::EraSummary(error) => {
231 write!(f, "era-summary-key from string error: {}", error)
232 }
233 FromStrError::Unbond(error) => {
234 write!(f, "unbond-key from string error: {}", error)
235 }
236 FromStrError::ChainspecRegistry(error) => {
237 write!(f, "chainspec-registry-key from string error: {}", error)
238 }
239 FromStrError::ChecksumRegistry(error) => {
240 write!(f, "checksum-registry-key from string error: {}", error)
241 }
242 FromStrError::UnknownPrefix => write!(f, "unknown prefix for key"),
243 }
244 }
245}
246
247impl Key {
248 #[doc(hidden)]
250 pub fn type_string(&self) -> String {
251 match self {
252 Key::Account(_) => String::from("Key::Account"),
253 Key::Hash(_) => String::from("Key::Hash"),
254 Key::URef(_) => String::from("Key::URef"),
255 Key::Transfer(_) => String::from("Key::Transfer"),
256 Key::DeployInfo(_) => String::from("Key::DeployInfo"),
257 Key::EraInfo(_) => String::from("Key::EraInfo"),
258 Key::Balance(_) => String::from("Key::Balance"),
259 Key::Bid(_) => String::from("Key::Bid"),
260 Key::Withdraw(_) => String::from("Key::Unbond"),
261 Key::Dictionary(_) => String::from("Key::Dictionary"),
262 Key::SystemContractRegistry => String::from("Key::SystemContractRegistry"),
263 Key::EraSummary => String::from("Key::EraSummary"),
264 Key::Unbond(_) => String::from("Key::Unbond"),
265 Key::ChainspecRegistry => String::from("Key::ChainspecRegistry"),
266 Key::ChecksumRegistry => String::from("Key::ChecksumRegistry"),
267 }
268 }
269
270 pub const fn max_serialized_length() -> usize {
272 KEY_UREF_SERIALIZED_LENGTH
273 }
274
275 #[must_use]
279 pub fn normalize(self) -> Key {
280 match self {
281 Key::URef(uref) => Key::URef(uref.remove_access_rights()),
282 other => other,
283 }
284 }
285
286 pub fn to_formatted_string(self) -> String {
288 match self {
289 Key::Account(account_hash) => account_hash.to_formatted_string(),
290 Key::Hash(addr) => format!("{}{}", HASH_PREFIX, base16::encode_lower(&addr)),
291 Key::URef(uref) => uref.to_formatted_string(),
292 Key::Transfer(transfer_addr) => transfer_addr.to_formatted_string(),
293 Key::DeployInfo(addr) => {
294 format!(
295 "{}{}",
296 DEPLOY_INFO_PREFIX,
297 base16::encode_lower(addr.as_bytes())
298 )
299 }
300 Key::EraInfo(era_id) => {
301 format!("{}{}", ERA_INFO_PREFIX, era_id.value())
302 }
303 Key::Balance(uref_addr) => {
304 format!("{}{}", BALANCE_PREFIX, base16::encode_lower(&uref_addr))
305 }
306 Key::Bid(account_hash) => {
307 format!("{}{}", BID_PREFIX, base16::encode_lower(&account_hash))
308 }
309 Key::Withdraw(account_hash) => {
310 format!("{}{}", WITHDRAW_PREFIX, base16::encode_lower(&account_hash))
311 }
312 Key::Dictionary(dictionary_addr) => {
313 format!(
314 "{}{}",
315 DICTIONARY_PREFIX,
316 base16::encode_lower(&dictionary_addr)
317 )
318 }
319 Key::SystemContractRegistry => {
320 format!(
321 "{}{}",
322 SYSTEM_CONTRACT_REGISTRY_PREFIX,
323 base16::encode_lower(&PADDING_BYTES)
324 )
325 }
326 Key::EraSummary => {
327 format!(
328 "{}{}",
329 ERA_SUMMARY_PREFIX,
330 base16::encode_lower(&PADDING_BYTES)
331 )
332 }
333 Key::Unbond(account_hash) => {
334 format!("{}{}", UNBOND_PREFIX, base16::encode_lower(&account_hash))
335 }
336 Key::ChainspecRegistry => {
337 format!(
338 "{}{}",
339 CHAINSPEC_REGISTRY_PREFIX,
340 base16::encode_lower(&PADDING_BYTES)
341 )
342 }
343 Key::ChecksumRegistry => {
344 format!(
345 "{}{}",
346 CHECKSUM_REGISTRY_PREFIX,
347 base16::encode_lower(&PADDING_BYTES)
348 )
349 }
350 }
351 }
352
353 pub fn from_formatted_str(input: &str) -> Result<Key, FromStrError> {
355 match AccountHash::from_formatted_str(input) {
356 Ok(account_hash) => return Ok(Key::Account(account_hash)),
357 Err(account::FromStrError::InvalidPrefix) => {}
358 Err(error) => return Err(error.into()),
359 }
360
361 if let Some(hex) = input.strip_prefix(HASH_PREFIX) {
362 let addr = checksummed_hex::decode(hex)
363 .map_err(|error| FromStrError::Hash(error.to_string()))?;
364 let hash_addr = HashAddr::try_from(addr.as_ref())
365 .map_err(|error| FromStrError::Hash(error.to_string()))?;
366 return Ok(Key::Hash(hash_addr));
367 }
368
369 if let Some(hex) = input.strip_prefix(DEPLOY_INFO_PREFIX) {
370 let hash = checksummed_hex::decode(hex)
371 .map_err(|error| FromStrError::DeployInfo(error.to_string()))?;
372 let hash_array = <[u8; DEPLOY_HASH_LENGTH]>::try_from(hash.as_ref())
373 .map_err(|error| FromStrError::DeployInfo(error.to_string()))?;
374 return Ok(Key::DeployInfo(DeployHash::new(hash_array)));
375 }
376
377 match TransferAddr::from_formatted_str(input) {
378 Ok(transfer_addr) => return Ok(Key::Transfer(transfer_addr)),
379 Err(TransferFromStrError::InvalidPrefix) => {}
380 Err(error) => return Err(error.into()),
381 }
382
383 match URef::from_formatted_str(input) {
384 Ok(uref) => return Ok(Key::URef(uref)),
385 Err(uref::FromStrError::InvalidPrefix) => {}
386 Err(error) => return Err(error.into()),
387 }
388
389 if let Some(era_summary_padding) = input.strip_prefix(ERA_SUMMARY_PREFIX) {
390 let padded_bytes = checksummed_hex::decode(era_summary_padding)
391 .map_err(|error| FromStrError::EraSummary(error.to_string()))?;
392 let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
393 FromStrError::EraSummary("Failed to deserialize era summary key".to_string())
394 })?;
395 return Ok(Key::EraSummary);
396 }
397
398 if let Some(era_id_str) = input.strip_prefix(ERA_INFO_PREFIX) {
399 let era_id = EraId::from_str(era_id_str)
400 .map_err(|error| FromStrError::EraInfo(error.to_string()))?;
401 return Ok(Key::EraInfo(era_id));
402 }
403
404 if let Some(hex) = input.strip_prefix(BALANCE_PREFIX) {
405 let addr = checksummed_hex::decode(hex)
406 .map_err(|error| FromStrError::Balance(error.to_string()))?;
407 let uref_addr = URefAddr::try_from(addr.as_ref())
408 .map_err(|error| FromStrError::Balance(error.to_string()))?;
409 return Ok(Key::Balance(uref_addr));
410 }
411
412 if let Some(hex) = input.strip_prefix(BID_PREFIX) {
413 let hash = checksummed_hex::decode(hex)
414 .map_err(|error| FromStrError::Bid(error.to_string()))?;
415 let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
416 .map_err(|error| FromStrError::Bid(error.to_string()))?;
417 return Ok(Key::Bid(AccountHash::new(account_hash)));
418 }
419
420 if let Some(hex) = input.strip_prefix(WITHDRAW_PREFIX) {
421 let hash = checksummed_hex::decode(hex)
422 .map_err(|error| FromStrError::Withdraw(error.to_string()))?;
423 let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
424 .map_err(|error| FromStrError::Withdraw(error.to_string()))?;
425 return Ok(Key::Withdraw(AccountHash::new(account_hash)));
426 }
427
428 if let Some(hex) = input.strip_prefix(UNBOND_PREFIX) {
429 let hash = checksummed_hex::decode(hex)
430 .map_err(|error| FromStrError::Unbond(error.to_string()))?;
431 let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
432 .map_err(|error| FromStrError::Unbond(error.to_string()))?;
433 return Ok(Key::Unbond(AccountHash::new(account_hash)));
434 }
435
436 if let Some(dictionary_addr) = input.strip_prefix(DICTIONARY_PREFIX) {
437 let dictionary_addr_bytes = checksummed_hex::decode(dictionary_addr)
438 .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
439 let addr = DictionaryAddr::try_from(dictionary_addr_bytes.as_ref())
440 .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
441 return Ok(Key::Dictionary(addr));
442 }
443
444 if let Some(registry_address) = input.strip_prefix(SYSTEM_CONTRACT_REGISTRY_PREFIX) {
445 let padded_bytes = checksummed_hex::decode(registry_address)
446 .map_err(|error| FromStrError::SystemContractRegistry(error.to_string()))?;
447 let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
448 FromStrError::SystemContractRegistry(
449 "Failed to deserialize system registry key".to_string(),
450 )
451 })?;
452 return Ok(Key::SystemContractRegistry);
453 }
454
455 if let Some(registry_address) = input.strip_prefix(CHAINSPEC_REGISTRY_PREFIX) {
456 let padded_bytes = checksummed_hex::decode(registry_address)
457 .map_err(|error| FromStrError::ChainspecRegistry(error.to_string()))?;
458 let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
459 FromStrError::ChainspecRegistry(
460 "Failed to deserialize chainspec registry key".to_string(),
461 )
462 })?;
463 return Ok(Key::ChainspecRegistry);
464 }
465
466 if let Some(registry_address) = input.strip_prefix(CHECKSUM_REGISTRY_PREFIX) {
467 let padded_bytes = checksummed_hex::decode(registry_address)
468 .map_err(|error| FromStrError::ChecksumRegistry(error.to_string()))?;
469 let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
470 FromStrError::ChecksumRegistry(
471 "Failed to deserialize checksum registry key".to_string(),
472 )
473 })?;
474 return Ok(Key::ChecksumRegistry);
475 }
476
477 Err(FromStrError::UnknownPrefix)
478 }
479
480 pub fn into_account(self) -> Option<AccountHash> {
483 match self {
484 Key::Account(bytes) => Some(bytes),
485 _ => None,
486 }
487 }
488
489 pub fn into_hash(self) -> Option<HashAddr> {
492 match self {
493 Key::Hash(hash) => Some(hash),
494 _ => None,
495 }
496 }
497
498 pub fn as_uref(&self) -> Option<&URef> {
501 match self {
502 Key::URef(uref) => Some(uref),
503 _ => None,
504 }
505 }
506
507 pub fn as_uref_mut(&mut self) -> Option<&mut URef> {
510 match self {
511 Key::URef(uref) => Some(uref),
512 _ => None,
513 }
514 }
515
516 pub fn as_balance(&self) -> Option<&URefAddr> {
519 if let Self::Balance(v) = self {
520 Some(v)
521 } else {
522 None
523 }
524 }
525
526 pub fn into_uref(self) -> Option<URef> {
528 match self {
529 Key::URef(uref) => Some(uref),
530 _ => None,
531 }
532 }
533
534 pub fn as_dictionary(&self) -> Option<&DictionaryAddr> {
537 match self {
538 Key::Dictionary(v) => Some(v),
539 _ => None,
540 }
541 }
542
543 pub fn uref_to_hash(&self) -> Option<Key> {
545 let uref = self.as_uref()?;
546 let addr = uref.addr();
547 Some(Key::Hash(addr))
548 }
549
550 pub fn withdraw_to_unbond(&self) -> Option<Key> {
552 if let Key::Withdraw(account_hash) = self {
553 return Some(Key::Unbond(*account_hash));
554 }
555 None
556 }
557
558 pub fn dictionary(seed_uref: URef, dictionary_item_key: &[u8]) -> Key {
561 let mut hasher = VarBlake2b::new(BLAKE2B_DIGEST_LENGTH).expect("should create hasher");
563 hasher.update(seed_uref.addr().as_ref());
564 hasher.update(dictionary_item_key);
565 let mut addr = HashAddr::default();
567 hasher.finalize_variable(|hash| addr.clone_from_slice(hash));
568 Key::Dictionary(addr)
569 }
570
571 pub fn is_dictionary_key(&self) -> bool {
573 if let Key::Dictionary(_) = self {
574 return true;
575 }
576 false
577 }
578
579 pub fn as_account(&self) -> Option<&AccountHash> {
581 if let Self::Account(v) = self {
582 Some(v)
583 } else {
584 None
585 }
586 }
587}
588
589impl Display for Key {
590 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
591 match self {
592 Key::Account(account_hash) => write!(f, "Key::Account({})", account_hash),
593 Key::Hash(addr) => write!(f, "Key::Hash({})", base16::encode_lower(&addr)),
594 Key::URef(uref) => write!(f, "Key::{}", uref), Key::Transfer(transfer_addr) => write!(f, "Key::Transfer({})", transfer_addr),
596 Key::DeployInfo(addr) => write!(
597 f,
598 "Key::DeployInfo({})",
599 base16::encode_lower(addr.as_bytes())
600 ),
601 Key::EraInfo(era_id) => write!(f, "Key::EraInfo({})", era_id),
602 Key::Balance(uref_addr) => {
603 write!(f, "Key::Balance({})", base16::encode_lower(uref_addr))
604 }
605 Key::Bid(account_hash) => write!(f, "Key::Bid({})", account_hash),
606 Key::Withdraw(account_hash) => write!(f, "Key::Withdraw({})", account_hash),
607 Key::Dictionary(addr) => {
608 write!(f, "Key::Dictionary({})", base16::encode_lower(addr))
609 }
610 Key::SystemContractRegistry => write!(
611 f,
612 "Key::SystemContractRegistry({})",
613 base16::encode_lower(&PADDING_BYTES)
614 ),
615 Key::EraSummary => write!(
616 f,
617 "Key::EraSummary({})",
618 base16::encode_lower(&PADDING_BYTES),
619 ),
620 Key::Unbond(account_hash) => write!(f, "Key::Unbond({})", account_hash),
621 Key::ChainspecRegistry => write!(
622 f,
623 "Key::ChainspecRegistry({})",
624 base16::encode_lower(&PADDING_BYTES)
625 ),
626 Key::ChecksumRegistry => {
627 write!(
628 f,
629 "Key::ChecksumRegistry({})",
630 base16::encode_lower(&PADDING_BYTES)
631 )
632 }
633 }
634 }
635}
636
637impl Debug for Key {
638 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
639 write!(f, "{}", self)
640 }
641}
642
643impl Tagged<KeyTag> for Key {
644 fn tag(&self) -> KeyTag {
645 match self {
646 Key::Account(_) => KeyTag::Account,
647 Key::Hash(_) => KeyTag::Hash,
648 Key::URef(_) => KeyTag::URef,
649 Key::Transfer(_) => KeyTag::Transfer,
650 Key::DeployInfo(_) => KeyTag::DeployInfo,
651 Key::EraInfo(_) => KeyTag::EraInfo,
652 Key::Balance(_) => KeyTag::Balance,
653 Key::Bid(_) => KeyTag::Bid,
654 Key::Withdraw(_) => KeyTag::Withdraw,
655 Key::Dictionary(_) => KeyTag::Dictionary,
656 Key::SystemContractRegistry => KeyTag::SystemContractRegistry,
657 Key::EraSummary => KeyTag::EraSummary,
658 Key::Unbond(_) => KeyTag::Unbond,
659 Key::ChainspecRegistry => KeyTag::ChainspecRegistry,
660 Key::ChecksumRegistry => KeyTag::ChecksumRegistry,
661 }
662 }
663}
664
665impl Tagged<u8> for Key {
666 fn tag(&self) -> u8 {
667 let key_tag: KeyTag = self.tag();
668 key_tag as u8
669 }
670}
671
672impl From<URef> for Key {
673 fn from(uref: URef) -> Key {
674 Key::URef(uref)
675 }
676}
677
678impl From<AccountHash> for Key {
679 fn from(account_hash: AccountHash) -> Key {
680 Key::Account(account_hash)
681 }
682}
683
684impl From<TransferAddr> for Key {
685 fn from(transfer_addr: TransferAddr) -> Key {
686 Key::Transfer(transfer_addr)
687 }
688}
689
690impl From<ContractHash> for Key {
691 fn from(contract_hash: ContractHash) -> Key {
692 Key::Hash(contract_hash.value())
693 }
694}
695
696impl From<ContractWasmHash> for Key {
697 fn from(wasm_hash: ContractWasmHash) -> Key {
698 Key::Hash(wasm_hash.value())
699 }
700}
701
702impl From<ContractPackageHash> for Key {
703 fn from(package_hash: ContractPackageHash) -> Key {
704 Key::Hash(package_hash.value())
705 }
706}
707
708impl ToBytes for Key {
709 fn to_bytes(&self) -> Result<Vec<u8>, Error> {
710 let mut result = bytesrepr::unchecked_allocate_buffer(self);
711 self.write_bytes(&mut result)?;
712 Ok(result)
713 }
714
715 fn serialized_length(&self) -> usize {
716 match self {
717 Key::Account(account_hash) => {
718 KEY_ID_SERIALIZED_LENGTH + account_hash.serialized_length()
719 }
720 Key::Hash(_) => KEY_HASH_SERIALIZED_LENGTH,
721 Key::URef(_) => KEY_UREF_SERIALIZED_LENGTH,
722 Key::Transfer(_) => KEY_TRANSFER_SERIALIZED_LENGTH,
723 Key::DeployInfo(_) => KEY_DEPLOY_INFO_SERIALIZED_LENGTH,
724 Key::EraInfo(_) => KEY_ERA_INFO_SERIALIZED_LENGTH,
725 Key::Balance(_) => KEY_BALANCE_SERIALIZED_LENGTH,
726 Key::Bid(_) => KEY_BID_SERIALIZED_LENGTH,
727 Key::Withdraw(_) => KEY_WITHDRAW_SERIALIZED_LENGTH,
728 Key::Dictionary(_) => KEY_DICTIONARY_SERIALIZED_LENGTH,
729 Key::SystemContractRegistry => KEY_SYSTEM_CONTRACT_REGISTRY_SERIALIZED_LENGTH,
730 Key::EraSummary => KEY_ERA_SUMMARY_SERIALIZED_LENGTH,
731 Key::Unbond(_) => KEY_UNBOND_SERIALIZED_LENGTH,
732 Key::ChainspecRegistry => KEY_CHAINSPEC_REGISTRY_SERIALIZED_LENGTH,
733 Key::ChecksumRegistry => KEY_CHECKSUM_REGISTRY_SERIALIZED_LENGTH,
734 }
735 }
736
737 fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), Error> {
738 writer.push(self.tag());
739 match self {
740 Key::Account(account_hash) => account_hash.write_bytes(writer),
741 Key::Hash(hash) => hash.write_bytes(writer),
742 Key::URef(uref) => uref.write_bytes(writer),
743 Key::Transfer(addr) => addr.write_bytes(writer),
744 Key::DeployInfo(deploy_hash) => deploy_hash.write_bytes(writer),
745 Key::EraInfo(era_id) => era_id.write_bytes(writer),
746 Key::Balance(uref_addr) => uref_addr.write_bytes(writer),
747 Key::Bid(account_hash) => account_hash.write_bytes(writer),
748 Key::Withdraw(account_hash) => account_hash.write_bytes(writer),
749 Key::Dictionary(addr) => addr.write_bytes(writer),
750 Key::Unbond(account_hash) => account_hash.write_bytes(writer),
751 Key::SystemContractRegistry
752 | Key::EraSummary
753 | Key::ChainspecRegistry
754 | Key::ChecksumRegistry => PADDING_BYTES.write_bytes(writer),
755 }
756 }
757}
758
759impl FromBytes for Key {
760 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error> {
761 let (tag, remainder) = u8::from_bytes(bytes)?;
762 match tag {
763 tag if tag == KeyTag::Account as u8 => {
764 let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
765 Ok((Key::Account(account_hash), rem))
766 }
767 tag if tag == KeyTag::Hash as u8 => {
768 let (hash, rem) = HashAddr::from_bytes(remainder)?;
769 Ok((Key::Hash(hash), rem))
770 }
771 tag if tag == KeyTag::URef as u8 => {
772 let (uref, rem) = URef::from_bytes(remainder)?;
773 Ok((Key::URef(uref), rem))
774 }
775 tag if tag == KeyTag::Transfer as u8 => {
776 let (transfer_addr, rem) = TransferAddr::from_bytes(remainder)?;
777 Ok((Key::Transfer(transfer_addr), rem))
778 }
779 tag if tag == KeyTag::DeployInfo as u8 => {
780 let (deploy_hash, rem) = DeployHash::from_bytes(remainder)?;
781 Ok((Key::DeployInfo(deploy_hash), rem))
782 }
783 tag if tag == KeyTag::EraInfo as u8 => {
784 let (era_id, rem) = EraId::from_bytes(remainder)?;
785 Ok((Key::EraInfo(era_id), rem))
786 }
787 tag if tag == KeyTag::Balance as u8 => {
788 let (uref_addr, rem) = URefAddr::from_bytes(remainder)?;
789 Ok((Key::Balance(uref_addr), rem))
790 }
791 tag if tag == KeyTag::Bid as u8 => {
792 let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
793 Ok((Key::Bid(account_hash), rem))
794 }
795 tag if tag == KeyTag::Withdraw as u8 => {
796 let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
797 Ok((Key::Withdraw(account_hash), rem))
798 }
799 tag if tag == KeyTag::Dictionary as u8 => {
800 let (addr, rem) = DictionaryAddr::from_bytes(remainder)?;
801 Ok((Key::Dictionary(addr), rem))
802 }
803 tag if tag == KeyTag::SystemContractRegistry as u8 => {
804 let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
805 Ok((Key::SystemContractRegistry, rem))
806 }
807 tag if tag == KeyTag::EraSummary as u8 => {
808 let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
809 Ok((Key::EraSummary, rem))
810 }
811 tag if tag == KeyTag::Unbond as u8 => {
812 let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
813 Ok((Key::Unbond(account_hash), rem))
814 }
815 tag if tag == KeyTag::ChainspecRegistry as u8 => {
816 let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
817 Ok((Key::ChainspecRegistry, rem))
818 }
819 tag if tag == KeyTag::ChecksumRegistry as u8 => {
820 let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
821 Ok((Key::ChecksumRegistry, rem))
822 }
823 _ => Err(Error::Formatting),
824 }
825 }
826}
827
828#[allow(dead_code)]
829fn please_add_to_distribution_impl(key: Key) {
830 match key {
833 Key::Account(_) => unimplemented!(),
834 Key::Hash(_) => unimplemented!(),
835 Key::URef(_) => unimplemented!(),
836 Key::Transfer(_) => unimplemented!(),
837 Key::DeployInfo(_) => unimplemented!(),
838 Key::EraInfo(_) => unimplemented!(),
839 Key::Balance(_) => unimplemented!(),
840 Key::Bid(_) => unimplemented!(),
841 Key::Withdraw(_) => unimplemented!(),
842 Key::Dictionary(_) => unimplemented!(),
843 Key::SystemContractRegistry => unimplemented!(),
844 Key::EraSummary => unimplemented!(),
845 Key::Unbond(_) => unimplemented!(),
846 Key::ChainspecRegistry => unimplemented!(),
847 Key::ChecksumRegistry => unimplemented!(),
848 }
849}
850
851impl Distribution<Key> for Standard {
852 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Key {
853 match rng.gen_range(0..=14) {
854 0 => Key::Account(rng.gen()),
855 1 => Key::Hash(rng.gen()),
856 2 => Key::URef(rng.gen()),
857 3 => Key::Transfer(rng.gen()),
858 4 => Key::DeployInfo(rng.gen()),
859 5 => Key::EraInfo(rng.gen()),
860 6 => Key::Balance(rng.gen()),
861 7 => Key::Bid(rng.gen()),
862 8 => Key::Withdraw(rng.gen()),
863 9 => Key::Dictionary(rng.gen()),
864 10 => Key::SystemContractRegistry,
865 11 => Key::EraSummary,
866 12 => Key::Unbond(rng.gen()),
867 13 => Key::ChainspecRegistry,
868 14 => Key::ChecksumRegistry,
869 _ => unreachable!(),
870 }
871 }
872}
873
874mod serde_helpers {
875 use super::*;
876
877 #[derive(Serialize, Deserialize)]
878 pub(super) enum HumanReadable {
879 Account(String),
880 Hash(String),
881 URef(String),
882 Transfer(String),
883 DeployInfo(String),
884 EraInfo(String),
885 Balance(String),
886 Bid(String),
887 Withdraw(String),
888 Dictionary(String),
889 SystemContractRegistry(String),
890 EraSummary(String),
891 Unbond(String),
892 ChainspecRegistry(String),
893 ChecksumRegistry(String),
894 }
895
896 impl From<&Key> for HumanReadable {
897 fn from(key: &Key) -> Self {
898 let formatted_string = key.to_formatted_string();
899 match key {
900 Key::Account(_) => HumanReadable::Account(formatted_string),
901 Key::Hash(_) => HumanReadable::Hash(formatted_string),
902 Key::URef(_) => HumanReadable::URef(formatted_string),
903 Key::Transfer(_) => HumanReadable::Transfer(formatted_string),
904 Key::DeployInfo(_) => HumanReadable::DeployInfo(formatted_string),
905 Key::EraInfo(_) => HumanReadable::EraInfo(formatted_string),
906 Key::Balance(_) => HumanReadable::Balance(formatted_string),
907 Key::Bid(_) => HumanReadable::Bid(formatted_string),
908 Key::Withdraw(_) => HumanReadable::Withdraw(formatted_string),
909 Key::Dictionary(_) => HumanReadable::Dictionary(formatted_string),
910 Key::SystemContractRegistry => {
911 HumanReadable::SystemContractRegistry(formatted_string)
912 }
913 Key::EraSummary => HumanReadable::EraSummary(formatted_string),
914 Key::Unbond(_) => HumanReadable::Unbond(formatted_string),
915 Key::ChainspecRegistry => HumanReadable::ChainspecRegistry(formatted_string),
916 Key::ChecksumRegistry => HumanReadable::ChecksumRegistry(formatted_string),
917 }
918 }
919 }
920
921 impl TryFrom<HumanReadable> for Key {
922 type Error = FromStrError;
923
924 fn try_from(helper: HumanReadable) -> Result<Self, Self::Error> {
925 match helper {
926 HumanReadable::Account(formatted_string)
927 | HumanReadable::Hash(formatted_string)
928 | HumanReadable::URef(formatted_string)
929 | HumanReadable::Transfer(formatted_string)
930 | HumanReadable::DeployInfo(formatted_string)
931 | HumanReadable::EraInfo(formatted_string)
932 | HumanReadable::Balance(formatted_string)
933 | HumanReadable::Bid(formatted_string)
934 | HumanReadable::Withdraw(formatted_string)
935 | HumanReadable::Dictionary(formatted_string)
936 | HumanReadable::SystemContractRegistry(formatted_string)
937 | HumanReadable::EraSummary(formatted_string)
938 | HumanReadable::Unbond(formatted_string)
939 | HumanReadable::ChainspecRegistry(formatted_string)
940 | HumanReadable::ChecksumRegistry(formatted_string) => {
941 Key::from_formatted_str(&formatted_string)
942 }
943 }
944 }
945 }
946
947 #[derive(Serialize)]
948 pub(super) enum BinarySerHelper<'a> {
949 Account(&'a AccountHash),
950 Hash(&'a HashAddr),
951 URef(&'a URef),
952 Transfer(&'a TransferAddr),
953 DeployInfo(&'a DeployHash),
954 EraInfo(&'a EraId),
955 Balance(&'a URefAddr),
956 Bid(&'a AccountHash),
957 Withdraw(&'a AccountHash),
958 Dictionary(&'a HashAddr),
959 SystemContractRegistry,
960 EraSummary,
961 Unbond(&'a AccountHash),
962 ChainspecRegistry,
963 ChecksumRegistry,
964 }
965
966 impl<'a> From<&'a Key> for BinarySerHelper<'a> {
967 fn from(key: &'a Key) -> Self {
968 match key {
969 Key::Account(account_hash) => BinarySerHelper::Account(account_hash),
970 Key::Hash(hash_addr) => BinarySerHelper::Hash(hash_addr),
971 Key::URef(uref) => BinarySerHelper::URef(uref),
972 Key::Transfer(transfer_addr) => BinarySerHelper::Transfer(transfer_addr),
973 Key::DeployInfo(deploy_hash) => BinarySerHelper::DeployInfo(deploy_hash),
974 Key::EraInfo(era_id) => BinarySerHelper::EraInfo(era_id),
975 Key::Balance(uref_addr) => BinarySerHelper::Balance(uref_addr),
976 Key::Bid(account_hash) => BinarySerHelper::Bid(account_hash),
977 Key::Withdraw(account_hash) => BinarySerHelper::Withdraw(account_hash),
978 Key::Dictionary(addr) => BinarySerHelper::Dictionary(addr),
979 Key::SystemContractRegistry => BinarySerHelper::SystemContractRegistry,
980 Key::EraSummary => BinarySerHelper::EraSummary,
981 Key::Unbond(account_hash) => BinarySerHelper::Unbond(account_hash),
982 Key::ChainspecRegistry => BinarySerHelper::ChainspecRegistry,
983 Key::ChecksumRegistry => BinarySerHelper::ChecksumRegistry,
984 }
985 }
986 }
987
988 #[derive(Deserialize)]
989 pub(super) enum BinaryDeserHelper {
990 Account(AccountHash),
991 Hash(HashAddr),
992 URef(URef),
993 Transfer(TransferAddr),
994 DeployInfo(DeployHash),
995 EraInfo(EraId),
996 Balance(URefAddr),
997 Bid(AccountHash),
998 Withdraw(AccountHash),
999 Dictionary(DictionaryAddr),
1000 SystemContractRegistry,
1001 EraSummary,
1002 Unbond(AccountHash),
1003 ChainspecRegistry,
1004 ChecksumRegistry,
1005 }
1006
1007 impl From<BinaryDeserHelper> for Key {
1008 fn from(helper: BinaryDeserHelper) -> Self {
1009 match helper {
1010 BinaryDeserHelper::Account(account_hash) => Key::Account(account_hash),
1011 BinaryDeserHelper::Hash(hash_addr) => Key::Hash(hash_addr),
1012 BinaryDeserHelper::URef(uref) => Key::URef(uref),
1013 BinaryDeserHelper::Transfer(transfer_addr) => Key::Transfer(transfer_addr),
1014 BinaryDeserHelper::DeployInfo(deploy_hash) => Key::DeployInfo(deploy_hash),
1015 BinaryDeserHelper::EraInfo(era_id) => Key::EraInfo(era_id),
1016 BinaryDeserHelper::Balance(uref_addr) => Key::Balance(uref_addr),
1017 BinaryDeserHelper::Bid(account_hash) => Key::Bid(account_hash),
1018 BinaryDeserHelper::Withdraw(account_hash) => Key::Withdraw(account_hash),
1019 BinaryDeserHelper::Dictionary(addr) => Key::Dictionary(addr),
1020 BinaryDeserHelper::SystemContractRegistry => Key::SystemContractRegistry,
1021 BinaryDeserHelper::EraSummary => Key::EraSummary,
1022 BinaryDeserHelper::Unbond(account_hash) => Key::Unbond(account_hash),
1023 BinaryDeserHelper::ChainspecRegistry => Key::ChainspecRegistry,
1024 BinaryDeserHelper::ChecksumRegistry => Key::ChecksumRegistry,
1025 }
1026 }
1027 }
1028}
1029
1030impl Serialize for Key {
1031 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1032 if serializer.is_human_readable() {
1033 serde_helpers::HumanReadable::from(self).serialize(serializer)
1034 } else {
1035 serde_helpers::BinarySerHelper::from(self).serialize(serializer)
1036 }
1037 }
1038}
1039
1040impl<'de> Deserialize<'de> for Key {
1041 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1042 if deserializer.is_human_readable() {
1043 let human_readable = serde_helpers::HumanReadable::deserialize(deserializer)?;
1044 Key::try_from(human_readable).map_err(SerdeError::custom)
1045 } else {
1046 let binary_helper = serde_helpers::BinaryDeserHelper::deserialize(deserializer)?;
1047 Ok(Key::from(binary_helper))
1048 }
1049 }
1050}
1051
1052#[cfg(test)]
1053mod tests {
1054 use std::string::ToString;
1055
1056 use serde_json::json;
1057
1058 use super::*;
1059 use crate::{
1060 account::ACCOUNT_HASH_FORMATTED_STRING_PREFIX,
1061 bytesrepr::{Error, FromBytes},
1062 transfer::TRANSFER_ADDR_FORMATTED_STRING_PREFIX,
1063 uref::UREF_FORMATTED_STRING_PREFIX,
1064 AccessRights, URef,
1065 };
1066
1067 const ACCOUNT_KEY: Key = Key::Account(AccountHash::new([42; 32]));
1068 const HASH_KEY: Key = Key::Hash([42; 32]);
1069 const UREF_KEY: Key = Key::URef(URef::new([42; 32], AccessRights::READ));
1070 const TRANSFER_KEY: Key = Key::Transfer(TransferAddr::new([42; 32]));
1071 const DEPLOY_INFO_KEY: Key = Key::DeployInfo(DeployHash::new([42; 32]));
1072 const ERA_INFO_KEY: Key = Key::EraInfo(EraId::new(42));
1073 const BALANCE_KEY: Key = Key::Balance([42; 32]);
1074 const BID_KEY: Key = Key::Bid(AccountHash::new([42; 32]));
1075 const WITHDRAW_KEY: Key = Key::Withdraw(AccountHash::new([42; 32]));
1076 const DICTIONARY_KEY: Key = Key::Dictionary([42; 32]);
1077 const SYSTEM_CONTRACT_REGISTRY_KEY: Key = Key::SystemContractRegistry;
1078 const ERA_SUMMARY_KEY: Key = Key::EraSummary;
1079 const UNBOND_KEY: Key = Key::Unbond(AccountHash::new([42; 32]));
1080 const CHAINSPEC_REGISTRY_KEY: Key = Key::ChainspecRegistry;
1081 const CHECKSUM_REGISTRY_KEY: Key = Key::ChecksumRegistry;
1082 const KEYS: &[Key] = &[
1083 ACCOUNT_KEY,
1084 HASH_KEY,
1085 UREF_KEY,
1086 TRANSFER_KEY,
1087 DEPLOY_INFO_KEY,
1088 ERA_INFO_KEY,
1089 BALANCE_KEY,
1090 BID_KEY,
1091 WITHDRAW_KEY,
1092 DICTIONARY_KEY,
1093 SYSTEM_CONTRACT_REGISTRY_KEY,
1094 ERA_SUMMARY_KEY,
1095 UNBOND_KEY,
1096 CHAINSPEC_REGISTRY_KEY,
1097 CHECKSUM_REGISTRY_KEY,
1098 ];
1099 const HEX_STRING: &str = "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a";
1100
1101 fn test_readable(right: AccessRights, is_true: bool) {
1102 assert_eq!(right.is_readable(), is_true)
1103 }
1104
1105 #[test]
1106 fn test_is_readable() {
1107 test_readable(AccessRights::READ, true);
1108 test_readable(AccessRights::READ_ADD, true);
1109 test_readable(AccessRights::READ_WRITE, true);
1110 test_readable(AccessRights::READ_ADD_WRITE, true);
1111 test_readable(AccessRights::ADD, false);
1112 test_readable(AccessRights::ADD_WRITE, false);
1113 test_readable(AccessRights::WRITE, false);
1114 }
1115
1116 fn test_writable(right: AccessRights, is_true: bool) {
1117 assert_eq!(right.is_writeable(), is_true)
1118 }
1119
1120 #[test]
1121 fn test_is_writable() {
1122 test_writable(AccessRights::WRITE, true);
1123 test_writable(AccessRights::READ_WRITE, true);
1124 test_writable(AccessRights::ADD_WRITE, true);
1125 test_writable(AccessRights::READ, false);
1126 test_writable(AccessRights::ADD, false);
1127 test_writable(AccessRights::READ_ADD, false);
1128 test_writable(AccessRights::READ_ADD_WRITE, true);
1129 }
1130
1131 fn test_addable(right: AccessRights, is_true: bool) {
1132 assert_eq!(right.is_addable(), is_true)
1133 }
1134
1135 #[test]
1136 fn test_is_addable() {
1137 test_addable(AccessRights::ADD, true);
1138 test_addable(AccessRights::READ_ADD, true);
1139 test_addable(AccessRights::READ_WRITE, false);
1140 test_addable(AccessRights::ADD_WRITE, true);
1141 test_addable(AccessRights::READ, false);
1142 test_addable(AccessRights::WRITE, false);
1143 test_addable(AccessRights::READ_ADD_WRITE, true);
1144 }
1145
1146 #[test]
1147 fn should_display_key() {
1148 assert_eq!(
1149 format!("{}", ACCOUNT_KEY),
1150 format!("Key::Account({})", HEX_STRING)
1151 );
1152 assert_eq!(
1153 format!("{}", HASH_KEY),
1154 format!("Key::Hash({})", HEX_STRING)
1155 );
1156 assert_eq!(
1157 format!("{}", UREF_KEY),
1158 format!("Key::URef({}, READ)", HEX_STRING)
1159 );
1160 assert_eq!(
1161 format!("{}", TRANSFER_KEY),
1162 format!("Key::Transfer({})", HEX_STRING)
1163 );
1164 assert_eq!(
1165 format!("{}", DEPLOY_INFO_KEY),
1166 format!("Key::DeployInfo({})", HEX_STRING)
1167 );
1168 assert_eq!(
1169 format!("{}", ERA_INFO_KEY),
1170 "Key::EraInfo(era 42)".to_string()
1171 );
1172 assert_eq!(
1173 format!("{}", BALANCE_KEY),
1174 format!("Key::Balance({})", HEX_STRING)
1175 );
1176 assert_eq!(format!("{}", BID_KEY), format!("Key::Bid({})", HEX_STRING));
1177 assert_eq!(
1178 format!("{}", WITHDRAW_KEY),
1179 format!("Key::Withdraw({})", HEX_STRING)
1180 );
1181 assert_eq!(
1182 format!("{}", DICTIONARY_KEY),
1183 format!("Key::Dictionary({})", HEX_STRING)
1184 );
1185 assert_eq!(
1186 format!("{}", SYSTEM_CONTRACT_REGISTRY_KEY),
1187 format!(
1188 "Key::SystemContractRegistry({})",
1189 base16::encode_lower(&PADDING_BYTES)
1190 )
1191 );
1192 assert_eq!(
1193 format!("{}", ERA_SUMMARY_KEY),
1194 format!("Key::EraSummary({})", base16::encode_lower(&PADDING_BYTES))
1195 );
1196 assert_eq!(
1197 format!("{}", UNBOND_KEY),
1198 format!("Key::Unbond({})", HEX_STRING)
1199 );
1200 assert_eq!(
1201 format!("{}", CHAINSPEC_REGISTRY_KEY),
1202 format!(
1203 "Key::ChainspecRegistry({})",
1204 base16::encode_lower(&PADDING_BYTES)
1205 )
1206 );
1207 assert_eq!(
1208 format!("{}", CHECKSUM_REGISTRY_KEY),
1209 format!(
1210 "Key::ChecksumRegistry({})",
1211 base16::encode_lower(&PADDING_BYTES),
1212 )
1213 );
1214 }
1215
1216 #[test]
1217 fn abuse_vec_key() {
1218 let bytes: Vec<u8> = vec![255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
1220 let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
1221 assert_eq!(
1222 res.expect_err("should fail"),
1223 Error::EarlyEndOfStream,
1224 "length prefix says 2^32-1, but there's not enough data in the stream"
1225 );
1226
1227 let bytes: Vec<u8> = vec![255, 255, 255, 254, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
1229 let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
1230 assert_eq!(
1231 res.expect_err("should fail"),
1232 Error::EarlyEndOfStream,
1233 "length prefix says 2^32-2, but there's not enough data in the stream"
1234 );
1235
1236 let bytes: Vec<u8> = vec![0, 0, 0, 254, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
1238 let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
1239 assert_eq!(
1240 res.expect_err("should fail"),
1241 Error::EarlyEndOfStream,
1242 "length prefix says 254, but there's not enough data in the stream"
1243 );
1244 }
1245
1246 #[test]
1247 fn check_key_account_getters() {
1248 let account = [42; 32];
1249 let account_hash = AccountHash::new(account);
1250 let key1 = Key::Account(account_hash);
1251 assert_eq!(key1.into_account(), Some(account_hash));
1252 assert!(key1.into_hash().is_none());
1253 assert!(key1.as_uref().is_none());
1254 }
1255
1256 #[test]
1257 fn check_key_hash_getters() {
1258 let hash = [42; KEY_HASH_LENGTH];
1259 let key1 = Key::Hash(hash);
1260 assert!(key1.into_account().is_none());
1261 assert_eq!(key1.into_hash(), Some(hash));
1262 assert!(key1.as_uref().is_none());
1263 }
1264
1265 #[test]
1266 fn check_key_uref_getters() {
1267 let uref = URef::new([42; 32], AccessRights::READ_ADD_WRITE);
1268 let key1 = Key::URef(uref);
1269 assert!(key1.into_account().is_none());
1270 assert!(key1.into_hash().is_none());
1271 assert_eq!(key1.as_uref(), Some(&uref));
1272 }
1273
1274 #[test]
1275 fn key_max_serialized_length() {
1276 let mut got_max = false;
1277 for key in KEYS {
1278 assert!(key.serialized_length() <= Key::max_serialized_length());
1279 if key.serialized_length() == Key::max_serialized_length() {
1280 got_max = true;
1281 }
1282 }
1283 assert!(
1284 got_max,
1285 "None of the Key variants has a serialized_length equal to \
1286 Key::max_serialized_length(), so Key::max_serialized_length() should be reduced"
1287 );
1288 }
1289
1290 #[test]
1291 fn should_parse_key_from_str() {
1292 for key in KEYS {
1293 let string = key.to_formatted_string();
1294 let parsed_key = Key::from_formatted_str(&string).unwrap();
1295 assert_eq!(parsed_key, *key, "{string} (key = {key:?})");
1296 }
1297 }
1298
1299 #[test]
1300 fn should_fail_to_parse_key_from_str() {
1301 assert!(
1302 Key::from_formatted_str(ACCOUNT_HASH_FORMATTED_STRING_PREFIX)
1303 .unwrap_err()
1304 .to_string()
1305 .starts_with("account-key from string error: ")
1306 );
1307 assert!(Key::from_formatted_str(HASH_PREFIX)
1308 .unwrap_err()
1309 .to_string()
1310 .starts_with("hash-key from string error: "));
1311 assert!(Key::from_formatted_str(UREF_FORMATTED_STRING_PREFIX)
1312 .unwrap_err()
1313 .to_string()
1314 .starts_with("uref-key from string error: "));
1315 assert!(
1316 Key::from_formatted_str(TRANSFER_ADDR_FORMATTED_STRING_PREFIX)
1317 .unwrap_err()
1318 .to_string()
1319 .starts_with("transfer-key from string error: ")
1320 );
1321 assert!(Key::from_formatted_str(DEPLOY_INFO_PREFIX)
1322 .unwrap_err()
1323 .to_string()
1324 .starts_with("deploy-info-key from string error: "));
1325 assert!(Key::from_formatted_str(ERA_INFO_PREFIX)
1326 .unwrap_err()
1327 .to_string()
1328 .starts_with("era-info-key from string error: "));
1329 assert!(Key::from_formatted_str(BALANCE_PREFIX)
1330 .unwrap_err()
1331 .to_string()
1332 .starts_with("balance-key from string error: "));
1333 assert!(Key::from_formatted_str(BID_PREFIX)
1334 .unwrap_err()
1335 .to_string()
1336 .starts_with("bid-key from string error: "));
1337 assert!(Key::from_formatted_str(WITHDRAW_PREFIX)
1338 .unwrap_err()
1339 .to_string()
1340 .starts_with("withdraw-key from string error: "));
1341 assert!(Key::from_formatted_str(DICTIONARY_PREFIX)
1342 .unwrap_err()
1343 .to_string()
1344 .starts_with("dictionary-key from string error: "));
1345 assert!(Key::from_formatted_str(SYSTEM_CONTRACT_REGISTRY_PREFIX)
1346 .unwrap_err()
1347 .to_string()
1348 .starts_with("system-contract-registry-key from string error: "));
1349 assert!(Key::from_formatted_str(ERA_SUMMARY_PREFIX)
1350 .unwrap_err()
1351 .to_string()
1352 .starts_with("era-summary-key from string error"));
1353 assert!(Key::from_formatted_str(UNBOND_PREFIX)
1354 .unwrap_err()
1355 .to_string()
1356 .starts_with("unbond-key from string error: "));
1357 assert!(Key::from_formatted_str(CHAINSPEC_REGISTRY_PREFIX)
1358 .unwrap_err()
1359 .to_string()
1360 .starts_with("chainspec-registry-key from string error: "));
1361 assert!(Key::from_formatted_str(CHECKSUM_REGISTRY_PREFIX)
1362 .unwrap_err()
1363 .to_string()
1364 .starts_with("checksum-registry-key from string error: "));
1365 let invalid_prefix = "a-0000000000000000000000000000000000000000000000000000000000000000";
1366 assert_eq!(
1367 Key::from_formatted_str(invalid_prefix)
1368 .unwrap_err()
1369 .to_string(),
1370 "unknown prefix for key"
1371 );
1372
1373 let missing_hyphen_prefix =
1374 "hash0000000000000000000000000000000000000000000000000000000000000000";
1375 assert_eq!(
1376 Key::from_formatted_str(missing_hyphen_prefix)
1377 .unwrap_err()
1378 .to_string(),
1379 "unknown prefix for key"
1380 );
1381
1382 let no_prefix = "0000000000000000000000000000000000000000000000000000000000000000";
1383 assert_eq!(
1384 Key::from_formatted_str(no_prefix).unwrap_err().to_string(),
1385 "unknown prefix for key"
1386 );
1387 }
1388
1389 #[test]
1390 fn key_to_json() {
1391 let expected_json = &[
1392 json!({ "Account": format!("account-hash-{}", HEX_STRING) }),
1393 json!({ "Hash": format!("hash-{}", HEX_STRING) }),
1394 json!({ "URef": format!("uref-{}-001", HEX_STRING) }),
1395 json!({ "Transfer": format!("transfer-{}", HEX_STRING) }),
1396 json!({ "DeployInfo": format!("deploy-{}", HEX_STRING) }),
1397 json!({ "EraInfo": "era-42" }),
1398 json!({ "Balance": format!("balance-{}", HEX_STRING) }),
1399 json!({ "Bid": format!("bid-{}", HEX_STRING) }),
1400 json!({ "Withdraw": format!("withdraw-{}", HEX_STRING) }),
1401 json!({ "Dictionary": format!("dictionary-{}", HEX_STRING) }),
1402 json!({
1403 "SystemContractRegistry":
1404 format!(
1405 "system-contract-registry-{}",
1406 base16::encode_lower(&PADDING_BYTES)
1407 )
1408 }),
1409 json!({
1410 "EraSummary": format!("era-summary-{}", base16::encode_lower(&PADDING_BYTES))
1411 }),
1412 json!({ "Unbond": format!("unbond-{}", HEX_STRING) }),
1413 json!({
1414 "ChainspecRegistry":
1415 format!(
1416 "chainspec-registry-{}",
1417 base16::encode_lower(&PADDING_BYTES)
1418 )
1419 }),
1420 json!({
1421 "ChecksumRegistry":
1422 format!("checksum-registry-{}", base16::encode_lower(&PADDING_BYTES))
1423 }),
1424 ];
1425
1426 assert_eq!(
1427 KEYS.len(),
1428 expected_json.len(),
1429 "There should be exactly one expected JSON string per test key"
1430 );
1431
1432 for (key, expected_json_key) in KEYS.iter().zip(expected_json.iter()) {
1433 assert_eq!(serde_json::to_value(key).unwrap(), *expected_json_key);
1434 }
1435 }
1436
1437 #[test]
1438 fn serialization_roundtrip_bincode() {
1439 for key in KEYS {
1440 let encoded = bincode::serialize(key).unwrap();
1441 let decoded = bincode::deserialize(&encoded).unwrap();
1442 assert_eq!(key, &decoded);
1443 }
1444 }
1445
1446 #[test]
1447 fn serialization_roundtrip_json() {
1448 let round_trip = |key: &Key| {
1449 let encoded = serde_json::to_value(key).unwrap();
1450 let decoded = serde_json::from_value(encoded).unwrap();
1451 assert_eq!(key, &decoded);
1452 };
1453
1454 for key in KEYS {
1455 round_trip(key);
1456 }
1457
1458 let zeros = [0; BLAKE2B_DIGEST_LENGTH];
1459
1460 round_trip(&Key::Account(AccountHash::new(zeros)));
1461 round_trip(&Key::Hash(zeros));
1462 round_trip(&Key::URef(URef::new(zeros, AccessRights::READ)));
1463 round_trip(&Key::Transfer(TransferAddr::new(zeros)));
1464 round_trip(&Key::DeployInfo(DeployHash::new(zeros)));
1465 round_trip(&Key::EraInfo(EraId::from(0)));
1466 round_trip(&Key::Balance(URef::new(zeros, AccessRights::READ).addr()));
1467 round_trip(&Key::Bid(AccountHash::new(zeros)));
1468 round_trip(&Key::Withdraw(AccountHash::new(zeros)));
1469 round_trip(&Key::Dictionary(zeros));
1470 round_trip(&Key::SystemContractRegistry);
1471 round_trip(&Key::EraSummary);
1472 round_trip(&Key::Unbond(AccountHash::new(zeros)));
1473 round_trip(&Key::ChainspecRegistry);
1474 round_trip(&Key::ChecksumRegistry);
1475 }
1476}