mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
fix: use correct type for NewPooledTransactionHashes68 (#1548)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4564,6 +4564,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"ethers-core",
|
||||
"futures",
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"metrics",
|
||||
"pin-project",
|
||||
|
||||
@ -45,6 +45,7 @@ ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features =
|
||||
test-fuzz = "3.0.4"
|
||||
tokio-util = { version = "0.7.4", features = ["io", "codec"] }
|
||||
hex-literal = "0.3"
|
||||
hex = "0.4"
|
||||
rand = "0.8"
|
||||
secp256k1 = { version = "0.24.2", features = ["global-context", "rand-std", "recovery"] }
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
//! Types for broadcasting new data.
|
||||
use crate::{EthMessage, EthVersion};
|
||||
use bytes::Bytes;
|
||||
use reth_codecs::derive_arbitrary;
|
||||
use reth_primitives::{Block, TransactionSigned, H256, U128};
|
||||
use reth_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper};
|
||||
use reth_rlp::{
|
||||
Decodable, Encodable, RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
@ -193,10 +196,32 @@ impl From<Vec<H256>> for NewPooledTransactionHashes66 {
|
||||
/// Same as [`NewPooledTransactionHashes66`] but extends that that beside the transaction hashes,
|
||||
/// the node sends the transaction types and their sizes (as defined in EIP-2718) as well.
|
||||
#[derive_arbitrary(rlp)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, RlpEncodable, RlpDecodable, Default)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct NewPooledTransactionHashes68 {
|
||||
/// Transaction types for new transactions that have appeared on the network.
|
||||
///
|
||||
/// ## Note on RLP encoding and decoding
|
||||
///
|
||||
/// In the [eth/68 spec](https://eips.ethereum.org/EIPS/eip-5793#specification) this is defined
|
||||
/// the following way:
|
||||
/// * `[type_0: B_1, type_1: B_1, ...]`
|
||||
///
|
||||
/// This would make it seem like the [`Encodable`](reth_rlp::Encodable) and
|
||||
/// [`Decodable`](reth_rlp::Decodable) implementations should directly use a `Vec<u8>` for
|
||||
/// encoding and decoding, because it looks like this field should be encoded as a _list_ of
|
||||
/// bytes.
|
||||
///
|
||||
/// However, [this is implemented in geth as a `[]byte`
|
||||
/// type](https://github.com/ethereum/go-ethereum/blob/82d934b1dd80cdd8190803ea9f73ed2c345e2576/eth/protocols/eth/protocol.go#L308-L313),
|
||||
/// which [ends up being encoded as a RLP
|
||||
/// string](https://github.com/ethereum/go-ethereum/blob/82d934b1dd80cdd8190803ea9f73ed2c345e2576/rlp/encode_test.go#L171-L176),
|
||||
/// **not** a RLP list.
|
||||
///
|
||||
/// Because of this, we do not directly use the `Vec<u8>` when encoding and decoding, and
|
||||
/// instead use the [`Encodable`](reth_rlp::Encodable) and [`Decodable`](reth_rlp::Decodable)
|
||||
/// implementations for `&[u8]` instead, which encodes into a RLP string, and expects an RLP
|
||||
/// string when decoding.
|
||||
pub types: Vec<u8>,
|
||||
/// Transaction sizes for new transactions that have appeared on the network.
|
||||
pub sizes: Vec<usize>,
|
||||
@ -204,10 +229,80 @@ pub struct NewPooledTransactionHashes68 {
|
||||
pub hashes: Vec<H256>,
|
||||
}
|
||||
|
||||
impl Encodable for NewPooledTransactionHashes68 {
|
||||
fn length(&self) -> usize {
|
||||
#[derive(RlpEncodable)]
|
||||
struct EncodableNewPooledTransactionHashes68<'a> {
|
||||
types: &'a [u8],
|
||||
sizes: &'a Vec<usize>,
|
||||
hashes: &'a Vec<H256>,
|
||||
}
|
||||
|
||||
let encodable = EncodableNewPooledTransactionHashes68 {
|
||||
types: &self.types[..],
|
||||
sizes: &self.sizes,
|
||||
hashes: &self.hashes,
|
||||
};
|
||||
|
||||
encodable.length()
|
||||
}
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
#[derive(RlpEncodable)]
|
||||
struct EncodableNewPooledTransactionHashes68<'a> {
|
||||
types: &'a [u8],
|
||||
sizes: &'a Vec<usize>,
|
||||
hashes: &'a Vec<H256>,
|
||||
}
|
||||
|
||||
let encodable = EncodableNewPooledTransactionHashes68 {
|
||||
types: &self.types[..],
|
||||
sizes: &self.sizes,
|
||||
hashes: &self.hashes,
|
||||
};
|
||||
|
||||
encodable.encode(out);
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for NewPooledTransactionHashes68 {
|
||||
fn decode(buf: &mut &[u8]) -> Result<Self, reth_rlp::DecodeError> {
|
||||
#[derive(RlpDecodable)]
|
||||
struct EncodableNewPooledTransactionHashes68 {
|
||||
types: Bytes,
|
||||
sizes: Vec<usize>,
|
||||
hashes: Vec<H256>,
|
||||
}
|
||||
|
||||
let encodable = EncodableNewPooledTransactionHashes68::decode(buf)?;
|
||||
Ok(Self { types: encodable.types.into(), sizes: encodable.sizes, hashes: encodable.hashes })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use bytes::BytesMut;
|
||||
use hex_literal::hex;
|
||||
use reth_rlp::{Decodable, Encodable};
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Takes as input a struct / encoded hex message pair, ensuring that we encode to the exact hex
|
||||
/// message, and decode to the exact struct.
|
||||
fn test_encoding_vector<T: Encodable + Decodable + PartialEq + std::fmt::Debug>(
|
||||
input: (T, &[u8]),
|
||||
) {
|
||||
let (expected_decoded, expected_encoded) = input;
|
||||
let mut encoded = BytesMut::new();
|
||||
expected_decoded.encode(&mut encoded);
|
||||
|
||||
assert_eq!(hex::encode(&encoded), hex::encode(expected_encoded));
|
||||
|
||||
let decoded = T::decode(&mut encoded.as_ref()).unwrap();
|
||||
assert_eq!(expected_decoded, decoded);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_return_latest_block() {
|
||||
let mut blocks = NewBlockHashes(vec![BlockHashNumber { hash: H256::random(), number: 0 }]);
|
||||
@ -219,4 +314,125 @@ mod tests {
|
||||
let latest = blocks.latest().unwrap();
|
||||
assert_eq!(latest.number, 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eth_68_tx_hash_roundtrip() {
|
||||
let vectors = vec![
|
||||
(
|
||||
NewPooledTransactionHashes68 { types: vec![], sizes: vec![], hashes: vec![] },
|
||||
&hex!("c380c0c0")[..],
|
||||
),
|
||||
(
|
||||
NewPooledTransactionHashes68 {
|
||||
types: vec![0x00],
|
||||
sizes: vec![0x00],
|
||||
hashes: vec![H256::from_str(
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
)
|
||||
.unwrap()],
|
||||
},
|
||||
&hex!("e500c180e1a00000000000000000000000000000000000000000000000000000000000000000")[..],
|
||||
),
|
||||
(
|
||||
NewPooledTransactionHashes68 {
|
||||
types: vec![0x00, 0x00],
|
||||
sizes: vec![0x00, 0x00],
|
||||
hashes: vec![
|
||||
H256::from_str(
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
)
|
||||
.unwrap(),
|
||||
H256::from_str(
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
)
|
||||
.unwrap(),
|
||||
],
|
||||
},
|
||||
&hex!("f84a820000c28080f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000")[..],
|
||||
),
|
||||
(
|
||||
NewPooledTransactionHashes68 {
|
||||
types: vec![0x02],
|
||||
sizes: vec![0xb6],
|
||||
hashes: vec![H256::from_str(
|
||||
"0xfecbed04c7b88d8e7221a0a3f5dc33f220212347fc167459ea5cc9c3eb4c1124",
|
||||
)
|
||||
.unwrap()],
|
||||
},
|
||||
&hex!("e602c281b6e1a0fecbed04c7b88d8e7221a0a3f5dc33f220212347fc167459ea5cc9c3eb4c1124")[..],
|
||||
),
|
||||
(
|
||||
NewPooledTransactionHashes68 {
|
||||
types: vec![0xff, 0xff],
|
||||
sizes: vec![0xffffffff, 0xffffffff],
|
||||
hashes: vec![
|
||||
H256::from_str(
|
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
)
|
||||
.unwrap(),
|
||||
H256::from_str(
|
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
)
|
||||
.unwrap(),
|
||||
],
|
||||
},
|
||||
&hex!("f85282ffffca84ffffffff84fffffffff842a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[..],
|
||||
),
|
||||
(
|
||||
NewPooledTransactionHashes68 {
|
||||
types: vec![0xff, 0xff],
|
||||
sizes: vec![0xffffffff, 0xffffffff],
|
||||
hashes: vec![
|
||||
H256::from_str(
|
||||
"0xbeefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafe",
|
||||
)
|
||||
.unwrap(),
|
||||
H256::from_str(
|
||||
"0xbeefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafe",
|
||||
)
|
||||
.unwrap(),
|
||||
],
|
||||
},
|
||||
&hex!("f85282ffffca84ffffffff84fffffffff842a0beefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafea0beefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafebeefcafe")[..],
|
||||
),
|
||||
(
|
||||
NewPooledTransactionHashes68 {
|
||||
types: vec![0x10, 0x10],
|
||||
sizes: vec![0xdeadc0de, 0xdeadc0de],
|
||||
hashes: vec![
|
||||
H256::from_str(
|
||||
"0x3b9aca00f0671c9a2a1b817a0a78d3fe0c0f776cccb2a8c3c1b412a4f4e4d4e2",
|
||||
)
|
||||
.unwrap(),
|
||||
H256::from_str(
|
||||
"0x3b9aca00f0671c9a2a1b817a0a78d3fe0c0f776cccb2a8c3c1b412a4f4e4d4e2",
|
||||
)
|
||||
.unwrap(),
|
||||
],
|
||||
},
|
||||
&hex!("f852821010ca84deadc0de84deadc0def842a03b9aca00f0671c9a2a1b817a0a78d3fe0c0f776cccb2a8c3c1b412a4f4e4d4e2a03b9aca00f0671c9a2a1b817a0a78d3fe0c0f776cccb2a8c3c1b412a4f4e4d4e2")[..],
|
||||
),
|
||||
(
|
||||
NewPooledTransactionHashes68 {
|
||||
types: vec![0x6f, 0x6f],
|
||||
sizes: vec![0x7fffffff, 0x7fffffff],
|
||||
hashes: vec![
|
||||
H256::from_str(
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000002",
|
||||
)
|
||||
.unwrap(),
|
||||
H256::from_str(
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000002",
|
||||
)
|
||||
.unwrap(),
|
||||
],
|
||||
},
|
||||
&hex!("f852826f6fca847fffffff847ffffffff842a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000002")[..],
|
||||
),
|
||||
];
|
||||
|
||||
for vector in vectors {
|
||||
test_encoding_vector(vector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user