From f6b1fd4a7f6a96c1b6ff2a02836e1a153fb37e6f Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Fri, 20 Oct 2023 18:52:00 +0100 Subject: [PATCH] fix issue in key and increase test coverage --- .../src/engine_state/execution_kind.rs | 2 +- execution_engine/src/engine_state/genesis.rs | 4 +- execution_engine/src/engine_state/upgrade.rs | 6 +- execution_engine/src/runtime/mod.rs | 15 +- execution_engine/src/runtime_context/mod.rs | 12 +- execution_engine/src/runtime_context/tests.rs | 2 +- execution_engine/src/tracking_copy/tests.rs | 2 +- .../tests/src/test/contract_api/dictionary.rs | 2 +- .../tests/src/test/explorer/faucet.rs | 5 +- .../test/regression/regression_20211110.rs | 2 +- .../regression/transforms_must_be_ordered.rs | 2 +- .../components/transaction_acceptor/tests.rs | 2 +- resources/test/rpc_schema.json | 8 +- .../contracts/explorer/faucet/README.md | 9 - .../tutorial/increment-counter/src/main.rs | 2 +- types/src/addressable_entity.rs | 2 +- types/src/byte_code.rs | 122 +++--- types/src/key.rs | 380 +++++++++--------- types/src/package.rs | 61 ++- .../tests/fixtures/ABI/stored_value.json | 2 +- 20 files changed, 340 insertions(+), 302 deletions(-) diff --git a/execution_engine/src/engine_state/execution_kind.rs b/execution_engine/src/engine_state/execution_kind.rs index 474c86246e..856ed831f9 100644 --- a/execution_engine/src/engine_state/execution_kind.rs +++ b/execution_engine/src/engine_state/execution_kind.rs @@ -88,7 +88,7 @@ impl ExecutionKind { })?; let entity_hash = match entity_key { - Key::Hash(hash) | Key::AddressableEntity((_, hash)) => { + Key::Hash(hash) | Key::AddressableEntity(_, hash) => { AddressableEntityHash::new(hash) } _ => return Err(Error::InvalidKeyVariant), diff --git a/execution_engine/src/engine_state/genesis.rs b/execution_engine/src/engine_state/genesis.rs index 2afa6731b7..6bbc6841ab 100644 --- a/execution_engine/src/engine_state/genesis.rs +++ b/execution_engine/src/engine_state/genesis.rs @@ -1173,13 +1173,13 @@ where package }; - let byte_code_key = Key::ByteCode((ByteCodeKind::Empty, byte_code_hash.value())); + let byte_code_key = Key::ByteCode(ByteCodeKind::Empty, byte_code_hash.value()); self.tracking_copy .borrow_mut() .write(byte_code_key, StoredValue::ByteCode(byte_code)); - let entity_key = Key::AddressableEntity((package_kind.tag(), entity_hash.value())); + let entity_key = Key::AddressableEntity(package_kind.tag(), entity_hash.value()); self.tracking_copy .borrow_mut() diff --git a/execution_engine/src/engine_state/upgrade.rs b/execution_engine/src/engine_state/upgrade.rs index fac35aca96..e63d037483 100644 --- a/execution_engine/src/engine_state/upgrade.rs +++ b/execution_engine/src/engine_state/upgrade.rs @@ -223,10 +223,10 @@ where if let Some(StoredValue::AddressableEntity(system_entity)) = self .tracking_copy .borrow_mut() - .read(&Key::AddressableEntity(( + .read(&Key::AddressableEntity( PackageKindTag::System, contract_hash.value(), - ))) + )) .map_err(|_| { ProtocolUpgradeError::UnableToRetrieveSystemContract( system_contract_type.to_string(), @@ -315,7 +315,7 @@ where contract_package }; - let byte_code_key = Key::ByteCode((ByteCodeKind::Empty, byte_code_hash.value())); + let byte_code_key = Key::ByteCode(ByteCodeKind::Empty, byte_code_hash.value()); self.tracking_copy .borrow_mut() .write(byte_code_key, StoredValue::ByteCode(byte_code)); diff --git a/execution_engine/src/runtime/mod.rs b/execution_engine/src/runtime/mod.rs index 533e33c8d1..a85db2acaf 100644 --- a/execution_engine/src/runtime/mod.rs +++ b/execution_engine/src/runtime/mod.rs @@ -1375,10 +1375,10 @@ where let byte_code_key = match package.get_package_kind() { PackageKind::System(_) | PackageKind::Account(_) => { - Key::ByteCode((ByteCodeKind::Empty, byte_code_addr)) + Key::ByteCode(ByteCodeKind::Empty, byte_code_addr) } PackageKind::SmartContract => { - Key::ByteCode((ByteCodeKind::V1CasperWasm, byte_code_addr)) + Key::ByteCode(ByteCodeKind::V1CasperWasm, byte_code_addr) } }; @@ -1711,14 +1711,14 @@ where entity.update_session_entity(ByteCodeHash::new(byte_code_hash), entry_points); self.context.metered_write_gs_unsafe( - Key::ByteCode((ByteCodeKind::V1CasperWasm, byte_code_hash)), + Key::ByteCode(ByteCodeKind::V1CasperWasm, byte_code_hash), byte_code, )?; let package_kind = package.get_package_kind(); self.context.metered_write_gs_unsafe( - Key::AddressableEntity((package_kind.tag(), entity_hash.value())), + Key::AddressableEntity(package_kind.tag(), entity_hash.value()), updated_session_entity, )?; @@ -1773,11 +1773,11 @@ where }; self.context.metered_write_gs_unsafe( - Key::ByteCode((ByteCodeKind::V1CasperWasm, byte_code_hash)), + Key::ByteCode(ByteCodeKind::V1CasperWasm, byte_code_hash), byte_code, )?; - let entity_key = Key::AddressableEntity((PackageKindTag::SmartContract, entity_hash)); + let entity_key = Key::AddressableEntity(PackageKindTag::SmartContract, entity_hash); let entity = AddressableEntity::new( package_hash, @@ -3303,8 +3303,7 @@ where self.context .metered_write_gs_unsafe(byte_code_key, StoredValue::ByteCode(byte_code))?; - let entity_key = - Key::AddressableEntity((package_kind.tag(), contract_hash.value())); + let entity_key = Key::AddressableEntity(package_kind.tag(), contract_hash.value()); self.context .metered_write_gs_unsafe(entity_key, updated_entity.clone())?; diff --git a/execution_engine/src/runtime_context/mod.rs b/execution_engine/src/runtime_context/mod.rs index bce5cb50c7..b5458180b7 100644 --- a/execution_engine/src/runtime_context/mod.rs +++ b/execution_engine/src/runtime_context/mod.rs @@ -711,15 +711,15 @@ where | Key::ChecksumRegistry | Key::BidAddr(_) | Key::Package(_) - | Key::AddressableEntity(_) - | Key::ByteCode(_) => true, + | Key::AddressableEntity(..) + | Key::ByteCode(..) => true, } } /// Tests whether addition to `key` is valid. pub fn is_addable(&self, key: &Key) -> bool { match key { - Key::AddressableEntity((_, entity_addr)) => { + Key::AddressableEntity(_, entity_addr) => { match self.get_entity_key().into_entity_hash() { Some(entity_hash) => entity_hash == AddressableEntityHash::new(*entity_addr), None => false, @@ -742,7 +742,7 @@ where | Key::ChecksumRegistry | Key::BidAddr(_) | Key::Package(_) - | Key::ByteCode(_) => false, + | Key::ByteCode(..) => false, } } @@ -766,8 +766,8 @@ where | Key::ChecksumRegistry | Key::BidAddr(_) | Key::Package(_) - | Key::AddressableEntity(_) - | Key::ByteCode(_) => false, + | Key::AddressableEntity(..) + | Key::ByteCode(..) => false, } } diff --git a/execution_engine/src/runtime_context/tests.rs b/execution_engine/src/runtime_context/tests.rs index 660c2957e0..a301792a07 100644 --- a/execution_engine/src/runtime_context/tests.rs +++ b/execution_engine/src/runtime_context/tests.rs @@ -116,7 +116,7 @@ fn random_account_key(entropy_source: &mut G) -> Key { fn random_contract_key(entropy_source: &mut G) -> Key { let mut key_hash = [0u8; 32]; entropy_source.fill_bytes(&mut key_hash); - Key::AddressableEntity((PackageKindTag::SmartContract, key_hash)) + Key::AddressableEntity(PackageKindTag::SmartContract, key_hash) } // Create URef Key. diff --git a/execution_engine/src/tracking_copy/tests.rs b/execution_engine/src/tracking_copy/tests.rs index 408312fb12..75e21e982e 100644 --- a/execution_engine/src/tracking_copy/tests.rs +++ b/execution_engine/src/tracking_copy/tests.rs @@ -451,7 +451,7 @@ proptest! { AssociatedKeys::default(), ActionThresholds::default(), )); - let contract_key = Key::AddressableEntity((PackageKindTag::SmartContract,hash)); + let contract_key = Key::AddressableEntity(PackageKindTag::SmartContract,hash); // create account which knows about contract let mut account_named_keys = NamedKeys::new(); diff --git a/execution_engine_testing/tests/src/test/contract_api/dictionary.rs b/execution_engine_testing/tests/src/test/contract_api/dictionary.rs index c35d8937b6..e77a77e6eb 100644 --- a/execution_engine_testing/tests/src/test/contract_api/dictionary.rs +++ b/execution_engine_testing/tests/src/test/contract_api/dictionary.rs @@ -104,7 +104,7 @@ fn query_dictionary_item( return Err("Provided base key is not an account".to_string()); } } - Key::AddressableEntity(_) => { + Key::AddressableEntity(..) => { if let Some(name) = dictionary_name { let stored_value = builder.query(None, key, &[])?; diff --git a/execution_engine_testing/tests/src/test/explorer/faucet.rs b/execution_engine_testing/tests/src/test/explorer/faucet.rs index 65c5ea4d74..c0f43148fe 100644 --- a/execution_engine_testing/tests/src/test/explorer/faucet.rs +++ b/execution_engine_testing/tests/src/test/explorer/faucet.rs @@ -863,9 +863,8 @@ fn should_allow_funding_by_an_authorized_account() { #[test] fn faucet_costs() { // This test will fail if execution costs vary. The expected costs should not be updated - // without understanding why the cost has changed. If the costs do change, it should be - // reflected in the "Costs by Entry Point" section of the faucet crate's README.md. - const EXPECTED_FAUCET_INSTALL_COST: u64 = 84_201_467_790; + // without understanding why the cost has changed. + const EXPECTED_FAUCET_INSTALL_COST: u64 = 84_201_467_720; const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 650_487_100; const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 3_247_573_380; const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 3_368_370_660; diff --git a/execution_engine_testing/tests/src/test/regression/regression_20211110.rs b/execution_engine_testing/tests/src/test/regression/regression_20211110.rs index 70ddb0e6ab..ec1ad093ee 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20211110.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20211110.rs @@ -64,7 +64,7 @@ fn regression_20211110() { .get(CONTRACT_HASH_NAME) .unwrap() { - Key::AddressableEntity((_, addr)) => AddressableEntityHash::new(*addr), + Key::AddressableEntity(_, addr) => AddressableEntityHash::new(*addr), _ => panic!("Couldn't find regression contract."), }; diff --git a/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs b/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs index 2ed0af92be..57012e3c45 100644 --- a/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs +++ b/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs @@ -41,7 +41,7 @@ fn contract_transforms_should_be_ordered_in_the_effects() { .get("ordered-transforms-contract-hash") .unwrap() { - Key::AddressableEntity((_package_kind, addr)) => AddressableEntityHash::new(*addr), + Key::AddressableEntity(_package_kind, addr) => AddressableEntityHash::new(*addr), _ => panic!("Couldn't find ordered-transforms contract."), }; diff --git a/node/src/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index 454adc674c..bb13ccb165 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -753,7 +753,7 @@ impl reactor::Reactor for Reactor { } else if let Key::Account(account_hash) = key { let account = create_account(account_hash, self.test_scenario); Some(AddressableEntity::from(account)) - } else if let Key::AddressableEntity(_) = key { + } else if let Key::AddressableEntity(..) = key { match self.test_scenario { TestScenario::FromPeerCustomPaymentContract( ContractScenario::MissingContractAtHash, diff --git a/resources/test/rpc_schema.json b/resources/test/rpc_schema.json index 4b90e9051f..18651a4550 100644 --- a/resources/test/rpc_schema.json +++ b/resources/test/rpc_schema.json @@ -4714,14 +4714,14 @@ ] }, "ByteCode": { - "description": "A container for contract's WASM bytes.", + "description": "A container for contract's Wasm bytes.", "type": "object", "required": [ - "byte_code_kind", - "bytes" + "bytes", + "kind" ], "properties": { - "byte_code_kind": { + "kind": { "$ref": "#/components/schemas/ByteCodeKind" }, "bytes": { diff --git a/smart_contracts/contracts/explorer/faucet/README.md b/smart_contracts/contracts/explorer/faucet/README.md index 43a708c7f5..c3a226681c 100644 --- a/smart_contracts/contracts/explorer/faucet/README.md +++ b/smart_contracts/contracts/explorer/faucet/README.md @@ -30,12 +30,3 @@ After an interval passes after then last user was funded, the available amount w `distributions_per_interval`, `available_amount`, `time_interval` and `max_distributions_per_interval` must be set and must be a number greater than `0` for the contract to run properly. If you try to invoke the contract before these variables are set, then you'll get an error. - -### Costs by Entry Point - -| feature | cost | -|--------------------------|------------------| -| faucet install | `84_007_229_270` | -| faucet set variables | `648_705_070` | -| faucet call by installer | `3_245_605_770` | -| faucet call by user | `3_364_807_470` | diff --git a/smart_contracts/contracts/tutorial/increment-counter/src/main.rs b/smart_contracts/contracts/tutorial/increment-counter/src/main.rs index 08fe8abeab..87a13b2d97 100644 --- a/smart_contracts/contracts/tutorial/increment-counter/src/main.rs +++ b/smart_contracts/contracts/tutorial/increment-counter/src/main.rs @@ -19,7 +19,7 @@ pub extern "C" fn call() { // Read the Counter smart contract's ContractHash. let contract_hash = { let counter_uref = runtime::get_key(COUNTER_KEY).unwrap_or_revert_with(ApiError::GetKey); - if let Key::AddressableEntity((_, hash)) = counter_uref { + if let Key::AddressableEntity(_, hash) = counter_uref { AddressableEntityHash::new(hash) } else { runtime::revert(ApiError::User(66)); diff --git a/types/src/addressable_entity.rs b/types/src/addressable_entity.rs index 5c2dbf2328..15fdc839ca 100644 --- a/types/src/addressable_entity.rs +++ b/types/src/addressable_entity.rs @@ -329,7 +329,7 @@ impl TryFrom for AddressableEntityHash { type Error = ApiError; fn try_from(value: Key) -> Result { - if let Key::AddressableEntity((_, entity_addr)) = value { + if let Key::AddressableEntity(_, entity_addr) = value { Ok(AddressableEntityHash::new(entity_addr)) } else { Err(ApiError::Formatting) diff --git a/types/src/byte_code.rs b/types/src/byte_code.rs index 700e7cdade..415ac7eb5c 100644 --- a/types/src/byte_code.rs +++ b/types/src/byte_code.rs @@ -149,8 +149,7 @@ impl ToBytes for ByteCodeHash { #[inline(always)] fn write_bytes(&self, writer: &mut Vec) -> Result<(), Error> { - self.0.write_bytes(writer)?; - Ok(()) + self.0.write_bytes(writer) } } @@ -230,11 +229,11 @@ impl JsonSchema for ByteCodeHash { } } +/// The type of Byte code. #[repr(u8)] #[cfg_attr(feature = "datasize", derive(DataSize))] #[cfg_attr(feature = "json-schema", derive(JsonSchema))] #[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash, Serialize, Deserialize)] -/// The type of Byte code. pub enum ByteCodeKind { /// Empty byte code. Empty = 0, @@ -242,23 +241,9 @@ pub enum ByteCodeKind { V1CasperWasm = 1, } -impl TryFrom for ByteCodeKind { - type Error = Error; - - fn try_from(value: u8) -> Result { - match value { - 0 => Ok(ByteCodeKind::Empty), - 1 => Ok(ByteCodeKind::V1CasperWasm), - _ => Err(Error::Formatting), - } - } -} - impl ToBytes for ByteCodeKind { fn to_bytes(&self) -> Result, Error> { - let mut buffer = bytesrepr::allocate_buffer(self)?; - self.write_bytes(&mut buffer)?; - Ok(buffer) + (*self as u8).to_bytes() } fn serialized_length(&self) -> usize { @@ -266,11 +251,35 @@ impl ToBytes for ByteCodeKind { } fn write_bytes(&self, writer: &mut Vec) -> Result<(), Error> { + (*self as u8).write_bytes(writer) + } +} + +impl FromBytes for ByteCodeKind { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error> { + let (byte_code_kind, remainder) = u8::from_bytes(bytes)?; + match byte_code_kind { + byte_code_kind if byte_code_kind == ByteCodeKind::Empty as u8 => { + Ok((ByteCodeKind::Empty, remainder)) + } + byte_code_kind if byte_code_kind == ByteCodeKind::V1CasperWasm as u8 => { + Ok((ByteCodeKind::V1CasperWasm, remainder)) + } + _ => Err(Error::Formatting), + } + } +} + +impl Display for ByteCodeKind { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - ByteCodeKind::Empty => 0u8.write_bytes(writer)?, - ByteCodeKind::V1CasperWasm => 1u8.write_bytes(writer)?, + ByteCodeKind::Empty => { + write!(f, "empty") + } + ByteCodeKind::V1CasperWasm => { + write!(f, "v1-casper-wasm") + } } - Ok(()) } } @@ -285,17 +294,17 @@ impl Distribution for Standard { } } -/// A container for contract's WASM bytes. +/// A container for contract's Wasm bytes. #[derive(PartialEq, Eq, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "datasize", derive(DataSize))] #[cfg_attr(feature = "json-schema", derive(JsonSchema))] pub struct ByteCode { - byte_code_kind: ByteCodeKind, + kind: ByteCodeKind, bytes: Bytes, } impl Debug for ByteCode { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if self.bytes.len() > BYTE_CODE_MAX_DISPLAY_LEN { write!( f, @@ -309,10 +318,10 @@ impl Debug for ByteCode { } impl ByteCode { - /// Creates new WASM object from bytes. - pub fn new(byte_code_kind: ByteCodeKind, bytes: Vec) -> Self { + /// Creates new Wasm object from bytes. + pub fn new(kind: ByteCodeKind, bytes: Vec) -> Self { ByteCode { - byte_code_kind, + kind, bytes: bytes.into(), } } @@ -322,14 +331,14 @@ impl ByteCode { self.bytes.into() } - /// Returns a slice of contained WASM bytes. + /// Returns a slice of contained Wasm bytes. pub fn bytes(&self) -> &[u8] { self.bytes.as_ref() } /// Return the type of byte code. - pub fn byte_code_tag(&self) -> ByteCodeKind { - self.byte_code_kind + pub fn kind(&self) -> ByteCodeKind { + self.kind } } @@ -341,11 +350,11 @@ impl ToBytes for ByteCode { } fn serialized_length(&self) -> usize { - self.byte_code_kind.serialized_length() + self.bytes.serialized_length() + self.kind.serialized_length() + self.bytes.serialized_length() } fn write_bytes(&self, writer: &mut Vec) -> Result<(), Error> { - self.byte_code_kind.write_bytes(writer)?; + self.kind.write_bytes(writer)?; self.bytes.write_bytes(writer)?; Ok(()) } @@ -353,33 +362,29 @@ impl ToBytes for ByteCode { impl FromBytes for ByteCode { fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error> { - let (byte_code_kind, remainder) = u8::from_bytes(bytes)?; - let (bytes, rem1) = FromBytes::from_bytes(remainder)?; - let byte_code_kind = ByteCodeKind::try_from(byte_code_kind)?; - Ok(( - ByteCode { - byte_code_kind, - bytes, - }, - rem1, - )) + let (kind, remainder) = ByteCodeKind::from_bytes(bytes)?; + let (bytes, remainder) = Bytes::from_bytes(remainder)?; + Ok((ByteCode { kind, bytes }, remainder)) } } #[cfg(test)] mod tests { + use rand::RngCore; + use super::*; + use crate::testing::TestRng; + #[test] - fn test_debug_repr_of_short_wasm() { + fn debug_repr_of_short_wasm() { const SIZE: usize = 8; let wasm_bytes = vec![0; SIZE]; let byte_code = ByteCode::new(ByteCodeKind::V1CasperWasm, wasm_bytes); - // String output is less than the bytes itself assert_eq!(format!("{:?}", byte_code), "ByteCode(0x0000000000000000)"); } #[test] - fn test_debug_repr_of_long_wasm() { + fn debug_repr_of_long_wasm() { const SIZE: usize = 65; let wasm_bytes = vec![0; SIZE]; let byte_code = ByteCode::new(ByteCodeKind::V1CasperWasm, wasm_bytes); @@ -390,6 +395,18 @@ mod tests { ); } + #[test] + fn byte_code_bytesrepr_roundtrip() { + let rng = &mut TestRng::new(); + let byte_code = ByteCode::new(rng.gen(), vec![]); + bytesrepr::test_serialization_roundtrip(&byte_code); + + let mut buffer = vec![0u8; rng.gen_range(1..100)]; + rng.fill_bytes(buffer.as_mut()); + let byte_code = ByteCode::new(rng.gen(), buffer); + bytesrepr::test_serialization_roundtrip(&byte_code); + } + #[test] fn contract_wasm_hash_from_slice() { let bytes: Vec = (0..32).collect(); @@ -424,8 +441,16 @@ mod tests { } #[test] - fn contract_wasm_hash_serde_roundtrip() { - let byte_code_hash = ByteCodeHash([255; 32]); + fn contract_wasm_hash_bytesrepr_roundtrip() { + let rng = &mut TestRng::new(); + let byte_code_hash = ByteCodeHash(rng.gen()); + bytesrepr::test_serialization_roundtrip(&byte_code_hash); + } + + #[test] + fn contract_wasm_hash_bincode_roundtrip() { + let rng = &mut TestRng::new(); + let byte_code_hash = ByteCodeHash(rng.gen()); let serialized = bincode::serialize(&byte_code_hash).unwrap(); let deserialized = bincode::deserialize(&serialized).unwrap(); assert_eq!(byte_code_hash, deserialized) @@ -433,7 +458,8 @@ mod tests { #[test] fn contract_wasm_hash_json_roundtrip() { - let byte_code_hash = ByteCodeHash([255; 32]); + let rng = &mut TestRng::new(); + let byte_code_hash = ByteCodeHash(rng.gen()); let json_string = serde_json::to_string_pretty(&byte_code_hash).unwrap(); let decoded = serde_json::from_str(&json_string).unwrap(); assert_eq!(byte_code_hash, decoded) diff --git a/types/src/key.rs b/types/src/key.rs index fb63753ef6..bb43e9e26b 100644 --- a/types/src/key.rs +++ b/types/src/key.rs @@ -58,17 +58,13 @@ const ERA_SUMMARY_PREFIX: &str = "era-summary-"; const CHAINSPEC_REGISTRY_PREFIX: &str = "chainspec-registry-"; const CHECKSUM_REGISTRY_PREFIX: &str = "checksum-registry-"; const BID_ADDR_PREFIX: &str = "bid-addr-"; -const PACKAGE_ADDR_PREFIX: &str = "package-"; -const ENTITY_ADDR_PREFIX: &str = "addressable-entity-"; - +const PACKAGE_PREFIX: &str = "package-"; +const ENTITY_PREFIX: &str = "addressable-entity-"; const ACCOUNT_ENTITY_PREFIX: &str = "account-"; const CONTRACT_ENTITY_PREFIX: &str = "contract-"; const SYSTEM_ENTITY_PREFIX: &str = "system-"; - -const BYTE_CODE_ADDR_PREFIX: &str = "byte-code-"; - -const WASM_PREFIX: &str = "v1-wasm-"; - +const BYTE_CODE_PREFIX: &str = "byte-code-"; +const V1_WASM_PREFIX: &str = "v1-wasm-"; const EMPTY_PREFIX: &str = "empty-"; /// The number of bytes in a Blake2b hash @@ -193,38 +189,39 @@ pub enum Key { Hash(HashAddr), /// A `Key` which is a [`URef`], under which most types of data can be stored. URef(URef), - /// A `Key` under which we store a transfer. + /// A `Key` under which a transfer is stored. Transfer(TransferAddr), - /// A `Key` under which we store a deploy info. + /// A `Key` under which a deploy info is stored. DeployInfo(DeployHash), - /// A `Key` under which we store an era info. + /// A `Key` under which an era info is stored. EraInfo(EraId), - /// A `Key` under which we store a purse balance. + /// A `Key` under which a purse balance is stored. Balance(URefAddr), - /// A `Key` under which we store bid information + /// A `Key` under which bid information is stored. Bid(AccountHash), - /// A `Key` under which we store withdraw information. + /// A `Key` under which withdraw information is stored. Withdraw(AccountHash), - /// A `Key` variant whose value is derived by hashing [`URef`]s address and arbitrary data. + /// A `Key` whose value is derived by hashing a [`URef`] address and arbitrary data, under + /// which a dictionary is stored. Dictionary(DictionaryAddr), - /// A `Key` variant under which system contract hashes are stored. + /// A `Key` under which system contract hashes are stored. SystemContractRegistry, - /// A `Key` under which we store current era info. + /// A `Key` under which current era info is stored. EraSummary, - /// A `Key` under which we store unbond information. + /// A `Key` under which unbond information is stored. Unbond(AccountHash), - /// A `Key` variant under which chainspec and other hashes are stored. + /// A `Key` under which chainspec and other hashes are stored. ChainspecRegistry, - /// A `Key` variant under which we store a registry of checksums. + /// A `Key` under which a registry of checksums is stored. ChecksumRegistry, - /// A `Key` under which we store bid information + /// A `Key` under which bid information is stored. BidAddr(BidAddr), - /// A `Key` under which we store package information. + /// A `Key` under which package information is stored. Package(PackageAddr), - /// A `Key` under which we write an addressable entity. - AddressableEntity((PackageKindTag, EntityAddr)), - /// A `Key` under which we write a byte code record. - ByteCode((ByteCodeKind, ByteCodeAddr)), + /// A `Key` under which an addressable entity is stored. + AddressableEntity(PackageKindTag, EntityAddr), + /// A `Key` under which a byte code record is stored. + ByteCode(ByteCodeKind, ByteCodeAddr), } #[cfg(feature = "json-schema")] @@ -380,8 +377,8 @@ impl Key { Key::ChecksumRegistry => String::from("Key::ChecksumRegistry"), Key::BidAddr(_) => String::from("Key::BidAddr"), Key::Package(_) => String::from("Key::Package"), - Key::AddressableEntity(_) => String::from("Key::AddressableEntity"), - Key::ByteCode(_) => String::from("Key::ByteCode"), + Key::AddressableEntity(..) => String::from("Key::AddressableEntity"), + Key::ByteCode(..) => String::from("Key::ByteCode"), } } @@ -469,17 +466,13 @@ impl Key { format!("{}{}", BID_ADDR_PREFIX, bid_addr) } Key::Package(package_addr) => { - format!( - "{}{}", - PACKAGE_ADDR_PREFIX, - base16::encode_lower(&package_addr) - ) + format!("{}{}", PACKAGE_PREFIX, base16::encode_lower(&package_addr)) } - Key::AddressableEntity((package_tag, entity_addr)) => match package_tag { + Key::AddressableEntity(package_tag, entity_addr) => match package_tag { PackageKindTag::System => { format!( "{}{}{}", - ENTITY_ADDR_PREFIX, + ENTITY_PREFIX, SYSTEM_ENTITY_PREFIX, base16::encode_lower(&entity_addr) ) @@ -487,7 +480,7 @@ impl Key { PackageKindTag::Account => { format!( "{}{}{}", - ENTITY_ADDR_PREFIX, + ENTITY_PREFIX, ACCOUNT_ENTITY_PREFIX, base16::encode_lower(&entity_addr) ) @@ -495,17 +488,17 @@ impl Key { PackageKindTag::SmartContract => { format!( "{}{}{}", - ENTITY_ADDR_PREFIX, + ENTITY_PREFIX, CONTRACT_ENTITY_PREFIX, base16::encode_lower(&entity_addr) ) } }, - Key::ByteCode((byte_code_kind, byte_code_addr)) => match byte_code_kind { + Key::ByteCode(byte_code_kind, byte_code_addr) => match byte_code_kind { ByteCodeKind::Empty => { format!( "{}{}{}", - BYTE_CODE_ADDR_PREFIX, + BYTE_CODE_PREFIX, EMPTY_PREFIX, base16::encode_lower(&byte_code_addr) ) @@ -513,8 +506,8 @@ impl Key { ByteCodeKind::V1CasperWasm => { format!( "{}{}{}", - BYTE_CODE_ADDR_PREFIX, - WASM_PREFIX, + BYTE_CODE_PREFIX, + V1_WASM_PREFIX, base16::encode_lower(&byte_code_addr) ) } @@ -682,57 +675,44 @@ impl Key { return Ok(Key::ChecksumRegistry); } - if let Some(entity_string) = - input.strip_prefix(&format!("{}{}", ENTITY_ADDR_PREFIX, ACCOUNT_ENTITY_PREFIX)) - { - let addr = checksummed_hex::decode(entity_string) - .map_err(|error| FromStrError::AddressableEntity(error.to_string()))?; - let hash_addr = EntityAddr::try_from(addr.as_ref()) - .map_err(|error| FromStrError::AddressableEntity(error.to_string()))?; - return Ok(Key::AddressableEntity((PackageKindTag::Account, hash_addr))); - } - - if let Some(entity_string) = - input.strip_prefix(&format!("{}{}", ENTITY_ADDR_PREFIX, SYSTEM_ENTITY_PREFIX)) - { - let addr = checksummed_hex::decode(entity_string) - .map_err(|error| FromStrError::AddressableEntity(error.to_string()))?; - let hash_addr = EntityAddr::try_from(addr.as_ref()) - .map_err(|error| FromStrError::AddressableEntity(error.to_string()))?; - return Ok(Key::AddressableEntity((PackageKindTag::System, hash_addr))); + if let Some(package_addr) = input.strip_prefix(PACKAGE_PREFIX) { + let package_addr_bytes = checksummed_hex::decode(package_addr) + .map_err(|error| FromStrError::Dictionary(error.to_string()))?; + let addr = PackageAddr::try_from(package_addr_bytes.as_ref()) + .map_err(|error| FromStrError::Package(error.to_string()))?; + return Ok(Key::Package(addr)); } - if let Some(entity_string) = - input.strip_prefix(&format!("{}{}", ENTITY_ADDR_PREFIX, CONTRACT_ENTITY_PREFIX)) - { - let addr = checksummed_hex::decode(entity_string) + if let Some(entity) = input.strip_prefix(ENTITY_PREFIX) { + let (addr_str, tag) = if let Some(str) = entity.strip_prefix(ACCOUNT_ENTITY_PREFIX) { + (str, PackageKindTag::Account) + } else if let Some(str) = entity.strip_prefix(SYSTEM_ENTITY_PREFIX) { + (str, PackageKindTag::System) + } else if let Some(str) = entity.strip_prefix(CONTRACT_ENTITY_PREFIX) { + (str, PackageKindTag::SmartContract) + } else { + return Err(FromStrError::UnknownPrefix); + }; + let addr = checksummed_hex::decode(addr_str) .map_err(|error| FromStrError::AddressableEntity(error.to_string()))?; - let hash_addr = EntityAddr::try_from(addr.as_ref()) + let entity_addr = EntityAddr::try_from(addr.as_ref()) .map_err(|error| FromStrError::AddressableEntity(error.to_string()))?; - return Ok(Key::AddressableEntity(( - PackageKindTag::SmartContract, - hash_addr, - ))); + return Ok(Key::AddressableEntity(tag, entity_addr)); } - if let Some(byte_code_string) = - input.strip_prefix(&format!("{}{}", BYTE_CODE_ADDR_PREFIX, EMPTY_PREFIX)) - { - let addr = checksummed_hex::decode(byte_code_string) - .map_err(|error| FromStrError::ByteCode(error.to_string()))?; - let byte_code_addr = ByteCodeAddr::try_from(addr.as_ref()) - .map_err(|error| FromStrError::ByteCode(error.to_string()))?; - return Ok(Key::ByteCode((ByteCodeKind::Empty, byte_code_addr))); - } - - if let Some(byte_code_string) = - input.strip_prefix(&format!("{}{}", BYTE_CODE_ADDR_PREFIX, WASM_PREFIX)) - { - let addr = checksummed_hex::decode(byte_code_string) + if let Some(byte_code) = input.strip_prefix(BYTE_CODE_PREFIX) { + let (addr_str, tag) = if let Some(str) = byte_code.strip_prefix(EMPTY_PREFIX) { + (str, ByteCodeKind::Empty) + } else if let Some(str) = byte_code.strip_prefix(V1_WASM_PREFIX) { + (str, ByteCodeKind::V1CasperWasm) + } else { + return Err(FromStrError::UnknownPrefix); + }; + let addr = checksummed_hex::decode(addr_str) .map_err(|error| FromStrError::ByteCode(error.to_string()))?; let byte_code_addr = ByteCodeAddr::try_from(addr.as_ref()) .map_err(|error| FromStrError::ByteCode(error.to_string()))?; - return Ok(Key::ByteCode((ByteCodeKind::V1CasperWasm, byte_code_addr))); + return Ok(Key::ByteCode(tag, byte_code_addr)); } Err(FromStrError::UnknownPrefix) @@ -760,7 +740,7 @@ impl Key { /// returns `None`. pub fn into_entity_addr(self) -> Option { match self { - Key::AddressableEntity((_, hash)) => Some(hash), + Key::AddressableEntity(_, hash) => Some(hash), _ => None, } } @@ -867,7 +847,7 @@ impl Key { package_kind_tag: PackageKindTag, entity_hash: AddressableEntityHash, ) -> Self { - Key::AddressableEntity((package_kind_tag, entity_hash.value())) + Key::AddressableEntity(package_kind_tag, entity_hash.value()) } /// Creates a new [`Key::AddressableEntity`] for a Smart contract. @@ -877,7 +857,7 @@ impl Key { /// Creates a new [`Key::ByteCode`] variant from a byte code kind and an byte code addr. pub fn byte_code_key(byte_code_kind: ByteCodeKind, byte_code_addr: ByteCodeAddr) -> Self { - Key::ByteCode((byte_code_kind, byte_code_addr)) + Key::ByteCode(byte_code_kind, byte_code_addr) } /// Returns true if the key is of type [`Key::Dictionary`]. @@ -916,7 +896,7 @@ impl Key { /// Returns if they inner Key is for a system contract entity. pub fn is_system_key(&self) -> bool { - if let Self::AddressableEntity((PackageKindTag::System, _)) = self { + if let Self::AddressableEntity(PackageKindTag::System, _) = self { return true; } @@ -972,17 +952,17 @@ impl Display for Key { Key::Package(package_addr) => { write!(f, "Key::Package({})", base16::encode_lower(package_addr)) } - Key::AddressableEntity((kind_tag, entity_addr)) => write!( + Key::AddressableEntity(kind_tag, entity_addr) => write!( f, "Key::AddressableEntity({}-{})", - *kind_tag as u8, + kind_tag, base16::encode_lower(entity_addr) ), - Key::ByteCode((kind, byte_code_addr)) => { + Key::ByteCode(kind, byte_code_addr) => { write!( f, "Key::ByteCode({}-{})", - *kind as u8, + kind, base16::encode_lower(byte_code_addr) ) } @@ -1016,8 +996,8 @@ impl Tagged for Key { Key::ChecksumRegistry => KeyTag::ChecksumRegistry, Key::BidAddr(_) => KeyTag::BidAddr, Key::Package(_) => KeyTag::Package, - Key::AddressableEntity(_) => KeyTag::AddressableEntity, - Key::ByteCode(_) => KeyTag::ByteCode, + Key::AddressableEntity(..) => KeyTag::AddressableEntity, + Key::ByteCode(..) => KeyTag::ByteCode, } } } @@ -1104,12 +1084,10 @@ impl ToBytes for Key { } }, Key::Package(_) => KEY_PACKAGE_SERIALIZED_LENGTH, - Key::AddressableEntity(_) => { + Key::AddressableEntity(..) => { U8_SERIALIZED_LENGTH + KEY_ID_SERIALIZED_LENGTH + ADDR_LENGTH } - Key::ByteCode((byte_code_kind, _)) => { - byte_code_kind.serialized_length() + KEY_ID_SERIALIZED_LENGTH + ADDR_LENGTH - } + Key::ByteCode(..) => U8_SERIALIZED_LENGTH + KEY_ID_SERIALIZED_LENGTH + ADDR_LENGTH, } } @@ -1140,11 +1118,11 @@ impl ToBytes for Key { BidAddrTag::Validator | BidAddrTag::Delegator => bid_addr.write_bytes(writer), }, Key::Package(package_addr) => package_addr.write_bytes(writer), - Key::AddressableEntity((package_kind, entity_addr)) => { - writer.push(*package_kind as u8); + Key::AddressableEntity(package_kind_tag, entity_addr) => { + package_kind_tag.write_bytes(writer)?; entity_addr.write_bytes(writer) } - Key::ByteCode((byte_code_kind, byte_code_addr)) => { + Key::ByteCode(byte_code_kind, byte_code_addr) => { byte_code_kind.write_bytes(writer)?; byte_code_addr.write_bytes(writer) } @@ -1225,17 +1203,14 @@ impl FromBytes for Key { Ok((Key::Package(package_addr), rem)) } tag if tag == KeyTag::AddressableEntity as u8 => { - let (package_kind_tag, rem) = u8::from_bytes(remainder)?; - let package_kind_tag = PackageKindTag::try_from(package_kind_tag)?; + let (package_kind_tag, rem) = PackageKindTag::from_bytes(remainder)?; let (entity_addr, rem) = EntityAddr::from_bytes(rem)?; - Ok((Key::AddressableEntity((package_kind_tag, entity_addr)), rem)) + Ok((Key::AddressableEntity(package_kind_tag, entity_addr), rem)) } tag if tag == KeyTag::ByteCode as u8 => { - let (byte_code_kind, remainder) = u8::from_bytes(remainder)?; - let byte_code_kind = ByteCodeKind::try_from(byte_code_kind)?; - let (byte_code_addr, rem) = ByteCodeAddr::from_bytes(remainder)?; - - Ok((Key::ByteCode((byte_code_kind, byte_code_addr)), rem)) + let (byte_code_kind, rem) = ByteCodeKind::from_bytes(remainder)?; + let (byte_code_addr, rem) = ByteCodeAddr::from_bytes(rem)?; + Ok((Key::ByteCode(byte_code_kind, byte_code_addr), rem)) } _ => Err(Error::Formatting), } @@ -1264,8 +1239,8 @@ fn please_add_to_distribution_impl(key: Key) { Key::ChecksumRegistry => unimplemented!(), Key::BidAddr(_) => unimplemented!(), Key::Package(_) => unimplemented!(), - Key::AddressableEntity(_) => unimplemented!(), - Key::ByteCode(_) => unimplemented!(), + Key::AddressableEntity(..) => unimplemented!(), + Key::ByteCode(..) => unimplemented!(), } } @@ -1290,8 +1265,8 @@ impl Distribution for Standard { 14 => Key::ChecksumRegistry, 15 => Key::BidAddr(rng.gen()), 16 => Key::Package(rng.gen()), - 17 => Key::AddressableEntity((rng.gen(), rng.gen())), - 18 => Key::ByteCode((rng.gen(), rng.gen())), + 17 => Key::AddressableEntity(rng.gen(), rng.gen()), + 18 => Key::ByteCode(rng.gen(), rng.gen()), _ => unreachable!(), } } @@ -1320,8 +1295,8 @@ mod serde_helpers { ChecksumRegistry, BidAddr(&'a BidAddr), Package(&'a PackageAddr), - AddressableEntity((&'a PackageKindTag, &'a EntityAddr)), - ByteCode((&'a ByteCodeKind, &'a ByteCodeAddr)), + AddressableEntity(&'a PackageKindTag, &'a EntityAddr), + ByteCode(&'a ByteCodeKind, &'a ByteCodeAddr), } #[derive(Deserialize)] @@ -1344,8 +1319,8 @@ mod serde_helpers { ChecksumRegistry, BidAddr(BidAddr), Package(PackageAddr), - AddressableEntity((PackageKindTag, EntityAddr)), - ByteCode((ByteCodeKind, ByteCodeAddr)), + AddressableEntity(PackageKindTag, EntityAddr), + ByteCode(ByteCodeKind, ByteCodeAddr), } impl<'a> From<&'a Key> for BinarySerHelper<'a> { @@ -1368,11 +1343,11 @@ mod serde_helpers { Key::ChecksumRegistry => BinarySerHelper::ChecksumRegistry, Key::BidAddr(bid_addr) => BinarySerHelper::BidAddr(bid_addr), Key::Package(package_addr) => BinarySerHelper::Package(package_addr), - Key::AddressableEntity((package_kind, entity_addr)) => { - BinarySerHelper::AddressableEntity((package_kind, entity_addr)) + Key::AddressableEntity(package_kind, entity_addr) => { + BinarySerHelper::AddressableEntity(package_kind, entity_addr) } - Key::ByteCode((byte_code_kind, byte_code_addr)) => { - BinarySerHelper::ByteCode((byte_code_kind, byte_code_addr)) + Key::ByteCode(byte_code_kind, byte_code_addr) => { + BinarySerHelper::ByteCode(byte_code_kind, byte_code_addr) } } } @@ -1398,11 +1373,11 @@ mod serde_helpers { BinaryDeserHelper::ChecksumRegistry => Key::ChecksumRegistry, BinaryDeserHelper::BidAddr(bid_addr) => Key::BidAddr(bid_addr), BinaryDeserHelper::Package(package_addr) => Key::Package(package_addr), - BinaryDeserHelper::AddressableEntity((package_kind, entity_addr)) => { - Key::AddressableEntity((package_kind, entity_addr)) + BinaryDeserHelper::AddressableEntity(package_kind, entity_addr) => { + Key::AddressableEntity(package_kind, entity_addr) } - BinaryDeserHelper::ByteCode((byte_kind, byte_code_addr)) => { - Key::ByteCode((byte_kind, byte_code_addr)) + BinaryDeserHelper::ByteCode(byte_kind, byte_code_addr) => { + Key::ByteCode(byte_kind, byte_code_addr) } } } @@ -1462,6 +1437,15 @@ mod tests { const UNBOND_KEY: Key = Key::Unbond(AccountHash::new([42; 32])); const CHAINSPEC_REGISTRY_KEY: Key = Key::ChainspecRegistry; const CHECKSUM_REGISTRY_KEY: Key = Key::ChecksumRegistry; + const PACKAGE_KEY: Key = Key::Package([42; 32]); + const ADDRESSABLE_ENTITY_SYSTEM_KEY: Key = + Key::AddressableEntity(PackageKindTag::System, [42; 32]); + const ADDRESSABLE_ENTITY_ACCOUNT_KEY: Key = + Key::AddressableEntity(PackageKindTag::Account, [42; 32]); + const ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY: Key = + Key::AddressableEntity(PackageKindTag::SmartContract, [42; 32]); + const BYTE_CODE_EMPTY_KEY: Key = Key::ByteCode(ByteCodeKind::Empty, [42; 32]); + const BYTE_CODE_V1_WASM_KEY: Key = Key::ByteCode(ByteCodeKind::V1CasperWasm, [42; 32]); const KEYS: &[Key] = &[ ACCOUNT_KEY, HASH_KEY, @@ -1481,6 +1465,12 @@ mod tests { UNIFIED_BID_KEY, VALIDATOR_BID_KEY, DELEGATOR_BID_KEY, + PACKAGE_KEY, + ADDRESSABLE_ENTITY_SYSTEM_KEY, + ADDRESSABLE_ENTITY_ACCOUNT_KEY, + ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY, + BYTE_CODE_EMPTY_KEY, + BYTE_CODE_V1_WASM_KEY, ]; const HEX_STRING: &str = "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"; const UNIFIED_HEX_STRING: &str = @@ -1615,6 +1605,30 @@ mod tests { base16::encode_lower(&PADDING_BYTES), ) ); + assert_eq!( + format!("{}", PACKAGE_KEY), + format!("Key::Package({})", HEX_STRING) + ); + assert_eq!( + format!("{}", ADDRESSABLE_ENTITY_SYSTEM_KEY), + format!("Key::AddressableEntity(system-{})", HEX_STRING) + ); + assert_eq!( + format!("{}", ADDRESSABLE_ENTITY_ACCOUNT_KEY), + format!("Key::AddressableEntity(account-{})", HEX_STRING) + ); + assert_eq!( + format!("{}", ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY), + format!("Key::AddressableEntity(smart-contract-{})", HEX_STRING) + ); + assert_eq!( + format!("{}", BYTE_CODE_EMPTY_KEY), + format!("Key::ByteCode(empty-{})", HEX_STRING) + ); + assert_eq!( + format!("{}", BYTE_CODE_V1_WASM_KEY), + format!("Key::ByteCode(v1-casper-wasm-{})", HEX_STRING) + ); } #[test] @@ -1707,14 +1721,11 @@ mod tests { let parsed_bid_key = Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})"); if let Key::Bid(parsed_account_hash) = parsed_bid_key { - assert_eq!( - parsed_account_hash, account_hash, - "account hash should equal" - ); - assert_eq!(legacy_bid_key, parsed_bid_key, "bid keys should equal"); + assert_eq!(parsed_account_hash, account_hash,); + assert_eq!(legacy_bid_key, parsed_bid_key); let translated_string = parsed_bid_key.to_formatted_string(); - assert_eq!(original_string, translated_string, "strings should equal"); + assert_eq!(original_string, translated_string); } else { panic!("should have account hash"); } @@ -1724,102 +1735,58 @@ mod tests { fn should_parse_legacy_unified_bid_key_from_string() { let legacy_bid_addr = BidAddr::legacy([1; 32]); let legacy_bid_key = Key::BidAddr(legacy_bid_addr); - assert!( - legacy_bid_addr.tag() == BidAddrTag::Unified, - "legacy_bid_addr should be legacy" - ); + assert_eq!(legacy_bid_addr.tag(), BidAddrTag::Unified,); let original_string = legacy_bid_key.to_formatted_string(); - println!("{}", original_string); - let parsed_key = Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})"); let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr"); - assert!(parsed_key.is_bid_addr_key(), "parsed_key should be bid key"); - assert_eq!( - parsed_bid_addr.tag(), - legacy_bid_addr.tag(), - "bid addr tags should equal" - ); - assert_eq!(*parsed_bid_addr, legacy_bid_addr, "bid addr's should equal"); + assert!(parsed_key.is_bid_addr_key()); + assert_eq!(parsed_bid_addr.tag(), legacy_bid_addr.tag(),); + assert_eq!(*parsed_bid_addr, legacy_bid_addr); let translated_string = parsed_key.to_formatted_string(); - assert_eq!(original_string, translated_string, "strings should equal"); - - assert_eq!( - parsed_key.as_bid_addr(), - legacy_bid_key.as_bid_addr(), - "should equal" - ); + assert_eq!(original_string, translated_string); + assert_eq!(parsed_key.as_bid_addr(), legacy_bid_key.as_bid_addr(),); } #[test] fn should_parse_validator_bid_key_from_string() { let validator_bid_addr = BidAddr::new_validator_addr([1; 32]); let validator_bid_key = Key::BidAddr(validator_bid_addr); - assert!( - validator_bid_addr.tag() == BidAddrTag::Validator, - "validator_bid_addr should be validator" - ); + assert_eq!(validator_bid_addr.tag(), BidAddrTag::Validator,); let original_string = validator_bid_key.to_formatted_string(); let parsed_key = Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})"); let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr"); - assert!(parsed_key.is_bid_addr_key(), "parsed_key should be bid key"); - assert_eq!( - parsed_bid_addr.tag(), - validator_bid_addr.tag(), - "bid addr tags should equal" - ); - assert_eq!( - *parsed_bid_addr, validator_bid_addr, - "bid addr's should equal" - ); + assert!(parsed_key.is_bid_addr_key()); + assert_eq!(parsed_bid_addr.tag(), validator_bid_addr.tag(),); + assert_eq!(*parsed_bid_addr, validator_bid_addr,); let translated_string = parsed_key.to_formatted_string(); - assert_eq!(original_string, translated_string, "strings should equal"); - - assert_eq!( - parsed_key.as_bid_addr(), - validator_bid_key.as_bid_addr(), - "should equal" - ); + assert_eq!(original_string, translated_string); + assert_eq!(parsed_key.as_bid_addr(), validator_bid_key.as_bid_addr(),); } #[test] fn should_parse_delegator_bid_key_from_string() { let delegator_bid_addr = BidAddr::new_delegator_addr(([1; 32], [9; 32])); let delegator_bid_key = Key::BidAddr(delegator_bid_addr); - assert!( - delegator_bid_addr.tag() == BidAddrTag::Delegator, - "delegator_bid_addr should be delegator" - ); + assert_eq!(delegator_bid_addr.tag(), BidAddrTag::Delegator,); let original_string = delegator_bid_key.to_formatted_string(); let parsed_key = Key::from_formatted_str(&original_string).expect("{string} (key = {key:?})"); let parsed_bid_addr = parsed_key.as_bid_addr().expect("must have bid addr"); - assert!(parsed_key.is_bid_addr_key(), "parsed_key should be bid key"); - assert_eq!( - parsed_bid_addr.tag(), - delegator_bid_addr.tag(), - "bid addr tags should equal" - ); - assert_eq!( - *parsed_bid_addr, delegator_bid_addr, - "bid addr's should equal" - ); + assert!(parsed_key.is_bid_addr_key()); + assert_eq!(parsed_bid_addr.tag(), delegator_bid_addr.tag(),); + assert_eq!(*parsed_bid_addr, delegator_bid_addr,); let translated_string = parsed_key.to_formatted_string(); - assert_eq!(original_string, translated_string, "strings should equal"); - - assert_eq!( - parsed_key.as_bid_addr(), - delegator_bid_key.as_bid_addr(), - "should equal" - ); + assert_eq!(original_string, translated_string); + assert_eq!(parsed_key.as_bid_addr(), delegator_bid_key.as_bid_addr(),); } #[test] @@ -1905,6 +1872,22 @@ mod tests { "{}", bid_addr_err ); + assert!(Key::from_formatted_str(PACKAGE_PREFIX) + .unwrap_err() + .to_string() + .starts_with("package-key from string error: ")); + assert!( + Key::from_formatted_str(&format!("{}{}", ENTITY_PREFIX, ACCOUNT_ENTITY_PREFIX)) + .unwrap_err() + .to_string() + .starts_with("addressable-entity-key from string error: ") + ); + assert!( + Key::from_formatted_str(&format!("{}{}", BYTE_CODE_PREFIX, EMPTY_PREFIX)) + .unwrap_err() + .to_string() + .starts_with("byte-code-key from string error: ") + ); let invalid_prefix = "a-0000000000000000000000000000000000000000000000000000000000000000"; assert_eq!( Key::from_formatted_str(invalid_prefix) @@ -1977,10 +1960,15 @@ mod tests { round_trip(&Key::BidAddr(BidAddr::new_delegator_addr((zeros, nines)))); round_trip(&Key::Withdraw(AccountHash::new(zeros))); round_trip(&Key::Dictionary(zeros)); - round_trip(&Key::SystemContractRegistry); - round_trip(&Key::EraSummary); round_trip(&Key::Unbond(AccountHash::new(zeros))); - round_trip(&Key::ChainspecRegistry); - round_trip(&Key::ChecksumRegistry); + round_trip(&Key::Package(zeros)); + round_trip(&Key::AddressableEntity(PackageKindTag::System, zeros)); + round_trip(&Key::AddressableEntity(PackageKindTag::Account, zeros)); + round_trip(&Key::AddressableEntity( + PackageKindTag::SmartContract, + zeros, + )); + round_trip(&Key::ByteCode(ByteCodeKind::Empty, zeros)); + round_trip(&Key::ByteCode(ByteCodeKind::V1CasperWasm, zeros)); } } diff --git a/types/src/package.rs b/types/src/package.rs index cab96d9a84..4e82f527e8 100644 --- a/types/src/package.rs +++ b/types/src/package.rs @@ -634,19 +634,54 @@ pub enum PackageKindTag { SmartContract = 2, } -impl TryFrom for PackageKindTag { - type Error = bytesrepr::Error; - - fn try_from(value: u8) -> Result { - match value { - 0 => Ok(PackageKindTag::System), - 1 => Ok(PackageKindTag::Account), - 2 => Ok(PackageKindTag::SmartContract), +impl ToBytes for PackageKindTag { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + (*self as u8).to_bytes() + } + + fn serialized_length(&self) -> usize { + U8_SERIALIZED_LENGTH + } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + (*self as u8).write_bytes(writer) + } +} + +impl FromBytes for PackageKindTag { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (package_kind_tag, remainder) = u8::from_bytes(bytes)?; + match package_kind_tag { + package_kind_tag if package_kind_tag == PackageKindTag::System as u8 => { + Ok((PackageKindTag::System, remainder)) + } + package_kind_tag if package_kind_tag == PackageKindTag::Account as u8 => { + Ok((PackageKindTag::Account, remainder)) + } + package_kind_tag if package_kind_tag == PackageKindTag::SmartContract as u8 => { + Ok((PackageKindTag::SmartContract, remainder)) + } _ => Err(bytesrepr::Error::Formatting), } } } +impl Display for PackageKindTag { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + PackageKindTag::System => { + write!(f, "system") + } + PackageKindTag::Account => { + write!(f, "account") + } + PackageKindTag::SmartContract => { + write!(f, "smart-contract") + } + } + } +} + #[cfg(any(feature = "testing", test))] impl Distribution for Standard { fn sample(&self, rng: &mut R) -> PackageKindTag { @@ -795,14 +830,14 @@ impl FromBytes for PackageKind { impl Display for PackageKind { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - PackageKind::SmartContract => { - write!(f, "PackageKind:Wasm") - } PackageKind::System(system_entity) => { - write!(f, "PackageKind:System({})", system_entity) + write!(f, "PackageKind::System({})", system_entity) } PackageKind::Account(account_hash) => { - write!(f, "PackageKind:Account({})", account_hash) + write!(f, "PackageKind::Account({})", account_hash) + } + PackageKind::SmartContract => { + write!(f, "PackageKind::SmartContract") } } } diff --git a/utils/validation/tests/fixtures/ABI/stored_value.json b/utils/validation/tests/fixtures/ABI/stored_value.json index 8a4a8bd1b9..54df5892c8 100644 --- a/utils/validation/tests/fixtures/ABI/stored_value.json +++ b/utils/validation/tests/fixtures/ABI/stored_value.json @@ -128,7 +128,7 @@ "type": "StoredValue", "value": { "ByteCode": { - "byte_code_kind": "V1CasperWasm", + "kind": "V1CasperWasm", "bytes": "0061736d010000000104016000000302010005030100010708010463616c6c00000a040102000b" } }