Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support no_std for alloy-genesis/alloy-serde #320

Merged
merged 12 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ thiserror-no-std = "2.0.2"
url = "2.5"

## serde
serde = { version = "1.0", features = ["derive"], default-features = false }
serde_json = "1.0"
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde_json = { version = "1.0" }

## misc-testing
arbitrary = "1.3"
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ contribution follows the linting rules and passes clippy.
## Note on `no_std`

Because these crates are primarily json-rpc focused, we do not intend to support
`no_std` for them at this time.
`no_std` for most of them at this time.
But the following basic crates support `no_std`:
- alloy-eips
- alloy-genesis
- alloy-serde

## Credits

Expand Down
9 changes: 9 additions & 0 deletions crates/genesis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ serde.workspace = true

[dev-dependencies]
serde_json.workspace = true

[features]
default = ["std"]
std = [
"alloy-primitives/std",
"alloy-serde/std",
# serde
"serde/std",
]
33 changes: 19 additions & 14 deletions crates/genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![deny(unused_must_use, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

use alloc::collections::BTreeMap;

use alloy_primitives::{Address, Bytes, B256, U256};
use alloy_serde::{
Expand All @@ -24,7 +29,6 @@ use alloy_serde::{
storage::deserialize_storage_map,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// The genesis block specification.
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -52,7 +56,7 @@ pub struct Genesis {
/// The genesis header coinbase address.
pub coinbase: Address,
/// The initial state of accounts in the genesis block.
pub alloc: HashMap<Address, GenesisAccount>,
pub alloc: BTreeMap<Address, GenesisAccount>,
// NOTE: the following fields:
// * base_fee_per_gas
// * excess_blob_gas
Expand Down Expand Up @@ -102,7 +106,7 @@ impl Genesis {
};

// fund account
let mut alloc = HashMap::new();
let mut alloc = BTreeMap::default();
alloc.insert(
signer_addr,
GenesisAccount {
Expand Down Expand Up @@ -226,7 +230,7 @@ pub struct GenesisAccount {
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_storage_map"
)]
pub storage: Option<HashMap<B256, B256>>,
pub storage: Option<BTreeMap<B256, B256>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually prefer the BtreeMap change here so serialize/deserialize is consistent

/// The account's private key. Should only be used for testing.
#[serde(rename = "secretKey", default, skip_serializing_if = "Option::is_none")]
pub private_key: Option<B256>,
Expand All @@ -252,7 +256,7 @@ impl GenesisAccount {
}

/// Set the storage.
pub fn with_storage(mut self, storage: Option<HashMap<B256, B256>>) -> Self {
pub fn with_storage(mut self, storage: Option<BTreeMap<B256, B256>>) -> Self {
self.storage = storage;
self
}
Expand Down Expand Up @@ -538,8 +542,9 @@ pub struct CliqueConfig {
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
use alloy_primitives::hex;
use std::str::FromStr;
use core::str::FromStr;

#[test]
fn test_genesis() {
Expand All @@ -555,7 +560,7 @@ mod tests {
let coinbase = hex!("265873b6faf3258b3ab0827805386a2a20ed040e").into();
// create dummy account
let first_address: Address = hex!("7618a8c597b89e01c66a1f662078992c52a30c9a").into();
let mut account = HashMap::default();
let mut account = BTreeMap::default();
account.insert(first_address, GenesisAccount::default());

// check values updated
Expand Down Expand Up @@ -587,18 +592,18 @@ mod tests {
nonce: Some(1),
balance: U256::from(1),
code: Some(Bytes::from(b"code")),
storage: Some(HashMap::default()),
storage: Some(BTreeMap::default()),
private_key: None,
};
let mut updated_account = HashMap::default();
let mut updated_account = BTreeMap::default();
updated_account.insert(same_address, new_alloc_account);
let custom_genesis = custom_genesis.extend_accounts(updated_account.clone());
assert_ne!(account, updated_account);
assert_eq!(custom_genesis.alloc.len(), 1);

// add second account
let different_address = hex!("94e0681e3073dd71cec54b53afe988f39078fd1a").into();
let more_accounts = HashMap::from([(different_address, GenesisAccount::default())]);
let more_accounts = BTreeMap::from([(different_address, GenesisAccount::default())]);
let custom_genesis = custom_genesis.extend_accounts(more_accounts);
assert_eq!(custom_genesis.alloc.len(), 2);

Expand All @@ -619,7 +624,7 @@ mod tests {
let code = Some(Bytes::from(b"code"));
let root = hex!("9474ddfcea39c5a690d2744103e39d1ff1b03d18db10fc147d970ad24699395a").into();
let value = hex!("58eb8294d9bb16832a9dabfcb270fff99ab8ee1d8764e4f3d9fdf59ec1dee469").into();
let mut map = HashMap::default();
let mut map = BTreeMap::default();
map.insert(root, value);
let storage = Some(map);

Expand Down Expand Up @@ -1054,7 +1059,7 @@ mod tests {
.get(&Address::from_str("0000000000000000000000000000000000000314").unwrap())
.expect("missing account for parsed genesis");
let storage = alloc_entry.storage.as_ref().expect("missing storage for parsed genesis");
let expected_storage = HashMap::from_iter(vec![
let expected_storage = BTreeMap::from_iter(vec![
(
B256::from_str(
"0x0000000000000000000000000000000000000000000000000000000000000000",
Expand Down Expand Up @@ -1162,7 +1167,7 @@ mod tests {
excess_blob_gas: None,
blob_gas_used: None,
number: None,
alloc: HashMap::from_iter(vec![
alloc: BTreeMap::from_iter(vec![
(
Address::from_str("0xdbdbdb2cbd23b783741e8d7fcf51e459b497e4a6").unwrap(),
GenesisAccount {
Expand Down Expand Up @@ -1190,7 +1195,7 @@ mod tests {
balance: U256::from_str("0x21").unwrap(),
nonce: None,
code: None,
storage: Some(HashMap::from_iter(vec![
storage: Some(BTreeMap::from_iter(vec![
(

B256::from_str("0x0000000000000000000000000000000000000000000000000000000000000001").
Expand Down
16 changes: 12 additions & 4 deletions crates/serde/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ repository.workspace = true
exclude.workspace = true

[dependencies]
# ethereum
alloy-primitives = { workspace = true, features = ["rlp", "serde"] }

serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
# serde
serde = { workspace = true }
serde_json = { workspace = true, default-features = false, features = ["alloc"] }

[dev-dependencies]
alloy-primitives = { workspace = true, features = [
Expand All @@ -25,3 +24,12 @@ alloy-primitives = { workspace = true, features = [
"serde",
"arbitrary",
] }

[features]
default = ["std"]
std = [
"alloy-primitives/std",
# serde
"serde/std",
"serde_json/std",
]
9 changes: 8 additions & 1 deletion crates/serde/src/json_u256.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
//! Json U256 serde helpers.

#[cfg(not(feature = "std"))]
use alloc::string::String;
use alloc::{fmt, format};
use core::str::FromStr;

use alloy_primitives::U256;
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde_json::Value;
use std::{fmt, str::FromStr};

/// Wrapper around primitive U256 type that also supports deserializing numbers
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
Expand Down Expand Up @@ -175,6 +180,8 @@ where
#[cfg(test)]
mod test {
use super::JsonU256;
#[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
use alloy_primitives::U256;
use serde::{Deserialize, Serialize};

Expand Down
11 changes: 8 additions & 3 deletions crates/serde/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,25 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![deny(unused_must_use, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

use alloc::format;

use alloy_primitives::B256;
use serde::Serializer;

pub mod json_u256;
pub use json_u256::JsonU256;
pub use self::json_u256::JsonU256;

/// Helpers for dealing with numbers.
pub mod num;
pub use num::*;
pub use self::num::*;

/// Storage related helpers.
pub mod storage;
pub use storage::JsonStorageKey;
pub use self::storage::JsonStorageKey;

/// Serialize a byte vec as a hex string _without_ the "0x" prefix.
///
Expand Down
5 changes: 4 additions & 1 deletion crates/serde/src/num.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
//! Numeric serde helpers.

#[cfg(not(feature = "std"))]
use alloc::string::ToString;
use core::str::FromStr;

use alloy_primitives::{U256, U64};
use serde::{de, Deserialize, Deserializer, Serialize};
use std::str::FromStr;

/// A `u64` wrapper type that deserializes from hex or a u64 and serializes as hex.
///
Expand Down
15 changes: 9 additions & 6 deletions crates/serde/src/storage.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#[cfg(not(feature = "std"))]
use alloc::string::{String, ToString};
use alloc::{collections::BTreeMap, fmt::Write};

use alloy_primitives::{Bytes, B256, U256};
use serde::{Deserialize, Deserializer, Serialize};
use std::{collections::HashMap, fmt::Write};

/// A storage key type that can be serialized to and from a hex string up to 32 bytes. Used for
/// `eth_getStorageAt` and `eth_getProof` RPCs.
Expand Down Expand Up @@ -87,15 +90,15 @@ where
/// ```
pub fn deserialize_storage_map<'de, D>(
deserializer: D,
) -> Result<Option<HashMap<B256, B256>>, D::Error>
) -> Result<Option<BTreeMap<B256, B256>>, D::Error>
where
D: Deserializer<'de>,
{
let map = Option::<HashMap<Bytes, Bytes>>::deserialize(deserializer)?;
let map = Option::<BTreeMap<Bytes, Bytes>>::deserialize(deserializer)?;
match map {
Some(mut map) => {
let mut res_map = HashMap::with_capacity(map.len());
for (k, v) in map.drain() {
Some(map) => {
let mut res_map = BTreeMap::new();
for (k, v) in map {
let k_deserialized = from_bytes_to_b256::<'de, D>(k)?;
let v_deserialized = from_bytes_to_b256::<'de, D>(v)?;
res_map.insert(k_deserialized, v_deserialized);
Expand Down
18 changes: 0 additions & 18 deletions crates/serde/src/u64_hex.rs

This file was deleted.

Loading