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::ValidatorRev => BidAddr::new_validator_rev_addr(validator_bytes),
758                BidAddrTag::DelegatedAccount => {
759                    let delegator_bytes = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(
760                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
761                    )
762                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
763                    BidAddr::new_delegator_account_addr((validator_bytes, delegator_bytes))
764                }
765                BidAddrTag::DelegatedPurse => {
766                    let uref = <[u8; UREF_ADDR_LENGTH]>::try_from(
767                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
768                    )
769                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
770                    BidAddr::DelegatedPurse {
771                        validator: AccountHash::new(validator_bytes),
772                        delegator: uref,
773                    }
774                }
775                BidAddrTag::Credit => {
776                    let era_id = bytesrepr::deserialize_from_slice(
777                        &bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..],
778                    )
779                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
780                    BidAddr::Credit {
781                        validator: AccountHash::new(validator_bytes),
782                        era_id,
783                    }
784                }
785                BidAddrTag::ReservedDelegationAccount => {
786                    let delegator_bytes = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(
787                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
788                    )
789                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
790                    BidAddr::new_reservation_account_addr((validator_bytes, delegator_bytes))
791                }
792                BidAddrTag::ReservedDelegationPurse => {
793                    let uref = <[u8; UREF_ADDR_LENGTH]>::try_from(
794                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
795                    )
796                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
797                    BidAddr::ReservedDelegationPurse {
798                        validator: AccountHash::new(validator_bytes),
799                        delegator: uref,
800                    }
801                }
802                BidAddrTag::UnbondAccount => {
803                    let unbonder_bytes = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(
804                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
805                    )
806                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
807                    BidAddr::UnbondAccount {
808                        validator: AccountHash::new(validator_bytes),
809                        unbonder: AccountHash::new(unbonder_bytes),
810                    }
811                }
812                BidAddrTag::UnbondPurse => {
813                    let uref = <[u8; UREF_ADDR_LENGTH]>::try_from(
814                        bytes[BidAddr::VALIDATOR_BID_ADDR_LENGTH..].as_ref(),
815                    )
816                    .map_err(|err| FromStrError::BidAddr(err.to_string()))?;
817                    BidAddr::UnbondPurse {
818                        validator: AccountHash::new(validator_bytes),
819                        unbonder: uref,
820                    }
821                }
822            };
823            return Ok(Key::BidAddr(bid_addr));
824        }
825
826        if let Some(hex) = input.strip_prefix(BID_PREFIX) {
827            let hash = checksummed_hex::decode(hex)
828                .map_err(|error| FromStrError::Bid(error.to_string()))?;
829            let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
830                .map_err(|error| FromStrError::Bid(error.to_string()))?;
831            return Ok(Key::Bid(AccountHash::new(account_hash)));
832        }
833
834        if let Some(hex) = input.strip_prefix(WITHDRAW_PREFIX) {
835            let hash = checksummed_hex::decode(hex)
836                .map_err(|error| FromStrError::Withdraw(error.to_string()))?;
837            let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
838                .map_err(|error| FromStrError::Withdraw(error.to_string()))?;
839            return Ok(Key::Withdraw(AccountHash::new(account_hash)));
840        }
841
842        if let Some(hex) = input.strip_prefix(UNBOND_PREFIX) {
843            let hash = checksummed_hex::decode(hex)
844                .map_err(|error| FromStrError::Unbond(error.to_string()))?;
845            let account_hash = <[u8; ACCOUNT_HASH_LENGTH]>::try_from(hash.as_ref())
846                .map_err(|error| FromStrError::Unbond(error.to_string()))?;
847            return Ok(Key::Unbond(AccountHash::new(account_hash)));
848        }
849
850        if let Some(dictionary_addr) = input.strip_prefix(DICTIONARY_PREFIX) {
851            let dictionary_addr_bytes = checksummed_hex::decode(dictionary_addr)
852                .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
853            let addr = DictionaryAddr::try_from(dictionary_addr_bytes.as_ref())
854                .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
855            return Ok(Key::Dictionary(addr));
856        }
857
858        if let Some(registry_address) = input.strip_prefix(SYSTEM_ENTITY_REGISTRY_PREFIX) {
859            let padded_bytes = checksummed_hex::decode(registry_address)
860                .map_err(|error| FromStrError::SystemEntityRegistry(error.to_string()))?;
861            let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
862                FromStrError::SystemEntityRegistry(
863                    "Failed to deserialize system registry key".to_string(),
864                )
865            })?;
866            return Ok(Key::SystemEntityRegistry);
867        }
868
869        if let Some(registry_address) = input.strip_prefix(CHAINSPEC_REGISTRY_PREFIX) {
870            let padded_bytes = checksummed_hex::decode(registry_address)
871                .map_err(|error| FromStrError::ChainspecRegistry(error.to_string()))?;
872            let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
873                FromStrError::ChainspecRegistry(
874                    "Failed to deserialize chainspec registry key".to_string(),
875                )
876            })?;
877            return Ok(Key::ChainspecRegistry);
878        }
879
880        if let Some(registry_address) = input.strip_prefix(CHECKSUM_REGISTRY_PREFIX) {
881            let padded_bytes = checksummed_hex::decode(registry_address)
882                .map_err(|error| FromStrError::ChecksumRegistry(error.to_string()))?;
883            let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
884                FromStrError::ChecksumRegistry(
885                    "Failed to deserialize checksum registry key".to_string(),
886                )
887            })?;
888            return Ok(Key::ChecksumRegistry);
889        }
890
891        if let Some(package_addr) = input.strip_prefix(PACKAGE_PREFIX) {
892            let package_addr_bytes = checksummed_hex::decode(package_addr)
893                .map_err(|error| FromStrError::Dictionary(error.to_string()))?;
894            let addr = PackageAddr::try_from(package_addr_bytes.as_ref())
895                .map_err(|error| FromStrError::Package(error.to_string()))?;
896            return Ok(Key::SmartContract(addr));
897        }
898
899        match EntityAddr::from_formatted_str(input) {
900            Ok(entity_addr) => return Ok(Key::AddressableEntity(entity_addr)),
901            Err(addressable_entity::FromStrError::InvalidPrefix) => {}
902            Err(error) => {
903                return Err(FromStrError::AddressableEntity(error.to_string()));
904            }
905        }
906
907        match ByteCodeAddr::from_formatted_string(input) {
908            Ok(byte_code_addr) => return Ok(Key::ByteCode(byte_code_addr)),
909            Err(byte_code::FromStrError::InvalidPrefix) => {}
910            Err(error) => return Err(FromStrError::ByteCode(error.to_string())),
911        }
912
913        match MessageAddr::from_formatted_str(input) {
914            Ok(message_addr) => return Ok(Key::Message(message_addr)),
915            Err(contract_messages::FromStrError::InvalidPrefix) => {}
916            Err(error) => return Err(error.into()),
917        }
918
919        match NamedKeyAddr::from_formatted_str(input) {
920            Ok(named_key) => return Ok(Key::NamedKey(named_key)),
921            Err(addressable_entity::FromStrError::InvalidPrefix) => {}
922            Err(error) => return Err(FromStrError::NamedKey(error.to_string())),
923        }
924
925        if let Some(block_time) = input.strip_prefix(BLOCK_GLOBAL_TIME_PREFIX) {
926            let padded_bytes = checksummed_hex::decode(block_time)
927                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
928            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
929                FromStrError::BlockGlobal("Failed to deserialize global block time key".to_string())
930            })?;
931            return Ok(BlockGlobalAddr::BlockTime.into());
932        }
933
934        if let Some(message_count) = input.strip_prefix(BLOCK_GLOBAL_MESSAGE_COUNT_PREFIX) {
935            let padded_bytes = checksummed_hex::decode(message_count)
936                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
937            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
938                FromStrError::BlockGlobal(
939                    "Failed to deserialize global block message count key".to_string(),
940                )
941            })?;
942            return Ok(BlockGlobalAddr::MessageCount.into());
943        }
944
945        if let Some(protocol_version) = input.strip_prefix(BLOCK_GLOBAL_PROTOCOL_VERSION_PREFIX) {
946            let padded_bytes = checksummed_hex::decode(protocol_version)
947                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
948            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
949                FromStrError::BlockGlobal(
950                    "Failed to deserialize global block protocol version key".to_string(),
951                )
952            })?;
953            return Ok(BlockGlobalAddr::ProtocolVersion.into());
954        }
955
956        if let Some(addressable_entity) = input.strip_prefix(BLOCK_GLOBAL_ADDRESSABLE_ENTITY_PREFIX)
957        {
958            let padded_bytes = checksummed_hex::decode(addressable_entity)
959                .map_err(|error| FromStrError::BlockGlobal(error.to_string()))?;
960            let _padding: [u8; 31] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| {
961                FromStrError::BlockGlobal(
962                    "Failed to deserialize global block addressable entity key".to_string(),
963                )
964            })?;
965            return Ok(BlockGlobalAddr::AddressableEntity.into());
966        }
967
968        match EntryPointAddr::from_formatted_str(input) {
969            Ok(entry_point_addr) => return Ok(Key::EntryPoint(entry_point_addr)),
970            Err(addressable_entity::FromStrError::InvalidPrefix) => {}
971            Err(error) => return Err(FromStrError::EntryPoint(error.to_string())),
972        }
973
974        if let Some(entity_addr_formatted) = input.strip_prefix(STATE_PREFIX) {
975            match EntityAddr::from_formatted_str(entity_addr_formatted) {
976                Ok(entity_addr) => return Ok(Key::State(entity_addr)),
977                Err(addressable_entity::FromStrError::InvalidPrefix) => {}
978                Err(error) => {
979                    return Err(FromStrError::State(error.to_string()));
980                }
981            }
982        }
983
984        Err(FromStrError::UnknownPrefix)
985    }
986
987    /// Returns the inner bytes of `self` if `self` is of type [`Key::Account`], otherwise returns
988    /// `None`.
989    pub fn into_account(self) -> Option<AccountHash> {
990        match self {
991            Key::Account(bytes) => Some(bytes),
992            _ => None,
993        }
994    }
995
996    /// Returns the inner bytes of `self` if `self` is of type [`Key::Hash`], otherwise returns
997    /// `None`.
998    pub fn into_hash_addr(self) -> Option<HashAddr> {
999        match self {
1000            Key::Hash(hash) => Some(hash),
1001            _ => None,
1002        }
1003    }
1004
1005    /// Returns the inner bytes of `self` if `self` is of type [`Key::AddressableEntity`], otherwise
1006    /// returns `None`.
1007    pub fn into_entity_hash_addr(self) -> Option<HashAddr> {
1008        match self {
1009            Key::AddressableEntity(entity_addr) => Some(entity_addr.value()),
1010            Key::Account(account_hash) => Some(account_hash.value()),
1011            Key::Hash(hash) => Some(hash),
1012            _ => None,
1013        }
1014    }
1015
1016    /// Returns the inner bytes of `self` if `self` is of type [`Key::SmartContract`], otherwise
1017    /// returns `None`.
1018    pub fn into_package_addr(self) -> Option<PackageAddr> {
1019        match self {
1020            Key::Hash(hash) => Some(hash),
1021            Key::SmartContract(package_addr) => Some(package_addr),
1022            _ => None,
1023        }
1024    }
1025
1026    /// Returns [`AddressableEntityHash`] of `self` if `self` is of type [`Key::AddressableEntity`],
1027    /// otherwise returns `None`.
1028    pub fn into_entity_hash(self) -> Option<AddressableEntityHash> {
1029        let entity_addr = self.into_entity_hash_addr()?;
1030        Some(AddressableEntityHash::new(entity_addr))
1031    }
1032
1033    /// Returns [`PackageHash`] of `self` if `self` is of type [`Key::SmartContract`], otherwise
1034    /// returns `None`.
1035    pub fn into_package_hash(self) -> Option<PackageHash> {
1036        let package_addr = self.into_package_addr()?;
1037        Some(PackageHash::new(package_addr))
1038    }
1039
1040    /// Returns [`NamedKeyAddr`] of `self` if `self` is of type [`Key::NamedKey`], otherwise
1041    /// returns `None`.
1042    pub fn into_named_key_addr(self) -> Option<NamedKeyAddr> {
1043        match self {
1044            Key::NamedKey(addr) => Some(addr),
1045            _ => None,
1046        }
1047    }
1048
1049    /// Returns the inner [`URef`] if `self` is of type [`Key::URef`], otherwise returns `None`.
1050    pub fn into_uref(self) -> Option<URef> {
1051        match self {
1052            Key::URef(uref) => Some(uref),
1053            _ => None,
1054        }
1055    }
1056
1057    /// Returns a reference to the inner [`URef`] if `self` is of type [`Key::URef`], otherwise
1058    /// returns `None`.
1059    pub fn as_uref(&self) -> Option<&URef> {
1060        match self {
1061            Key::URef(uref) => Some(uref),
1062            _ => None,
1063        }
1064    }
1065
1066    /// Returns a reference to the inner [`URef`] if `self` is of type [`Key::URef`], otherwise
1067    /// returns `None`.
1068    pub fn as_uref_mut(&mut self) -> Option<&mut URef> {
1069        match self {
1070            Key::URef(uref) => Some(uref),
1071            _ => None,
1072        }
1073    }
1074
1075    /// Returns a reference to the inner `URefAddr` if `self` is of type [`Key::Balance`],
1076    /// otherwise returns `None`.
1077    pub fn as_balance(&self) -> Option<&URefAddr> {
1078        if let Self::Balance(v) = self {
1079            Some(v)
1080        } else {
1081            None
1082        }
1083    }
1084
1085    /// Returns a reference to the inner `BalanceHoldAddr` if `self` is of type
1086    /// [`Key::BalanceHold`], otherwise returns `None`.
1087    pub fn as_balance_hold(&self) -> Option<&BalanceHoldAddr> {
1088        if let Self::BalanceHold(addr) = self {
1089            Some(addr)
1090        } else {
1091            None
1092        }
1093    }
1094
1095    /// Returns a reference to the inner [`DictionaryAddr`] if `self` is of type
1096    /// [`Key::Dictionary`], otherwise returns `None`.
1097    pub fn as_dictionary(&self) -> Option<&DictionaryAddr> {
1098        match self {
1099            Key::Dictionary(v) => Some(v),
1100            _ => None,
1101        }
1102    }
1103
1104    /// Returns a reference to the inner `BidAddr` if `self` is of type [`Key::Bid`],
1105    /// otherwise returns `None`.
1106    pub fn as_bid_addr(&self) -> Option<&BidAddr> {
1107        if let Self::BidAddr(addr) = self {
1108            Some(addr)
1109        } else {
1110            None
1111        }
1112    }
1113
1114    /// Returns a reference to the inner `TopicNameHash` if `self` is of the type [`Key::Message`]
1115    /// otherwise returns `None`.
1116    pub fn as_message_topic_name_hash(&self) -> Option<TopicNameHash> {
1117        if let Self::Message(addr) = self {
1118            Some(addr.topic_name_hash())
1119        } else {
1120            None
1121        }
1122    }
1123
1124    /// Casts a [`Key::URef`] to a [`Key::Hash`]
1125    pub fn uref_to_hash(&self) -> Option<Key> {
1126        let uref = self.as_uref()?;
1127        let addr = uref.addr();
1128        Some(Key::Hash(addr))
1129    }
1130
1131    /// Casts a [`Key::Withdraw`] to a [`Key::Unbond`]
1132    pub fn withdraw_to_unbond(&self) -> Option<Key> {
1133        if let Key::Withdraw(account_hash) = self {
1134            return Some(Key::Unbond(*account_hash));
1135        }
1136        None
1137    }
1138
1139    /// Creates a new [`Key::Dictionary`] variant based on a `seed_uref` and a `dictionary_item_key`
1140    /// bytes.
1141    pub fn dictionary(seed_uref: URef, dictionary_item_key: &[u8]) -> Key {
1142        // NOTE: Expect below is safe because the length passed is supported.
1143        let mut hasher = VarBlake2b::new(BLAKE2B_DIGEST_LENGTH).expect("should create hasher");
1144        hasher.update(seed_uref.addr().as_ref());
1145        hasher.update(dictionary_item_key);
1146        // NOTE: Assumed safe as size of `HashAddr` equals to the output provided by hasher.
1147        let mut addr = HashAddr::default();
1148        hasher.finalize_variable(|hash| addr.clone_from_slice(hash));
1149        Key::Dictionary(addr)
1150    }
1151
1152    /// Creates a new [`Key::AddressableEntity`] variant from a package kind and an entity
1153    /// hash.
1154    pub fn addressable_entity_key(
1155        entity_kind_tag: EntityKindTag,
1156        entity_hash: AddressableEntityHash,
1157    ) -> Self {
1158        let entity_addr = match entity_kind_tag {
1159            EntityKindTag::System => EntityAddr::new_system(entity_hash.value()),
1160            EntityKindTag::Account => EntityAddr::new_account(entity_hash.value()),
1161            EntityKindTag::SmartContract => EntityAddr::new_smart_contract(entity_hash.value()),
1162        };
1163
1164        Key::AddressableEntity(entity_addr)
1165    }
1166
1167    /// Creates a new [`Key::AddressableEntity`] for a Smart contract.
1168    pub fn contract_entity_key(entity_hash: AddressableEntityHash) -> Key {
1169        Self::addressable_entity_key(EntityKindTag::SmartContract, entity_hash)
1170    }
1171
1172    /// Creates a new [`Key::ByteCode`] variant from a byte code kind and an byte code addr.
1173    pub fn byte_code_key(byte_code_addr: ByteCodeAddr) -> Self {
1174        Key::ByteCode(byte_code_addr)
1175    }
1176
1177    /// Creates a new [`Key::Message`] variant that identifies an indexed message based on an
1178    /// `hash_addr`, `topic_name_hash` and message `index`.
1179    pub fn message(entity_addr: EntityAddr, topic_name_hash: TopicNameHash, index: u32) -> Key {
1180        Key::Message(MessageAddr::new_message_addr(
1181            entity_addr,
1182            topic_name_hash,
1183            index,
1184        ))
1185    }
1186
1187    /// Creates a new [`Key::Message`] variant that identifies a message topic based on an
1188    /// `hash_addr` and a hash of the topic name.
1189    pub fn message_topic(entity_addr: EntityAddr, topic_name_hash: TopicNameHash) -> Key {
1190        Key::Message(MessageAddr::new_topic_addr(entity_addr, topic_name_hash))
1191    }
1192
1193    /// Creates a new [`Key::EntryPoint`] variant from an entrypoint addr.
1194    pub fn entry_point(entry_point_addr: EntryPointAddr) -> Self {
1195        Key::EntryPoint(entry_point_addr)
1196    }
1197
1198    /// Returns true if the key is of type [`Key::Dictionary`].
1199    pub fn is_dictionary_key(&self) -> bool {
1200        if let Key::Dictionary(_) = self {
1201            return true;
1202        }
1203        false
1204    }
1205
1206    /// Returns true if the key is of type [`Key::Bid`].
1207    pub fn is_balance_key(&self) -> bool {
1208        if let Key::Balance(_) = self {
1209            return true;
1210        }
1211        false
1212    }
1213
1214    /// Returns true if the key is of type [`Key::BidAddr`].
1215    pub fn is_bid_addr_key(&self) -> bool {
1216        if let Key::BidAddr(_) = self {
1217            return true;
1218        }
1219        false
1220    }
1221
1222    /// Returns true if the key is of type [`Key::NamedKey`].
1223    pub fn is_named_key(&self) -> bool {
1224        if let Key::NamedKey(_) = self {
1225            return true;
1226        }
1227
1228        false
1229    }
1230
1231    /// Returns if the inner address is for a system contract entity.
1232    pub fn is_system_key(&self) -> bool {
1233        if let Self::AddressableEntity(entity_addr) = self {
1234            return match entity_addr.tag() {
1235                EntityKindTag::System => true,
1236                EntityKindTag::SmartContract | EntityKindTag::Account => false,
1237            };
1238        }
1239        false
1240    }
1241
1242    /// Return true if the inner Key is of the smart contract type.
1243    pub fn is_smart_contract_key(&self) -> bool {
1244        matches!(
1245            self,
1246            Self::AddressableEntity(EntityAddr::SmartContract(_)) | Self::Hash(_)
1247        )
1248    }
1249
1250    /// Returns true if the key is of type [`Key::NamedKey`] and its Entry variant.
1251    pub fn is_named_key_entry(&self) -> bool {
1252        matches!(self, Self::NamedKey(_))
1253    }
1254
1255    /// Returns true if the key is of type [`Key::NamedKey`] and the variants have the
1256    /// same [`EntityAddr`].
1257    pub fn is_entry_for_base(&self, entity_addr: &EntityAddr) -> bool {
1258        if let Self::NamedKey(named_key_addr) = self {
1259            named_key_addr.entity_addr() == *entity_addr
1260        } else {
1261            false
1262        }
1263    }
1264
1265    /// Is the record under this key readable by the entity corresponding to the imputed address?
1266    pub fn is_readable(&self, entity_addr: &EntityAddr) -> bool {
1267        if entity_addr.is_system() {
1268            // the system can read everything
1269            return true;
1270        }
1271        let ret = match self {
1272            Key::BidAddr(_) => {
1273                // all bids are public information
1274                true
1275            }
1276            Key::URef(uref) => {
1277                // uref's require explicit permissions
1278                uref.is_readable()
1279            }
1280            Key::SystemEntityRegistry | Key::SmartContract(_) => {
1281                // the system entities and all packages are public info
1282                true
1283            }
1284            Key::Unbond(account_hash) => {
1285                // and an account holder can read their own account record
1286                entity_addr.tag() == EntityKindTag::Account
1287                    && entity_addr.value() == account_hash.value()
1288            }
1289            Key::NamedKey(named_key_addr) => {
1290                // an entity can read its own named keys
1291                &named_key_addr.entity_addr() == entity_addr
1292            }
1293            Key::ByteCode(_)
1294            | Key::Account(_)
1295            | Key::Hash(_)
1296            | Key::AddressableEntity(_)
1297            | Key::Balance(_)
1298            | Key::BalanceHold(_)
1299            | Key::Dictionary(_)
1300            | Key::Message(_)
1301            | Key::BlockGlobal(_)
1302            | Key::EntryPoint(_) => true,
1303            _ => false,
1304        };
1305        if !ret {
1306            let reading_entity_key = Key::AddressableEntity(*entity_addr);
1307            warn!(?reading_entity_key, attempted_key=?self,  "attempt to read without permission")
1308        }
1309        ret
1310    }
1311
1312    /// Is the record under this key addable by the entity corresponding to the imputed address?
1313    pub fn is_addable(&self, entity_addr: &EntityAddr) -> bool {
1314        // unlike readable / writeable which are universally supported,
1315        //  only some data types support commutative add / extension
1316        let ret = match self {
1317            Key::URef(uref) => uref.is_addable(),
1318            Key::AddressableEntity(addr_entity_addr) => {
1319                // an entity can extend itself (only associated keys, currently)
1320                entity_addr == addr_entity_addr
1321            }
1322            Key::NamedKey(named_key_addr) => {
1323                // an entity can extend its own named keys
1324                &named_key_addr.entity_addr() == entity_addr
1325            }
1326            _ => {
1327                // other data types do not support commutative addition / extension
1328                let adding_entity_key = Key::AddressableEntity(*entity_addr);
1329                warn!(?adding_entity_key, attempted_key=?self,  "attempt to add on an unsupported data type");
1330                return false; // we want the above more explicit warn message, not both messages.
1331            }
1332        };
1333        if !ret {
1334            let adding_entity_key = Key::AddressableEntity(*entity_addr);
1335            warn!(?adding_entity_key, attempted_key=?self,  "attempt to add without permission");
1336        }
1337        ret
1338    }
1339
1340    /// Is the record under this key writeable by the entity corresponding to the imputed address?
1341    pub fn is_writeable(&self, entity_addr: &EntityAddr) -> bool {
1342        if entity_addr.is_system() {
1343            // the system can write everything
1344            return true;
1345        }
1346        let ret = match self {
1347            Key::URef(uref) => uref.is_writeable(),
1348            Key::NamedKey(named_key_addr) => {
1349                // an entity can write to its own named keys
1350                &named_key_addr.entity_addr() == entity_addr
1351            }
1352            _ => {
1353                // only the system can write other kinds of records
1354                false
1355            }
1356        };
1357        if !ret {
1358            let writing_entity_key = Key::AddressableEntity(*entity_addr);
1359            warn!(?writing_entity_key, attempted_key=?self,  "attempt to write without permission")
1360        }
1361        ret
1362    }
1363
1364    /// Returns an entity addr for a [`Key::AddressableEntity`].
1365    pub fn into_entity_addr(self) -> Option<EntityAddr> {
1366        match self {
1367            Key::AddressableEntity(entity_addr) => Some(entity_addr),
1368            _ => None,
1369        }
1370    }
1371}
1372
1373impl Display for Key {
1374    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1375        match self {
1376            Key::Account(account_hash) => write!(f, "Key::Account({})", account_hash),
1377            Key::Hash(addr) => write!(f, "Key::Hash({})", base16::encode_lower(&addr)),
1378            Key::URef(uref) => write!(f, "Key::{}", uref), /* Display impl for URef will append */
1379            Key::Transfer(transfer_v1_addr) => {
1380                write!(f, "Key::Transfer({})", transfer_v1_addr)
1381            }
1382            Key::DeployInfo(addr) => write!(
1383                f,
1384                "Key::DeployInfo({})",
1385                base16::encode_lower(addr.as_ref())
1386            ),
1387            Key::EraInfo(era_id) => write!(f, "Key::EraInfo({})", era_id),
1388            Key::Balance(uref_addr) => {
1389                write!(f, "Key::Balance({})", base16::encode_lower(uref_addr))
1390            }
1391            Key::Bid(account_hash) => write!(f, "Key::Bid({})", account_hash),
1392            Key::Withdraw(account_hash) => write!(f, "Key::Withdraw({})", account_hash),
1393            Key::Dictionary(addr) => {
1394                write!(f, "Key::Dictionary({})", base16::encode_lower(addr))
1395            }
1396            Key::SystemEntityRegistry => write!(
1397                f,
1398                "Key::SystemEntityRegistry({})",
1399                base16::encode_lower(&PADDING_BYTES)
1400            ),
1401            Key::EraSummary => write!(
1402                f,
1403                "Key::EraSummary({})",
1404                base16::encode_lower(&PADDING_BYTES),
1405            ),
1406            Key::Unbond(account_hash) => write!(f, "Key::Unbond({})", account_hash),
1407            Key::ChainspecRegistry => write!(
1408                f,
1409                "Key::ChainspecRegistry({})",
1410                base16::encode_lower(&PADDING_BYTES)
1411            ),
1412            Key::ChecksumRegistry => {
1413                write!(
1414                    f,
1415                    "Key::ChecksumRegistry({})",
1416                    base16::encode_lower(&PADDING_BYTES)
1417                )
1418            }
1419            Key::BidAddr(bid_addr) => write!(f, "Key::BidAddr({})", bid_addr),
1420            Key::Message(message_addr) => {
1421                write!(f, "Key::Message({})", message_addr)
1422            }
1423            Key::SmartContract(package_addr) => {
1424                write!(f, "Key::Package({})", base16::encode_lower(package_addr))
1425            }
1426            Key::AddressableEntity(entity_addr) => write!(
1427                f,
1428                "Key::AddressableEntity({}-{})",
1429                entity_addr.tag(),
1430                base16::encode_lower(&entity_addr.value())
1431            ),
1432            Key::ByteCode(byte_code_addr) => {
1433                write!(f, "Key::ByteCode({})", byte_code_addr)
1434            }
1435            Key::NamedKey(named_key_addr) => {
1436                write!(f, "Key::NamedKey({})", named_key_addr)
1437            }
1438            Key::BlockGlobal(addr) => {
1439                write!(
1440                    f,
1441                    "Key::BlockGlobal({}-{})",
1442                    addr,
1443                    base16::encode_lower(&BLOCK_GLOBAL_PADDING_BYTES)
1444                )
1445            }
1446            Key::BalanceHold(balance_hold_addr) => {
1447                write!(f, "Key::BalanceHold({})", balance_hold_addr)
1448            }
1449            Key::EntryPoint(entry_point_addr) => {
1450                write!(f, "Key::EntryPointAddr({})", entry_point_addr)
1451            }
1452            Key::State(entity_addr) => {
1453                write!(f, "Key::State({})", entity_addr)
1454            }
1455        }
1456    }
1457}
1458
1459impl Debug for Key {
1460    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1461        write!(f, "{}", self)
1462    }
1463}
1464
1465impl Tagged<KeyTag> for Key {
1466    fn tag(&self) -> KeyTag {
1467        match self {
1468            Key::Account(_) => KeyTag::Account,
1469            Key::Hash(_) => KeyTag::Hash,
1470            Key::URef(_) => KeyTag::URef,
1471            Key::Transfer(_) => KeyTag::Transfer,
1472            Key::DeployInfo(_) => KeyTag::DeployInfo,
1473            Key::EraInfo(_) => KeyTag::EraInfo,
1474            Key::Balance(_) => KeyTag::Balance,
1475            Key::Bid(_) => KeyTag::Bid,
1476            Key::Withdraw(_) => KeyTag::Withdraw,
1477            Key::Dictionary(_) => KeyTag::Dictionary,
1478            Key::SystemEntityRegistry => KeyTag::SystemEntityRegistry,
1479            Key::EraSummary => KeyTag::EraSummary,
1480            Key::Unbond(_) => KeyTag::Unbond,
1481            Key::ChainspecRegistry => KeyTag::ChainspecRegistry,
1482            Key::ChecksumRegistry => KeyTag::ChecksumRegistry,
1483            Key::BidAddr(_) => KeyTag::BidAddr,
1484            Key::SmartContract(_) => KeyTag::Package,
1485            Key::AddressableEntity(..) => KeyTag::AddressableEntity,
1486            Key::ByteCode(..) => KeyTag::ByteCode,
1487            Key::Message(_) => KeyTag::Message,
1488            Key::NamedKey(_) => KeyTag::NamedKey,
1489            Key::BlockGlobal(_) => KeyTag::BlockGlobal,
1490            Key::BalanceHold(_) => KeyTag::BalanceHold,
1491            Key::EntryPoint(_) => KeyTag::EntryPoint,
1492            Key::State(_) => KeyTag::State,
1493        }
1494    }
1495}
1496
1497impl Tagged<u8> for Key {
1498    fn tag(&self) -> u8 {
1499        let key_tag: KeyTag = self.tag();
1500        key_tag as u8
1501    }
1502}
1503
1504impl From<URef> for Key {
1505    fn from(uref: URef) -> Key {
1506        Key::URef(uref)
1507    }
1508}
1509
1510impl From<AccountHash> for Key {
1511    fn from(account_hash: AccountHash) -> Key {
1512        Key::Account(account_hash)
1513    }
1514}
1515
1516impl From<PackageHash> for Key {
1517    fn from(package_hash: PackageHash) -> Key {
1518        Key::SmartContract(package_hash.value())
1519    }
1520}
1521
1522impl From<ContractWasmHash> for Key {
1523    fn from(wasm_hash: ContractWasmHash) -> Self {
1524        Key::Hash(wasm_hash.value())
1525    }
1526}
1527
1528impl From<ContractPackageHash> for Key {
1529    fn from(contract_package_hash: ContractPackageHash) -> Self {
1530        Key::Hash(contract_package_hash.value())
1531    }
1532}
1533
1534impl From<ContractHash> for Key {
1535    fn from(contract_hash: ContractHash) -> Self {
1536        Key::Hash(contract_hash.value())
1537    }
1538}
1539
1540impl From<EntityAddr> for Key {
1541    fn from(entity_addr: EntityAddr) -> Self {
1542        Key::AddressableEntity(entity_addr)
1543    }
1544}
1545
1546impl From<NamedKeyAddr> for Key {
1547    fn from(value: NamedKeyAddr) -> Self {
1548        Key::NamedKey(value)
1549    }
1550}
1551
1552impl From<ByteCodeAddr> for Key {
1553    fn from(value: ByteCodeAddr) -> Self {
1554        Key::ByteCode(value)
1555    }
1556}
1557
1558impl ToBytes for Key {
1559    fn to_bytes(&self) -> Result<Vec<u8>, Error> {
1560        let mut result = bytesrepr::unchecked_allocate_buffer(self);
1561        self.write_bytes(&mut result)?;
1562        Ok(result)
1563    }
1564
1565    fn serialized_length(&self) -> usize {
1566        match self {
1567            Key::Account(account_hash) => {
1568                KEY_ID_SERIALIZED_LENGTH + account_hash.serialized_length()
1569            }
1570            Key::Hash(_) => KEY_HASH_SERIALIZED_LENGTH,
1571            Key::URef(_) => KEY_UREF_SERIALIZED_LENGTH,
1572            Key::Transfer(_) => KEY_TRANSFER_SERIALIZED_LENGTH,
1573            Key::DeployInfo(_) => KEY_DEPLOY_INFO_SERIALIZED_LENGTH,
1574            Key::EraInfo(_) => KEY_ERA_INFO_SERIALIZED_LENGTH,
1575            Key::Balance(_) => KEY_BALANCE_SERIALIZED_LENGTH,
1576            Key::Bid(_) => KEY_BID_SERIALIZED_LENGTH,
1577            Key::Withdraw(_) => KEY_WITHDRAW_SERIALIZED_LENGTH,
1578            Key::Dictionary(_) => KEY_DICTIONARY_SERIALIZED_LENGTH,
1579            Key::SystemEntityRegistry => KEY_SYSTEM_ENTITY_REGISTRY_SERIALIZED_LENGTH,
1580            Key::EraSummary => KEY_ERA_SUMMARY_SERIALIZED_LENGTH,
1581            Key::Unbond(_) => KEY_UNBOND_SERIALIZED_LENGTH,
1582            Key::ChainspecRegistry => KEY_CHAINSPEC_REGISTRY_SERIALIZED_LENGTH,
1583            Key::ChecksumRegistry => KEY_CHECKSUM_REGISTRY_SERIALIZED_LENGTH,
1584            Key::BidAddr(bid_addr) => KEY_ID_SERIALIZED_LENGTH + bid_addr.serialized_length(),
1585            Key::SmartContract(_) => KEY_PACKAGE_SERIALIZED_LENGTH,
1586            Key::AddressableEntity(entity_addr) => {
1587                KEY_ID_SERIALIZED_LENGTH + entity_addr.serialized_length()
1588            }
1589            Key::ByteCode(byte_code_addr) => {
1590                KEY_ID_SERIALIZED_LENGTH + byte_code_addr.serialized_length()
1591            }
1592            Key::Message(message_addr) => {
1593                KEY_ID_SERIALIZED_LENGTH + message_addr.serialized_length()
1594            }
1595            Key::NamedKey(named_key_addr) => {
1596                KEY_ID_SERIALIZED_LENGTH + named_key_addr.serialized_length()
1597            }
1598            Key::BlockGlobal(addr) => {
1599                KEY_ID_SERIALIZED_LENGTH
1600                    + addr.serialized_length()
1601                    + BLOCK_GLOBAL_PADDING_BYTES.len()
1602            }
1603            Key::BalanceHold(balance_hold_addr) => {
1604                KEY_ID_SERIALIZED_LENGTH + balance_hold_addr.serialized_length()
1605            }
1606            Key::EntryPoint(entry_point_addr) => {
1607                U8_SERIALIZED_LENGTH + entry_point_addr.serialized_length()
1608            }
1609            Key::State(entity_addr) => KEY_ID_SERIALIZED_LENGTH + entity_addr.serialized_length(),
1610        }
1611    }
1612
1613    fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), Error> {
1614        writer.push(self.tag());
1615        match self {
1616            Key::Account(account_hash) => account_hash.write_bytes(writer),
1617            Key::Hash(hash) => hash.write_bytes(writer),
1618            Key::URef(uref) => uref.write_bytes(writer),
1619            Key::Transfer(addr) => addr.write_bytes(writer),
1620            Key::DeployInfo(deploy_hash) => deploy_hash.write_bytes(writer),
1621            Key::EraInfo(era_id) => era_id.write_bytes(writer),
1622            Key::Balance(uref_addr) => uref_addr.write_bytes(writer),
1623            Key::Bid(account_hash) => account_hash.write_bytes(writer),
1624            Key::Withdraw(account_hash) => account_hash.write_bytes(writer),
1625            Key::Dictionary(addr) => addr.write_bytes(writer),
1626            Key::Unbond(account_hash) => account_hash.write_bytes(writer),
1627            Key::SystemEntityRegistry
1628            | Key::EraSummary
1629            | Key::ChainspecRegistry
1630            | Key::ChecksumRegistry => PADDING_BYTES.write_bytes(writer),
1631            Key::BlockGlobal(addr) => {
1632                addr.write_bytes(writer)?;
1633                BLOCK_GLOBAL_PADDING_BYTES.write_bytes(writer)
1634            }
1635            Key::BidAddr(bid_addr) => bid_addr.write_bytes(writer),
1636            Key::SmartContract(package_addr) => package_addr.write_bytes(writer),
1637            Key::AddressableEntity(entity_addr) => entity_addr.write_bytes(writer),
1638            Key::ByteCode(byte_code_addr) => byte_code_addr.write_bytes(writer),
1639            Key::Message(message_addr) => message_addr.write_bytes(writer),
1640            Key::NamedKey(named_key_addr) => named_key_addr.write_bytes(writer),
1641            Key::BalanceHold(balance_hold_addr) => balance_hold_addr.write_bytes(writer),
1642            Key::EntryPoint(entry_point_addr) => entry_point_addr.write_bytes(writer),
1643            Key::State(entity_addr) => entity_addr.write_bytes(writer),
1644        }
1645    }
1646}
1647
1648impl FromBytes for Key {
1649    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error> {
1650        if bytes.is_empty() {
1651            error!("FromBytes for Key: bytes length should not be 0");
1652        }
1653        let (tag, remainder) = match KeyTag::from_bytes(bytes) {
1654            Ok((tag, rem)) => (tag, rem),
1655            Err(err) => {
1656                error!(%err, "FromBytes for Key");
1657                return Err(err);
1658            }
1659        };
1660        match tag {
1661            KeyTag::Account => {
1662                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1663                Ok((Key::Account(account_hash), rem))
1664            }
1665            KeyTag::Hash => {
1666                let (hash, rem) = HashAddr::from_bytes(remainder)?;
1667                Ok((Key::Hash(hash), rem))
1668            }
1669            KeyTag::URef => {
1670                let (uref, rem) = URef::from_bytes(remainder)?;
1671                Ok((Key::URef(uref), rem))
1672            }
1673            KeyTag::Transfer => {
1674                let (transfer_v1_addr, rem) = TransferAddr::from_bytes(remainder)?;
1675                Ok((Key::Transfer(transfer_v1_addr), rem))
1676            }
1677            KeyTag::DeployInfo => {
1678                let (deploy_hash, rem) = DeployHash::from_bytes(remainder)?;
1679                Ok((Key::DeployInfo(deploy_hash), rem))
1680            }
1681            KeyTag::EraInfo => {
1682                let (era_id, rem) = EraId::from_bytes(remainder)?;
1683                Ok((Key::EraInfo(era_id), rem))
1684            }
1685            KeyTag::Balance => {
1686                let (uref_addr, rem) = URefAddr::from_bytes(remainder)?;
1687                Ok((Key::Balance(uref_addr), rem))
1688            }
1689            KeyTag::Bid => {
1690                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1691                Ok((Key::Bid(account_hash), rem))
1692            }
1693            KeyTag::Withdraw => {
1694                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1695                Ok((Key::Withdraw(account_hash), rem))
1696            }
1697            KeyTag::Dictionary => {
1698                let (addr, rem) = DictionaryAddr::from_bytes(remainder)?;
1699                Ok((Key::Dictionary(addr), rem))
1700            }
1701            KeyTag::SystemEntityRegistry => {
1702                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1703                Ok((Key::SystemEntityRegistry, rem))
1704            }
1705            KeyTag::EraSummary => {
1706                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1707                Ok((Key::EraSummary, rem))
1708            }
1709            KeyTag::Unbond => {
1710                let (account_hash, rem) = AccountHash::from_bytes(remainder)?;
1711                Ok((Key::Unbond(account_hash), rem))
1712            }
1713            KeyTag::ChainspecRegistry => {
1714                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1715                Ok((Key::ChainspecRegistry, rem))
1716            }
1717            KeyTag::ChecksumRegistry => {
1718                let (_, rem) = <[u8; 32]>::from_bytes(remainder)?;
1719                Ok((Key::ChecksumRegistry, rem))
1720            }
1721            KeyTag::BidAddr => {
1722                let (bid_addr, rem) = BidAddr::from_bytes(remainder)?;
1723                Ok((Key::BidAddr(bid_addr), rem))
1724            }
1725            KeyTag::Package => {
1726                let (package_addr, rem) = PackageAddr::from_bytes(remainder)?;
1727                Ok((Key::SmartContract(package_addr), rem))
1728            }
1729            KeyTag::AddressableEntity => {
1730                let (entity_addr, rem) = EntityAddr::from_bytes(remainder)?;
1731                Ok((Key::AddressableEntity(entity_addr), rem))
1732            }
1733            KeyTag::ByteCode => {
1734                let (byte_code_addr, rem) = ByteCodeAddr::from_bytes(remainder)?;
1735                Ok((Key::ByteCode(byte_code_addr), rem))
1736            }
1737            KeyTag::Message => {
1738                let (message_addr, rem) = MessageAddr::from_bytes(remainder)?;
1739                Ok((Key::Message(message_addr), rem))
1740            }
1741            KeyTag::NamedKey => {
1742                let (named_key_addr, rem) = NamedKeyAddr::from_bytes(remainder)?;
1743                Ok((Key::NamedKey(named_key_addr), rem))
1744            }
1745            KeyTag::BlockGlobal => {
1746                let (addr, rem) = BlockGlobalAddr::from_bytes(remainder)?;
1747                let (_, rem) = <[u8; 31]>::from_bytes(rem)?; // strip padding
1748                Ok((Key::BlockGlobal(addr), rem))
1749            }
1750            KeyTag::BalanceHold => {
1751                let (balance_hold_addr, rem) = BalanceHoldAddr::from_bytes(remainder)?;
1752                Ok((Key::BalanceHold(balance_hold_addr), rem))
1753            }
1754            KeyTag::EntryPoint => {
1755                let (entry_point_addr, rem) = EntryPointAddr::from_bytes(remainder)?;
1756                Ok((Key::EntryPoint(entry_point_addr), rem))
1757            }
1758            KeyTag::State => {
1759                let (entity_addr, rem) = EntityAddr::from_bytes(remainder)?;
1760                Ok((Key::State(entity_addr), rem))
1761            }
1762        }
1763    }
1764}
1765
1766#[allow(dead_code)]
1767fn please_add_to_distribution_impl(key: Key) {
1768    // If you've been forced to come here, you likely need to add your variant to the
1769    // `Distribution` impl for `Key`.
1770    match key {
1771        Key::Account(_) => unimplemented!(),
1772        Key::Hash(_) => unimplemented!(),
1773        Key::URef(_) => unimplemented!(),
1774        Key::Transfer(_) => unimplemented!(),
1775        Key::DeployInfo(_) => unimplemented!(),
1776        Key::EraInfo(_) => unimplemented!(),
1777        Key::Balance(_) => unimplemented!(),
1778        Key::Bid(_) => unimplemented!(),
1779        Key::Withdraw(_) => unimplemented!(),
1780        Key::Dictionary(_) => unimplemented!(),
1781        Key::SystemEntityRegistry => unimplemented!(),
1782        Key::EraSummary => unimplemented!(),
1783        Key::Unbond(_) => unimplemented!(),
1784        Key::ChainspecRegistry => unimplemented!(),
1785        Key::ChecksumRegistry => unimplemented!(),
1786        Key::BidAddr(_) => unimplemented!(),
1787        Key::SmartContract(_) => unimplemented!(),
1788        Key::AddressableEntity(..) => unimplemented!(),
1789        Key::ByteCode(..) => unimplemented!(),
1790        Key::Message(_) => unimplemented!(),
1791        Key::NamedKey(_) => unimplemented!(),
1792        Key::BlockGlobal(_) => unimplemented!(),
1793        Key::BalanceHold(_) => unimplemented!(),
1794        Key::EntryPoint(_) => unimplemented!(),
1795        Key::State(_) => unimplemented!(),
1796    }
1797}
1798
1799#[cfg(any(feature = "testing", test))]
1800impl Distribution<Key> for Standard {
1801    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Key {
1802        match rng.gen_range(0..=24) {
1803            0 => Key::Account(rng.gen()),
1804            1 => Key::Hash(rng.gen()),
1805            2 => Key::URef(rng.gen()),
1806            3 => Key::Transfer(TransferAddr::new(rng.gen())),
1807            4 => Key::DeployInfo(DeployHash::from_raw(rng.gen())),
1808            5 => Key::EraInfo(EraId::new(rng.gen())),
1809            6 => Key::Balance(rng.gen()),
1810            7 => Key::Bid(rng.gen()),
1811            8 => Key::Withdraw(rng.gen()),
1812            9 => Key::Dictionary(rng.gen()),
1813            10 => Key::SystemEntityRegistry,
1814            11 => Key::EraSummary,
1815            12 => Key::Unbond(rng.gen()),
1816            13 => Key::ChainspecRegistry,
1817            14 => Key::ChecksumRegistry,
1818            15 => Key::BidAddr(rng.gen()),
1819            16 => Key::SmartContract(rng.gen()),
1820            17 => Key::AddressableEntity(rng.gen()),
1821            18 => Key::ByteCode(rng.gen()),
1822            19 => Key::Message(rng.gen()),
1823            20 => Key::NamedKey(NamedKeyAddr::new_named_key_entry(rng.gen(), rng.gen())),
1824            21 => Key::BlockGlobal(rng.gen()),
1825            22 => Key::BalanceHold(rng.gen()),
1826            23 => Key::EntryPoint(rng.gen()),
1827            24 => Key::State(rng.gen()),
1828            _ => unreachable!(),
1829        }
1830    }
1831}
1832
1833mod serde_helpers {
1834    use super::*;
1835
1836    #[derive(Serialize)]
1837    pub(super) enum BinarySerHelper<'a> {
1838        Account(&'a AccountHash),
1839        Hash(&'a HashAddr),
1840        URef(&'a URef),
1841        Transfer(&'a TransferAddr),
1842        #[serde(with = "crate::serde_helpers::deploy_hash_as_array")]
1843        DeployInfo(&'a DeployHash),
1844        EraInfo(&'a EraId),
1845        Balance(&'a URefAddr),
1846        Bid(&'a AccountHash),
1847        Withdraw(&'a AccountHash),
1848        Dictionary(&'a HashAddr),
1849        SystemEntityRegistry,
1850        EraSummary,
1851        Unbond(&'a AccountHash),
1852        ChainspecRegistry,
1853        ChecksumRegistry,
1854        BidAddr(&'a BidAddr),
1855        Package(&'a PackageAddr),
1856        AddressableEntity(&'a EntityAddr),
1857        ByteCode(&'a ByteCodeAddr),
1858        Message(&'a MessageAddr),
1859        NamedKey(&'a NamedKeyAddr),
1860        BlockGlobal(&'a BlockGlobalAddr),
1861        BalanceHold(&'a BalanceHoldAddr),
1862        EntryPoint(&'a EntryPointAddr),
1863        State(&'a EntityAddr),
1864    }
1865
1866    #[derive(Deserialize)]
1867    pub(super) enum BinaryDeserHelper {
1868        Account(AccountHash),
1869        Hash(HashAddr),
1870        URef(URef),
1871        Transfer(TransferAddr),
1872        #[serde(with = "crate::serde_helpers::deploy_hash_as_array")]
1873        DeployInfo(DeployHash),
1874        EraInfo(EraId),
1875        Balance(URefAddr),
1876        Bid(AccountHash),
1877        Withdraw(AccountHash),
1878        Dictionary(DictionaryAddr),
1879        SystemEntityRegistry,
1880        EraSummary,
1881        Unbond(AccountHash),
1882        ChainspecRegistry,
1883        ChecksumRegistry,
1884        BidAddr(BidAddr),
1885        Package(PackageAddr),
1886        AddressableEntity(EntityAddr),
1887        ByteCode(ByteCodeAddr),
1888        Message(MessageAddr),
1889        NamedKey(NamedKeyAddr),
1890        BlockGlobal(BlockGlobalAddr),
1891        BalanceHold(BalanceHoldAddr),
1892        EntryPoint(EntryPointAddr),
1893        State(EntityAddr),
1894    }
1895
1896    impl<'a> From<&'a Key> for BinarySerHelper<'a> {
1897        fn from(key: &'a Key) -> Self {
1898            match key {
1899                Key::Account(account_hash) => BinarySerHelper::Account(account_hash),
1900                Key::Hash(hash_addr) => BinarySerHelper::Hash(hash_addr),
1901                Key::URef(uref) => BinarySerHelper::URef(uref),
1902                Key::Transfer(transfer_v1_addr) => BinarySerHelper::Transfer(transfer_v1_addr),
1903                Key::DeployInfo(deploy_hash) => BinarySerHelper::DeployInfo(deploy_hash),
1904                Key::EraInfo(era_id) => BinarySerHelper::EraInfo(era_id),
1905                Key::Balance(uref_addr) => BinarySerHelper::Balance(uref_addr),
1906                Key::Bid(account_hash) => BinarySerHelper::Bid(account_hash),
1907                Key::Withdraw(account_hash) => BinarySerHelper::Withdraw(account_hash),
1908                Key::Dictionary(addr) => BinarySerHelper::Dictionary(addr),
1909                Key::SystemEntityRegistry => BinarySerHelper::SystemEntityRegistry,
1910                Key::EraSummary => BinarySerHelper::EraSummary,
1911                Key::Unbond(account_hash) => BinarySerHelper::Unbond(account_hash),
1912                Key::ChainspecRegistry => BinarySerHelper::ChainspecRegistry,
1913                Key::ChecksumRegistry => BinarySerHelper::ChecksumRegistry,
1914                Key::BidAddr(bid_addr) => BinarySerHelper::BidAddr(bid_addr),
1915                Key::Message(message_addr) => BinarySerHelper::Message(message_addr),
1916                Key::SmartContract(package_addr) => BinarySerHelper::Package(package_addr),
1917                Key::AddressableEntity(entity_addr) => {
1918                    BinarySerHelper::AddressableEntity(entity_addr)
1919                }
1920                Key::ByteCode(byte_code_addr) => BinarySerHelper::ByteCode(byte_code_addr),
1921                Key::NamedKey(named_key_addr) => BinarySerHelper::NamedKey(named_key_addr),
1922                Key::BlockGlobal(addr) => BinarySerHelper::BlockGlobal(addr),
1923                Key::BalanceHold(balance_hold_addr) => {
1924                    BinarySerHelper::BalanceHold(balance_hold_addr)
1925                }
1926                Key::EntryPoint(entry_point_addr) => BinarySerHelper::EntryPoint(entry_point_addr),
1927                Key::State(entity_addr) => BinarySerHelper::State(entity_addr),
1928            }
1929        }
1930    }
1931
1932    impl From<BinaryDeserHelper> for Key {
1933        fn from(helper: BinaryDeserHelper) -> Self {
1934            match helper {
1935                BinaryDeserHelper::Account(account_hash) => Key::Account(account_hash),
1936                BinaryDeserHelper::Hash(hash_addr) => Key::Hash(hash_addr),
1937                BinaryDeserHelper::URef(uref) => Key::URef(uref),
1938                BinaryDeserHelper::Transfer(transfer_v1_addr) => Key::Transfer(transfer_v1_addr),
1939                BinaryDeserHelper::DeployInfo(deploy_hash) => Key::DeployInfo(deploy_hash),
1940                BinaryDeserHelper::EraInfo(era_id) => Key::EraInfo(era_id),
1941                BinaryDeserHelper::Balance(uref_addr) => Key::Balance(uref_addr),
1942                BinaryDeserHelper::Bid(account_hash) => Key::Bid(account_hash),
1943                BinaryDeserHelper::Withdraw(account_hash) => Key::Withdraw(account_hash),
1944                BinaryDeserHelper::Dictionary(addr) => Key::Dictionary(addr),
1945                BinaryDeserHelper::SystemEntityRegistry => Key::SystemEntityRegistry,
1946                BinaryDeserHelper::EraSummary => Key::EraSummary,
1947                BinaryDeserHelper::Unbond(account_hash) => Key::Unbond(account_hash),
1948                BinaryDeserHelper::ChainspecRegistry => Key::ChainspecRegistry,
1949                BinaryDeserHelper::ChecksumRegistry => Key::ChecksumRegistry,
1950                BinaryDeserHelper::BidAddr(bid_addr) => Key::BidAddr(bid_addr),
1951                BinaryDeserHelper::Message(message_addr) => Key::Message(message_addr),
1952                BinaryDeserHelper::Package(package_addr) => Key::SmartContract(package_addr),
1953                BinaryDeserHelper::AddressableEntity(entity_addr) => {
1954                    Key::AddressableEntity(entity_addr)
1955                }
1956                BinaryDeserHelper::ByteCode(byte_code_addr) => Key::ByteCode(byte_code_addr),
1957                BinaryDeserHelper::NamedKey(named_key_addr) => Key::NamedKey(named_key_addr),
1958                BinaryDeserHelper::BlockGlobal(addr) => Key::BlockGlobal(addr),
1959                BinaryDeserHelper::BalanceHold(balance_hold_addr) => {
1960                    Key::BalanceHold(balance_hold_addr)
1961                }
1962                BinaryDeserHelper::EntryPoint(entry_point_addr) => {
1963                    Key::EntryPoint(entry_point_addr)
1964                }
1965                BinaryDeserHelper::State(entity_addr) => Key::State(entity_addr),
1966            }
1967        }
1968    }
1969}
1970
1971impl Serialize for Key {
1972    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1973        if serializer.is_human_readable() {
1974            self.to_formatted_string().serialize(serializer)
1975        } else {
1976            serde_helpers::BinarySerHelper::from(self).serialize(serializer)
1977        }
1978    }
1979}
1980
1981impl<'de> Deserialize<'de> for Key {
1982    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1983        if deserializer.is_human_readable() {
1984            let formatted_key = String::deserialize(deserializer)?;
1985            Key::from_formatted_str(&formatted_key).map_err(SerdeError::custom)
1986        } else {
1987            let binary_helper = serde_helpers::BinaryDeserHelper::deserialize(deserializer)?;
1988            Ok(Key::from(binary_helper))
1989        }
1990    }
1991}
1992
1993#[cfg(test)]
1994mod tests {
1995    use std::string::ToString;
1996
1997    use super::*;
1998    use crate::{
1999        account::ACCOUNT_HASH_FORMATTED_STRING_PREFIX,
2000        bytesrepr::{Error, FromBytes},
2001        uref::UREF_FORMATTED_STRING_PREFIX,
2002        AccessRights, BlockTime, URef,
2003    };
2004
2005    const TRANSFER_ADDR_FORMATTED_STRING_PREFIX: &str = "transfer-";
2006    const ENTITY_PREFIX: &str = "entity-";
2007    const ACCOUNT_ENTITY_PREFIX: &str = "account-";
2008
2009    const BYTE_CODE_PREFIX: &str = "byte-code-";
2010    const EMPTY_PREFIX: &str = "empty-";
2011
2012    const ACCOUNT_KEY: Key = Key::Account(AccountHash::new([42; 32]));
2013    const HASH_KEY: Key = Key::Hash([42; 32]);
2014    const UREF_KEY: Key = Key::URef(URef::new([42; 32], AccessRights::READ));
2015    const TRANSFER_KEY: Key = Key::Transfer(TransferAddr::new([42; 32]));
2016    const DEPLOY_INFO_KEY: Key = Key::DeployInfo(DeployHash::from_raw([42; 32]));
2017    const ERA_INFO_KEY: Key = Key::EraInfo(EraId::new(42));
2018    const BALANCE_KEY: Key = Key::Balance([42; 32]);
2019    const BID_KEY: Key = Key::Bid(AccountHash::new([42; 32]));
2020    const UNIFIED_BID_KEY: Key = Key::BidAddr(BidAddr::legacy([42; 32]));
2021    const VALIDATOR_BID_KEY: Key = Key::BidAddr(BidAddr::new_validator_addr([2; 32]));
2022    const DELEGATOR_BID_KEY: Key =
2023        Key::BidAddr(BidAddr::new_delegator_account_addr(([2; 32], [9; 32])));
2024    const WITHDRAW_KEY: Key = Key::Withdraw(AccountHash::new([42; 32]));
2025    const DICTIONARY_KEY: Key = Key::Dictionary([42; 32]);
2026    const SYSTEM_ENTITY_REGISTRY_KEY: Key = Key::SystemEntityRegistry;
2027    const ERA_SUMMARY_KEY: Key = Key::EraSummary;
2028    const UNBOND_KEY: Key = Key::Unbond(AccountHash::new([42; 32]));
2029    const CHAINSPEC_REGISTRY_KEY: Key = Key::ChainspecRegistry;
2030    const CHECKSUM_REGISTRY_KEY: Key = Key::ChecksumRegistry;
2031    const PACKAGE_KEY: Key = Key::SmartContract([42; 32]);
2032    const ADDRESSABLE_ENTITY_SYSTEM_KEY: Key =
2033        Key::AddressableEntity(EntityAddr::new_system([42; 32]));
2034    const ADDRESSABLE_ENTITY_ACCOUNT_KEY: Key =
2035        Key::AddressableEntity(EntityAddr::new_account([42; 32]));
2036    const ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY: Key =
2037        Key::AddressableEntity(EntityAddr::new_smart_contract([42; 32]));
2038    const BYTE_CODE_EMPTY_KEY: Key = Key::ByteCode(ByteCodeAddr::Empty);
2039    const BYTE_CODE_V1_WASM_KEY: Key = Key::ByteCode(ByteCodeAddr::V1CasperWasm([42; 32]));
2040    const MESSAGE_TOPIC_KEY: Key = Key::Message(MessageAddr::new_topic_addr(
2041        EntityAddr::SmartContract([42; 32]),
2042        TopicNameHash::new([42; 32]),
2043    ));
2044    const MESSAGE_KEY: Key = Key::Message(MessageAddr::new_message_addr(
2045        EntityAddr::SmartContract([42; 32]),
2046        TopicNameHash::new([2; 32]),
2047        15,
2048    ));
2049    const NAMED_KEY: Key = Key::NamedKey(NamedKeyAddr::new_named_key_entry(
2050        EntityAddr::new_smart_contract([42; 32]),
2051        [43; 32],
2052    ));
2053    const BLOCK_TIME_KEY: Key = Key::BlockGlobal(BlockGlobalAddr::BlockTime);
2054    const BLOCK_MESSAGE_COUNT_KEY: Key = Key::BlockGlobal(BlockGlobalAddr::MessageCount);
2055    // const STATE_KEY: Key = Key::State(EntityAddr::new_contract_entity_addr([42; 32]));
2056    const BALANCE_HOLD: Key =
2057        Key::BalanceHold(BalanceHoldAddr::new_gas([42; 32], BlockTime::new(100)));
2058    const STATE_KEY: Key = Key::State(EntityAddr::new_smart_contract([42; 32]));
2059    const KEYS: &[Key] = &[
2060        ACCOUNT_KEY,
2061        HASH_KEY,
2062        UREF_KEY,
2063        TRANSFER_KEY,
2064        DEPLOY_INFO_KEY,
2065        ERA_INFO_KEY,
2066        BALANCE_KEY,
2067        BID_KEY,
2068        WITHDRAW_KEY,
2069        DICTIONARY_KEY,
2070        SYSTEM_ENTITY_REGISTRY_KEY,
2071        ERA_SUMMARY_KEY,
2072        UNBOND_KEY,
2073        CHAINSPEC_REGISTRY_KEY,
2074        CHECKSUM_REGISTRY_KEY,
2075        UNIFIED_BID_KEY,
2076        VALIDATOR_BID_KEY,
2077        DELEGATOR_BID_KEY,
2078        PACKAGE_KEY,
2079        ADDRESSABLE_ENTITY_SYSTEM_KEY,
2080        ADDRESSABLE_ENTITY_ACCOUNT_KEY,
2081        ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY,
2082        BYTE_CODE_EMPTY_KEY,
2083        BYTE_CODE_V1_WASM_KEY,
2084        MESSAGE_TOPIC_KEY,
2085        MESSAGE_KEY,
2086        NAMED_KEY,
2087        BLOCK_TIME_KEY,
2088        BLOCK_MESSAGE_COUNT_KEY,
2089        BALANCE_HOLD,
2090        STATE_KEY,
2091    ];
2092    const HEX_STRING: &str = "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a";
2093    const TOPIC_NAME_HEX_STRING: &str =
2094        "0202020202020202020202020202020202020202020202020202020202020202";
2095    const MESSAGE_INDEX_HEX_STRING: &str = "f";
2096    const UNIFIED_HEX_STRING: &str =
2097        "002a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a";
2098    const VALIDATOR_HEX_STRING: &str =
2099        "010202020202020202020202020202020202020202020202020202020202020202";
2100    const DELEGATOR_HEX_STRING: &str =
2101        "0202020202020202020202020202020202020202020202020202020202020202020909090909090909090909090909090909090909090909090909090909090909";
2102
2103    fn test_readable(right: AccessRights, is_true: bool) {
2104        assert_eq!(right.is_readable(), is_true)
2105    }
2106
2107    #[test]
2108    fn test_is_readable() {
2109        test_readable(AccessRights::READ, true);
2110        test_readable(AccessRights::READ_ADD, true);
2111        test_readable(AccessRights::READ_WRITE, true);
2112        test_readable(AccessRights::READ_ADD_WRITE, true);
2113        test_readable(AccessRights::ADD, false);
2114        test_readable(AccessRights::ADD_WRITE, false);
2115        test_readable(AccessRights::WRITE, false);
2116    }
2117
2118    fn test_writable(right: AccessRights, is_true: bool) {
2119        assert_eq!(right.is_writeable(), is_true)
2120    }
2121
2122    #[test]
2123    fn test_is_writable() {
2124        test_writable(AccessRights::WRITE, true);
2125        test_writable(AccessRights::READ_WRITE, true);
2126        test_writable(AccessRights::ADD_WRITE, true);
2127        test_writable(AccessRights::READ, false);
2128        test_writable(AccessRights::ADD, false);
2129        test_writable(AccessRights::READ_ADD, false);
2130        test_writable(AccessRights::READ_ADD_WRITE, true);
2131    }
2132
2133    fn test_addable(right: AccessRights, is_true: bool) {
2134        assert_eq!(right.is_addable(), is_true)
2135    }
2136
2137    #[test]
2138    fn test_is_addable() {
2139        test_addable(AccessRights::ADD, true);
2140        test_addable(AccessRights::READ_ADD, true);
2141        test_addable(AccessRights::READ_WRITE, false);
2142        test_addable(AccessRights::ADD_WRITE, true);
2143        test_addable(AccessRights::READ, false);
2144        test_addable(AccessRights::WRITE, false);
2145        test_addable(AccessRights::READ_ADD_WRITE, true);
2146    }
2147
2148    #[test]
2149    fn should_display_key() {
2150        assert_eq!(
2151            format!("{}", ACCOUNT_KEY),
2152            format!("Key::Account({})", HEX_STRING)
2153        );
2154        assert_eq!(
2155            format!("{}", HASH_KEY),
2156            format!("Key::Hash({})", HEX_STRING)
2157        );
2158        assert_eq!(
2159            format!("{}", UREF_KEY),
2160            format!("Key::URef({}, READ)", HEX_STRING)
2161        );
2162        assert_eq!(
2163            format!("{}", TRANSFER_KEY),
2164            format!("Key::Transfer({})", HEX_STRING)
2165        );
2166        assert_eq!(
2167            format!("{}", DEPLOY_INFO_KEY),
2168            format!("Key::DeployInfo({})", HEX_STRING)
2169        );
2170        assert_eq!(
2171            format!("{}", ERA_INFO_KEY),
2172            "Key::EraInfo(era 42)".to_string()
2173        );
2174        assert_eq!(
2175            format!("{}", BALANCE_KEY),
2176            format!("Key::Balance({})", HEX_STRING)
2177        );
2178        assert_eq!(format!("{}", BID_KEY), format!("Key::Bid({})", HEX_STRING));
2179        assert_eq!(
2180            format!("{}", UNIFIED_BID_KEY),
2181            format!("Key::BidAddr({})", UNIFIED_HEX_STRING)
2182        );
2183        assert_eq!(
2184            format!("{}", VALIDATOR_BID_KEY),
2185            format!("Key::BidAddr({})", VALIDATOR_HEX_STRING)
2186        );
2187        assert_eq!(
2188            format!("{}", DELEGATOR_BID_KEY),
2189            format!("Key::BidAddr({})", DELEGATOR_HEX_STRING)
2190        );
2191        assert_eq!(
2192            format!("{}", WITHDRAW_KEY),
2193            format!("Key::Withdraw({})", HEX_STRING)
2194        );
2195        assert_eq!(
2196            format!("{}", DICTIONARY_KEY),
2197            format!("Key::Dictionary({})", HEX_STRING)
2198        );
2199        assert_eq!(
2200            format!("{}", SYSTEM_ENTITY_REGISTRY_KEY),
2201            format!(
2202                "Key::SystemEntityRegistry({})",
2203                base16::encode_lower(&PADDING_BYTES)
2204            )
2205        );
2206        assert_eq!(
2207            format!("{}", ERA_SUMMARY_KEY),
2208            format!("Key::EraSummary({})", base16::encode_lower(&PADDING_BYTES))
2209        );
2210        assert_eq!(
2211            format!("{}", UNBOND_KEY),
2212            format!("Key::Unbond({})", HEX_STRING)
2213        );
2214        assert_eq!(
2215            format!("{}", CHAINSPEC_REGISTRY_KEY),
2216            format!(
2217                "Key::ChainspecRegistry({})",
2218                base16::encode_lower(&PADDING_BYTES)
2219            )
2220        );
2221        assert_eq!(
2222            format!("{}", CHECKSUM_REGISTRY_KEY),
2223            format!(
2224                "Key::ChecksumRegistry({})",
2225                base16::encode_lower(&PADDING_BYTES),
2226            )
2227        );
2228        assert_eq!(
2229            format!("{}", PACKAGE_KEY),
2230            format!("Key::Package({})", HEX_STRING)
2231        );
2232        assert_eq!(
2233            format!("{}", ADDRESSABLE_ENTITY_SYSTEM_KEY),
2234            format!("Key::AddressableEntity(system-{})", HEX_STRING)
2235        );
2236        assert_eq!(
2237            format!("{}", ADDRESSABLE_ENTITY_ACCOUNT_KEY),
2238            format!("Key::AddressableEntity(account-{})", HEX_STRING)
2239        );
2240        assert_eq!(
2241            format!("{}", ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY),
2242            format!("Key::AddressableEntity(contract-{})", HEX_STRING)
2243        );
2244        assert_eq!(
2245            format!("{}", BYTE_CODE_EMPTY_KEY),
2246            format!(
2247                "Key::ByteCode(byte-code-empty-{})",
2248                base16::encode_lower(&[0u8; 32])
2249            )
2250        );
2251        assert_eq!(
2252            format!("{}", BYTE_CODE_V1_WASM_KEY),
2253            format!("Key::ByteCode(byte-code-v1-wasm-{})", HEX_STRING)
2254        );
2255        assert_eq!(
2256            format!("{}", MESSAGE_TOPIC_KEY),
2257            format!(
2258                "Key::Message(entity-contract-{}-{})",
2259                HEX_STRING, HEX_STRING
2260            )
2261        );
2262        assert_eq!(
2263            format!("{}", MESSAGE_KEY),
2264            format!(
2265                "Key::Message(entity-contract-{}-{}-{})",
2266                HEX_STRING, TOPIC_NAME_HEX_STRING, MESSAGE_INDEX_HEX_STRING
2267            )
2268        );
2269
2270        assert_eq!(
2271            format!("{}", STATE_KEY),
2272            format!(
2273                "Key::State(entity-contract-{})",
2274                base16::encode_lower(&[42; 32])
2275            )
2276        );
2277        assert_eq!(
2278            format!("{}", BLOCK_TIME_KEY),
2279            format!(
2280                "Key::BlockGlobal({}-{})",
2281                BlockGlobalAddr::BlockTime,
2282                base16::encode_lower(&BLOCK_GLOBAL_PADDING_BYTES)
2283            )
2284        );
2285        assert_eq!(
2286            format!("{}", BLOCK_MESSAGE_COUNT_KEY),
2287            format!(
2288                "Key::BlockGlobal({}-{})",
2289                BlockGlobalAddr::MessageCount,
2290                base16::encode_lower(&BLOCK_GLOBAL_PADDING_BYTES)
2291            )
2292        );
2293    }
2294
2295    #[test]
2296    fn abuse_vec_key() {
2297        // Prefix is 2^32-1 = shouldn't allocate that much
2298        let bytes: Vec<u8> = vec![255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2299        let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
2300        assert_eq!(
2301            res.expect_err("should fail"),
2302            Error::EarlyEndOfStream,
2303            "length prefix says 2^32-1, but there's not enough data in the stream"
2304        );
2305
2306        // Prefix is 2^32-2 = shouldn't allocate that much
2307        let bytes: Vec<u8> = vec![255, 255, 255, 254, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2308        let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
2309        assert_eq!(
2310            res.expect_err("should fail"),
2311            Error::EarlyEndOfStream,
2312            "length prefix says 2^32-2, but there's not enough data in the stream"
2313        );
2314
2315        // Valid prefix but not enough data in the stream
2316        let bytes: Vec<u8> = vec![0, 0, 0, 254, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2317        let res: Result<(Vec<Key>, &[u8]), _> = FromBytes::from_bytes(&bytes);
2318        assert_eq!(
2319            res.expect_err("should fail"),
2320            Error::EarlyEndOfStream,
2321            "length prefix says 254, but there's not enough data in the stream"
2322        );
2323    }
2324
2325    #[test]
2326    fn check_key_account_getters() {
2327        let account = [42; 32];
2328        let account_hash = AccountHash::new(account);
2329        let key1 = Key::Account(account_hash);
2330        assert_eq!(key1.into_account(), Some(account_hash));
2331        assert!(key1.into_entity_hash_addr().is_some());
2332        assert!(key1.as_uref().is_none());
2333    }
2334
2335    #[test]
2336    fn check_key_hash_getters() {
2337        let hash = [42; KEY_HASH_LENGTH];
2338        let key1 = Key::Hash(hash);
2339        assert!(key1.into_account().is_none());
2340        assert_eq!(key1.into_hash_addr(), Some(hash));
2341        assert!(key1.as_uref().is_none());
2342    }
2343
2344    #[test]
2345    fn check_entity_key_getters() {
2346        let hash = [42; KEY_HASH_LENGTH];
2347        let key1 = Key::contract_entity_key(AddressableEntityHash::new(hash));
2348        assert!(key1.into_account().is_none());
2349        assert_eq!(key1.into_entity_hash_addr(), Some(hash));
2350        assert!(key1.as_uref().is_none());
2351    }
2352
2353    #[test]
2354    fn check_package_key_getters() {
2355        let hash = [42; KEY_HASH_LENGTH];
2356        let key1 = Key::SmartContract(hash);
2357        assert!(key1.into_account().is_none());
2358        assert_eq!(key1.into_package_addr(), Some(hash));
2359        assert!(key1.as_uref().is_none());
2360    }
2361
2362    #[test]
2363    fn check_key_uref_getters() {
2364        let uref = URef::new([42; 32], AccessRights::READ_ADD_WRITE);
2365        let key1 = Key::URef(uref);
2366        assert!(key1.into_account().is_none());
2367        assert!(key1.into_entity_hash_addr().is_none());
2368        assert_eq!(key1.as_uref(), Some(&uref));
2369    }
2370
2371    #[test]
2372    fn key_max_serialized_length() {
2373        let mut got_max = false;
2374        for key in KEYS {
2375            let expected = Key::max_serialized_length();
2376            let actual = key.serialized_length();
2377            assert!(
2378                actual <= expected,
2379                "key too long {} expected {} actual {}",
2380                key,
2381                expected,
2382                actual
2383            );
2384            if actual == Key::max_serialized_length() {
2385                got_max = true;
2386            }
2387        }
2388        assert!(
2389            got_max,
2390            "None of the Key variants has a serialized_length equal to \
2391            Key::max_serialized_length(), so Key::max_serialized_length() should be reduced"
2392        );
2393    }
2394
2395    #[test]
2396    fn should_parse_legacy_bid_key_from_string() {
2397        let account_hash = AccountHash([1; 32]);
2398        let legacy_bid_key = Key::Bid(account_hash);
2399        let original_string = legacy_bid_key.to_formatted_string();
2400
2401        let parsed_bid_key =
2402            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2403        if let Key::Bid(parsed_account_hash) = parsed_bid_key {
2404            assert_eq!(parsed_account_hash, account_hash,);
2405            assert_eq!(legacy_bid_key, parsed_bid_key);
2406
2407            let translated_string = parsed_bid_key.to_formatted_string();
2408            assert_eq!(original_string, translated_string);
2409        } else {
2410            panic!("should have account hash");
2411        }
2412    }
2413
2414    #[test]
2415    fn should_parse_legacy_unified_bid_key_from_string() {
2416        let legacy_bid_addr = BidAddr::legacy([1; 32]);
2417        let legacy_bid_key = Key::BidAddr(legacy_bid_addr);
2418        assert_eq!(legacy_bid_addr.tag(), BidAddrTag::Unified,);
2419
2420        let original_string = legacy_bid_key.to_formatted_string();
2421        let parsed_key =
2422            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2423        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2424        assert!(parsed_key.is_bid_addr_key());
2425        assert_eq!(parsed_bid_addr.tag(), legacy_bid_addr.tag(),);
2426        assert_eq!(*parsed_bid_addr, legacy_bid_addr);
2427
2428        let translated_string = parsed_key.to_formatted_string();
2429        assert_eq!(original_string, translated_string);
2430        assert_eq!(parsed_key.as_bid_addr(), legacy_bid_key.as_bid_addr(),);
2431    }
2432
2433    #[test]
2434    fn should_parse_validator_bid_key_from_string() {
2435        let validator_bid_addr = BidAddr::new_validator_addr([1; 32]);
2436        let validator_bid_key = Key::BidAddr(validator_bid_addr);
2437        assert_eq!(validator_bid_addr.tag(), BidAddrTag::Validator,);
2438
2439        let original_string = validator_bid_key.to_formatted_string();
2440        let parsed_key =
2441            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2442        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2443        assert!(parsed_key.is_bid_addr_key());
2444        assert_eq!(parsed_bid_addr.tag(), validator_bid_addr.tag(),);
2445        assert_eq!(*parsed_bid_addr, validator_bid_addr,);
2446
2447        let translated_string = parsed_key.to_formatted_string();
2448        assert_eq!(original_string, translated_string);
2449        assert_eq!(parsed_key.as_bid_addr(), validator_bid_key.as_bid_addr(),);
2450    }
2451
2452    #[test]
2453    fn should_parse_delegator_bid_key_from_string() {
2454        let delegator_bid_addr = BidAddr::new_delegator_account_addr(([1; 32], [9; 32]));
2455        let delegator_bid_key = Key::BidAddr(delegator_bid_addr);
2456        assert_eq!(delegator_bid_addr.tag(), BidAddrTag::DelegatedAccount);
2457
2458        let original_string = delegator_bid_key.to_formatted_string();
2459
2460        let parsed_key =
2461            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2462        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2463        assert!(parsed_key.is_bid_addr_key());
2464        assert_eq!(parsed_bid_addr.tag(), delegator_bid_addr.tag(),);
2465        assert_eq!(*parsed_bid_addr, delegator_bid_addr,);
2466
2467        let translated_string = parsed_key.to_formatted_string();
2468        assert_eq!(original_string, translated_string);
2469        assert_eq!(parsed_key.as_bid_addr(), delegator_bid_key.as_bid_addr(),);
2470    }
2471
2472    #[test]
2473    fn should_parse_credit_bid_key_from_string() {
2474        let credit_bid_addr = BidAddr::Credit {
2475            validator: AccountHash::new([1; 32]),
2476            era_id: 1.into(),
2477        };
2478        let delegator_bid_key = Key::BidAddr(credit_bid_addr);
2479        assert_eq!(credit_bid_addr.tag(), BidAddrTag::Credit);
2480
2481        let original_string = delegator_bid_key.to_formatted_string();
2482
2483        let parsed_key =
2484            Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})");
2485        let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr");
2486        assert!(parsed_key.is_bid_addr_key());
2487        assert_eq!(parsed_bid_addr.tag(), credit_bid_addr.tag(),);
2488        assert_eq!(*parsed_bid_addr, credit_bid_addr,);
2489
2490        let translated_string = parsed_key.to_formatted_string();
2491        assert_eq!(original_string, translated_string);
2492        assert_eq!(parsed_key.as_bid_addr(), delegator_bid_key.as_bid_addr());
2493    }
2494
2495    #[test]
2496    fn should_parse_key_from_str() {
2497        for key in KEYS {
2498            let string = key.to_formatted_string();
2499            let parsed_key = Key::from_formatted_str(&string).expect("{string} (key = {key:?})");
2500            assert_eq!(parsed_key, *key, "{string} (key = {key:?})");
2501        }
2502    }
2503
2504    #[test]
2505    fn should_fail_to_parse_key_from_str() {
2506        assert!(
2507            Key::from_formatted_str(ACCOUNT_HASH_FORMATTED_STRING_PREFIX)
2508                .unwrap_err()
2509                .to_string()
2510                .starts_with("account-key from string error: ")
2511        );
2512        assert!(Key::from_formatted_str(HASH_PREFIX)
2513            .unwrap_err()
2514            .to_string()
2515            .starts_with("hash-key from string error: "));
2516        assert!(Key::from_formatted_str(UREF_FORMATTED_STRING_PREFIX)
2517            .unwrap_err()
2518            .to_string()
2519            .starts_with("uref-key from string error: "));
2520        assert!(
2521            Key::from_formatted_str(TRANSFER_ADDR_FORMATTED_STRING_PREFIX)
2522                .unwrap_err()
2523                .to_string()
2524                .starts_with("legacy-transfer-key from string error: ")
2525        );
2526        assert!(Key::from_formatted_str(DEPLOY_INFO_PREFIX)
2527            .unwrap_err()
2528            .to_string()
2529            .starts_with("deploy-info-key from string error: "));
2530        assert!(Key::from_formatted_str(ERA_INFO_PREFIX)
2531            .unwrap_err()
2532            .to_string()
2533            .starts_with("era-info-key from string error: "));
2534        assert!(Key::from_formatted_str(BALANCE_PREFIX)
2535            .unwrap_err()
2536            .to_string()
2537            .starts_with("balance-key from string error: "));
2538        assert!(Key::from_formatted_str(BID_PREFIX)
2539            .unwrap_err()
2540            .to_string()
2541            .starts_with("bid-key from string error: "));
2542        assert!(Key::from_formatted_str(WITHDRAW_PREFIX)
2543            .unwrap_err()
2544            .to_string()
2545            .starts_with("withdraw-key from string error: "));
2546        assert!(Key::from_formatted_str(DICTIONARY_PREFIX)
2547            .unwrap_err()
2548            .to_string()
2549            .starts_with("dictionary-key from string error: "));
2550        assert!(Key::from_formatted_str(SYSTEM_ENTITY_REGISTRY_PREFIX)
2551            .unwrap_err()
2552            .to_string()
2553            .starts_with("system-contract-registry-key from string error: "));
2554        assert!(Key::from_formatted_str(ERA_SUMMARY_PREFIX)
2555            .unwrap_err()
2556            .to_string()
2557            .starts_with("era-summary-key from string error"));
2558        assert!(Key::from_formatted_str(UNBOND_PREFIX)
2559            .unwrap_err()
2560            .to_string()
2561            .starts_with("unbond-key from string error: "));
2562        assert!(Key::from_formatted_str(CHAINSPEC_REGISTRY_PREFIX)
2563            .unwrap_err()
2564            .to_string()
2565            .starts_with("chainspec-registry-key from string error: "));
2566        assert!(Key::from_formatted_str(CHECKSUM_REGISTRY_PREFIX)
2567            .unwrap_err()
2568            .to_string()
2569            .starts_with("checksum-registry-key from string error: "));
2570        let bid_addr_err = Key::from_formatted_str(BID_ADDR_PREFIX)
2571            .unwrap_err()
2572            .to_string();
2573        assert!(
2574            bid_addr_err.starts_with("bid-addr-key from string error: "),
2575            "{}",
2576            bid_addr_err
2577        );
2578        assert!(Key::from_formatted_str(PACKAGE_PREFIX)
2579            .unwrap_err()
2580            .to_string()
2581            .starts_with("package-key from string error: "));
2582
2583        let error_string =
2584            Key::from_formatted_str(&format!("{}{}", ENTITY_PREFIX, ACCOUNT_ENTITY_PREFIX))
2585                .unwrap_err()
2586                .to_string();
2587        assert!(error_string.starts_with("addressable-entity-key from string error: "));
2588        assert!(
2589            Key::from_formatted_str(&format!("{}{}", BYTE_CODE_PREFIX, EMPTY_PREFIX))
2590                .unwrap_err()
2591                .to_string()
2592                .starts_with("byte-code-key from string error: ")
2593        );
2594        let invalid_prefix = "a-0000000000000000000000000000000000000000000000000000000000000000";
2595        assert_eq!(
2596            Key::from_formatted_str(invalid_prefix)
2597                .unwrap_err()
2598                .to_string(),
2599            "unknown prefix for key"
2600        );
2601
2602        let missing_hyphen_prefix =
2603            "hash0000000000000000000000000000000000000000000000000000000000000000";
2604        assert_eq!(
2605            Key::from_formatted_str(missing_hyphen_prefix)
2606                .unwrap_err()
2607                .to_string(),
2608            "unknown prefix for key"
2609        );
2610
2611        let no_prefix = "0000000000000000000000000000000000000000000000000000000000000000";
2612        assert_eq!(
2613            Key::from_formatted_str(no_prefix).unwrap_err().to_string(),
2614            "unknown prefix for key"
2615        );
2616
2617        let balance_hold_err = Key::from_formatted_str(BALANCE_HOLD_PREFIX)
2618            .unwrap_err()
2619            .to_string();
2620        assert!(
2621            balance_hold_err.starts_with("balance-hold from string error: "),
2622            "{}",
2623            bid_addr_err
2624        );
2625    }
2626
2627    #[test]
2628    fn key_to_json() {
2629        for key in KEYS.iter() {
2630            assert_eq!(
2631                serde_json::to_string(key).unwrap(),
2632                format!("\"{}\"", key.to_formatted_string())
2633            );
2634        }
2635    }
2636
2637    #[test]
2638    fn serialization_roundtrip_bincode() {
2639        for key in KEYS {
2640            let encoded = bincode::serialize(key).unwrap();
2641            let decoded = bincode::deserialize(&encoded).unwrap();
2642            assert_eq!(key, &decoded);
2643        }
2644    }
2645
2646    #[test]
2647    fn key_tag_bytes_roundtrip() {
2648        for key in KEYS {
2649            let tag: KeyTag = key.tag();
2650            bytesrepr::test_serialization_roundtrip(&tag);
2651        }
2652    }
2653
2654    #[test]
2655    fn bytesrepr_serialization_roundtrip() {
2656        bytesrepr::test_serialization_roundtrip(&ACCOUNT_KEY);
2657        bytesrepr::test_serialization_roundtrip(&HASH_KEY);
2658        bytesrepr::test_serialization_roundtrip(&UREF_KEY);
2659        bytesrepr::test_serialization_roundtrip(&TRANSFER_KEY);
2660        bytesrepr::test_serialization_roundtrip(&DEPLOY_INFO_KEY);
2661        bytesrepr::test_serialization_roundtrip(&ERA_INFO_KEY);
2662        bytesrepr::test_serialization_roundtrip(&BALANCE_KEY);
2663        bytesrepr::test_serialization_roundtrip(&BID_KEY);
2664        bytesrepr::test_serialization_roundtrip(&WITHDRAW_KEY);
2665        bytesrepr::test_serialization_roundtrip(&DICTIONARY_KEY);
2666        // bytesrepr::test_serialization_roundtrip(&SYSTEM_CONTRACT_REGISTRY_KEY);
2667        bytesrepr::test_serialization_roundtrip(&ERA_SUMMARY_KEY);
2668        bytesrepr::test_serialization_roundtrip(&UNBOND_KEY);
2669        bytesrepr::test_serialization_roundtrip(&CHAINSPEC_REGISTRY_KEY);
2670        bytesrepr::test_serialization_roundtrip(&CHECKSUM_REGISTRY_KEY);
2671        // bytesrepr::test_serialization_roundtrip(&UNIFIED_BID_KEY);
2672        bytesrepr::test_serialization_roundtrip(&VALIDATOR_BID_KEY);
2673        bytesrepr::test_serialization_roundtrip(&DELEGATOR_BID_KEY);
2674        bytesrepr::test_serialization_roundtrip(&PACKAGE_KEY);
2675        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SYSTEM_KEY);
2676        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_ACCOUNT_KEY);
2677        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY);
2678        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_EMPTY_KEY);
2679        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_V1_WASM_KEY);
2680        bytesrepr::test_serialization_roundtrip(&MESSAGE_TOPIC_KEY);
2681        bytesrepr::test_serialization_roundtrip(&MESSAGE_KEY);
2682        bytesrepr::test_serialization_roundtrip(&NAMED_KEY);
2683        bytesrepr::test_serialization_roundtrip(&STATE_KEY);
2684    }
2685
2686    #[test]
2687    fn serialization_roundtrip_json() {
2688        for key in KEYS {
2689            round_trip(key);
2690        }
2691
2692        let zeros = [0; BLAKE2B_DIGEST_LENGTH];
2693        let nines = [9; BLAKE2B_DIGEST_LENGTH];
2694
2695        round_trip(&Key::Account(AccountHash::new(zeros)));
2696        round_trip(&Key::Hash(zeros));
2697        round_trip(&Key::URef(URef::new(zeros, AccessRights::READ)));
2698        round_trip(&Key::Transfer(TransferAddr::new(zeros)));
2699        round_trip(&Key::DeployInfo(DeployHash::from_raw(zeros)));
2700        round_trip(&Key::EraInfo(EraId::from(0)));
2701        round_trip(&Key::Balance(URef::new(zeros, AccessRights::READ).addr()));
2702        round_trip(&Key::Bid(AccountHash::new(zeros)));
2703        round_trip(&Key::BidAddr(BidAddr::legacy(zeros)));
2704        round_trip(&Key::BidAddr(BidAddr::new_validator_addr(zeros)));
2705        round_trip(&Key::BidAddr(BidAddr::new_delegator_account_addr((
2706            zeros, nines,
2707        ))));
2708        round_trip(&Key::Withdraw(AccountHash::new(zeros)));
2709        round_trip(&Key::Dictionary(zeros));
2710        round_trip(&Key::Unbond(AccountHash::new(zeros)));
2711        round_trip(&Key::SmartContract(zeros));
2712        round_trip(&Key::AddressableEntity(EntityAddr::new_system(zeros)));
2713        round_trip(&Key::AddressableEntity(EntityAddr::new_account(zeros)));
2714        round_trip(&Key::AddressableEntity(EntityAddr::new_smart_contract(
2715            zeros,
2716        )));
2717        round_trip(&Key::ByteCode(ByteCodeAddr::Empty));
2718        round_trip(&Key::ByteCode(ByteCodeAddr::V1CasperWasm(zeros)));
2719        round_trip(&Key::Message(MessageAddr::new_topic_addr(
2720            EntityAddr::new_smart_contract(zeros),
2721            nines.into(),
2722        )));
2723        round_trip(&Key::Message(MessageAddr::new_message_addr(
2724            EntityAddr::new_smart_contract(zeros),
2725            nines.into(),
2726            1,
2727        )));
2728        round_trip(&Key::NamedKey(NamedKeyAddr::default()));
2729        round_trip(&Key::BlockGlobal(BlockGlobalAddr::BlockTime));
2730        round_trip(&Key::BlockGlobal(BlockGlobalAddr::MessageCount));
2731        round_trip(&Key::BlockGlobal(BlockGlobalAddr::ProtocolVersion));
2732        round_trip(&Key::BlockGlobal(BlockGlobalAddr::AddressableEntity));
2733        round_trip(&Key::BalanceHold(BalanceHoldAddr::default()));
2734        round_trip(&Key::State(EntityAddr::new_system(zeros)));
2735    }
2736
2737    #[test]
2738    fn state_json_deserialization() {
2739        let mut test_rng = TestRng::new();
2740        let state_key = Key::State(EntityAddr::new_account(test_rng.gen()));
2741        round_trip(&state_key);
2742
2743        let state_key = Key::State(EntityAddr::new_system(test_rng.gen()));
2744        round_trip(&state_key);
2745
2746        let state_key = Key::State(EntityAddr::new_smart_contract(test_rng.gen()));
2747        round_trip(&state_key);
2748    }
2749
2750    #[test]
2751    fn roundtrip() {
2752        bytesrepr::test_serialization_roundtrip(&ACCOUNT_KEY);
2753        bytesrepr::test_serialization_roundtrip(&HASH_KEY);
2754        bytesrepr::test_serialization_roundtrip(&UREF_KEY);
2755        bytesrepr::test_serialization_roundtrip(&TRANSFER_KEY);
2756        bytesrepr::test_serialization_roundtrip(&DEPLOY_INFO_KEY);
2757        bytesrepr::test_serialization_roundtrip(&ERA_INFO_KEY);
2758        bytesrepr::test_serialization_roundtrip(&BALANCE_KEY);
2759        bytesrepr::test_serialization_roundtrip(&BID_KEY);
2760        bytesrepr::test_serialization_roundtrip(&WITHDRAW_KEY);
2761        bytesrepr::test_serialization_roundtrip(&DICTIONARY_KEY);
2762        bytesrepr::test_serialization_roundtrip(&SYSTEM_ENTITY_REGISTRY_KEY);
2763        bytesrepr::test_serialization_roundtrip(&ERA_SUMMARY_KEY);
2764        bytesrepr::test_serialization_roundtrip(&UNBOND_KEY);
2765        bytesrepr::test_serialization_roundtrip(&CHAINSPEC_REGISTRY_KEY);
2766        bytesrepr::test_serialization_roundtrip(&CHECKSUM_REGISTRY_KEY);
2767        bytesrepr::test_serialization_roundtrip(&UNIFIED_BID_KEY);
2768        bytesrepr::test_serialization_roundtrip(&VALIDATOR_BID_KEY);
2769        bytesrepr::test_serialization_roundtrip(&DELEGATOR_BID_KEY);
2770        bytesrepr::test_serialization_roundtrip(&PACKAGE_KEY);
2771        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SYSTEM_KEY);
2772        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_ACCOUNT_KEY);
2773        bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY);
2774        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_EMPTY_KEY);
2775        bytesrepr::test_serialization_roundtrip(&BYTE_CODE_V1_WASM_KEY);
2776        bytesrepr::test_serialization_roundtrip(&MESSAGE_TOPIC_KEY);
2777        bytesrepr::test_serialization_roundtrip(&MESSAGE_KEY);
2778        bytesrepr::test_serialization_roundtrip(&NAMED_KEY);
2779    }
2780
2781    fn round_trip(key: &Key) {
2782        let encoded = serde_json::to_value(key).unwrap();
2783        let decoded = serde_json::from_value(encoded.clone())
2784            .unwrap_or_else(|_| panic!("{} {}", key, encoded));
2785        assert_eq!(key, &decoded);
2786    }
2787}
2788
2789#[cfg(test)]
2790mod proptest {
2791    use crate::gens;
2792    use proptest::prelude::*;
2793
2794    proptest! {
2795        #[test]
2796        fn test_json_roundtrip_for_bidaddr_key(key in gens::all_keys_arb()) {
2797            let json_string = serde_json::to_string_pretty(&key).unwrap();
2798            let decoded = serde_json::from_str(&json_string).unwrap();
2799            assert_eq!(key, decoded);
2800        }
2801    }
2802}