From 65aa4ff55cb0b4440164aa5ad53445b21cb2e176 Mon Sep 17 00:00:00 2001 From: zie1ony Date: Mon, 18 Jul 2022 19:14:32 +0200 Subject: [PATCH] Pointing dependencies of odra at github. --- backend/Cargo.toml | 4 +- common/Cargo.toml | 7 +- common/src/casper_address.rs | 193 +++++++++++++++++++++++++++++++++++ test_env/Cargo.toml | 4 +- 4 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 common/src/casper_address.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index c5de565..f51bcbc 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -# odra = { git = "https://github.com/odradev/odra.git", default-features = false, features = [ "wasm" ] } -odra = { path = "../../../odra/core", default-features = false, features = ["wasm"] } +odra = { git = "https://github.com/odradev/odra.git", default-features = false, features = [ "wasm" ] } +# odra = { path = "../../../odra/core", default-features = false, features = ["wasm"] } casper-contract = { version = "1.4.4", default-features = false, features = ["std", "test-support"] } casper-commons = { path = "../common", features = [ "wasm" ] } proc-macro2 = "1.0.39" diff --git a/common/Cargo.toml b/common/Cargo.toml index 333d942..20f0519 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -4,10 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] -# odra-types = { git = "https://github.com/odradev/odra.git" } -odra-types = { path = "../../../odra/types" } +# odra-types = { path = "../../../odra/types" } +# odra = { path = "../../../odra/core", default-features = false } casper-types = "1.5.0" -odra = { path = "../../../odra/core", default-features = false } +odra-types = { git = "https://github.com/odradev/odra.git" } +odra = { git = "https://github.com/odradev/odra.git" } [features] wasm = [ "odra/wasm" ] diff --git a/common/src/casper_address.rs b/common/src/casper_address.rs new file mode 100644 index 0000000..3636592 --- /dev/null +++ b/common/src/casper_address.rs @@ -0,0 +1,193 @@ +use casper_types::{ + account::AccountHash, + bytesrepr::{self, FromBytes, ToBytes}, + CLType, CLTyped, ContractPackageHash, Key, +}; + +use odra_types::Address as OdraAddress; + +/// An enum representing an [`AccountHash`] or a [`ContractPackageHash`]. +/// +/// It is taken from [`CasperLabs's ERC20`](https://raw.githubusercontent.com/casper-ecosystem/erc20/master/erc20/src/address.rs). +/// It is copied instead of imported for the flexebility. +#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Copy, Debug)] +pub enum CasperAddress { + /// Represents an account hash. + Account(AccountHash), + /// Represents a contract package hash. + Contract(ContractPackageHash), +} + +impl CasperAddress { + /// Returns the inner account hash if `self` is the `Account` variant. + pub fn as_account_hash(&self) -> Option<&AccountHash> { + if let Self::Account(v) = self { + Some(v) + } else { + None + } + } + + /// Returns the inner contract hash if `self` is the `Contract` variant. + pub fn as_contract_package_hash(&self) -> Option<&ContractPackageHash> { + if let Self::Contract(v) = self { + Some(v) + } else { + None + } + } + + pub fn is_contract(&self) -> bool { + self.as_contract_package_hash().is_some() + } +} + +impl From for CasperAddress { + fn from(contract_package_hash: ContractPackageHash) -> Self { + Self::Contract(contract_package_hash) + } +} + +impl From for CasperAddress { + fn from(account_hash: AccountHash) -> Self { + Self::Account(account_hash) + } +} + +impl From for Key { + fn from(address: CasperAddress) -> Self { + match address { + CasperAddress::Account(account_hash) => Key::Account(account_hash), + CasperAddress::Contract(contract_package_hash) => Key::Hash(contract_package_hash.value()), + } + } +} + +impl TryFrom for CasperAddress { + type Error = String; + + fn try_from(key: Key) -> Result { + match key { + Key::Account(account_hash) => Ok(CasperAddress::Account(account_hash)), + Key::Hash(contract_package_hash) => Ok(CasperAddress::Contract(ContractPackageHash::new(contract_package_hash))), + _ => Err(String::from("Unsupport Key type.")) + } + } +} + +impl CLTyped for CasperAddress { + fn cl_type() -> CLType { + CLType::Key + } +} + +impl ToBytes for CasperAddress { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + Key::from(*self).to_bytes() + } + + fn serialized_length(&self) -> usize { + Key::from(*self).serialized_length() + } +} + +impl FromBytes for CasperAddress { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (key, remainder) = Key::from_bytes(bytes)?; + + let address = match key { + Key::Account(account_hash) => CasperAddress::Account(account_hash), + Key::Hash(raw_contract_package_hash) => + CasperAddress::Contract(ContractPackageHash::new(raw_contract_package_hash)), + _ => return Err(bytesrepr::Error::Formatting), + }; + + Ok((address, remainder)) + } +} + +impl Into for CasperAddress { + fn into(self) -> OdraAddress { + OdraAddress::new(&self.to_bytes().unwrap()) + } +} + +impl From<&OdraAddress> for CasperAddress { + fn from(address: &OdraAddress) -> Self { + let bytes = address.bytes(); + //TODO to add error handling + ::from_bytes(bytes).unwrap().0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // TODO: casper-types > 1.5.0 will have prefix fixed. + const CONTRACT_PACKAGE_HASH: &str = "contract-package-wasm7ba9daac84bebee8111c186588f21ebca35550b6cf1244e71768bd871938be6a"; + const ACCOUNT_HASH: &str = "account-hash-3b4ffcfb21411ced5fc1560c3f6ffed86f4885e5ea05cde49d90962a48a14d95"; + + fn mock_account_hash() -> AccountHash { + AccountHash::from_formatted_str(ACCOUNT_HASH).unwrap() + } + + fn mock_contract_package_hash() -> ContractPackageHash { + ContractPackageHash::from_formatted_str(CONTRACT_PACKAGE_HASH).unwrap() + } + + fn test- + + #[test] + fn test_casper_address_account_hash_conversion() { + let account_hash = mock_account_hash(); + + // It is possible to convert CasperAddress back to AccountHash. + let casper_address = CasperAddress::from(account_hash); + assert_eq!(casper_address.as_account_hash().unwrap(), &account_hash); + + // It is not possible to convert CasperAddress to ContractPackageHash. + assert!(casper_address.as_contract_package_hash().is_none()); + + // And it is not a contract. + assert!(!casper_address.is_contract()); + + // It can be converted into a Key and back to CasperAddress. + let key = Key::from(casper_address); + let restored = CasperAddress::try_from(key); + assert_eq!(restored.unwrap(), casper_address); + + // It can be converted into bytes and back. + let bytes = casper_address.to_bytes().unwrap(); + + } + + #[test] + fn test_casper_address_contract_package_hash_conversion() { + let contract_package_hash = mock_contract_package_hash(); + let casper_address = CasperAddress::from(contract_package_hash); + + // It is possible to convert CasperAddress back to ContractPackageHash. + assert_eq!(casper_address.as_contract_package_hash().unwrap(), &contract_package_hash); + + // It is not possible to convert CasperAddress to AccountHash. + assert!(casper_address.as_account_hash().is_none()); + + // And it is a contract. + assert!(casper_address.is_contract()); + + // It can be converted into a Key and back to CasperAddress. + let key = Key::from(casper_address); + let restored = CasperAddress::try_from(key); + assert_eq!(restored.unwrap(), casper_address); + } + + #[test] + fn test_casper_address_key_conversion_fails() { + let bad_key = Key::SystemContractRegistry; + assert_eq!( + CasperAddress::try_from(bad_key), + Err(String::from("Unsupport Key type.")) + ); + } +} \ No newline at end of file diff --git a/test_env/Cargo.toml b/test_env/Cargo.toml index 636b865..4062faa 100644 --- a/test_env/Cargo.toml +++ b/test_env/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -# odra = { git = "https://github.com/odradev/odra.git", default-features = false, features = [ "wasm-test" ] } -odra = { path = "../../../odra/core", default-features = false, features = [ "wasm-test" ] } +odra = { git = "https://github.com/odradev/odra.git", default-features = false, features = [ "wasm-test" ] } +# odra = { path = "../../../odra/core", default-features = false, features = [ "wasm-test" ] } casper-commons = { path = "../common", features = [ "wasm-test" ] } casper-engine-test-support = { version = "2.0.3", features = ["test-support"] } casper-execution-engine = { version = "2.0.0" }