casper_types/
key.rs

1//! Key types.
2
3use 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
15#[cfg(any(feature = "testing", test))]
16use crate::testing::TestRng;
17
18#[cfg(doc)]
19use crate::CLValue;
20use blake2::{
21    digest::{Update, VariableOutput},
22    VarBlake2b,
23};
24#[cfg(feature = "datasize")]
25use datasize::DataSize;
26#[cfg(any(feature = "testing", test))]
27use rand::{
28    distributions::{Distribution, Standard},
29    Rng,
30};
31#[cfg(feature = "json-schema")]
32use schemars::JsonSchema;
33use serde::{de::Error as SerdeError, Deserialize, Deserializer, Serialize, Serializer};
34use tracing::{error, warn};
35
36use crate::{
37    account::{AccountHash, ACCOUNT_HASH_LENGTH},
38    addressable_entity::{
39        self, AddressableEntityHash, EntityAddr, EntityKindTag, EntryPointAddr, NamedKeyAddr,
40    },
41    block::BlockGlobalAddr,
42    byte_code,
43    bytesrepr::{
44        self, Error, FromBytes, ToBytes, U32_SERIALIZED_LENGTH, U64_SERIALIZED_LENGTH,
45        U8_SERIALIZED_LENGTH,
46    },
47    checksummed_hex,
48    contract_messages::{self, MessageAddr, TopicNameHash, TOPIC_NAME_HASH_LENGTH},
49    contract_wasm::ContractWasmHash,
50    contracts::{ContractHash, ContractPackageHash},
51    package::PackageHash,
52    system::{
53        auction::{BidAddr, BidAddrTag},
54        mint::BalanceHoldAddr,
55    },
56    uref::{self, URef, URefAddr, UREF_SERIALIZED_LENGTH},
57    ByteCodeAddr, DeployHash, Digest, EraId, Tagged, TransferAddr, TransferFromStrError,
58    TRANSFER_ADDR_LENGTH, UREF_ADDR_LENGTH,
59};
60
61const HASH_PREFIX: &str = "hash-";
62const DEPLOY_INFO_PREFIX: &str = "deploy-";
63const TRANSFER_PREFIX: &str = "transfer-";
64const ERA_INFO_PREFIX: &str = "era-";
65const BALANCE_PREFIX: &str = "balance-";
66const BALANCE_HOLD_PREFIX: &str = "balance-hold-";
67const BID_PREFIX: &str = "bid-";
68const WITHDRAW_PREFIX: &str = "withdraw-";
69const DICTIONARY_PREFIX: &str = "dictionary-";
70const UNBOND_PREFIX: &str = "unbond-";
71const SYSTEM_ENTITY_REGISTRY_PREFIX: &str = "system-entity-registry-";
72const ERA_SUMMARY_PREFIX: &str = "era-summary-";
73const CHAINSPEC_REGISTRY_PREFIX: &str = "chainspec-registry-";
74const CHECKSUM_REGISTRY_PREFIX: &str = "checksum-registry-";
75const BID_ADDR_PREFIX: &str = "bid-addr-";
76const PACKAGE_PREFIX: &str = "package-";
77const BLOCK_GLOBAL_TIME_PREFIX: &str = "block-time-";
78const BLOCK_GLOBAL_MESSAGE_COUNT_PREFIX: &str = "block-message-count-";
79const BLOCK_GLOBAL_PROTOCOL_VERSION_PREFIX: &str = "block-protocol-version-";
80const BLOCK_GLOBAL_ADDRESSABLE_ENTITY_PREFIX: &str = "block-addressable-entity-";
81const STATE_PREFIX: &str = "state-";
82
83/// The number of bytes in a Blake2b hash
84pub const BLAKE2B_DIGEST_LENGTH: usize = 32;
85/// The number of bytes in a [`Key::Hash`].
86pub const KEY_HASH_LENGTH: usize = 32;
87/// The number of bytes in a [`Key::Transfer`].
88pub const KEY_TRANSFER_LENGTH: usize = TRANSFER_ADDR_LENGTH;
89/// The number of bytes in a [`Key::DeployInfo`].
90pub const KEY_DEPLOY_INFO_LENGTH: usize = DeployHash::LENGTH;
91/// The number of bytes in a [`Key::Dictionary`].
92pub const KEY_DICTIONARY_LENGTH: usize = 32;
93/// The maximum length for a `dictionary_item_key`.
94pub const DICTIONARY_ITEM_KEY_MAX_LENGTH: usize = 128;
95/// The maximum length for an `Addr`.
96pub const ADDR_LENGTH: usize = 32;
97const PADDING_BYTES: [u8; 32] = [0u8; 32];
98const BLOCK_GLOBAL_PADDING_BYTES: [u8; 31] = [0u8; 31];
99const KEY_ID_SERIALIZED_LENGTH: usize = 1;
100// u8 used to determine the ID
101const KEY_HASH_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
102const KEY_UREF_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + UREF_SERIALIZED_LENGTH;
103const KEY_TRANSFER_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_TRANSFER_LENGTH;
104const KEY_DEPLOY_INFO_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_DEPLOY_INFO_LENGTH;
105const KEY_ERA_INFO_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + U64_SERIALIZED_LENGTH;
106const KEY_BALANCE_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + UREF_ADDR_LENGTH;
107const KEY_BID_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
108const KEY_WITHDRAW_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
109const KEY_UNBOND_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH;
110const KEY_DICTIONARY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_DICTIONARY_LENGTH;
111const KEY_SYSTEM_ENTITY_REGISTRY_SERIALIZED_LENGTH: usize =
112    KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
113const KEY_ERA_SUMMARY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
114const KEY_CHAINSPEC_REGISTRY_SERIALIZED_LENGTH: usize =
115    KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
116const KEY_CHECKSUM_REGISTRY_SERIALIZED_LENGTH: usize =
117    KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len();
118const KEY_PACKAGE_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + 32;
119const KEY_MESSAGE_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH
120    + U8_SERIALIZED_LENGTH
121    + KEY_HASH_LENGTH
122    + TOPIC_NAME_HASH_LENGTH
123    + U8_SERIALIZED_LENGTH
124    + U32_SERIALIZED_LENGTH;
125
126const MAX_SERIALIZED_LENGTH: usize = KEY_MESSAGE_SERIALIZED_LENGTH;
127
128/// An alias for [`Key`]s hash variant.
129pub type HashAddr = [u8; KEY_HASH_LENGTH];
130
131/// An alias for [`Key`]s package variant.
132pub type PackageAddr = [u8; ADDR_LENGTH];
133
134/// An alias for [`Key`]s dictionary variant.
135pub type DictionaryAddr = [u8; KEY_DICTIONARY_LENGTH];
136
137#[allow(missing_docs)]
138#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
139#[repr(u8)]
140pub enum KeyTag {
141    Account = 0,
142    Hash = 1,
143    URef = 2,
144    Transfer = 3,
145    DeployInfo = 4,
146    EraInfo = 5,
147    Balance = 6,
148    Bid = 7,
149    Withdraw = 8,
150    Dictionary = 9,
151    SystemEntityRegistry = 10,
152    EraSummary = 11,
153    Unbond = 12,
154    ChainspecRegistry = 13,
155    ChecksumRegistry = 14,
156    BidAddr = 15,
157    Package = 16,
158    AddressableEntity = 17,
159    ByteCode = 18,
160    Message = 19,
161    NamedKey = 20,
162    BlockGlobal = 21,
163    BalanceHold = 22,
164    EntryPoint = 23,
165    State = 24,
166}
167
168impl KeyTag {
169    /// Returns a random `KeyTag`.
170    #[cfg(any(feature = "testing", test))]
171    pub fn random(rng: &mut TestRng) -> Self {
172        match rng.gen_range(0..=23) {
173            0 => KeyTag::Account,
174            1 => KeyTag::Hash,
175            2 => KeyTag::URef,
176            3 => KeyTag::Transfer,
177            4 => KeyTag::DeployInfo,
178            5 => KeyTag::EraInfo,
179            6 => KeyTag::Balance,
180            7 => KeyTag::Bid,
181            8 => KeyTag::Withdraw,
182            9 => KeyTag::Dictionary,
183            10 => KeyTag::SystemEntityRegistry,
184            11 => KeyTag::EraSummary,
185            12 => KeyTag::Unbond,
186            13 => KeyTag::ChainspecRegistry,
187            14 => KeyTag::ChecksumRegistry,
188            15 => KeyTag::BidAddr,
189            16 => KeyTag::Package,
190            17 => KeyTag::AddressableEntity,
191            18 => KeyTag::ByteCode,
192            19 => KeyTag::Message,
193            20 => KeyTag::NamedKey,
194            21 => KeyTag::BlockGlobal,
195            22 => KeyTag::BalanceHold,
196            23 => KeyTag::EntryPoint,
197            24 => KeyTag::State,
198            _ => panic!(),
199        }
200    }
201}
202
203impl Display for KeyTag {
204    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
205        match self {
206            KeyTag::Account => write!(f, "Account"),
207            KeyTag::Hash => write!(f, "Hash"),
208            KeyTag::URef => write!(f, "URef"),
209            KeyTag::Transfer => write!(f, "Transfer"),
210            KeyTag::DeployInfo => write!(f, "DeployInfo"),
211            KeyTag::EraInfo => write!(f, "EraInfo"),
212            KeyTag::Balance => write!(f, "Balance"),
213            KeyTag::Bid => write!(f, "Bid"),
214            KeyTag::Withdraw => write!(f, "Withdraw"),
215            KeyTag::Dictionary => write!(f, "Dictionary"),
216            KeyTag::SystemEntityRegistry => write!(f, "SystemEntityRegistry"),
217            KeyTag::EraSummary => write!(f, "EraSummary"),
218            KeyTag::Unbond => write!(f, "Unbond"),
219            KeyTag::ChainspecRegistry => write!(f, "ChainspecRegistry"),
220            KeyTag::ChecksumRegistry => write!(f, "ChecksumRegistry"),
221            KeyTag::BidAddr => write!(f, "BidAddr"),
222            KeyTag::Package => write!(f, "Package"),
223            KeyTag::AddressableEntity => write!(f, "AddressableEntity"),
224            KeyTag::ByteCode => write!(f, "ByteCode"),
225            KeyTag::Message => write!(f, "Message"),
226            KeyTag::NamedKey => write!(f, "NamedKey"),
227            KeyTag::BlockGlobal => write!(f, "BlockGlobal"),
228            KeyTag::BalanceHold => write!(f, "BalanceHold"),
229            KeyTag::State => write!(f, "State"),
230            KeyTag::EntryPoint => write!(f, "EntryPoint"),
231        }
232    }
233}
234
235impl ToBytes for KeyTag {
236    fn to_bytes(&self) -> Result<Vec<u8>, Error> {
237        let mut result = bytesrepr::unchecked_allocate_buffer(self);
238        self.write_bytes(&mut result)?;
239        Ok(result)
240    }
241
242    fn serialized_length(&self) -> usize {
243        KEY_ID_SERIALIZED_LENGTH
244    }
245
246    fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), Error> {
247        writer.push(*self as u8);
248        Ok(())
249    }
250}
251
252impl FromBytes for KeyTag {
253    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error> {
254        let (id, rem) = u8::from_bytes(bytes)?;
255        let tag = match id {
256            tag if tag == KeyTag::Account as u8 => KeyTag::Account,
257            tag if tag == KeyTag::Hash as u8 => KeyTag::Hash,
258            tag if tag == KeyTag::URef as u8 => KeyTag::URef,
259            tag if tag == KeyTag::Transfer as u8 => KeyTag::Transfer,
260            tag if tag == KeyTag::DeployInfo as u8 => KeyTag::DeployInfo,
261            tag if tag == KeyTag::EraInfo as u8 => KeyTag::EraInfo,
262            tag if tag == KeyTag::Balance as u8 => KeyTag::Balance,
263            tag if tag == KeyTag::Bid as u8 => KeyTag::Bid,
264            tag if tag == KeyTag::Withdraw as u8 => KeyTag::Withdraw,
265            tag if tag == KeyTag::Dictionary as u8 => KeyTag::Dictionary,
266            tag if tag == KeyTag::SystemEntityRegistry as u8 => KeyTag::SystemEntityRegistry,
267            tag if tag == KeyTag::EraSummary as u8 => KeyTag::EraSummary,
268            tag if tag == KeyTag::Unbond as u8 => KeyTag::Unbond,
269            tag if tag == KeyTag::ChainspecRegistry as u8 => KeyTag::ChainspecRegistry,
270            tag if tag == KeyTag::ChecksumRegistry as u8 => KeyTag::ChecksumRegistry,
271            tag if tag == KeyTag::BidAddr as u8 => KeyTag::BidAddr,
272            tag if tag == KeyTag::Package as u8 => KeyTag::Package,
273            tag if tag == KeyTag::AddressableEntity as u8 => KeyTag::AddressableEntity,
274            tag if tag == KeyTag::ByteCode as u8 => KeyTag::ByteCode,
275            tag if tag == KeyTag::Message as u8 => KeyTag::Message,
276            tag if tag == KeyTag::NamedKey as u8 => KeyTag::NamedKey,
277            tag if tag == KeyTag::BlockGlobal as u8 => KeyTag::BlockGlobal,
278            tag if tag == KeyTag::BalanceHold as u8 => KeyTag::BalanceHold,
279            tag if tag == KeyTag::EntryPoint as u8 => KeyTag::EntryPoint,
280            tag if tag == KeyTag::State as u8 => KeyTag::State,
281            _ => return Err(Error::Formatting),
282        };
283        Ok((tag, rem))
284    }
285}
286
287/// The key under which data (e.g. [`CLValue`]s, smart contracts, user accounts) are stored in
288/// global state.
289#[repr(C)]
290#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
291#[cfg_attr(feature = "datasize", derive(DataSize))]
292pub enum Key {
293    /// A `Key` under which a user account is stored.
294    Account(AccountHash),
295    /// A `Key` under which a smart contract is stored and which is the pseudo-hash of the
296    /// contract.
297    Hash(HashAddr),
298    /// A `Key` which is a [`URef`], under which most types of data can be stored.
299    URef(URef),
300    /// A `Key` under which a transfer is stored.
301    Transfer(TransferAddr),
302    /// A `Key` under which a deploy info is stored.
303    DeployInfo(DeployHash),
304    /// A `Key` under which an era info is stored.
305    EraInfo(EraId),
306    /// A `Key` under which a purse balance is stored.
307    Balance(URefAddr),
308    /// A `Key` under which bid information is stored.
309    Bid(AccountHash),
310    /// A `Key` under which withdraw information is stored.
311    Withdraw(AccountHash),
312    /// A `Key` whose value is derived by hashing a [`URef`] address and arbitrary data, under
313    /// which a dictionary is stored.
314    Dictionary(DictionaryAddr),
315    /// A `Key` under which system entity hashes are stored.
316    SystemEntityRegistry,
317    /// A `Key` under which current era info is stored.
318    EraSummary,
319    /// A `Key` under which unbond information is stored.
320    Unbond(AccountHash),
321    /// A `Key` under which chainspec and other hashes are stored.
322    ChainspecRegistry,
323    /// A `Key` under which a registry of checksums is stored.
324    ChecksumRegistry,
325    /// A `Key` under which bid information is stored.
326    BidAddr(BidAddr),
327    /// A `Key` under which package information is stored.
328    SmartContract(PackageAddr),
329    /// A `Key` under which an addressable entity is stored.
330    AddressableEntity(EntityAddr),
331    /// A `Key` under which a byte code record is stored.
332    ByteCode(ByteCodeAddr),
333    /// A `Key` under which a message is stored.
334    Message(MessageAddr),
335    /// A `Key` under which a single named key entry is stored.
336    NamedKey(NamedKeyAddr),
337    /// A `Key` under which per-block details are stored to global state.
338    BlockGlobal(BlockGlobalAddr),
339    /// A `Key` under which a hold on a purse balance is stored.
340    BalanceHold(BalanceHoldAddr),
341    /// A `Key` under which a entrypoint record is written.
342    EntryPoint(EntryPointAddr),
343    /// A `Key` under which a contract's state lives.
344    State(EntityAddr),
345}
346
347#[cfg(feature = "json-schema")]
348impl JsonSchema for Key {
349    fn schema_name() -> String {
350        String::from("Key")
351    }
352
353    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
354        let schema = gen.subschema_for::<String>();
355        let mut schema_object = schema.into_object();
356        schema_object.metadata().description = Some(
357            "The key as a formatted string, under which data (e.g. `CLValue`s, smart contracts, \
358                user accounts) are stored in global state."
359                .to_string(),
360        );
361        schema_object.into()
362    }
363}
364
365/// Errors produced when converting a `String` into a `Key`.
366#[derive(Debug)]
367#[non_exhaustive]
368pub enum FromStrError {
369    /// Account parse error.
370    Account(addressable_entity::FromStrError),
371    /// Hash parse error.
372    Hash(String),
373    /// URef parse error.
374    URef(uref::FromStrError),
375    /// Transfer parse error.
376    Transfer(TransferFromStrError),
377    /// DeployInfo parse error.
378    DeployInfo(String),
379    /// EraInfo parse error.
380    EraInfo(String),
381    /// Balance parse error.
382    Balance(String),
383    /// Bid parse error.
384    Bid(String),
385    /// Withdraw parse error.
386    Withdraw(String),
387    /// Dictionary parse error.
388    Dictionary(String),
389    /// System entity registry parse error.
390    SystemEntityRegistry(String),
391    /// Era summary parse error.
392    EraSummary(String),
393    /// Unbond parse error.
394    Unbond(String),
395    /// Chainspec registry error.
396    ChainspecRegistry(String),
397    /// Checksum registry error.
398    ChecksumRegistry(String),
399    /// Bid parse error.
400    BidAddr(String),
401    /// Package parse error.
402    Package(String),
403    /// Entity parse error.
404    AddressableEntity(String),
405    /// Byte code parse error.
406    ByteCode(String),
407    /// Message parse error.
408    Message(contract_messages::FromStrError),
409    /// Named key parse error.
410    NamedKey(String),
411    /// BlockGlobal key parse error.
412    BlockGlobal(String),
413    /// Balance hold parse error.
414    BalanceHold(String),
415    /// Entry point parse error.
416    EntryPoint(String),
417    /// State key parse error.
418    State(String),
419    /// Unknown prefix.
420    UnknownPrefix,
421}
422
423impl From<addressable_entity::FromStrError> for FromStrError {
424    fn from(error: addressable_entity::FromStrError) -> Self {
425        FromStrError::Account(error)
426    }
427}
428
429impl From<uref::FromStrError> for FromStrError {
430    fn from(error: uref::FromStrError) -> Self {
431        FromStrError::URef(error)
432    }
433}
434
435impl From<contract_messages::FromStrError> for FromStrError {
436    fn from(error: contract_messages::FromStrError) -> Self {
437        FromStrError::Message(error)
438    }
439}
440
441impl Display for FromStrError {
442    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
443        match self {
444            FromStrError::Account(error) => write!(f, "account-key from string error: {}", error),
445            FromStrError::Hash(error) => write!(f, "hash-key from string error: {}", error),
446            FromStrError::URef(error) => write!(f, "uref-key from string error: {}", error),
447            FromStrError::Transfer(error) => {
448                write!(f, "legacy-transfer-key from string error: {}", error)
449            }
450            FromStrError::DeployInfo(error) => {
451                write!(f, "deploy-info-key from string error: {}", error)
452            }
453            FromStrError::EraInfo(error) => write!(f, "era-info-key from string error: {}", error),
454            FromStrError::Balance(error) => write!(f, "balance-key from string error: {}", error),
455            FromStrError::Bid(error) => write!(f, "bid-key from string error: {}", error),
456            FromStrError::Withdraw(error) => write!(f, "withdraw-key from string error: {}", error),
457            FromStrError::Dictionary(error) => {
458                write!(f, "dictionary-key from string error: {}", error)
459            }
460            FromStrError::SystemEntityRegistry(error) => {
461                write!(
462                    f,
463                    "system-contract-registry-key from string error: {}",
464                    error
465                )
466            }
467            FromStrError::EraSummary(error) => {
468                write!(f, "era-summary-key from string error: {}", error)
469            }
470            FromStrError::Unbond(error) => {
471                write!(f, "unbond-key from string error: {}", error)
472            }
473            FromStrError::ChainspecRegistry(error) => {
474                write!(f, "chainspec-registry-key from string error: {}", error)
475            }
476            FromStrError::ChecksumRegistry(error) => {
477                write!(f, "checksum-registry-key from string error: {}", error)
478            }
479            FromStrError::BidAddr(error) => write!(f, "bid-addr-key from string error: {}", error),
480            FromStrError::Package(error) => write!(f, "package-key from string error: {}", error),
481            FromStrError::AddressableEntity(error) => {
482                write!(f, "addressable-entity-key from string error: {}", error)
483            }
484            FromStrError::ByteCode(error) => {
485                write!(f, "byte-code-key from string error: {}", error)
486            }
487            FromStrError::Message(error) => {
488                write!(f, "message-key from string error: {}", error)
489            }
490            FromStrError::NamedKey(error) => {
491                write!(f, "named-key from string error: {}", error)
492            }
493            FromStrError::BlockGlobal(error) => {
494                write!(f, "block-message-count-key form string error: {}", error)
495            }
496            FromStrError::BalanceHold(error) => {
497                write!(f, "balance-hold from string error: {}", error)
498            }
499            FromStrError::EntryPoint(error) => {
500                write!(f, "entry-point from string error: {}", error)
501            }
502            FromStrError::UnknownPrefix => write!(f, "unknown prefix for key"),
503            FromStrError::State(error) => write!(f, "state-key from string error: {}", error),
504        }
505    }
506}
507
508impl Key {
509    // This method is not intended to be used by third party crates.
510    #[doc(hidden)]
511    pub fn type_string(&self) -> String {
512        match self {
513            Key::Account(_) => String::from("Key::Account"),
514            Key::Hash(_) => String::from("Key::Hash"),
515            Key::URef(_) => String::from("Key::URef"),
516            Key::Transfer(_) => String::from("Key::Transfer"),
517            Key::DeployInfo(_) => String::from("Key::DeployInfo"),
518            Key::EraInfo(_) => String::from("Key::EraInfo"),
519            Key::Balance(_) => String::from("Key::Balance"),
520            Key::Bid(_) => String::from("Key::Bid"),
521            Key::Withdraw(_) => String::from("Key::Unbond"),
522            Key::Dictionary(_) => String::from("Key::Dictionary"),
523            Key::SystemEntityRegistry => String::from("Key::SystemEntityRegistry"),
524            Key::EraSummary => String::from("Key::EraSummary"),
525            Key::Unbond(_) => String::from("Key::Unbond"),
526            Key::ChainspecRegistry => String::from("Key::ChainspecRegistry"),
527            Key::ChecksumRegistry => String::from("Key::ChecksumRegistry"),
528            Key::BidAddr(_) => String::from("Key::BidAddr"),
529            Key::SmartContract(_) => String::from("Key::SmartContract"),
530            Key::AddressableEntity(_) => String::from("Key::AddressableEntity"),
531            Key::ByteCode(_) => String::from("Key::ByteCode"),
532            Key::Message(_) => String::from("Key::Message"),
533            Key::NamedKey(_) => String::from("Key::NamedKey"),
534            Key::BlockGlobal(_) => String::from("Key::BlockGlobal"),
535            Key::BalanceHold(_) => String::from("Key::BalanceHold"),
536            Key::EntryPoint(_) => String::from("Key::EntryPoint"),
537            Key::State(_) => String::from("Key::State"),
538        }
539    }
540
541    /// Returns the maximum size a [`Key`] can be serialized into.
542    pub const fn max_serialized_length() -> usize {
543        MAX_SERIALIZED_LENGTH
544    }
545
546    /// If `self` is of type [`Key::URef`], returns `self` with the
547    /// [`AccessRights`](crate::AccessRights) stripped from the wrapped [`URef`], otherwise
548    /// returns `self` unmodified.
549    #[must_use]
550    pub fn normalize(self) -> Key {
551        match self {
552            Key::URef(uref) => Key::URef(uref.remove_access_rights()),
553            other => other,
554        }
555    }
556
557    /// Returns a human-readable version of `self`, with the inner bytes encoded to Base16.
558    pub fn to_formatted_string(self) -> String {
559        match self {
560            Key::Account(account_hash) => account_hash.to_formatted_string(),
561            Key::Hash(addr) => format!("{}{}", HASH_PREFIX, base16::encode_lower(&addr)),
562            Key::URef(uref) => uref.to_formatted_string(),
563            Key::Transfer(transfer_v1_addr) => {
564                format!(
565                    "{}{}",
566                    TRANSFER_PREFIX,
567                    base16::encode_lower(&transfer_v1_addr.value())
568                )
569            }
570            Key::DeployInfo(deploy_hash) => {
571                format!(
572                    "{}{}",
573                    DEPLOY_INFO_PREFIX,
574                    base16::encode_lower(deploy_hash.as_ref())
575                )
576            }
577            Key::EraInfo(era_id) => {
578                format!("{}{}", ERA_INFO_PREFIX, era_id.value())
579            }
580            Key::Balance(uref_addr) => {
581                format!("{}{}", BALANCE_PREFIX, base16::encode_lower(&uref_addr))
582            }
583            Key::Bid(account_hash) => {
584                format!("{}{}", BID_PREFIX, base16::encode_lower(&account_hash))
585            }
586            Key::Withdraw(account_hash) => {
587                format!("{}{}", WITHDRAW_PREFIX, base16::encode_lower(&account_hash))
588            }
589            Key::Dictionary(dictionary_addr) => {
590                format!(
591                    "{}{}",
592                    DICTIONARY_PREFIX,
593                    base16::encode_lower(&dictionary_addr)
594                )
595            }
596            Key::SystemEntityRegistry => {
597                format!(
598                    "{}{}",
599                    SYSTEM_ENTITY_REGISTRY_PREFIX,
600                    base16::encode_lower(&PADDING_BYTES)
601                )
602            }
603            Key::EraSummary => {
604                format!(
605                    "{}{}",
606                    ERA_SUMMARY_PREFIX,
607                    base16::encode_lower(&PADDING_BYTES)
608                )
609            }
610            Key::Unbond(account_hash) => {
611                format!("{}{}", UNBOND_PREFIX, base16::encode_lower(&account_hash))
612            }
613            Key::ChainspecRegistry => {
614                format!(
615                    "{}{}",
616                    CHAINSPEC_REGISTRY_PREFIX,
617                    base16::encode_lower(&PADDING_BYTES)
618                )
619            }
620            Key::ChecksumRegistry => {
621                format!(
622                    "{}{}",
623                    CHECKSUM_REGISTRY_PREFIX,
624                    base16::encode_lower(&PADDING_BYTES)
625                )
626            }
627            Key::BidAddr(bid_addr) => {
628                format!("{}{}", BID_ADDR_PREFIX, bid_addr)
629            }
630            Key::Message(message_addr) => message_addr.to_formatted_string(),
631            Key::SmartContract(package_addr) => {
632                format!("{}{}", PACKAGE_PREFIX, base16::encode_lower(&package_addr))
633            }
634            Key::AddressableEntity(entity_addr) => {
635                format!("{}", entity_addr)
636            }
637            Key::ByteCode(byte_code_addr) => {
638                format!("{}", byte_code_addr)
639            }
640            Key::NamedKey(named_key) => {
641                format!("{}", named_key)
642            }
643            Key::BlockGlobal(addr) => {
644                let prefix = match addr {
645                    BlockGlobalAddr::BlockTime => BLOCK_GLOBAL_TIME_PREFIX,
646                    BlockGlobalAddr::MessageCount => BLOCK_GLOBAL_MESSAGE_COUNT_PREFIX,
647                    BlockGlobalAddr::ProtocolVersion => BLOCK_GLOBAL_PROTOCOL_VERSION_PREFIX,
648                    BlockGlobalAddr::AddressableEntity => BLOCK_GLOBAL_ADDRESSABLE_ENTITY_PREFIX,
649                };
650                format!(
651                    "{}{}",
652                    prefix,
653                    base16::encode_lower(&BLOCK_GLOBAL_PADDING_BYTES)
654                )
655            }
656            Key::BalanceHold(balance_hold_addr) => {
657                let tail = BalanceHoldAddr::to_formatted_string(&balance_hold_addr);
658                format!("{}{}", BALANCE_HOLD_PREFIX, tail)
659            }
660            Key::State(entity_addr) => {
661                format!("{}{}", STATE_PREFIX, entity_addr)
662            }
663            Key::EntryPoint(entry_point_addr) => {
664                format!("{}", entry_point_addr)
665            }
666        }
667    }
668
669    /// Parses a string formatted as per `Self::to_formatted_string()` into a `Key`.
670    pub fn from_formatted_str(input: &str) -> Result<Key, FromStrError> {
671        match AccountHash::from_formatted_str(input) {
672            Ok(account_hash) => return Ok(Key::Account(account_hash)),
673            Err(addressable_entity::FromStrError::InvalidPrefix) => {}
674            Err(error) => return Err(error.into()),
675        }
676
677        if let Some(hex) = input.strip_prefix(HASH_PREFIX) {
678            let addr = checksummed_hex::decode(hex)
679                .map_err(|error| FromStrError::Hash(error.to_string()))?;
680            let hash_addr = HashAddr::try_from(addr.as_ref())
681                .map_err(|error| FromStrError::Hash(error.to_string()))?;
682            return Ok(Key::Hash(hash_addr));
683        }
684
685        if let Some(hex) = input.strip_prefix(DEPLOY_INFO_PREFIX) {
686            let hash = checksummed_hex::decode(hex)
687                .map_err(|error| FromStrError::DeployInfo(error.to_string()))?;
688            let hash_array = <[u8; DeployHash::LENGTH]>::try_from(hash.as_ref())
689                .map_err(|error| FromStrError::DeployInfo(error.to_string()))?;
690            return Ok(Key::DeployInfo(DeployHash::new(Digest::from(hash_array))));
691        }
692
693        if let Some(hex) = input.strip_prefix(TRANSFER_PREFIX) {
694            let addr = checksummed_hex::decode(hex)
695                .map_err(|error| FromStrError::Transfer(TransferFromStrError::from(error)))?;
696            let addr_array = <[u8; TRANSFER_ADDR_LENGTH]>::try_from(addr.as_ref())
697                .map_err(|error| FromStrError::Transfer(TransferFromStrError::from(error)))?;
698            return Ok(Key::Transfer(TransferAddr::new(addr_array)));
699        }
700
701        match URef::from_formatted_str(input) {
702            Ok(uref) => return Ok(Key::URef(uref)),
703            Err(uref::FromStrError::InvalidPrefix) => {}
704            Err(error) => return Err(error.into()),
705        }
706
707        if let Some(era_summary_padding) = input.strip_prefix(ERA_SUMMARY_PREFIX) {
708            let padded_bytes = checksummed_hex::decode(era_summary_padding)
709                .map_err(|error| FromStrError::EraSummary(error.to_string()))?;
710            let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
711                FromStrError::EraSummary("Failed to deserialize era summary key".to_string())
712            })?;
713            return Ok(Key::EraSummary);
714        }
715
716        if let Some(era_id_str) = input.strip_prefix(ERA_INFO_PREFIX) {
717            let era_id = EraId::from_str(era_id_str)
718                .map_err(|error| FromStrError::EraInfo(error.to_string()))?;
719            return Ok(Key::EraInfo(era_id));
720        }
721
722        // note: BALANCE_HOLD must come before BALANCE due to overlapping head (balance-)
723        if let Some(hex) = input.strip_prefix(BALANCE_HOLD_PREFIX) {
724            let balance_hold_addr = BalanceHoldAddr::from_formatted_string(hex)?;
725            return Ok(Key::BalanceHold(balance_hold_addr));
726        }
727
728        if let Some(hex) = input.strip_prefix(BALANCE_PREFIX) {
729            let addr = checksummed_hex::decode(hex)
730                .map_err(|error| FromStrError::Balance(error.to_string()))?;
731            let uref_addr = URefAddr::try_from(addr.as_ref())
732                .map_err(|error| FromStrError::Balance(error.to_string()))?;
733            return Ok(Key::Balance(uref_addr));
734        }
735
736        // note: BID_ADDR must come before BID as their heads overlap (bid- / bid-addr-)
737        if let Some(hex) = input.strip_prefix(BID_ADDR_PREFIX) {
738            let bytes = checksummed_hex::decode(hex)
739                .map_err(|error| FromStrError::BidAddr(error.to_string()))?;
740            if bytes.is_empty() {
741                return Err(FromStrError::BidAddr(
742                    "bytes should not be 0 len".to_string(),
743                ));
744            }
745            let tag_bytes = <[u8; BidAddrTag::BID_ADDR_TAG_LENGTH]>::try_from(bytes[0..1].as_ref())
746                .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
747            let tag = BidAddrTag::try_from_u8(tag_bytes[0])
748                .ok_or_else(|| FromStrError::BidAddr("failed to parse bid addr tag".to_string()))?;
749            let validator_bytes = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(
750                bytes[1..BidAddr::VALIDATOR_BID_ADDR_LENGTH].as_ref(),
751            )
752            .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
753
754            let bid_addr = match tag {
755                BidAddrTag::Unified => BidAddr::legacy(validator_bytes),
756                BidAddrTag::Validator => BidAddr::new_validator_addr(validator_bytes),
757                BidAddrTag::DelegatedAccount => {
758                    let delegator_bytes = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(
759                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
760                    )
761                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
762                    BidAddr::new_delegator_account_addr((validator_bytes, delegator_bytes))
763                }
764                BidAddrTag::DelegatedPurse => {
765                    let uref = <[u8; UREF_ADDR_LENGTH]>::try_from(
766                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
767                    )
768                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
769                    BidAddr::DelegatedPurse {
770                        validator: AccountHash::new(validator_bytes),
771                        delegator: uref,
772                    }
773                }
774                BidAddrTag::Credit => {
775                    let era_id = bytesrepr::deserialize_from_slice(
776                        &bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..],
777                    )
778                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
779                    BidAddr::Credit {
780                        validator: AccountHash::new(validator_bytes),
781                        era_id,
782                    }
783                }
784                BidAddrTag::ReservedDelegationAccount => {
785                    let delegator_bytes = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(
786                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
787                    )
788                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
789                    BidAddr::new_reservation_account_addr((validator_bytes, delegator_bytes))
790                }
791                BidAddrTag::ReservedDelegationPurse => {
792                    let uref = <[u8; UREF_ADDR_LENGTH]>::try_from(
793                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
794                    )
795                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
796                    BidAddr::ReservedDelegationPurse {
797                        validator: AccountHash::new(validator_bytes),
798                        delegator: uref,
799                    }
800                }
801                BidAddrTag::UnbondAccount => {
802                    let unbonder_bytes = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(
803                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
804                    )
805                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
806                    BidAddr::UnbondAccount {
807                        validator: AccountHash::new(validator_bytes),
808                        unbonder: AccountHash::new(unbonder_bytes),
809                    }
810                }
811                BidAddrTag::UnbondPurse => {
812                    let uref = <[u8; UREF_ADDR_LENGTH]>::try_from(
813                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
814                    )
815                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
816                    BidAddr::UnbondPurse {
817                        validator: AccountHash::new(validator_bytes),
818                        unbonder: uref,
819                    }
820                }
821            };
822            return Ok(Key::BidAddr(bid_addr));
823        }
824
825        if let Some(hex) = input.strip_prefix(BID_PREFIX) {
826            let hash = checksummed_hex::decode(hex)
827                .map_err(|error| FromStrError::Bid(error.to_string()))?;
828            let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
829                .map_err(|error| FromStrError::Bid(error.to_string()))?;
830            return Ok(Key::Bid(AccountHash::new(account_hash)));
831        }
832
833        if let Some(hex) = input.strip_prefix(WITHDRAW_PREFIX) {
834            let hash = checksummed_hex::decode(hex)
835                .map_err(|error| FromStrError::Withdraw(error.to_string()))?;
836            let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
837                .map_err(|error| FromStrError::Withdraw(error.to_string()))?;
838            return Ok(Key::Withdraw(AccountHash::new(account_hash)));
839        }
840
841        if let Some(hex) = input.strip_prefix(UNBOND_PREFIX) {
842            let hash = checksummed_hex::decode(hex)
843                .map_err(|error| FromStrError::Unbond(error.to_string()))?;
844            let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
845                .map_err(|error| FromStrError::Unbond(error.to_string()))?;
846            return Ok(Key::Unbond(AccountHash::new(account_hash)));
847        }
848
849        if let Some(dictionary_addr) = input.strip_prefix(DICTIONARY_PREFIX) {
850            let dictionary_addr_bytes = checksummed_hex::decode(dictionary_addr)
851                .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
852            let addr = DictionaryAddr::try_from(dictionary_addr_bytes.as_ref())
853                .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
854            return Ok(Key::Dictionary(addr));
855        }
856
857        if let Some(registry_address) = input.strip_prefix(SYSTEM_ENTITY_REGISTRY_PREFIX) {
858            let padded_bytes = checksummed_hex::decode(registry_address)
859                .map_err(|error| FromStrError::SystemEntityRegistry(error.to_string()))?;
860            let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
861                FromStrError::SystemEntityRegistry(
862                    "Failed to deserialize system registry key".to_string(),
863                )
864            })?;
865            return Ok(Key::SystemEntityRegistry);
866        }
867
868        if let Some(registry_address) = input.strip_prefix(CHAINSPEC_REGISTRY_PREFIX) {
869            let padded_bytes = checksummed_hex::decode(registry_address)
870                .map_err(|error| FromStrError::ChainspecRegistry(error.to_string()))?;
871            let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
872                FromStrError::ChainspecRegistry(
873                    "Failed to deserialize chainspec registry key".to_string(),
874                )
875            })?;
876            return Ok(Key::ChainspecRegistry);
877        }
878
879        if let Some(registry_address) = input.strip_prefix(CHECKSUM_REGISTRY_PREFIX) {
880            let padded_bytes = checksummed_hex::decode(registry_address)
881                .map_err(|error| FromStrError::ChecksumRegistry(error.to_string()))?;
882            let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
883                FromStrError::ChecksumRegistry(
884                    "Failed to deserialize checksum registry key".to_string(),
885                )
886            })?;
887            return Ok(Key::ChecksumRegistry);
888        }
889
890        if let Some(package_addr) = input.strip_prefix(PACKAGE_PREFIX) {
891            let package_addr_bytes = checksummed_hex::decode(package_addr)
892                .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
893            let addr = PackageAddr::try_from(package_addr_bytes.as_ref())
894                .map_err(|error| FromStrError::Package(error.to_string()))?;
895            return Ok(Key::SmartContract(addr));
896        }
897
898        match EntityAddr::from_formatted_str(input) {
899            Ok(entity_addr) => return Ok(Key::AddressableEntity(entity_addr)),
900            Err(addressable_entity::FromStrError::InvalidPrefix) => {}
901            Err(error) => {
902                return Err(FromStrError::AddressableEntity(error.to_string()));
903            }
904        }
905
906        match ByteCodeAddr::from_formatted_string(input) {
907            Ok(byte_code_addr) => return Ok(Key::ByteCode(byte_code_addr)),
908            Err(byte_code::FromStrError::InvalidPrefix) => {}
909            Err(error) => return Err(FromStrError::ByteCode(error.to_string())),
910        }
911
912        match MessageAddr::from_formatted_str(input) {
913            Ok(message_addr) => return Ok(Key::Message(message_addr)),
914            Err(contract_messages::FromStrError::InvalidPrefix) => {}
915            Err(error) => return Err(error.into()),
916        }
917
918        match NamedKeyAddr::from_formatted_str(input) {
919            Ok(named_key) => return Ok(Key::NamedKey(named_key)),
920            Err(addressable_entity::FromStrError::InvalidPrefix) => {}
921            Err(error) => return Err(FromStrError::NamedKey(error.to_string())),
922        }
923
924        if let Some(block_time) = input.strip_prefix(BLOCK_GLOBAL_TIME_PREFIX) {
925            let padded_bytes = checksummed_hex::decode(block_time)
926                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
927            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
928                FromStrError::BlockGlobal("Failed to deserialize global block time key".to_string())
929            })?;
930            return Ok(BlockGlobalAddr::BlockTime.into());
931        }
932
933        if let Some(message_count) = input.strip_prefix(BLOCK_GLOBAL_MESSAGE_COUNT_PREFIX) {
934            let padded_bytes = checksummed_hex::decode(message_count)
935                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
936            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
937                FromStrError::BlockGlobal(
938                    "Failed to deserialize global block message count key".to_string(),
939                )
940            })?;
941            return Ok(BlockGlobalAddr::MessageCount.into());
942        }
943
944        if let Some(protocol_version) = input.strip_prefix(BLOCK_GLOBAL_PROTOCOL_VERSION_PREFIX) {
945            let padded_bytes = checksummed_hex::decode(protocol_version)
946                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
947            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
948                FromStrError::BlockGlobal(
949                    "Failed to deserialize global block protocol version key".to_string(),
950                )
951            })?;
952            return Ok(BlockGlobalAddr::ProtocolVersion.into());
953        }
954
955        if let Some(addressable_entity) = input.strip_prefix(BLOCK_GLOBAL_ADDRESSABLE_ENTITY_PREFIX)
956        {
957            let padded_bytes = checksummed_hex::decode(addressable_entity)
958                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
959            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
960                FromStrError::BlockGlobal(
961                    "Failed to deserialize global block addressable entity key".to_string(),
962                )
963            })?;
964            return Ok(BlockGlobalAddr::AddressableEntity.into());
965        }
966
967        match EntryPointAddr::from_formatted_str(input) {
968            Ok(entry_point_addr) => return Ok(Key::EntryPoint(entry_point_addr)),
969            Err(addressable_entity::FromStrError::InvalidPrefix) => {}
970            Err(error) => return Err(FromStrError::EntryPoint(error.to_string())),
971        }
972
973        if let Some(entity_addr_formatted) = input.strip_prefix(STATE_PREFIX) {
974            match EntityAddr::from_formatted_str(entity_addr_formatted) {
975                Ok(entity_addr) => return Ok(Key::State(entity_addr)),
976                Err(addressable_entity::FromStrError::InvalidPrefix) => {}
977                Err(error) => {
978                    return Err(FromStrError::State(error.to_string()));
979                }
980            }
981        }
982
983        Err(FromStrError::UnknownPrefix)
984    }
985
986    /// Returns the inner bytes of `self` if `self` is of type [`Key::Account`], otherwise returns
987    /// `None`.
988    pub fn into_account(self) -> Option<AccountHash> {
989        match self {
990            Key::Account(bytes) => Some(bytes),
991            _ => None,
992        }
993    }
994
995    /// Returns the inner bytes of `self` if `self` is of type [`Key::Hash`], otherwise returns
996    /// `None`.
997    pub fn into_hash_addr(self) -> Option<HashAddr> {
998        match self {
999            Key::Hash(hash) => Some(hash),
1000            _ => None,
1001        }
1002    }
1003
1004    /// Returns the inner bytes of `self` if `self` is of type [`Key::AddressableEntity`], otherwise
1005    /// returns `None`.
1006    pub fn into_entity_hash_addr(self) -> Option<HashAddr> {
1007        match self {
1008            Key::AddressableEntity(entity_addr) => Some(entity_addr.value()),
1009            Key::Account(account_hash) => Some(account_hash.value()),
1010            Key::Hash(hash) => Some(hash),
1011            _ => None,
1012        }
1013    }
1014
1015    /// Returns the inner bytes of `self` if `self` is of type [`Key::SmartContract`], otherwise
1016    /// returns `None`.
1017    pub fn into_package_addr(self) -> Option<PackageAddr> {
1018        match self {
1019            Key::Hash(hash) => Some(hash),
1020            Key::SmartContract(package_addr) => Some(package_addr),
1021            _ => None,
1022        }
1023    }
1024
1025    /// Returns [`AddressableEntityHash`] of `self` if `self` is of type [`Key::AddressableEntity`],
1026    /// otherwise returns `None`.
1027    pub fn into_entity_hash(self) -> Option<AddressableEntityHash> {
1028        let entity_addr = self.into_entity_hash_addr()?;
1029        Some(AddressableEntityHash::new(entity_addr))
1030    }
1031
1032    /// Returns [`PackageHash`] of `self` if `self` is of type [`Key::SmartContract`], otherwise
1033    /// returns `None`.
1034    pub fn into_package_hash(self) -> Option<PackageHash> {
1035        let package_addr = self.into_package_addr()?;
1036        Some(PackageHash::new(package_addr))
1037    }
1038
1039    /// Returns [`NamedKeyAddr`] of `self` if `self` is of type [`Key::NamedKey`], otherwise
1040    /// returns `None`.
1041    pub fn into_named_key_addr(self) -> Option<NamedKeyAddr> {
1042        match self {
1043            Key::NamedKey(addr) => Some(addr),
1044            _ => None,
1045        }
1046    }
1047
1048    /// Returns the inner [`URef`] if `self` is of type [`Key::URef`], otherwise returns `None`.
1049    pub fn into_uref(self) -> Option<URef> {
1050        match self {
1051            Key::URef(uref) => Some(uref),
1052            _ => None,
1053        }
1054    }
1055
1056    /// Returns a reference to the inner [`URef`] if `self` is of type [`Key::URef`], otherwise
1057    /// returns `None`.
1058    pub fn as_uref(&self) -> Option<&URef> {
1059        match self {
1060            Key::URef(uref) => Some(uref),
1061            _ => None,
1062        }
1063    }
1064
1065    /// Returns a reference to the inner [`URef`] if `self` is of type [`Key::URef`], otherwise
1066    /// returns `None`.
1067    pub fn as_uref_mut(&mut self) -> Option<&mut URef> {
1068        match self {
1069            Key::URef(uref) => Some(uref),
1070            _ => None,
1071        }
1072    }
1073
1074    /// Returns a reference to the inner `URefAddr` if `self` is of type [`Key::Balance`],
1075    /// otherwise returns `None`.
1076    pub fn as_balance(&self) -> Option<&URefAddr> {
1077        if let Self::Balance(v) = self {
1078            Some(v)
1079        } else {
1080            None
1081        }
1082    }
1083
1084    /// Returns a reference to the inner `BalanceHoldAddr` if `self` is of type
1085    /// [`Key::BalanceHold`], otherwise returns `None`.
1086    pub fn as_balance_hold(&self) -> Option<&BalanceHoldAddr> {
1087        if let Self::BalanceHold(addr) = self {
1088            Some(addr)
1089        } else {
1090            None
1091        }
1092    }
1093
1094    /// Returns a reference to the inner [`DictionaryAddr`] if `self` is of type
1095    /// [`Key::Dictionary`], otherwise returns `None`.
1096    pub fn as_dictionary(&self) -> Option<&DictionaryAddr> {
1097        match self {
1098            Key::Dictionary(v) => Some(v),
1099            _ => None,
1100        }
1101    }
1102
1103    /// Returns a reference to the inner `BidAddr` if `self` is of type [`Key::Bid`],
1104    /// otherwise returns `None`.
1105    pub fn as_bid_addr(&self) -> Option<&BidAddr> {
1106        if let Self::BidAddr(addr) = self {
1107            Some(addr)
1108        } else {
1109            None
1110        }
1111    }
1112
1113    /// Returns a reference to the inner `TopicNameHash` if `self` is of the type [`Key::Message`]
1114    /// otherwise returns `None`.
1115    pub fn as_message_topic_name_hash(&self) -> Option<TopicNameHash> {
1116        if let Self::Message(addr) = self {
1117            Some(addr.topic_name_hash())
1118        } else {
1119            None
1120        }
1121    }
1122
1123    /// Casts a [`Key::URef`] to a [`Key::Hash`]
1124    pub fn uref_to_hash(&self) -> Option<Key> {
1125        let uref = self.as_uref()?;
1126        let addr = uref.addr();
1127        Some(Key::Hash(addr))
1128    }
1129
1130    /// Casts a [`Key::Withdraw`] to a [`Key::Unbond`]
1131    pub fn withdraw_to_unbond(&self) -> Option<Key> {
1132        if let Key::Withdraw(account_hash) = self {
1133            return Some(Key::Unbond(*account_hash));
1134        }
1135        None
1136    }
1137
1138    /// Creates a new [`Key::Dictionary`] variant based on a `seed_uref` and a `dictionary_item_key`
1139    /// bytes.
1140    pub fn dictionary(seed_uref: URef, dictionary_item_key: &[u8]) -> Key {
1141        // NOTE: Expect below is safe because the length passed is supported.
1142        let mut hasher = VarBlake2b::new(BLAKE2B_DIGEST_LENGTH).expect("should create hasher");
1143        hasher.update(seed_uref.addr().as_ref());
1144        hasher.update(dictionary_item_key);
1145        // NOTE: Assumed safe as size of `HashAddr` equals to the output provided by hasher.
1146        let mut addr = HashAddr::default();
1147        hasher.finalize_variable(|hash| addr.clone_from_slice(hash));
1148        Key::Dictionary(addr)
1149    }
1150
1151    /// Creates a new [`Key::AddressableEntity`] variant from a package kind and an entity
1152    /// hash.
1153    pub fn addressable_entity_key(
1154        entity_kind_tag: EntityKindTag,
1155        entity_hash: AddressableEntityHash,
1156    ) -> Self {
1157        let entity_addr = match entity_kind_tag {
1158            EntityKindTag::System => EntityAddr::new_system(entity_hash.value()),
1159            EntityKindTag::Account => EntityAddr::new_account(entity_hash.value()),
1160            EntityKindTag::SmartContract => EntityAddr::new_smart_contract(entity_hash.value()),
1161        };
1162
1163        Key::AddressableEntity(entity_addr)
1164    }
1165
1166    /// Creates a new [`Key::AddressableEntity`] for a Smart contract.
1167    pub fn contract_entity_key(entity_hash: AddressableEntityHash) -> Key {
1168        Self::addressable_entity_key(EntityKindTag::SmartContract, entity_hash)
1169    }
1170
1171    /// Creates a new [`Key::ByteCode`] variant from a byte code kind and an byte code addr.
1172    pub fn byte_code_key(byte_code_addr: ByteCodeAddr) -> Self {
1173        Key::ByteCode(byte_code_addr)
1174    }
1175
1176    /// Creates a new [`Key::Message`] variant that identifies an indexed message based on an
1177    /// `hash_addr`, `topic_name_hash` and message `index`.
1178    pub fn message(entity_addr: EntityAddr, topic_name_hash: TopicNameHash, index: u32) -> Key {
1179        Key::Message(MessageAddr::new_message_addr(
1180            entity_addr,
1181            topic_name_hash,
1182            index,
1183        ))
1184    }
1185
1186    /// Creates a new [`Key::Message`] variant that identifies a message topic based on an
1187    /// `hash_addr` and a hash of the topic name.
1188    pub fn message_topic(entity_addr: EntityAddr, topic_name_hash: TopicNameHash) -> Key {
1189        Key::Message(MessageAddr::new_topic_addr(entity_addr, topic_name_hash))
1190    }
1191
1192    /// Creates a new [`Key::EntryPoint`] variant from an entrypoint addr.
1193    pub fn entry_point(entry_point_addr: EntryPointAddr) -> Self {
1194        Key::EntryPoint(entry_point_addr)
1195    }
1196
1197    /// Returns true if the key is of type [`Key::Dictionary`].
1198    pub fn is_dictionary_key(&self) -> bool {
1199        if let Key::Dictionary(_) = self {
1200            return true;
1201        }
1202        false
1203    }
1204
1205    /// Returns true if the key is of type [`Key::Bid`].
1206    pub fn is_balance_key(&self) -> bool {
1207        if let Key::Balance(_) = self {
1208            return true;
1209        }
1210        false
1211    }
1212
1213    /// Returns true if the key is of type [`Key::BidAddr`].
1214    pub fn is_bid_addr_key(&self) -> bool {
1215        if let Key::BidAddr(_) = self {
1216            return true;
1217        }
1218        false
1219    }
1220
1221    /// Returns true if the key is of type [`Key::NamedKey`].
1222    pub fn is_named_key(&self) -> bool {
1223        if let Key::NamedKey(_) = self {
1224            return true;
1225        }
1226
1227        false
1228    }
1229
1230    /// Returns if the inner address is for a system contract entity.
1231    pub fn is_system_key(&self) -> bool {
1232        if let Self::AddressableEntity(entity_addr) = self {
1233            return match entity_addr.tag() {
1234                EntityKindTag::System => true,
1235                EntityKindTag::SmartContract | EntityKindTag::Account => false,
1236            };
1237        }
1238        false
1239    }
1240
1241    /// Return true if the inner Key is of the smart contract type.
1242    pub fn is_smart_contract_key(&self) -> bool {
1243        matches!(
1244            self,
1245            Self::AddressableEntity(EntityAddr::SmartContract(_)) | Self::Hash(_)
1246        )
1247    }
1248
1249    /// Returns true if the key is of type [`Key::NamedKey`] and its Entry variant.
1250    pub fn is_named_key_entry(&self) -> bool {
1251        matches!(self, Self::NamedKey(_))
1252    }
1253
1254    /// Returns true if the key is of type [`Key::NamedKey`] and the variants have the
1255    /// same [`EntityAddr`].
1256    pub fn is_entry_for_base(&self, entity_addr: &EntityAddr) -> bool {
1257        if let Self::NamedKey(named_key_addr) = self {
1258            named_key_addr.entity_addr() == *entity_addr
1259        } else {
1260            false
1261        }
1262    }
1263
1264    /// Is the record under this key readable by the entity corresponding to the imputed address?
1265    pub fn is_readable(&self, entity_addr: &EntityAddr) -> bool {
1266        if entity_addr.is_system() {
1267            // the system can read everything
1268            return true;
1269        }
1270        let ret = match self {
1271            Key::BidAddr(_) => {
1272                // all bids are public information
1273                true
1274            }
1275            Key::URef(uref) => {
1276                // uref's require explicit permissions
1277                uref.is_readable()
1278            }
1279            Key::SystemEntityRegistry | Key::SmartContract(_) => {
1280                // the system entities and all packages are public info
1281                true
1282            }
1283            Key::Unbond(account_hash) => {
1284                // and an account holder can read their own account record
1285                entity_addr.tag() == EntityKindTag::Account
1286                    && entity_addr.value() == account_hash.value()
1287            }
1288            Key::NamedKey(named_key_addr) => {
1289                // an entity can read its own named keys
1290                &named_key_addr.entity_addr() == entity_addr
1291            }
1292            Key::ByteCode(_)
1293            | Key::Account(_)
1294            | Key::Hash(_)
1295            | Key::AddressableEntity(_)
1296            | Key::Balance(_)
1297            | Key::BalanceHold(_)
1298            | Key::Dictionary(_)
1299            | Key::Message(_)
1300            | Key::BlockGlobal(_)
1301            | Key::EntryPoint(_) => true,
1302            _ => false,
1303        };
1304        if !ret {
1305            let reading_entity_key = Key::AddressableEntity(*entity_addr);
1306            warn!(?reading_entity_key, attempted_key=?self,  "attempt to read without permission")
1307        }
1308        ret
1309    }
1310
1311    /// Is the record under this key addable by the entity corresponding to the imputed address?
1312    pub fn is_addable(&self, entity_addr: &EntityAddr) -> bool {
1313        // unlike readable / writeable which are universally supported,
1314        //  only some data types support commutative add / extension
1315        let ret = match self {
1316            Key::URef(uref) => uref.is_addable(),
1317            Key::AddressableEntity(addr_entity_addr) => {
1318                // an entity can extend itself (only associated keys, currently)
1319                entity_addr == addr_entity_addr
1320            }
1321            Key::NamedKey(named_key_addr) => {
1322                // an entity can extend its own named keys
1323                &named_key_addr.entity_addr() == entity_addr
1324            }
1325            _ => {
1326                // other data types do not support commutative addition / extension
1327                let adding_entity_key = Key::AddressableEntity(*entity_addr);
1328                warn!(?adding_entity_key, attempted_key=?self,  "attempt to add on an unsupported data type");
1329                return false; // we want the above more explicit warn message, not both messages.
1330            }
1331        };
1332        if !ret {
1333            let adding_entity_key = Key::AddressableEntity(*entity_addr);
1334            warn!(?adding_entity_key, attempted_key=?self,  "attempt to add without permission");
1335        }
1336        ret
1337    }
1338
1339    /// Is the record under this key writeable by the entity corresponding to the imputed address?
1340    pub fn is_writeable(&self, entity_addr: &EntityAddr) -> bool {
1341        if entity_addr.is_system() {
1342            // the system can write everything
1343            return true;
1344        }
1345        let ret = match self {
1346            Key::URef(uref) => uref.is_writeable(),
1347            Key::NamedKey(named_key_addr) => {
1348                // an entity can write to its own named keys
1349                &named_key_addr.entity_addr() == entity_addr
1350            }
1351            _ => {
1352                // only the system can write other kinds of records
1353                false
1354            }
1355        };
1356        if !ret {
1357            let writing_entity_key = Key::AddressableEntity(*entity_addr);
1358            warn!(?writing_entity_key, attempted_key=?self,  "attempt to write without permission")
1359        }
1360        ret
1361    }
1362
1363    /// Returns an entity addr for a [`Key::AddressableEntity`].
1364    pub fn into_entity_addr(self) -> Option<EntityAddr> {
1365        match self {
1366            Key::AddressableEntity(entity_addr) => Some(entity_addr),
1367            _ => None,
1368        }
1369    }
1370}
1371
1372impl Display for Key {
1373    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1374        match self {
1375            Key::Account(account_hash) => write!(f, "Key::Account({})", account_hash),
1376            Key::Hash(addr) => write!(f, "Key::Hash({})", base16::encode_lower(&addr)),
1377            Key::URef(uref) => write!(f, "Key::{}", uref), /* Display impl for URef will append */
1378            Key::Transfer(transfer_v1_addr) => {
1379                write!(f, "Key::Transfer({})", transfer_v1_addr)
1380            }
1381            Key::DeployInfo(addr) => write!(
1382                f,
1383                "Key::DeployInfo({})",
1384                base16::encode_lower(addr.as_ref())
1385            ),
1386            Key::EraInfo(era_id) => write!(f, "Key::EraInfo({})", era_id),
1387            Key::Balance(uref_addr) => {
1388                write!(f, "Key::Balance({})", base16::encode_lower(uref_addr))
1389            }
1390            Key::Bid(account_hash) => write!(f, "Key::Bid({})", account_hash),
1391            Key::Withdraw(account_hash) => write!(f, "Key::Withdraw({})", account_hash),
1392            Key::Dictionary(addr) => {
1393                write!(f, "Key::Dictionary({})", base16::encode_lower(addr))
1394            }
1395            Key::SystemEntityRegistry => write!(
1396                f,
1397                "Key::SystemEntityRegistry({})",
1398                base16::encode_lower(&PADDING_BYTES)
1399            ),
1400            Key::EraSummary => write!(
1401                f,
1402                "Key::EraSummary({})",
1403                base16::encode_lower(&PADDING_BYTES),
1404            ),
1405            Key::Unbond(account_hash) => write!(f, "Key::Unbond({})", account_hash),
1406            Key::ChainspecRegistry => write!(
1407                f,
1408                "Key::ChainspecRegistry({})",
1409                base16::encode_lower(&PADDING_BYTES)
1410            ),
1411            Key::ChecksumRegistry => {
1412                write!(
1413                    f,
1414                    "Key::ChecksumRegistry({})",
1415                    base16::encode_lower(&PADDING_BYTES)
1416                )
1417            }
1418            Key::BidAddr(bid_addr) => write!(f, "Key::BidAddr({})", bid_addr),
1419            Key::Message(message_addr) => {
1420                write!(f, "Key::Message({})", message_addr)
1421            }
1422            Key::SmartContract(package_addr) => {
1423                write!(f, "Key::Package({})", base16::encode_lower(package_addr))
1424            }
1425            Key::AddressableEntity(entity_addr) => write!(
1426                f,
1427                "Key::AddressableEntity({}-{})",
1428                entity_addr.tag(),
1429                base16::encode_lower(&entity_addr.value())
1430            ),
1431            Key::ByteCode(byte_code_addr) => {
1432                write!(f, "Key::ByteCode({})", byte_code_addr)
1433            }
1434            Key::NamedKey(named_key_addr) => {
1435                write!(f, "Key::NamedKey({})", named_key_addr)
1436            }
1437            Key::BlockGlobal(addr) => {
1438                write!(
1439                    f,
1440                    "Key::BlockGlobal({}-{})",
1441                    addr,
1442                    base16::encode_lower(&BLOCK_GLOBAL_PADDING_BYTES)
1443                )
1444            }
1445            Key::BalanceHold(balance_hold_addr) => {
1446                write!(f, "Key::BalanceHold({})", balance_hold_addr)
1447            }
1448            Key::EntryPoint(entry_point_addr) => {
1449                write!(f, "Key::EntryPointAddr({})", entry_point_addr)
1450            }
1451            Key::State(entity_addr) => {
1452                write!(f, "Key::State({})", entity_addr)
1453            }
1454        }
1455    }
1456}
1457
1458impl Debug for Key {
1459    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1460        write!(f, "{}", self)
1461    }
1462}
1463
1464impl Tagged<KeyTag> for Key {
1465    fn tag(&self) -> KeyTag {
1466        match self {
1467            Key::Account(_) => KeyTag::Account,
1468            Key::Hash(_) => KeyTag::Hash,
1469            Key::URef(_) => KeyTag::URef,
1470            Key::Transfer(_) => KeyTag::Transfer,
1471            Key::DeployInfo(_) => KeyTag::DeployInfo,
1472            Key::EraInfo(_) => KeyTag::EraInfo,
1473            Key::Balance(_) => KeyTag::Balance,
1474            Key::Bid(_) => KeyTag::Bid,
1475            Key::Withdraw(_) => KeyTag::Withdraw,
1476            Key::Dictionary(_) => KeyTag::Dictionary,
1477            Key::SystemEntityRegistry => KeyTag::SystemEntityRegistry,
1478            Key::EraSummary => KeyTag::EraSummary,
1479            Key::Unbond(_) => KeyTag::Unbond,
1480            Key::ChainspecRegistry => KeyTag::ChainspecRegistry,
1481            Key::ChecksumRegistry => KeyTag::ChecksumRegistry,
1482            Key::BidAddr(_) => KeyTag::BidAddr,
1483            Key::SmartContract(_) => KeyTag::Package,
1484            Key::AddressableEntity(..) => KeyTag::AddressableEntity,
1485            Key::ByteCode(..) => KeyTag::ByteCode,
1486            Key::Message(_) => KeyTag::Message,
1487            Key::NamedKey(_) => KeyTag::NamedKey,
1488            Key::BlockGlobal(_) => KeyTag::BlockGlobal,
1489            Key::BalanceHold(_) => KeyTag::BalanceHold,
1490            Key::EntryPoint(_) => KeyTag::EntryPoint,
1491            Key::State(_) => KeyTag::State,
1492        }
1493    }
1494}
1495
1496impl Tagged<u8> for Key {
1497    fn tag(&self) -> u8 {
1498        let key_tag: KeyTag = self.tag();
1499        key_tag as u8
1500    }
1501}
1502
1503impl From<URef> for Key {
1504    fn from(uref: URef) -> Key {
1505        Key::URef(uref)
1506    }
1507}
1508
1509impl From<AccountHash> for Key {
1510    fn from(account_hash: AccountHash) -> Key {
1511        Key::Account(account_hash)
1512    }
1513}
1514
1515impl From<PackageHash> for Key {
1516    fn from(package_hash: PackageHash) -> Key {
1517        Key::SmartContract(package_hash.value())
1518    }
1519}
1520
1521impl From<ContractWasmHash> for Key {
1522    fn from(wasm_hash: ContractWasmHash) -> Self {
1523        Key::Hash(wasm_hash.value())
1524    }
1525}
1526
1527impl From<ContractPackageHash> for Key {
1528    fn from(contract_package_hash: ContractPackageHash) -> Self {
1529        Key::Hash(contract_package_hash.value())
1530    }
1531}
1532
1533impl From<ContractHash> for Key {
1534    fn from(contract_hash: ContractHash) -> Self {
1535        Key::Hash(contract_hash.value())
1536    }
1537}
1538
1539impl From<EntityAddr> for Key {
1540    fn from(entity_addr: EntityAddr) -> Self {
1541        Key::AddressableEntity(entity_addr)
1542    }
1543}
1544
1545impl From<NamedKeyAddr> for Key {
1546    fn from(value: NamedKeyAddr) -> Self {
1547        Key::NamedKey(value)
1548    }
1549}
1550
1551impl From<ByteCodeAddr> for Key {
1552    fn from(value: ByteCodeAddr) -> Self {
1553        Key::ByteCode(value)
1554    }
1555}
1556
1557impl ToBytes for Key {
1558    fn to_bytes(&self) -> Result<Vec<u8>, Error> {
1559        let mut result = bytesrepr::unchecked_allocate_buffer(self);
1560        self.write_bytes(&mut result)?;
1561        Ok(result)
1562    }
1563
1564    fn serialized_length(&self) -> usize {
1565        match self {
1566            Key::Account(account_hash) => {
1567                KEY_ID_SERIALIZED_LENGTH + account_hash.serialized_length()
1568            }
1569            Key::Hash(_) => KEY_HASH_SERIALIZED_LENGTH,
1570            Key::URef(_) => KEY_UREF_SERIALIZED_LENGTH,
1571            Key::Transfer(_) => KEY_TRANSFER_SERIALIZED_LENGTH,
1572            Key::DeployInfo(_) => KEY_DEPLOY_INFO_SERIALIZED_LENGTH,
1573            Key::EraInfo(_) => KEY_ERA_INFO_SERIALIZED_LENGTH,
1574            Key::Balance(_) => KEY_BALANCE_SERIALIZED_LENGTH,
1575            Key::Bid(_) => KEY_BID_SERIALIZED_LENGTH,
1576            Key::Withdraw(_) => KEY_WITHDRAW_SERIALIZED_LENGTH,
1577            Key::Dictionary(_) => KEY_DICTIONARY_SERIALIZED_LENGTH,
1578            Key::SystemEntityRegistry => KEY_SYSTEM_ENTITY_REGISTRY_SERIALIZED_LENGTH,
1579            Key::EraSummary => KEY_ERA_SUMMARY_SERIALIZED_LENGTH,
1580            Key::Unbond(_) => KEY_UNBOND_SERIALIZED_LENGTH,
1581            Key::ChainspecRegistry => KEY_CHAINSPEC_REGISTRY_SERIALIZED_LENGTH,
1582            Key::ChecksumRegistry => KEY_CHECKSUM_REGISTRY_SERIALIZED_LENGTH,
1583            Key::BidAddr(bid_addr) => KEY_ID_SERIALIZED_LENGTH + bid_addr.serialized_length(),
1584            Key::SmartContract(_) => KEY_PACKAGE_SERIALIZED_LENGTH,
1585            Key::AddressableEntity(entity_addr) => {
1586                KEY_ID_SERIALIZED_LENGTH + entity_addr.serialized_length()
1587            }
1588            Key::ByteCode(byte_code_addr) => {
1589                KEY_ID_SERIALIZED_LENGTH + byte_code_addr.serialized_length()
1590            }
1591            Key::Message(message_addr) => {
1592                KEY_ID_SERIALIZED_LENGTH + message_addr.serialized_length()
1593            }
1594            Key::NamedKey(named_key_addr) => {
1595                KEY_ID_SERIALIZED_LENGTH + named_key_addr.serialized_length()
1596            }
1597            Key::BlockGlobal(addr) => {
1598                KEY_ID_SERIALIZED_LENGTH
1599                    + addr.serialized_length()
1600                    + BLOCK_GLOBAL_PADDING_BYTES.len()
1601            }
1602            Key::BalanceHold(balance_hold_addr) => {
1603                KEY_ID_SERIALIZED_LENGTH + balance_hold_addr.serialized_length()
1604            }
1605            Key::EntryPoint(entry_point_addr) => {
1606                U8_SERIALIZED_LENGTH + entry_point_addr.serialized_length()
1607            }
1608            Key::State(entity_addr) => KEY_ID_SERIALIZED_LENGTH + entity_addr.serialized_length(),
1609        }
1610    }
1611
1612    fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), Error> {
1613        writer.push(self.tag());
1614        match self {
1615            Key::Account(account_hash) => account_hash.write_bytes(writer),
1616            Key::Hash(hash) => hash.write_bytes(writer),
1617            Key::URef(uref) => uref.write_bytes(writer),
1618            Key::Transfer(addr) => addr.write_bytes(writer),
1619            Key::DeployInfo(deploy_hash) => deploy_hash.write_bytes(writer),
1620            Key::EraInfo(era_id) => era_id.write_bytes(writer),
1621            Key::Balance(uref_addr) => uref_addr.write_bytes(writer),
1622            Key::Bid(account_hash) => account_hash.write_bytes(writer),
1623            Key::Withdraw(account_hash) => account_hash.write_bytes(writer),
1624            Key::Dictionary(addr) => addr.write_bytes(writer),
1625            Key::Unbond(account_hash) => account_hash.write_bytes(writer),
1626            Key::SystemEntityRegistry
1627            | Key::EraSummary
1628            | Key::ChainspecRegistry
1629            | Key::ChecksumRegistry => PADDING_BYTES.write_bytes(writer),
1630            Key::BlockGlobal(addr) => {
1631                addr.write_bytes(writer)?;
1632                BLOCK_GLOBAL_PADDING_BYTES.write_bytes(writer)
1633            }
1634            Key::BidAddr(bid_addr) => bid_addr.write_bytes(writer),
1635            Key::SmartContract(package_addr) => package_addr.write_bytes(writer),
1636            Key::AddressableEntity(entity_addr) => entity_addr.write_bytes(writer),
1637            Key::ByteCode(byte_code_addr) => byte_code_addr.write_bytes(writer),
1638            Key::Message(message_addr) => message_addr.write_bytes(writer),
1639            Key::NamedKey(named_key_addr) => named_key_addr.write_bytes(writer),
1640            Key::BalanceHold(balance_hold_addr) => balance_hold_addr.write_bytes(writer),
1641            Key::EntryPoint(entry_point_addr) => entry_point_addr.write_bytes(writer),
1642            Key::State(entity_addr) => entity_addr.write_bytes(writer),
1643        }
1644    }
1645}
1646
1647impl FromBytes for Key {
1648    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error> {
1649        if bytes.is_empty() {
1650            error!("FromBytes for Key: bytes length should not be 0");
1651        }
1652        let (tag, remainder) = match KeyTag::from_bytes(bytes) {
1653            Ok((tag, rem)) => (tag, rem),
1654            Err(err) => {
1655                error!(%err, "FromBytes for Key");
1656                return Err(err);
1657            }
1658        };
1659        match tag {
1660            KeyTag::Account => {
1661                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1662                Ok((Key::Account(account_hash), rem))
1663            }
1664            KeyTag::Hash => {
1665                let (hash, rem) = HashAddr::from_bytes(remainder)?;
1666                Ok((Key::Hash(hash), rem))
1667            }
1668            KeyTag::URef => {
1669                let (uref, rem) = URef::from_bytes(remainder)?;
1670                Ok((Key::URef(uref), rem))
1671            }
1672            KeyTag::Transfer => {
1673                let (transfer_v1_addr, rem) = TransferAddr::from_bytes(remainder)?;
1674                Ok((Key::Transfer(transfer_v1_addr), rem))
1675            }
1676            KeyTag::DeployInfo => {
1677                let (deploy_hash, rem) = DeployHash::from_bytes(remainder)?;
1678                Ok((Key::DeployInfo(deploy_hash), rem))
1679            }
1680            KeyTag::EraInfo => {
1681                let (era_id, rem) = EraId::from_bytes(remainder)?;
1682                Ok((Key::EraInfo(era_id), rem))
1683            }
1684            KeyTag::Balance => {
1685                let (uref_addr, rem) = URefAddr::from_bytes(remainder)?;
1686                Ok((Key::Balance(uref_addr), rem))
1687            }
1688            KeyTag::Bid => {
1689                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1690                Ok((Key::Bid(account_hash), rem))
1691            }
1692            KeyTag::Withdraw => {
1693                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1694                Ok((Key::Withdraw(account_hash), rem))
1695            }
1696            KeyTag::Dictionary => {
1697                let (addr, rem) = DictionaryAddr::from_bytes(remainder)?;
1698                Ok((Key::Dictionary(addr), rem))
1699            }
1700            KeyTag::SystemEntityRegistry => {
1701                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1702                Ok((Key::SystemEntityRegistry, rem))
1703            }
1704            KeyTag::EraSummary => {
1705                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1706                Ok((Key::EraSummary, rem))
1707            }
1708            KeyTag::Unbond => {
1709                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1710                Ok((Key::Unbond(account_hash), rem))
1711            }
1712            KeyTag::ChainspecRegistry => {
1713                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1714                Ok((Key::ChainspecRegistry, rem))
1715            }
1716            KeyTag::ChecksumRegistry => {
1717                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1718                Ok((Key::ChecksumRegistry, rem))
1719            }
1720            KeyTag::BidAddr => {
1721                let (bid_addr, rem) = BidAddr::from_bytes(remainder)?;
1722                Ok((Key::BidAddr(bid_addr), rem))
1723            }
1724            KeyTag::Package => {
1725                let (package_addr, rem) = PackageAddr::from_bytes(remainder)?;
1726                Ok((Key::SmartContract(package_addr), rem))
1727            }
1728            KeyTag::AddressableEntity => {
1729                let (entity_addr, rem) = EntityAddr::from_bytes(remainder)?;
1730                Ok((Key::AddressableEntity(entity_addr), rem))
1731            }
1732            KeyTag::ByteCode => {
1733                let (byte_code_addr, rem) = ByteCodeAddr::from_bytes(remainder)?;
1734                Ok((Key::ByteCode(byte_code_addr), rem))
1735            }
1736            KeyTag::Message => {
1737                let (message_addr, rem) = MessageAddr::from_bytes(remainder)?;
1738                Ok((Key::Message(message_addr), rem))
1739            }
1740            KeyTag::NamedKey => {
1741                let (named_key_addr, rem) = NamedKeyAddr::from_bytes(remainder)?;
1742                Ok((Key::NamedKey(named_key_addr), rem))
1743            }
1744            KeyTag::BlockGlobal => {
1745                let (addr, rem) = BlockGlobalAddr::from_bytes(remainder)?;
1746                let (_, rem) = <[u8; 31]>::from_bytes(rem)?; // strip padding
1747                Ok((Key::BlockGlobal(addr), rem))
1748            }
1749            KeyTag::BalanceHold => {
1750                let (balance_hold_addr, rem) = BalanceHoldAddr::from_bytes(remainder)?;
1751                Ok((Key::BalanceHold(balance_hold_addr), rem))
1752            }
1753            KeyTag::EntryPoint => {
1754                let (entry_point_addr, rem) = EntryPointAddr::from_bytes(remainder)?;
1755                Ok((Key::EntryPoint(entry_point_addr), rem))
1756            }
1757            KeyTag::State => {
1758                let (entity_addr, rem) = EntityAddr::from_bytes(remainder)?;
1759                Ok((Key::State(entity_addr), rem))
1760            }
1761        }
1762    }
1763}
1764
1765#[allow(dead_code)]
1766fn please_add_to_distribution_impl(key: Key) {
1767    // If you've been forced to come here, you likely need to add your variant to the
1768    // `Distribution` impl for `Key`.
1769    match key {
1770        Key::Account(_) => unimplemented!(),
1771        Key::Hash(_) => unimplemented!(),
1772        Key::URef(_) => unimplemented!(),
1773        Key::Transfer(_) => unimplemented!(),
1774        Key::DeployInfo(_) => unimplemented!(),
1775        Key::EraInfo(_) => unimplemented!(),
1776        Key::Balance(_) => unimplemented!(),
1777        Key::Bid(_) => unimplemented!(),
1778        Key::Withdraw(_) => unimplemented!(),
1779        Key::Dictionary(_) => unimplemented!(),
1780        Key::SystemEntityRegistry => unimplemented!(),
1781        Key::EraSummary => unimplemented!(),
1782        Key::Unbond(_) => unimplemented!(),
1783        Key::ChainspecRegistry => unimplemented!(),
1784        Key::ChecksumRegistry => unimplemented!(),
1785        Key::BidAddr(_) => unimplemented!(),
1786        Key::SmartContract(_) => unimplemented!(),
1787        Key::AddressableEntity(..) => unimplemented!(),
1788        Key::ByteCode(..) => unimplemented!(),
1789        Key::Message(_) => unimplemented!(),
1790        Key::NamedKey(_) => unimplemented!(),
1791        Key::BlockGlobal(_) => unimplemented!(),
1792        Key::BalanceHold(_) => unimplemented!(),
1793        Key::EntryPoint(_) => unimplemented!(),
1794        Key::State(_) => unimplemented!(),
1795    }
1796}
1797
1798#[cfg(any(feature = "testing", test))]
1799impl Distribution<Key> for Standard {
1800    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Key {
1801        match rng.gen_range(0..=24) {
1802            0 => Key::Account(rng.gen()),
1803            1 => Key::Hash(rng.gen()),
1804            2 => Key::URef(rng.gen()),
1805            3 => Key::Transfer(TransferAddr::new(rng.gen())),
1806            4 => Key::DeployInfo(DeployHash::from_raw(rng.gen())),
1807            5 => Key::EraInfo(EraId::new(rng.gen())),
1808            6 => Key::Balance(rng.gen()),
1809            7 => Key::Bid(rng.gen()),
1810            8 => Key::Withdraw(rng.gen()),
1811            9 => Key::Dictionary(rng.gen()),
1812            10 => Key::SystemEntityRegistry,
1813            11 => Key::EraSummary,
1814            12 => Key::Unbond(rng.gen()),
1815            13 => Key::ChainspecRegistry,
1816            14 => Key::ChecksumRegistry,
1817            15 => Key::BidAddr(rng.gen()),
1818            16 => Key::SmartContract(rng.gen()),
1819            17 => Key::AddressableEntity(rng.gen()),
1820            18 => Key::ByteCode(rng.gen()),
1821            19 => Key::Message(rng.gen()),
1822            20 => Key::NamedKey(NamedKeyAddr::new_named_key_entry(rng.gen(), rng.gen())),
1823            21 => Key::BlockGlobal(rng.gen()),
1824            22 => Key::BalanceHold(rng.gen()),
1825            23 => Key::EntryPoint(rng.gen()),
1826            24 => Key::State(rng.gen()),
1827            _ => unreachable!(),
1828        }
1829    }
1830}
1831
1832mod serde_helpers {
1833    use super::*;
1834
1835    #[derive(Serialize)]
1836    pub(super) enum BinarySerHelper<'a> {
1837        Account(&'a AccountHash),
1838        Hash(&'a HashAddr),
1839        URef(&'a URef),
1840        Transfer(&'a TransferAddr),
1841        #[serde(with = "crate::serde_helpers::deploy_hash_as_array")]
1842        DeployInfo(&'a DeployHash),
1843        EraInfo(&'a EraId),
1844        Balance(&'a URefAddr),
1845        Bid(&'a AccountHash),
1846        Withdraw(&'a AccountHash),
1847        Dictionary(&'a HashAddr),
1848        SystemEntityRegistry,
1849        EraSummary,
1850        Unbond(&'a AccountHash),
1851        ChainspecRegistry,
1852        ChecksumRegistry,
1853        BidAddr(&'a BidAddr),
1854        Package(&'a PackageAddr),
1855        AddressableEntity(&'a EntityAddr),
1856        ByteCode(&'a ByteCodeAddr),
1857        Message(&'a MessageAddr),
1858        NamedKey(&'a NamedKeyAddr),
1859        BlockGlobal(&'a BlockGlobalAddr),
1860        BalanceHold(&'a BalanceHoldAddr),
1861        EntryPoint(&'a EntryPointAddr),
1862        State(&'a EntityAddr),
1863    }
1864
1865    #[derive(Deserialize)]
1866    pub(super) enum BinaryDeserHelper {
1867        Account(AccountHash),
1868        Hash(HashAddr),
1869        URef(URef),
1870        Transfer(TransferAddr),
1871        #[serde(with = "crate::serde_helpers::deploy_hash_as_array")]
1872        DeployInfo(DeployHash),
1873        EraInfo(EraId),
1874        Balance(URefAddr),
1875        Bid(AccountHash),
1876        Withdraw(AccountHash),
1877        Dictionary(DictionaryAddr),
1878        SystemEntityRegistry,
1879        EraSummary,
1880        Unbond(AccountHash),
1881        ChainspecRegistry,
1882        ChecksumRegistry,
1883        BidAddr(BidAddr),
1884        Package(PackageAddr),
1885        AddressableEntity(EntityAddr),
1886        ByteCode(ByteCodeAddr),
1887        Message(MessageAddr),
1888        NamedKey(NamedKeyAddr),
1889        BlockGlobal(BlockGlobalAddr),
1890        BalanceHold(BalanceHoldAddr),
1891        EntryPoint(EntryPointAddr),
1892        State(EntityAddr),
1893    }
1894
1895    impl<'a> From<&'a Key> for BinarySerHelper<'a> {
1896        fn from(key: &'a Key) -> Self {
1897            match key {
1898                Key::Account(account_hash) => BinarySerHelper::Account(account_hash),
1899                Key::Hash(hash_addr) => BinarySerHelper::Hash(hash_addr),
1900                Key::URef(uref) => BinarySerHelper::URef(uref),
1901                Key::Transfer(transfer_v1_addr) => BinarySerHelper::Transfer(transfer_v1_addr),
1902                Key::DeployInfo(deploy_hash) => BinarySerHelper::DeployInfo(deploy_hash),
1903                Key::EraInfo(era_id) => BinarySerHelper::EraInfo(era_id),
1904                Key::Balance(uref_addr) => BinarySerHelper::Balance(uref_addr),
1905                Key::Bid(account_hash) => BinarySerHelper::Bid(account_hash),
1906                Key::Withdraw(account_hash) => BinarySerHelper::Withdraw(account_hash),
1907                Key::Dictionary(addr) => BinarySerHelper::Dictionary(addr),
1908                Key::SystemEntityRegistry => BinarySerHelper::SystemEntityRegistry,
1909                Key::EraSummary => BinarySerHelper::EraSummary,
1910                Key::Unbond(account_hash) => BinarySerHelper::Unbond(account_hash),
1911                Key::ChainspecRegistry => BinarySerHelper::ChainspecRegistry,
1912                Key::ChecksumRegistry => BinarySerHelper::ChecksumRegistry,
1913                Key::BidAddr(bid_addr) => BinarySerHelper::BidAddr(bid_addr),
1914                Key::Message(message_addr) => BinarySerHelper::Message(message_addr),
1915                Key::SmartContract(package_addr) => BinarySerHelper::Package(package_addr),
1916                Key::AddressableEntity(entity_addr) => {
1917                    BinarySerHelper::AddressableEntity(entity_addr)
1918                }
1919                Key::ByteCode(byte_code_addr) => BinarySerHelper::ByteCode(byte_code_addr),
1920                Key::NamedKey(named_key_addr) => BinarySerHelper::NamedKey(named_key_addr),
1921                Key::BlockGlobal(addr) => BinarySerHelper::BlockGlobal(addr),
1922                Key::BalanceHold(balance_hold_addr) => {
1923                    BinarySerHelper::BalanceHold(balance_hold_addr)
1924                }
1925                Key::EntryPoint(entry_point_addr) => BinarySerHelper::EntryPoint(entry_point_addr),
1926                Key::State(entity_addr) => BinarySerHelper::State(entity_addr),
1927            }
1928        }
1929    }
1930
1931    impl From<BinaryDeserHelper> for Key {
1932        fn from(helper: BinaryDeserHelper) -> Self {
1933            match helper {
1934                BinaryDeserHelper::Account(account_hash) => Key::Account(account_hash),
1935                BinaryDeserHelper::Hash(hash_addr) => Key::Hash(hash_addr),
1936                BinaryDeserHelper::URef(uref) => Key::URef(uref),
1937                BinaryDeserHelper::Transfer(transfer_v1_addr) => Key::Transfer(transfer_v1_addr),
1938                BinaryDeserHelper::DeployInfo(deploy_hash) => Key::DeployInfo(deploy_hash),
1939                BinaryDeserHelper::EraInfo(era_id) => Key::EraInfo(era_id),
1940                BinaryDeserHelper::Balance(uref_addr) => Key::Balance(uref_addr),
1941                BinaryDeserHelper::Bid(account_hash) => Key::Bid(account_hash),
1942                BinaryDeserHelper::Withdraw(account_hash) => Key::Withdraw(account_hash),
1943                BinaryDeserHelper::Dictionary(addr) => Key::Dictionary(addr),
1944                BinaryDeserHelper::SystemEntityRegistry => Key::SystemEntityRegistry,
1945                BinaryDeserHelper::EraSummary => Key::EraSummary,
1946                BinaryDeserHelper::Unbond(account_hash) => Key::Unbond(account_hash),
1947                BinaryDeserHelper::ChainspecRegistry => Key::ChainspecRegistry,
1948                BinaryDeserHelper::ChecksumRegistry => Key::ChecksumRegistry,
1949                BinaryDeserHelper::BidAddr(bid_addr) => Key::BidAddr(bid_addr),
1950                BinaryDeserHelper::Message(message_addr) => Key::Message(message_addr),
1951                BinaryDeserHelper::Package(package_addr) => Key::SmartContract(package_addr),
1952                BinaryDeserHelper::AddressableEntity(entity_addr) => {
1953                    Key::AddressableEntity(entity_addr)
1954                }
1955                BinaryDeserHelper::ByteCode(byte_code_addr) => Key::ByteCode(byte_code_addr),
1956                BinaryDeserHelper::NamedKey(named_key_addr) => Key::NamedKey(named_key_addr),
1957                BinaryDeserHelper::BlockGlobal(addr) => Key::BlockGlobal(addr),
1958                BinaryDeserHelper::BalanceHold(balance_hold_addr) => {
1959                    Key::BalanceHold(balance_hold_addr)
1960                }
1961                BinaryDeserHelper::EntryPoint(entry_point_addr) => {
1962                    Key::EntryPoint(entry_point_addr)
1963                }
1964                BinaryDeserHelper::State(entity_addr) => Key::State(entity_addr),
1965            }
1966        }
1967    }
1968}
1969
1970impl Serialize for Key {
1971    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1972        if serializer.is_human_readable() {
1973            self.to_formatted_string().serialize(serializer)
1974        } else {
1975            serde_helpers::BinarySerHelper::from(self).serialize(serializer)
1976        }
1977    }
1978}
1979
1980impl<'de> Deserialize<'de> for Key {
1981    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1982        if deserializer.is_human_readable() {
1983            let formatted_key = String::deserialize(deserializer)?;
1984            Key::from_formatted_str(&formatted_key).map_err(SerdeError::custom)
1985        } else {
1986            let binary_helper = serde_helpers::BinaryDeserHelper::deserialize(deserializer)?;
1987            Ok(Key::from(binary_helper))
1988        }
1989    }
1990}
1991
1992#[cfg(test)]
1993mod tests {
1994    use std::string::ToString;
1995
1996    use super::*;
1997    use crate::{
1998        account::ACCOUNT_HASH_FORMATTED_STRING_PREFIX,
1999        bytesrepr::{Error, FromBytes},
2000        uref::UREF_FORMATTED_STRING_PREFIX,
2001        AccessRights, BlockTime, URef,
2002    };
2003
2004    const TRANSFER_ADDR_FORMATTED_STRING_PREFIX: &str = "transfer-";
2005    const ENTITY_PREFIX: &str = "entity-";
2006    const ACCOUNT_ENTITY_PREFIX: &str = "account-";
2007
2008    const BYTE_CODE_PREFIX: &str = "byte-code-";
2009    const EMPTY_PREFIX: &str = "empty-";
2010
2011    const ACCOUNT_KEY: Key = Key::Account(AccountHash::new([42; 32]));
2012    const HASH_KEY: Key = Key::Hash([42; 32]);
2013    const UREF_KEY: Key = Key::URef(URef::new([42; 32], AccessRights::READ));
2014    const TRANSFER_KEY: Key = Key::Transfer(TransferAddr::new([42; 32]));
2015    const DEPLOY_INFO_KEY: Key = Key::DeployInfo(DeployHash::from_raw([42; 32]));
2016    const ERA_INFO_KEY: Key = Key::EraInfo(EraId::new(42));
2017    const BALANCE_KEY: Key = Key::Balance([42; 32]);
2018    const BID_KEY: Key = Key::Bid(AccountHash::new([42; 32]));
2019    const UNIFIED_BID_KEY: Key = Key::BidAddr(BidAddr::legacy([42; 32]));
2020    const VALIDATOR_BID_KEY: Key = Key::BidAddr(BidAddr::new_validator_addr([2; 32]));
2021    const DELEGATOR_BID_KEY: Key =
2022        Key::BidAddr(BidAddr::new_delegator_account_addr(([2; 32], [9; 32])));
2023    const WITHDRAW_KEY: Key = Key::Withdraw(AccountHash::new([42; 32]));
2024    const DICTIONARY_KEY: Key = Key::Dictionary([42; 32]);
2025    const SYSTEM_ENTITY_REGISTRY_KEY: Key = Key::SystemEntityRegistry;
2026    const ERA_SUMMARY_KEY: Key = Key::EraSummary;
2027    const UNBOND_KEY: Key = Key::Unbond(AccountHash::new([42; 32]));
2028    const CHAINSPEC_REGISTRY_KEY: Key = Key::ChainspecRegistry;
2029    const CHECKSUM_REGISTRY_KEY: Key = Key::ChecksumRegistry;
2030    const PACKAGE_KEY: Key = Key::SmartContract([42; 32]);
2031    const ADDRESSABLE_ENTITY_SYSTEM_KEY: Key =
2032        Key::AddressableEntity(EntityAddr::new_system([42; 32]));
2033    const ADDRESSABLE_ENTITY_ACCOUNT_KEY: Key =
2034        Key::AddressableEntity(EntityAddr::new_account([42; 32]));
2035    const ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY: Key =
2036        Key::AddressableEntity(EntityAddr::new_smart_contract([42; 32]));
2037    const BYTE_CODE_EMPTY_KEY: Key = Key::ByteCode(ByteCodeAddr::Empty);
2038    const BYTE_CODE_V1_WASM_KEY: Key = Key::ByteCode(ByteCodeAddr::V1CasperWasm([42; 32]));
2039    const MESSAGE_TOPIC_KEY: Key = Key::Message(MessageAddr::new_topic_addr(
2040        EntityAddr::SmartContract([42; 32]),
2041        TopicNameHash::new([42; 32]),
2042    ));
2043    const MESSAGE_KEY: Key = Key::Message(MessageAddr::new_message_addr(
2044        EntityAddr::SmartContract([42; 32]),
2045        TopicNameHash::new([2; 32]),
2046        15,
2047    ));
2048    const NAMED_KEY: Key = Key::NamedKey(NamedKeyAddr::new_named_key_entry(
2049        EntityAddr::new_smart_contract([42; 32]),
2050        [43; 32],
2051    ));
2052    const BLOCK_TIME_KEY: Key = Key::BlockGlobal(BlockGlobalAddr::BlockTime);
2053    const BLOCK_MESSAGE_COUNT_KEY: Key = Key::BlockGlobal(BlockGlobalAddr::MessageCount);
2054    // const STATE_KEY: Key = Key::State(EntityAddr::new_contract_entity_addr([42; 32]));
2055    const BALANCE_HOLD: Key =
2056        Key::BalanceHold(BalanceHoldAddr::new_gas([42; 32], BlockTime::new(100)));
2057    const STATE_KEY: Key = Key::State(EntityAddr::new_smart_contract([42; 32]));
2058    const KEYS: &[Key] = &[
2059        ACCOUNT_KEY,
2060        HASH_KEY,
2061        UREF_KEY,
2062        TRANSFER_KEY,
2063        DEPLOY_INFO_KEY,
2064        ERA_INFO_KEY,
2065        BALANCE_KEY,
2066        BID_KEY,
2067        WITHDRAW_KEY,
2068        DICTIONARY_KEY,
2069        SYSTEM_ENTITY_REGISTRY_KEY,
2070        ERA_SUMMARY_KEY,
2071        UNBOND_KEY,
2072        CHAINSPEC_REGISTRY_KEY,
2073        CHECKSUM_REGISTRY_KEY,
2074        UNIFIED_BID_KEY,
2075        VALIDATOR_BID_KEY,
2076        DELEGATOR_BID_KEY,
2077        PACKAGE_KEY,
2078        ADDRESSABLE_ENTITY_SYSTEM_KEY,
2079        ADDRESSABLE_ENTITY_ACCOUNT_KEY,
2080        ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY,
2081        BYTE_CODE_EMPTY_KEY,
2082        BYTE_CODE_V1_WASM_KEY,
2083        MESSAGE_TOPIC_KEY,
2084        MESSAGE_KEY,
2085        NAMED_KEY,
2086        BLOCK_TIME_KEY,
2087        BLOCK_MESSAGE_COUNT_KEY,
2088        BALANCE_HOLD,
2089        STATE_KEY,
2090    ];
2091    const HEX_STRING: &str = "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a";
2092    const TOPIC_NAME_HEX_STRING: &str =
2093        "0202020202020202020202020202020202020202020202020202020202020202";
2094    const MESSAGE_INDEX_HEX_STRING: &str = "f";
2095    const UNIFIED_HEX_STRING: &str =
2096        "002a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a";
2097    const VALIDATOR_HEX_STRING: &str =
2098        "010202020202020202020202020202020202020202020202020202020202020202";
2099    const DELEGATOR_HEX_STRING: &str =
2100        "0202020202020202020202020202020202020202020202020202020202020202020909090909090909090909090909090909090909090909090909090909090909";
2101
2102    fn test_readable(right: AccessRights, is_true: bool) {
2103        assert_eq!(right.is_readable(), is_true)
2104    }
2105
2106    #[test]
2107    fn test_is_readable() {
2108        test_readable(AccessRights::READ, true);
2109        test_readable(AccessRights::READ_ADD, true);
2110        test_readable(AccessRights::READ_WRITE, true);
2111        test_readable(AccessRights::READ_ADD_WRITE, true);
2112        test_readable(AccessRights::ADD, false);
2113        test_readable(AccessRights::ADD_WRITE, false);
2114        test_readable(AccessRights::WRITE, false);
2115    }
2116
2117    fn test_writable(right: AccessRights, is_true: bool) {
2118        assert_eq!(right.is_writeable(), is_true)
2119    }
2120
2121    #[test]
2122    fn test_is_writable() {
2123        test_writable(AccessRights::WRITE, true);
2124        test_writable(AccessRights::READ_WRITE, true);
2125        test_writable(AccessRights::ADD_WRITE, true);
2126        test_writable(AccessRights::READ, false);
2127        test_writable(AccessRights::ADD, false);
2128        test_writable(AccessRights::READ_ADD, false);
2129        test_writable(AccessRights::READ_ADD_WRITE, true);
2130    }
2131
2132    fn test_addable(right: AccessRights, is_true: bool) {
2133        assert_eq!(right.is_addable(), is_true)
2134    }
2135
2136    #[test]
2137    fn test_is_addable() {
2138        test_addable(AccessRights::ADD, true);
2139        test_addable(AccessRights::READ_ADD, true);
2140        test_addable(AccessRights::READ_WRITE, false);
2141        test_addable(AccessRights::ADD_WRITE, true);
2142        test_addable(AccessRights::READ, false);
2143        test_addable(AccessRights::WRITE, false);
2144        test_addable(AccessRights::READ_ADD_WRITE, true);
2145    }
2146
2147    #[test]
2148    fn should_display_key() {
2149        assert_eq!(
2150            format!("{}", ACCOUNT_KEY),
2151            format!("Key::Account({})", HEX_STRING)
2152        );
2153        assert_eq!(
2154            format!("{}", HASH_KEY),
2155            format!("Key::Hash({})", HEX_STRING)
2156        );
2157        assert_eq!(
2158            format!("{}", UREF_KEY),
2159            format!("Key::URef({}, READ)", HEX_STRING)
2160        );
2161        assert_eq!(
2162            format!("{}", TRANSFER_KEY),
2163            format!("Key::Transfer({})", HEX_STRING)
2164        );
2165        assert_eq!(
2166            format!("{}", DEPLOY_INFO_KEY),
2167            format!("Key::DeployInfo({})", HEX_STRING)
2168        );
2169        assert_eq!(
2170            format!("{}", ERA_INFO_KEY),
2171            "Key::EraInfo(era 42)".to_string()
2172        );
2173        assert_eq!(
2174            format!("{}", BALANCE_KEY),
2175            format!("Key::Balance({})", HEX_STRING)
2176        );
2177        assert_eq!(format!("{}", BID_KEY), format!("Key::Bid({})", HEX_STRING));
2178        assert_eq!(
2179            format!("{}", UNIFIED_BID_KEY),
2180            format!("Key::BidAddr({})", UNIFIED_HEX_STRING)
2181        );
2182        assert_eq!(
2183            format!("{}", VALIDATOR_BID_KEY),
2184            format!("Key::BidAddr({})", VALIDATOR_HEX_STRING)
2185        );
2186        assert_eq!(
2187            format!("{}", DELEGATOR_BID_KEY),
2188            format!("Key::BidAddr({})", DELEGATOR_HEX_STRING)
2189        );
2190        assert_eq!(
2191            format!("{}", WITHDRAW_KEY),
2192            format!("Key::Withdraw({})", HEX_STRING)
2193        );
2194        assert_eq!(
2195            format!("{}", DICTIONARY_KEY),
2196            format!("Key::Dictionary({})", HEX_STRING)
2197        );
2198        assert_eq!(
2199            format!("{}", SYSTEM_ENTITY_REGISTRY_KEY),
2200            format!(
2201                "Key::SystemEntityRegistry({})",
2202                base16::encode_lower(&PADDING_BYTES)
2203            )
2204        );
2205        assert_eq!(
2206            format!("{}", ERA_SUMMARY_KEY),
2207            format!("Key::EraSummary({})", base16::encode_lower(&PADDING_BYTES))
2208        );
2209        assert_eq!(
2210            format!("{}", UNBOND_KEY),
2211            format!("Key::Unbond({})", HEX_STRING)
2212        );
2213        assert_eq!(
2214            format!("{}", CHAINSPEC_REGISTRY_KEY),
2215            format!(
2216                "Key::ChainspecRegistry({})",
2217                base16::encode_lower(&PADDING_BYTES)
2218            )
2219        );
2220        assert_eq!(
2221            format!("{}", CHECKSUM_REGISTRY_KEY),
2222            format!(
2223                "Key::ChecksumRegistry({})",
2224                base16::encode_lower(&PADDING_BYTES),
2225            )
2226        );
2227        assert_eq!(
2228            format!("{}", PACKAGE_KEY),
2229            format!("Key::Package({})", HEX_STRING)
2230        );
2231        assert_eq!(
2232            format!("{}", ADDRESSABLE_ENTITY_SYSTEM_KEY),
2233            format!("Key::AddressableEntity(system-{})", HEX_STRING)
2234        );
2235        assert_eq!(
2236            format!("{}", ADDRESSABLE_ENTITY_ACCOUNT_KEY),
2237            format!("Key::AddressableEntity(account-{})", HEX_STRING)
2238        );
2239        assert_eq!(
2240            format!("{}", ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY),
2241            format!("Key::AddressableEntity(contract-{})", HEX_STRING)
2242        );
2243        assert_eq!(
2244            format!("{}", BYTE_CODE_EMPTY_KEY),
2245            format!(
2246                "Key::ByteCode(byte-code-empty-{})",
2247                base16::encode_lower(&[0u8; 32])
2248            )
2249        );
2250        assert_eq!(
2251            format!("{}", BYTE_CODE_V1_WASM_KEY),
2252            format!("Key::ByteCode(byte-code-v1-wasm-{})", HEX_STRING)
2253        );
2254        assert_eq!(
2255            format!("{}", MESSAGE_TOPIC_KEY),
2256            format!(
2257                "Key::Message(entity-contract-{}-{})",
2258                HEX_STRING, HEX_STRING
2259            )
2260        );
2261        assert_eq!(
2262            format!("{}", MESSAGE_KEY),
2263            format!(
2264                "Key::Message(entity-contract-{}-{}-{})",
2265                HEX_STRING, TOPIC_NAME_HEX_STRING, MESSAGE_INDEX_HEX_STRING
2266            )
2267        );
2268
2269        assert_eq!(
2270            format!("{}", STATE_KEY),
2271            format!(
2272                "Key::State(entity-contract-{})",
2273                base16::encode_lower(&[42; 32])
2274            )
2275        );
2276        assert_eq!(
2277            format!("{}", BLOCK_TIME_KEY),
2278            format!(
2279                "Key::BlockGlobal({}-{})",
2280                BlockGlobalAddr::BlockTime,
2281                base16::encode_lower(&BLOCK_GLOBAL_PADDING_BYTES)
2282            )
2283        );
2284        assert_eq!(
2285            format!("{}", BLOCK_MESSAGE_COUNT_KEY),
2286            format!(
2287                "Key::BlockGlobal({}-{})",
2288                BlockGlobalAddr::MessageCount,
2289                base16::encode_lower(&BLOCK_GLOBAL_PADDING_BYTES)
2290            )
2291        );
2292    }
2293
2294    #[test]
2295    fn abuse_vec_key() {
2296        // Prefix is 2^32-1 = shouldn't allocate that much
2297        let bytes: Vec<u8> = vec![255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2298        let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
2299        assert_eq!(
2300            res.expect_err("should fail"),
2301            Error::EarlyEndOfStream,
2302            "length prefix says 2^32-1, but there's not enough data in the stream"
2303        );
2304
2305        // Prefix is 2^32-2 = shouldn't allocate that much
2306        let bytes: Vec<u8> = vec![255, 255, 255, 254, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2307        let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
2308        assert_eq!(
2309            res.expect_err("should fail"),
2310            Error::EarlyEndOfStream,
2311            "length prefix says 2^32-2, but there's not enough data in the stream"
2312        );
2313
2314        // Valid prefix but not enough data in the stream
2315        let bytes: Vec<u8> = vec![0, 0, 0, 254, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2316        let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
2317        assert_eq!(
2318            res.expect_err("should fail"),
2319            Error::EarlyEndOfStream,
2320            "length prefix says 254, but there's not enough data in the stream"
2321        );
2322    }
2323
2324    #[test]
2325    fn check_key_account_getters() {
2326        let account = [42; 32];
2327        let account_hash = AccountHash::new(account);
2328        let key1 = Key::Account(account_hash);
2329        assert_eq!(key1.into_account(), Some(account_hash));
2330        assert!(key1.into_entity_hash_addr().is_some());
2331        assert!(key1.as_uref().is_none());
2332    }
2333
2334    #[test]
2335    fn check_key_hash_getters() {
2336        let hash = [42; KEY_HASH_LENGTH];
2337        let key1 = Key::Hash(hash);
2338        assert!(key1.into_account().is_none());
2339        assert_eq!(key1.into_hash_addr(), Some(hash));
2340        assert!(key1.as_uref().is_none());
2341    }
2342
2343    #[test]
2344    fn check_entity_key_getters() {
2345        let hash = [42; KEY_HASH_LENGTH];
2346        let key1 = Key::contract_entity_key(AddressableEntityHash::new(hash));
2347        assert!(key1.into_account().is_none());
2348        assert_eq!(key1.into_entity_hash_addr(), Some(hash));
2349        assert!(key1.as_uref().is_none());
2350    }
2351
2352    #[test]
2353    fn check_package_key_getters() {
2354        let hash = [42; KEY_HASH_LENGTH];
2355        let key1 = Key::SmartContract(hash);
2356        assert!(key1.into_account().is_none());
2357        assert_eq!(key1.into_package_addr(), Some(hash));
2358        assert!(key1.as_uref().is_none());
2359    }
2360
2361    #[test]
2362    fn check_key_uref_getters() {
2363        let uref = URef::new([42; 32], AccessRights::READ_ADD_WRITE);
2364        let key1 = Key::URef(uref);
2365        assert!(key1.into_account().is_none());
2366        assert!(key1.into_entity_hash_addr().is_none());
2367        assert_eq!(key1.as_uref(), Some(&uref));
2368    }
2369
2370    #[test]
2371    fn key_max_serialized_length() {
2372        let mut got_max = false;
2373        for key in KEYS {
2374            let expected = Key::max_serialized_length();
2375            let actual = key.serialized_length();
2376            assert!(
2377                actual <= expected,
2378                "key too long {} expected {} actual {}",
2379                key,
2380                expected,
2381                actual
2382            );
2383            if actual == Key::max_serialized_length() {
2384                got_max = true;
2385            }
2386        }
2387        assert!(
2388            got_max,
2389            "None of the Key variants has a serialized_length equal to \
2390            Key::max_serialized_length(), so Key::max_serialized_length() should be reduced"
2391        );
2392    }
2393
2394    #[test]
2395    fn should_parse_legacy_bid_key_from_string() {
2396        let account_hash = AccountHash([1; 32]);
2397        let legacy_bid_key = Key::Bid(account_hash);
2398        let original_string = legacy_bid_key.to_formatted_string();
2399
2400        let parsed_bid_key =
2401            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2402        if let Key::Bid(parsed_account_hash) = parsed_bid_key {
2403            assert_eq!(parsed_account_hash, account_hash,);
2404            assert_eq!(legacy_bid_key, parsed_bid_key);
2405
2406            let translated_string = parsed_bid_key.to_formatted_string();
2407            assert_eq!(original_string, translated_string);
2408        } else {
2409            panic!("should have account hash");
2410        }
2411    }
2412
2413    #[test]
2414    fn should_parse_legacy_unified_bid_key_from_string() {
2415        let legacy_bid_addr = BidAddr::legacy([1; 32]);
2416        let legacy_bid_key = Key::BidAddr(legacy_bid_addr);
2417        assert_eq!(legacy_bid_addr.tag(), BidAddrTag::Unified,);
2418
2419        let original_string = legacy_bid_key.to_formatted_string();
2420        let parsed_key =
2421            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2422        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2423        assert!(parsed_key.is_bid_addr_key());
2424        assert_eq!(parsed_bid_addr.tag(), legacy_bid_addr.tag(),);
2425        assert_eq!(*parsed_bid_addr, legacy_bid_addr);
2426
2427        let translated_string = parsed_key.to_formatted_string();
2428        assert_eq!(original_string, translated_string);
2429        assert_eq!(parsed_key.as_bid_addr(), legacy_bid_key.as_bid_addr(),);
2430    }
2431
2432    #[test]
2433    fn should_parse_validator_bid_key_from_string() {
2434        let validator_bid_addr = BidAddr::new_validator_addr([1; 32]);
2435        let validator_bid_key = Key::BidAddr(validator_bid_addr);
2436        assert_eq!(validator_bid_addr.tag(), BidAddrTag::Validator,);
2437
2438        let original_string = validator_bid_key.to_formatted_string();
2439        let parsed_key =
2440            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2441        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2442        assert!(parsed_key.is_bid_addr_key());
2443        assert_eq!(parsed_bid_addr.tag(), validator_bid_addr.tag(),);
2444        assert_eq!(*parsed_bid_addr, validator_bid_addr,);
2445
2446        let translated_string = parsed_key.to_formatted_string();
2447        assert_eq!(original_string, translated_string);
2448        assert_eq!(parsed_key.as_bid_addr(), validator_bid_key.as_bid_addr(),);
2449    }
2450
2451    #[test]
2452    fn should_parse_delegator_bid_key_from_string() {
2453        let delegator_bid_addr = BidAddr::new_delegator_account_addr(([1; 32], [9; 32]));
2454        let delegator_bid_key = Key::BidAddr(delegator_bid_addr);
2455        assert_eq!(delegator_bid_addr.tag(), BidAddrTag::DelegatedAccount);
2456
2457        let original_string = delegator_bid_key.to_formatted_string();
2458
2459        let parsed_key =
2460            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2461        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2462        assert!(parsed_key.is_bid_addr_key());
2463        assert_eq!(parsed_bid_addr.tag(), delegator_bid_addr.tag(),);
2464        assert_eq!(*parsed_bid_addr, delegator_bid_addr,);
2465
2466        let translated_string = parsed_key.to_formatted_string();
2467        assert_eq!(original_string, translated_string);
2468        assert_eq!(parsed_key.as_bid_addr(), delegator_bid_key.as_bid_addr(),);
2469    }
2470
2471    #[test]
2472    fn should_parse_credit_bid_key_from_string() {
2473        let credit_bid_addr = BidAddr::Credit {
2474            validator: AccountHash::new([1; 32]),
2475            era_id: 1.into(),
2476        };
2477        let delegator_bid_key = Key::BidAddr(credit_bid_addr);
2478        assert_eq!(credit_bid_addr.tag(), BidAddrTag::Credit);
2479
2480        let original_string = delegator_bid_key.to_formatted_string();
2481
2482        let parsed_key =
2483            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2484        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2485        assert!(parsed_key.is_bid_addr_key());
2486        assert_eq!(parsed_bid_addr.tag(), credit_bid_addr.tag(),);
2487        assert_eq!(*parsed_bid_addr, credit_bid_addr,);
2488
2489        let translated_string = parsed_key.to_formatted_string();
2490        assert_eq!(original_string, translated_string);
2491        assert_eq!(parsed_key.as_bid_addr(), delegator_bid_key.as_bid_addr());
2492    }
2493
2494    #[test]
2495    fn should_parse_key_from_str() {
2496        for key in KEYS {
2497            let string = key.to_formatted_string();
2498            let parsed_key = Key::from_formatted_str(&string).expect("{string} (key = {key:?})");
2499            assert_eq!(parsed_key, *key, "{string} (key = {key:?})");
2500        }
2501    }
2502
2503    #[test]
2504    fn should_fail_to_parse_key_from_str() {
2505        assert!(
2506            Key::from_formatted_str(ACCOUNT_HASH_FORMATTED_STRING_PREFIX)
2507                .unwrap_err()
2508                .to_string()
2509                .starts_with("account-key from string error: ")
2510        );
2511        assert!(Key::from_formatted_str(HASH_PREFIX)
2512            .unwrap_err()
2513            .to_string()
2514            .starts_with("hash-key from string error: "));
2515        assert!(Key::from_formatted_str(UREF_FORMATTED_STRING_PREFIX)
2516            .unwrap_err()
2517            .to_string()
2518            .starts_with("uref-key from string error: "));
2519        assert!(
2520            Key::from_formatted_str(TRANSFER_ADDR_FORMATTED_STRING_PREFIX)
2521                .unwrap_err()
2522                .to_string()
2523                .starts_with("legacy-transfer-key from string error: ")
2524        );
2525        assert!(Key::from_formatted_str(DEPLOY_INFO_PREFIX)
2526            .unwrap_err()
2527            .to_string()
2528            .starts_with("deploy-info-key from string error: "));
2529        assert!(Key::from_formatted_str(ERA_INFO_PREFIX)
2530            .unwrap_err()
2531            .to_string()
2532            .starts_with("era-info-key from string error: "));
2533        assert!(Key::from_formatted_str(BALANCE_PREFIX)
2534            .unwrap_err()
2535            .to_string()
2536            .starts_with("balance-key from string error: "));
2537        assert!(Key::from_formatted_str(BID_PREFIX)
2538            .unwrap_err()
2539            .to_string()
2540            .starts_with("bid-key from string error: "));
2541        assert!(Key::from_formatted_str(WITHDRAW_PREFIX)
2542            .unwrap_err()
2543            .to_string()
2544            .starts_with("withdraw-key from string error: "));
2545        assert!(Key::from_formatted_str(DICTIONARY_PREFIX)
2546            .unwrap_err()
2547            .to_string()
2548            .starts_with("dictionary-key from string error: "));
2549        assert!(Key::from_formatted_str(SYSTEM_ENTITY_REGISTRY_PREFIX)
2550            .unwrap_err()
2551            .to_string()
2552            .starts_with("system-contract-registry-key from string error: "));
2553        assert!(Key::from_formatted_str(ERA_SUMMARY_PREFIX)
2554            .unwrap_err()
2555            .to_string()
2556            .starts_with("era-summary-key from string error"));
2557        assert!(Key::from_formatted_str(UNBOND_PREFIX)
2558            .unwrap_err()
2559            .to_string()
2560            .starts_with("unbond-key from string error: "));
2561        assert!(Key::from_formatted_str(CHAINSPEC_REGISTRY_PREFIX)
2562            .unwrap_err()
2563            .to_string()
2564            .starts_with("chainspec-registry-key from string error: "));
2565        assert!(Key::from_formatted_str(CHECKSUM_REGISTRY_PREFIX)
2566            .unwrap_err()
2567            .to_string()
2568            .starts_with("checksum-registry-key from string error: "));
2569        let bid_addr_err = Key::from_formatted_str(BID_ADDR_PREFIX)
2570            .unwrap_err()
2571            .to_string();
2572        assert!(
2573            bid_addr_err.starts_with("bid-addr-key from string error: "),
2574            "{}",
2575            bid_addr_err
2576        );
2577        assert!(Key::from_formatted_str(PACKAGE_PREFIX)
2578            .unwrap_err()
2579            .to_string()
2580            .starts_with("package-key from string error: "));
2581
2582        let error_string =
2583            Key::from_formatted_str(&format!("{}{}", ENTITY_PREFIX, ACCOUNT_ENTITY_PREFIX))
2584                .unwrap_err()
2585                .to_string();
2586        assert!(error_string.starts_with("addressable-entity-key from string error: "));
2587        assert!(
2588            Key::from_formatted_str(&format!("{}{}", BYTE_CODE_PREFIX, EMPTY_PREFIX))
2589                .unwrap_err()
2590                .to_string()
2591                .starts_with("byte-code-key from string error: ")
2592        );
2593        let invalid_prefix = "a-0000000000000000000000000000000000000000000000000000000000000000";
2594        assert_eq!(
2595            Key::from_formatted_str(invalid_prefix)
2596                .unwrap_err()
2597                .to_string(),
2598            "unknown prefix for key"
2599        );
2600
2601        let missing_hyphen_prefix =
2602            "hash0000000000000000000000000000000000000000000000000000000000000000";
2603        assert_eq!(
2604            Key::from_formatted_str(missing_hyphen_prefix)
2605                .unwrap_err()
2606                .to_string(),
2607            "unknown prefix for key"
2608        );
2609
2610        let no_prefix = "0000000000000000000000000000000000000000000000000000000000000000";
2611        assert_eq!(
2612            Key::from_formatted_str(no_prefix).unwrap_err().to_string(),
2613            "unknown prefix for key"
2614        );
2615
2616        let balance_hold_err = Key::from_formatted_str(BALANCE_HOLD_PREFIX)
2617            .unwrap_err()
2618            .to_string();
2619        assert!(
2620            balance_hold_err.starts_with("balance-hold from string error: "),
2621            "{}",
2622            bid_addr_err
2623        );
2624    }
2625
2626    #[test]
2627    fn key_to_json() {
2628        for key in KEYS.iter() {
2629            assert_eq!(
2630                serde_json::to_string(key).unwrap(),
2631                format!("\"{}\"", key.to_formatted_string())
2632            );
2633        }
2634    }
2635
2636    #[test]
2637    fn serialization_roundtrip_bincode() {
2638        for key in KEYS {
2639            let encoded = bincode::serialize(key).unwrap();
2640            let decoded = bincode::deserialize(&encoded).unwrap();
2641            assert_eq!(key, &decoded);
2642        }
2643    }
2644
2645    #[test]
2646    fn key_tag_bytes_roundtrip() {
2647        for key in KEYS {
2648            let tag: KeyTag = key.tag();
2649            bytesrepr::test_serialization_roundtrip(&tag);
2650        }
2651    }
2652
2653    #[test]
2654    fn bytesrepr_serialization_roundtrip() {
2655        bytesrepr::test_serialization_roundtrip(&ACCOUNT_KEY);
2656        bytesrepr::test_serialization_roundtrip(&HASH_KEY);
2657        bytesrepr::test_serialization_roundtrip(&UREF_KEY);
2658        bytesrepr::test_serialization_roundtrip(&TRANSFER_KEY);
2659        bytesrepr::test_serialization_roundtrip(&DEPLOY_INFO_KEY);
2660        bytesrepr::test_serialization_roundtrip(&ERA_INFO_KEY);
2661        bytesrepr::test_serialization_roundtrip(&BALANCE_KEY);
2662        bytesrepr::test_serialization_roundtrip(&BID_KEY);
2663        bytesrepr::test_serialization_roundtrip(&WITHDRAW_KEY);
2664        bytesrepr::test_serialization_roundtrip(&DICTIONARY_KEY);
2665        // bytesrepr::test_serialization_roundtrip(&SYSTEM_CONTRACT_REGISTRY_KEY);
2666        bytesrepr::test_serialization_roundtrip(&ERA_SUMMARY_KEY);
2667        bytesrepr::test_serialization_roundtrip(&UNBOND_KEY);
2668        bytesrepr::test_serialization_roundtrip(&CHAINSPEC_REGISTRY_KEY);
2669        bytesrepr::test_serialization_roundtrip(&CHECKSUM_REGISTRY_KEY);
2670        // bytesrepr::test_serialization_roundtrip(&UNIFIED_BID_KEY);
2671        bytesrepr::test_serialization_roundtrip(&VALIDATOR_BID_KEY);
2672        bytesrepr::test_serialization_roundtrip(&DELEGATOR_BID_KEY);
2673        bytesrepr::test_serialization_roundtrip(&PACKAGE_KEY);
2674        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SYSTEM_KEY);
2675        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_ACCOUNT_KEY);
2676        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY);
2677        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_EMPTY_KEY);
2678        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_V1_WASM_KEY);
2679        bytesrepr::test_serialization_roundtrip(&MESSAGE_TOPIC_KEY);
2680        bytesrepr::test_serialization_roundtrip(&MESSAGE_KEY);
2681        bytesrepr::test_serialization_roundtrip(&NAMED_KEY);
2682        bytesrepr::test_serialization_roundtrip(&STATE_KEY);
2683    }
2684
2685    #[test]
2686    fn serialization_roundtrip_json() {
2687        for key in KEYS {
2688            round_trip(key);
2689        }
2690
2691        let zeros = [0; BLAKE2B_DIGEST_LENGTH];
2692        let nines = [9; BLAKE2B_DIGEST_LENGTH];
2693
2694        round_trip(&Key::Account(AccountHash::new(zeros)));
2695        round_trip(&Key::Hash(zeros));
2696        round_trip(&Key::URef(URef::new(zeros, AccessRights::READ)));
2697        round_trip(&Key::Transfer(TransferAddr::new(zeros)));
2698        round_trip(&Key::DeployInfo(DeployHash::from_raw(zeros)));
2699        round_trip(&Key::EraInfo(EraId::from(0)));
2700        round_trip(&Key::Balance(URef::new(zeros, AccessRights::READ).addr()));
2701        round_trip(&Key::Bid(AccountHash::new(zeros)));
2702        round_trip(&Key::BidAddr(BidAddr::legacy(zeros)));
2703        round_trip(&Key::BidAddr(BidAddr::new_validator_addr(zeros)));
2704        round_trip(&Key::BidAddr(BidAddr::new_delegator_account_addr((
2705            zeros, nines,
2706        ))));
2707        round_trip(&Key::Withdraw(AccountHash::new(zeros)));
2708        round_trip(&Key::Dictionary(zeros));
2709        round_trip(&Key::Unbond(AccountHash::new(zeros)));
2710        round_trip(&Key::SmartContract(zeros));
2711        round_trip(&Key::AddressableEntity(EntityAddr::new_system(zeros)));
2712        round_trip(&Key::AddressableEntity(EntityAddr::new_account(zeros)));
2713        round_trip(&Key::AddressableEntity(EntityAddr::new_smart_contract(
2714            zeros,
2715        )));
2716        round_trip(&Key::ByteCode(ByteCodeAddr::Empty));
2717        round_trip(&Key::ByteCode(ByteCodeAddr::V1CasperWasm(zeros)));
2718        round_trip(&Key::Message(MessageAddr::new_topic_addr(
2719            EntityAddr::new_smart_contract(zeros),
2720            nines.into(),
2721        )));
2722        round_trip(&Key::Message(MessageAddr::new_message_addr(
2723            EntityAddr::new_smart_contract(zeros),
2724            nines.into(),
2725            1,
2726        )));
2727        round_trip(&Key::NamedKey(NamedKeyAddr::default()));
2728        round_trip(&Key::BlockGlobal(BlockGlobalAddr::BlockTime));
2729        round_trip(&Key::BlockGlobal(BlockGlobalAddr::MessageCount));
2730        round_trip(&Key::BlockGlobal(BlockGlobalAddr::ProtocolVersion));
2731        round_trip(&Key::BlockGlobal(BlockGlobalAddr::AddressableEntity));
2732        round_trip(&Key::BalanceHold(BalanceHoldAddr::default()));
2733        round_trip(&Key::State(EntityAddr::new_system(zeros)));
2734    }
2735
2736    #[test]
2737    fn state_json_deserialization() {
2738        let mut test_rng = TestRng::new();
2739        let state_key = Key::State(EntityAddr::new_account(test_rng.gen()));
2740        round_trip(&state_key);
2741
2742        let state_key = Key::State(EntityAddr::new_system(test_rng.gen()));
2743        round_trip(&state_key);
2744
2745        let state_key = Key::State(EntityAddr::new_smart_contract(test_rng.gen()));
2746        round_trip(&state_key);
2747    }
2748
2749    #[test]
2750    fn roundtrip() {
2751        bytesrepr::test_serialization_roundtrip(&ACCOUNT_KEY);
2752        bytesrepr::test_serialization_roundtrip(&HASH_KEY);
2753        bytesrepr::test_serialization_roundtrip(&UREF_KEY);
2754        bytesrepr::test_serialization_roundtrip(&TRANSFER_KEY);
2755        bytesrepr::test_serialization_roundtrip(&DEPLOY_INFO_KEY);
2756        bytesrepr::test_serialization_roundtrip(&ERA_INFO_KEY);
2757        bytesrepr::test_serialization_roundtrip(&BALANCE_KEY);
2758        bytesrepr::test_serialization_roundtrip(&BID_KEY);
2759        bytesrepr::test_serialization_roundtrip(&WITHDRAW_KEY);
2760        bytesrepr::test_serialization_roundtrip(&DICTIONARY_KEY);
2761        bytesrepr::test_serialization_roundtrip(&SYSTEM_ENTITY_REGISTRY_KEY);
2762        bytesrepr::test_serialization_roundtrip(&ERA_SUMMARY_KEY);
2763        bytesrepr::test_serialization_roundtrip(&UNBOND_KEY);
2764        bytesrepr::test_serialization_roundtrip(&CHAINSPEC_REGISTRY_KEY);
2765        bytesrepr::test_serialization_roundtrip(&CHECKSUM_REGISTRY_KEY);
2766        bytesrepr::test_serialization_roundtrip(&UNIFIED_BID_KEY);
2767        bytesrepr::test_serialization_roundtrip(&VALIDATOR_BID_KEY);
2768        bytesrepr::test_serialization_roundtrip(&DELEGATOR_BID_KEY);
2769        bytesrepr::test_serialization_roundtrip(&PACKAGE_KEY);
2770        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SYSTEM_KEY);
2771        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_ACCOUNT_KEY);
2772        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY);
2773        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_EMPTY_KEY);
2774        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_V1_WASM_KEY);
2775        bytesrepr::test_serialization_roundtrip(&MESSAGE_TOPIC_KEY);
2776        bytesrepr::test_serialization_roundtrip(&MESSAGE_KEY);
2777        bytesrepr::test_serialization_roundtrip(&NAMED_KEY);
2778    }
2779
2780    fn round_trip(key: &Key) {
2781        let encoded = serde_json::to_value(key).unwrap();
2782        let decoded = serde_json::from_value(encoded.clone())
2783            .unwrap_or_else(|_| panic!("{} {}", key, encoded));
2784        assert_eq!(key, &decoded);
2785    }
2786}
2787
2788#[cfg(test)]
2789mod proptest {
2790    use crate::gens;
2791    use proptest::prelude::*;
2792
2793    proptest! {
2794        #[test]
2795        fn test_json_roundtrip_for_bidaddr_key(key in gens::all_keys_arb()) {
2796            let json_string = serde_json::to_string_pretty(&key).unwrap();
2797            let decoded = serde_json::from_str(&json_string).unwrap();
2798            assert_eq!(key, decoded);
2799        }
2800    }
2801}