From 4c825ab558eb39c8f383685750943ba44b9762be Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 12:29:36 +0200 Subject: [PATCH 1/8] PrivateKeyHex in accounts --- .../examples/sov-value-setter/src/tests.rs | 5 +++-- .../sov-accounts/src/genesis.rs | 7 ++++--- .../sov-accounts/src/lib.rs | 13 ++++++------- .../sov-accounts/src/tests.rs | 18 ++++++++++++++++-- .../sov-modules-api/src/default_signature.rs | 2 +- module-system/sov-modules-api/src/lib.rs | 3 ++- .../sov-modules-api/src/pub_key_hex.rs | 12 ++++++------ 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/module-system/module-implementations/examples/sov-value-setter/src/tests.rs b/module-system/module-implementations/examples/sov-value-setter/src/tests.rs index 01e107f40..dddc5b7d0 100644 --- a/module-system/module-implementations/examples/sov-value-setter/src/tests.rs +++ b/module-system/module-implementations/examples/sov-value-setter/src/tests.rs @@ -7,8 +7,9 @@ use crate::{call, query, ValueSetterConfig}; #[test] fn test_config_serialization() { + /* let admin = Address::from([1; 32]); - let config = ValueSetterConfig:: { admin }; + let config = A let data = r#" { @@ -16,7 +17,7 @@ fn test_config_serialization() { }"#; let parsed_config: ValueSetterConfig = serde_json::from_str(data).unwrap(); - assert_eq!(parsed_config, config); + assert_eq!(parsed_config, config);*/ } #[test] diff --git a/module-system/module-implementations/sov-accounts/src/genesis.rs b/module-system/module-implementations/sov-accounts/src/genesis.rs index 9d9bb8f5d..9f1d61aa9 100644 --- a/module-system/module-implementations/sov-accounts/src/genesis.rs +++ b/module-system/module-implementations/sov-accounts/src/genesis.rs @@ -9,12 +9,13 @@ impl Accounts { config: &::Config, working_set: &mut WorkingSet, ) -> Result<()> { - for pub_key in config.pub_keys.iter() { - if self.accounts.get(pub_key, working_set).is_some() { + for pub_key_hex in config.pub_keys.iter() { + let pub_key = pub_key_hex.try_into().unwrap(); + if self.accounts.get(&pub_key, working_set).is_some() { bail!("Account already exists") } - self.create_default_account(pub_key.clone(), working_set)?; + self.create_default_account(pub_key, working_set)?; } Ok(()) diff --git a/module-system/module-implementations/sov-accounts/src/lib.rs b/module-system/module-implementations/sov-accounts/src/lib.rs index 922fce9f4..091ca0af8 100644 --- a/module-system/module-implementations/sov-accounts/src/lib.rs +++ b/module-system/module-implementations/sov-accounts/src/lib.rs @@ -12,18 +12,17 @@ pub use query::*; mod tests; pub use call::{CallMessage, UPDATE_ACCOUNT_MSG}; -use sov_modules_api::{Context, Error, ModuleInfo, WorkingSet}; +use sov_modules_api::{Context, Error, ModuleInfo, PublicKeyHex, WorkingSet}; /// Initial configuration for sov-accounts module. #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -#[serde(bound = "C::PublicKey: serde::Serialize + serde::de::DeserializeOwned")] -pub struct AccountConfig { +pub struct AccountConfig { /// Public keys to initialize the rollup. - pub pub_keys: Vec, + pub pub_keys: Vec, } -impl FromIterator for AccountConfig { - fn from_iter>(iter: T) -> Self { +impl FromIterator for AccountConfig { + fn from_iter>(iter: T) -> Self { Self { pub_keys: iter.into_iter().collect(), } @@ -59,7 +58,7 @@ pub struct Accounts { impl sov_modules_api::Module for Accounts { type Context = C; - type Config = AccountConfig; + type Config = AccountConfig; type CallMessage = call::CallMessage; diff --git a/module-system/module-implementations/sov-accounts/src/tests.rs b/module-system/module-implementations/sov-accounts/src/tests.rs index c57be2c65..5e6fbfe88 100644 --- a/module-system/module-implementations/sov-accounts/src/tests.rs +++ b/module-system/module-implementations/sov-accounts/src/tests.rs @@ -7,6 +7,20 @@ use crate::query::{self, Response}; use crate::{call, AccountConfig, Accounts}; type C = DefaultContext; +#[test] +fn test_config_serialization() { + /*let admin = Address::from([1; 32]); + let config = ValueSetterConfig:: { admin }; + + let data = r#" + { + "admin":"sov1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs259tk3" + }"#; + + let parsed_config: ValueSetterConfig = serde_json::from_str(data).unwrap(); + assert_eq!(parsed_config, config);*/ +} + #[test] fn test_config_account() { let priv_key = DefaultPrivateKey::generate(); @@ -14,8 +28,8 @@ fn test_config_account() { let init_pub_key = priv_key.pub_key(); let init_pub_key_addr = init_pub_key.to_address::<::Address>(); - let account_config = AccountConfig:: { - pub_keys: vec![init_pub_key.clone()], + let account_config = AccountConfig { + pub_keys: vec![init_pub_key.clone().try_into().unwrap()], }; let accounts = &mut Accounts::::default(); diff --git a/module-system/sov-modules-api/src/default_signature.rs b/module-system/sov-modules-api/src/default_signature.rs index 48c886f49..75b11777d 100644 --- a/module-system/sov-modules-api/src/default_signature.rs +++ b/module-system/sov-modules-api/src/default_signature.rs @@ -254,7 +254,7 @@ impl FromStr for DefaultPublicKey { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - let pk_hex = crate::pub_key_hex::PublicKeyHex::try_from(s)?; + let pk_hex = &crate::pub_key_hex::PublicKeyHex::try_from(s)?; pk_hex.try_into() } } diff --git a/module-system/sov-modules-api/src/lib.rs b/module-system/sov-modules-api/src/lib.rs index 053fdbd47..17b157cd5 100644 --- a/module-system/sov-modules-api/src/lib.rs +++ b/module-system/sov-modules-api/src/lib.rs @@ -27,8 +27,8 @@ pub mod transaction; #[cfg(feature = "native")] pub mod utils; +pub use pub_key_hex::PublicKeyHex; pub use state::*; - #[cfg(feature = "macros")] extern crate sov_modules_macros; @@ -164,6 +164,7 @@ pub trait PublicKey: + Sync + Serialize + for<'a> Deserialize<'a> + + for<'a> TryFrom<&'a PublicKeyHex, Error = anyhow::Error> { fn to_address(&self) -> A; } diff --git a/module-system/sov-modules-api/src/pub_key_hex.rs b/module-system/sov-modules-api/src/pub_key_hex.rs index 3c5d390c5..d104db597 100644 --- a/module-system/sov-modules-api/src/pub_key_hex.rs +++ b/module-system/sov-modules-api/src/pub_key_hex.rs @@ -63,11 +63,11 @@ impl From for PublicKeyHex { } } -impl TryFrom for DefaultPublicKey { +impl TryFrom<&PublicKeyHex> for DefaultPublicKey { type Error = anyhow::Error; - fn try_from(pub_key: PublicKeyHex) -> Result { - let bytes = hex::decode(pub_key.hex)?; + fn try_from(pub_key: &PublicKeyHex) -> Result { + let bytes = hex::decode(&pub_key.hex)?; let bytes: [u8; PUBLIC_KEY_LENGTH] = bytes .try_into() @@ -90,7 +90,7 @@ mod tests { fn test_pub_key_hex() { let pub_key = DefaultPrivateKey::generate().pub_key(); let pub_key_hex = PublicKeyHex::try_from(pub_key.clone()).unwrap(); - let converted_pub_key = DefaultPublicKey::try_from(pub_key_hex).unwrap(); + let converted_pub_key = DefaultPublicKey::try_from(&pub_key_hex).unwrap(); assert_eq!(pub_key, converted_pub_key); } @@ -100,8 +100,8 @@ mod tests { let pub_key_hex_lower: PublicKeyHex = key.try_into().unwrap(); let pub_key_hex_upper: PublicKeyHex = key.to_uppercase().try_into().unwrap(); - let pub_key_lower = DefaultPublicKey::try_from(pub_key_hex_lower).unwrap(); - let pub_key_upper = DefaultPublicKey::try_from(pub_key_hex_upper).unwrap(); + let pub_key_lower = DefaultPublicKey::try_from(&pub_key_hex_lower).unwrap(); + let pub_key_upper = DefaultPublicKey::try_from(&pub_key_hex_upper).unwrap(); assert_eq!(pub_key_lower, pub_key_upper) } From 4eba7b2acc9a7d279ba73a7c8eb6331433589085 Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 12:40:28 +0200 Subject: [PATCH 2/8] Add test_config_serialization --- .../sov-accounts/src/tests.rs | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/module-system/module-implementations/sov-accounts/src/tests.rs b/module-system/module-implementations/sov-accounts/src/tests.rs index 5e6fbfe88..9b6804cba 100644 --- a/module-system/module-implementations/sov-accounts/src/tests.rs +++ b/module-system/module-implementations/sov-accounts/src/tests.rs @@ -1,5 +1,8 @@ +use std::str::FromStr; + use sov_modules_api::default_context::DefaultContext; use sov_modules_api::default_signature::private_key::DefaultPrivateKey; +use sov_modules_api::default_signature::DefaultPublicKey; use sov_modules_api::{AddressBech32, Context, Module, PrivateKey, PublicKey, Spec, WorkingSet}; use sov_state::ProverStorage; @@ -9,22 +12,27 @@ type C = DefaultContext; #[test] fn test_config_serialization() { - /*let admin = Address::from([1; 32]); - let config = ValueSetterConfig:: { admin }; + let pub_key = &DefaultPublicKey::from_str( + "1cd4e2d9d5943e6f3d12589d31feee6bb6c11e7b8cd996a393623e207da72cbf", + ) + .unwrap(); + + let config = AccountConfig { + pub_keys: vec![pub_key.clone().try_into().unwrap()], + }; let data = r#" { - "admin":"sov1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs259tk3" + "pub_keys":["1cd4e2d9d5943e6f3d12589d31feee6bb6c11e7b8cd996a393623e207da72cbf"] }"#; - let parsed_config: ValueSetterConfig = serde_json::from_str(data).unwrap(); - assert_eq!(parsed_config, config);*/ + let parsed_config: AccountConfig = serde_json::from_str(data).unwrap(); + assert_eq!(parsed_config, config); } #[test] fn test_config_account() { let priv_key = DefaultPrivateKey::generate(); - let init_pub_key = priv_key.pub_key(); let init_pub_key_addr = init_pub_key.to_address::<::Address>(); From 8315d7b798a7439a8132dcf9ff59ff7d9167bf45 Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 12:47:42 +0200 Subject: [PATCH 3/8] Add accounts.json --- examples/demo-stf/src/genesis_config.rs | 14 ++++++++++---- examples/test-data/genesis/accounts.json | 3 +++ 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 examples/test-data/genesis/accounts.json diff --git a/examples/demo-stf/src/genesis_config.rs b/examples/demo-stf/src/genesis_config.rs index f0fe2b110..244321602 100644 --- a/examples/demo-stf/src/genesis_config.rs +++ b/examples/demo-stf/src/genesis_config.rs @@ -1,6 +1,7 @@ use anyhow::Context as AnyhowContext; #[cfg(feature = "experimental")] use reth_primitives::Bytes; +use sov_accounts::AccountConfig; use sov_chain_state::ChainStateConfig; use sov_cli::wallet_state::PrivateKeyAndAddress; #[cfg(feature = "experimental")] @@ -85,12 +86,17 @@ fn create_genesis_config( let value_setter_genesis_path = "../test-data/genesis/value_setter.json"; let value_setter_data = std::fs::read_to_string(value_setter_genesis_path) .with_context(|| format!("Failed to read genesis from {}", value_setter_genesis_path))?; - - let nft_config = sov_nft_module::NonFungibleTokenConfig {}; - let value_setter_config: ValueSetterConfig = serde_json::from_str(&value_setter_data) .with_context(|| format!("Failed to parse genesis from {}", value_setter_genesis_path))?; + let accounts_genesis_path = "../test-data/genesis/accounts.json"; + let accounts_data = std::fs::read_to_string(accounts_genesis_path) + .with_context(|| format!("Failed to read genesis from {}", accounts_genesis_path))?; + + let accounts_config: AccountConfig = serde_json::from_str(&accounts_data) + .with_context(|| format!("Failed to parse genesis from {}", accounts_genesis_path))?; + + let nft_config = sov_nft_module::NonFungibleTokenConfig {}; // This will be read from a file: #872 let chain_state_config = ChainStateConfig { // TODO: Put actual value @@ -104,7 +110,7 @@ fn create_genesis_config( (), chain_state_config, value_setter_config, - sov_accounts::AccountConfig { pub_keys: vec![] }, + accounts_config, #[cfg(feature = "experimental")] get_evm_config(evm_genesis_addresses), nft_config, diff --git a/examples/test-data/genesis/accounts.json b/examples/test-data/genesis/accounts.json new file mode 100644 index 000000000..3a134d04d --- /dev/null +++ b/examples/test-data/genesis/accounts.json @@ -0,0 +1,3 @@ +{ + "pub_keys":[] +} \ No newline at end of file From e7a002d5e1becf8477f36dd2cf0685b65ac515c0 Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 12:57:04 +0200 Subject: [PATCH 4/8] fix ci --- fuzz/fuzz_targets/accounts_call.rs | 2 +- module-system/module-implementations/sov-accounts/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzz/fuzz_targets/accounts_call.rs b/fuzz/fuzz_targets/accounts_call.rs index df64afe76..ceec6c61e 100644 --- a/fuzz/fuzz_targets/accounts_call.rs +++ b/fuzz/fuzz_targets/accounts_call.rs @@ -42,7 +42,7 @@ fuzz_target!(|input: (u16, [u8; 32], Vec)| -> Corpus { let storage = ::Storage::with_path(tmpdir.path()).unwrap(); let working_set = &mut WorkingSet::new(storage); - let config: AccountConfig = keys.iter().map(|k| k.pub_key()).collect(); + let config: AccountConfig = keys.iter().map(|k| k.pub_key()).collect(); let accounts: Accounts = Accounts::default(); accounts.genesis(&config, working_set).unwrap(); diff --git a/module-system/module-implementations/sov-accounts/src/lib.rs b/module-system/module-implementations/sov-accounts/src/lib.rs index 091ca0af8..915e29d4a 100644 --- a/module-system/module-implementations/sov-accounts/src/lib.rs +++ b/module-system/module-implementations/sov-accounts/src/lib.rs @@ -122,7 +122,7 @@ where ) -> arbitrary::Result { use sov_modules_api::Module; - let config: AccountConfig = u.arbitrary()?; + let config: AccountConfig = u.arbitrary()?; let accounts = Accounts::default(); accounts From d175cc31e2335f2b184f38cc5f8ce1fc5d351bf2 Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 13:04:22 +0200 Subject: [PATCH 5/8] fix CI --- module-system/module-implementations/sov-accounts/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-system/module-implementations/sov-accounts/src/lib.rs b/module-system/module-implementations/sov-accounts/src/lib.rs index 915e29d4a..f2e978ca9 100644 --- a/module-system/module-implementations/sov-accounts/src/lib.rs +++ b/module-system/module-implementations/sov-accounts/src/lib.rs @@ -94,7 +94,7 @@ where } #[cfg(feature = "arbitrary")] -impl<'a, C> arbitrary::Arbitrary<'a> for AccountConfig +impl<'a, C> arbitrary::Arbitrary<'a> for AccountConfig where C: Context, C::PublicKey: arbitrary::Arbitrary<'a>, From 69ed9d7aa24b491bab1d90a2991bdf8382eff2f0 Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 13:13:09 +0200 Subject: [PATCH 6/8] cleanup --- .../examples/sov-value-setter/src/tests.rs | 5 ++--- .../module-implementations/sov-accounts/src/genesis.rs | 2 +- .../module-implementations/sov-accounts/src/lib.rs | 6 +----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/module-system/module-implementations/examples/sov-value-setter/src/tests.rs b/module-system/module-implementations/examples/sov-value-setter/src/tests.rs index dddc5b7d0..01e107f40 100644 --- a/module-system/module-implementations/examples/sov-value-setter/src/tests.rs +++ b/module-system/module-implementations/examples/sov-value-setter/src/tests.rs @@ -7,9 +7,8 @@ use crate::{call, query, ValueSetterConfig}; #[test] fn test_config_serialization() { - /* let admin = Address::from([1; 32]); - let config = A + let config = ValueSetterConfig:: { admin }; let data = r#" { @@ -17,7 +16,7 @@ fn test_config_serialization() { }"#; let parsed_config: ValueSetterConfig = serde_json::from_str(data).unwrap(); - assert_eq!(parsed_config, config);*/ + assert_eq!(parsed_config, config); } #[test] diff --git a/module-system/module-implementations/sov-accounts/src/genesis.rs b/module-system/module-implementations/sov-accounts/src/genesis.rs index 9f1d61aa9..5b80b9857 100644 --- a/module-system/module-implementations/sov-accounts/src/genesis.rs +++ b/module-system/module-implementations/sov-accounts/src/genesis.rs @@ -10,7 +10,7 @@ impl Accounts { working_set: &mut WorkingSet, ) -> Result<()> { for pub_key_hex in config.pub_keys.iter() { - let pub_key = pub_key_hex.try_into().unwrap(); + let pub_key = pub_key_hex.try_into()?; if self.accounts.get(&pub_key, working_set).is_some() { bail!("Account already exists") } diff --git a/module-system/module-implementations/sov-accounts/src/lib.rs b/module-system/module-implementations/sov-accounts/src/lib.rs index f2e978ca9..7fa0a1e66 100644 --- a/module-system/module-implementations/sov-accounts/src/lib.rs +++ b/module-system/module-implementations/sov-accounts/src/lib.rs @@ -94,11 +94,7 @@ where } #[cfg(feature = "arbitrary")] -impl<'a, C> arbitrary::Arbitrary<'a> for AccountConfig -where - C: Context, - C::PublicKey: arbitrary::Arbitrary<'a>, -{ +impl<'a> arbitrary::Arbitrary<'a> for AccountConfig { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { // TODO we might want a dedicated struct that will generate the private key counterpart so // payloads can be signed and verified From 5f79bba064423efe33f584412d0ead6a24e1e3a0 Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 14:18:17 +0200 Subject: [PATCH 7/8] Arbitrary PublicKeyHex --- .../sov-modules-api/src/pub_key_hex.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/module-system/sov-modules-api/src/pub_key_hex.rs b/module-system/sov-modules-api/src/pub_key_hex.rs index d104db597..6a480a6b0 100644 --- a/module-system/sov-modules-api/src/pub_key_hex.rs +++ b/module-system/sov-modules-api/src/pub_key_hex.rs @@ -122,3 +122,21 @@ mod tests { assert_eq!(err.to_string(), "Bad hex conversion: odd input length") } } + +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for PublicKeyHex { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + use rand::rngs::StdRng; + use rand::SeedableRng; + + // it is important to generate the secret deterministically from the arbitrary argument + // so keys and signatures will be reproducible for a given seed. + // this unlocks fuzzy replay + let seed = <[u8; 32]>::arbitrary(u)?; + let rng = &mut StdRng::from_seed(seed); + //let key_pair = SigningKey::generate(rng); + + //Ok(Self { key_pair }) + todo!() + } +} From 1e86120684a4195bd64656b2fd206f91c7fe1303 Mon Sep 17 00:00:00 2001 From: bkolad Date: Fri, 29 Sep 2023 14:27:06 +0200 Subject: [PATCH 8/8] PublicKeyHex impl --- module-system/sov-modules-api/src/pub_key_hex.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/module-system/sov-modules-api/src/pub_key_hex.rs b/module-system/sov-modules-api/src/pub_key_hex.rs index 6a480a6b0..07667ca3c 100644 --- a/module-system/sov-modules-api/src/pub_key_hex.rs +++ b/module-system/sov-modules-api/src/pub_key_hex.rs @@ -126,17 +126,7 @@ mod tests { #[cfg(feature = "arbitrary")] impl<'a> arbitrary::Arbitrary<'a> for PublicKeyHex { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - use rand::rngs::StdRng; - use rand::SeedableRng; - - // it is important to generate the secret deterministically from the arbitrary argument - // so keys and signatures will be reproducible for a given seed. - // this unlocks fuzzy replay - let seed = <[u8; 32]>::arbitrary(u)?; - let rng = &mut StdRng::from_seed(seed); - //let key_pair = SigningKey::generate(rng); - - //Ok(Self { key_pair }) - todo!() + let hex: String = hex::encode(String::arbitrary(u)?); + Ok(PublicKeyHex::try_from(hex).unwrap()) } }