primitives: add own Bloom type with arbitrary (#746)

* add own Bloom type with arbitrary

* use impl_hash_compact instead

* add doc to exported macro

* remove unused crate and code

* fix rlp encode length for Bloom

* use RlpDecodableWrapper and RlpEncodableWrapper instead
This commit is contained in:
joshieDo
2023-01-06 19:10:19 +08:00
committed by GitHub
parent a94560fc5d
commit 258431aac8
8 changed files with 70 additions and 35 deletions

4
Cargo.lock generated
View File

@ -3851,14 +3851,16 @@ dependencies = [
"bytes",
"crc",
"derive_more",
"ethbloom",
"ethers-core",
"fixed-hash",
"hash-db",
"hex",
"hex-literal",
"impl-serde",
"modular-bitfield",
"parity-scale-codec",
"plain_hasher",
"proptest",
"rand 0.8.5",
"reth-codecs",
"reth-rlp",

View File

@ -273,7 +273,6 @@ mod ethereum_types_support {
fixed_hash_impl!(H256);
fixed_hash_impl!(H512);
fixed_hash_impl!(H520);
fixed_hash_impl!(Bloom);
macro_rules! fixed_uint_impl {
($t:ty, $n_bytes:tt) => {

View File

@ -265,7 +265,6 @@ mod ethereum_types_support {
fixed_hash_impl!(H256);
fixed_hash_impl!(H512);
fixed_hash_impl!(H520);
fixed_hash_impl!(Bloom);
macro_rules! fixed_uint_impl {
($t:ty, $n_bytes:tt) => {

View File

@ -23,7 +23,11 @@ revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "3a13c9c8a
ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
parity-scale-codec = { version = "3.2.1", features = ["derive", "bytes"] }
tiny-keccak = { version = "2.0", features = ["keccak"] }
ethbloom = { version = "0.13", features = ["codec"] }
# Bloom
fixed-hash = { version = "0.8", default-features = false, features = [
"rustc-hex",
] }
# crypto
secp256k1 = { version = "0.24.2", default-features = false, features = [
@ -47,6 +51,7 @@ hex-literal = "0.3"
modular-bitfield = "0.11.2"
derive_more = "0.99"
url = "2.3"
impl-serde = "0.4.0"
# proof related
triehash = "0.8"
@ -61,8 +66,13 @@ hex-literal = "0.3"
test-fuzz = "3.0.4"
rand = "0.8"
revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "3a13c9c8a0cda728941f1b26db0beb1025744ea9", features = ["with-serde", "arbitrary"] }
proptest = { version = "1.0" }
# necessary so we don't hit a "undeclared 'std'":
# https://github.com/paradigmxyz/reth/pull/177#discussion_r1021172198
secp256k1 = "0.24.2"
[features]
default = []
arbitrary = ["dep:arbitrary", "revm-interpreter/arbitrary"]

View File

@ -1,10 +1,46 @@
//! Bloom related utilities.
use crate::{keccak256, Log};
use bytes::Buf;
use derive_more::{AsRef, Deref};
use fixed_hash::construct_fixed_hash;
use impl_serde::impl_fixed_hash_serde;
use reth_codecs::{impl_hash_compact, Compact};
use reth_rlp::{RlpDecodableWrapper, RlpEncodableWrapper};
use crate::{keccak256, Bloom, Log};
#[cfg(test)]
use proptest::{
arbitrary::{any_with, Arbitrary as PropTestArbitrary, ParamsFor},
strategy::{BoxedStrategy, Strategy},
};
#[cfg(any(test, feature = "arbitrary"))]
use arbitrary::Arbitrary;
/// Length of bloom filter used for Ethereum.
pub const BLOOM_BYTE_LENGTH: usize = 256;
construct_fixed_hash! {
/// 2048 bits type.
#[cfg_attr(any(test, feature = "arbitrary"), derive(Arbitrary))]
#[derive(AsRef, Deref, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct Bloom(BLOOM_BYTE_LENGTH);
}
impl_hash_compact!(Bloom);
impl_fixed_hash_serde!(Bloom, BLOOM_BYTE_LENGTH);
#[cfg(test)]
impl PropTestArbitrary for Bloom {
type Parameters = ParamsFor<u8>;
type Strategy = BoxedStrategy<Bloom>;
fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
proptest::collection::vec(any_with::<u8>(args), BLOOM_BYTE_LENGTH)
.prop_map(move |vec| Bloom::from_slice(&vec))
.boxed()
}
}
// See Section 4.3.1 "Transaction Receipt" of the Yellow Paper
fn m3_2048(bloom: &mut Bloom, x: &[u8]) {
let hash = keccak256(x);
@ -69,4 +105,19 @@ mod tests {
))
);
}
#[test]
fn arbitrary() {
proptest::proptest!(|(bloom: Bloom)| {
let mut buf = vec![];
bloom.to_compact(&mut buf);
// Add noise
buf.push(1);
let (decoded, remaining_buf) = Bloom::from_compact(&buf, buf.len());
assert!(bloom == decoded);
assert!(remaining_buf.len() == 1);
});
}
}

View File

@ -33,9 +33,9 @@ pub mod proofs;
pub use account::Account;
pub use block::{Block, BlockHashOrNumber, SealedBlock};
pub use bloom::Bloom;
pub use chain::Chain;
pub use constants::{EMPTY_OMMER_ROOT, KECCAK_EMPTY, MAINNET_GENESIS};
pub use ethbloom::Bloom;
pub use forkid::{ForkFilter, ForkHash, ForkId, ForkTransition, ValidationError};
pub use hardfork::Hardfork;
pub use header::{Header, HeadersDirection, SealedHeader};

View File

@ -1,6 +1,5 @@
use bytes::{Buf, Bytes};
pub use codecs_derive::*;
use ethers_core::types::Bloom;
use revm_interpreter::{B160 as H160, B256 as H256, U256};
/// Trait that implements the `Compact` codec.
@ -222,6 +221,8 @@ impl Compact for Bytes {
}
}
/// Implements the [`Compact`] trait for fixed size hash types like [`H256`].
#[macro_export]
macro_rules! impl_hash_compact {
($($name:tt),+) => {
$(
@ -257,19 +258,6 @@ macro_rules! impl_hash_compact {
impl_hash_compact!(H256, H160);
impl Compact for Bloom {
fn to_compact(self, buf: &mut impl bytes::BufMut) -> usize {
buf.put_slice(&self.0);
256
}
fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
let result = Bloom::from_slice(&buf[..256]);
buf.advance(256);
(result, buf)
}
}
impl Compact for bool {
/// `bool` vars go directly to the `StructFlags` and are not written to the buffer.
fn to_compact(self, _: &mut impl bytes::BufMut) -> usize {
@ -303,19 +291,6 @@ mod tests {
assert_eq!(bytes::Bytes::from_compact(&buf, list.len()), (list, vec![1].as_slice()));
}
#[test]
fn compact_bloom() {
let mut buf = vec![];
assert_eq!(Bloom::default().to_compact(&mut buf), 256);
assert_eq!(buf, vec![0; 256]);
// Add some noise data.
buf.push(1);
// Bloom shouldn't care about the len passed, since it's not actually compacted.
assert_eq!(Bloom::from_compact(&buf, 1000), (Bloom::default(), vec![1u8].as_slice()));
}
#[test]
fn compact_address() {
let mut buf = vec![];

View File

@ -164,8 +164,7 @@ mod test {
ommer.ommers.push(Header::default());
ommer.ommers.push(Header::default());
assert!(
ommer.clone() ==
StoredBlockOmmers::decompress::<Vec<_>>(ommer.compress().into()).unwrap()
ommer.clone() == StoredBlockOmmers::decompress::<Vec<_>>(ommer.compress()).unwrap()
);
}
}