Skip to content

Commit

Permalink
Read accounts genesis from a file. (#959)
Browse files Browse the repository at this point in the history
* PrivateKeyHex in accounts

* Add test_config_serialization

* Add accounts.json

* fix ci

* fix CI

* cleanup

* Arbitrary PublicKeyHex

* PublicKeyHex impl
  • Loading branch information
bkolad authored Sep 29, 2023
1 parent ca038a7 commit 7229226
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 32 deletions.
14 changes: 10 additions & 4 deletions examples/demo-stf/src/genesis_config.rs
Original file line number Diff line number Diff line change
@@ -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")]
Expand Down Expand Up @@ -85,12 +86,17 @@ fn create_genesis_config<C: Context, Da: DaSpec>(
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<C> = 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
Expand All @@ -104,7 +110,7 @@ fn create_genesis_config<C: Context, Da: DaSpec>(
(),
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,
Expand Down
3 changes: 3 additions & 0 deletions examples/test-data/genesis/accounts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"pub_keys":[]
}
2 changes: 1 addition & 1 deletion fuzz/fuzz_targets/accounts_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fuzz_target!(|input: (u16, [u8; 32], Vec<DefaultPrivateKey>)| -> Corpus {
let storage = <C as Spec>::Storage::with_path(tmpdir.path()).unwrap();
let working_set = &mut WorkingSet::new(storage);

let config: AccountConfig<C> = keys.iter().map(|k| k.pub_key()).collect();
let config: AccountConfig = keys.iter().map(|k| k.pub_key()).collect();
let accounts: Accounts<C> = Accounts::default();
accounts.genesis(&config, working_set).unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ impl<C: sov_modules_api::Context> Accounts<C> {
config: &<Self as sov_modules_api::Module>::Config,
working_set: &mut WorkingSet<C>,
) -> 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()?;
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(())
Expand Down
21 changes: 8 additions & 13 deletions module-system/module-implementations/sov-accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<C: Context> {
pub struct AccountConfig {
/// Public keys to initialize the rollup.
pub pub_keys: Vec<C::PublicKey>,
pub pub_keys: Vec<PublicKeyHex>,
}

impl<C: Context> FromIterator<C::PublicKey> for AccountConfig<C> {
fn from_iter<T: IntoIterator<Item = C::PublicKey>>(iter: T) -> Self {
impl FromIterator<PublicKeyHex> for AccountConfig {
fn from_iter<T: IntoIterator<Item = PublicKeyHex>>(iter: T) -> Self {
Self {
pub_keys: iter.into_iter().collect(),
}
Expand Down Expand Up @@ -59,7 +58,7 @@ pub struct Accounts<C: Context> {
impl<C: Context> sov_modules_api::Module for Accounts<C> {
type Context = C;

type Config = AccountConfig<C>;
type Config = AccountConfig;

type CallMessage = call::CallMessage<C>;

Expand Down Expand Up @@ -95,11 +94,7 @@ where
}

#[cfg(feature = "arbitrary")]
impl<'a, C> arbitrary::Arbitrary<'a> for AccountConfig<C>
where
C: Context,
C::PublicKey: arbitrary::Arbitrary<'a>,
{
impl<'a> arbitrary::Arbitrary<'a> for AccountConfig {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
// TODO we might want a dedicated struct that will generate the private key counterpart so
// payloads can be signed and verified
Expand All @@ -123,7 +118,7 @@ where
) -> arbitrary::Result<Self> {
use sov_modules_api::Module;

let config: AccountConfig<C> = u.arbitrary()?;
let config: AccountConfig = u.arbitrary()?;
let accounts = Accounts::default();

accounts
Expand Down
28 changes: 25 additions & 3 deletions module-system/module-implementations/sov-accounts/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,43 @@
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;

use crate::query::{self, Response};
use crate::{call, AccountConfig, Accounts};
type C = DefaultContext;

#[test]
fn test_config_serialization() {
let pub_key = &DefaultPublicKey::from_str(
"1cd4e2d9d5943e6f3d12589d31feee6bb6c11e7b8cd996a393623e207da72cbf",
)
.unwrap();

let config = AccountConfig {
pub_keys: vec![pub_key.clone().try_into().unwrap()],
};

let data = r#"
{
"pub_keys":["1cd4e2d9d5943e6f3d12589d31feee6bb6c11e7b8cd996a393623e207da72cbf"]
}"#;

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::<<C as Spec>::Address>();

let account_config = AccountConfig::<C> {
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::<C>::default();
Expand Down
2 changes: 1 addition & 1 deletion module-system/sov-modules-api/src/default_signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ impl FromStr for DefaultPublicKey {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
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()
}
}
Expand Down
3 changes: 2 additions & 1 deletion module-system/sov-modules-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,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;

Expand Down Expand Up @@ -166,6 +166,7 @@ pub trait PublicKey:
+ Sync
+ Serialize
+ for<'a> Deserialize<'a>
+ for<'a> TryFrom<&'a PublicKeyHex, Error = anyhow::Error>
{
fn to_address<A: RollupAddress>(&self) -> A;
}
Expand Down
20 changes: 14 additions & 6 deletions module-system/sov-modules-api/src/pub_key_hex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ impl From<DefaultPublicKey> for PublicKeyHex {
}
}

impl TryFrom<PublicKeyHex> for DefaultPublicKey {
impl TryFrom<&PublicKeyHex> for DefaultPublicKey {
type Error = anyhow::Error;

fn try_from(pub_key: PublicKeyHex) -> Result<Self, Self::Error> {
let bytes = hex::decode(pub_key.hex)?;
fn try_from(pub_key: &PublicKeyHex) -> Result<Self, Self::Error> {
let bytes = hex::decode(&pub_key.hex)?;

let bytes: [u8; PUBLIC_KEY_LENGTH] = bytes
.try_into()
Expand All @@ -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);
}

Expand All @@ -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)
}
Expand All @@ -122,3 +122,11 @@ 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<Self> {
let hex: String = hex::encode(String::arbitrary(u)?);
Ok(PublicKeyHex::try_from(hex).unwrap())
}
}

0 comments on commit 7229226

Please sign in to comment.