diff --git a/ethportal-api/src/types/content_key/beacon.rs b/ethportal-api/src/types/content_key/beacon.rs index 72a97f3ed..c666490e8 100644 --- a/ethportal-api/src/types/content_key/beacon.rs +++ b/ethportal-api/src/types/content_key/beacon.rs @@ -1,7 +1,9 @@ use crate::{ types::content_key::{error::ContentKeyError, overlay::OverlayContentKey}, utils::bytes::hex_encode_compact, + RawContentKey, }; +use alloy_primitives::Bytes; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use sha2::{Digest, Sha256}; use ssz::{Decode, DecodeError, Encode}; @@ -81,22 +83,22 @@ pub struct HistoricalSummariesWithProofKey { pub epoch: u64, } -impl From<&BeaconContentKey> for Vec { +impl From<&BeaconContentKey> for Bytes { fn from(val: &BeaconContentKey) -> Self { val.to_bytes() } } -impl From for Vec { +impl From for Bytes { fn from(val: BeaconContentKey) -> Self { val.to_bytes() } } -impl TryFrom> for BeaconContentKey { +impl TryFrom for BeaconContentKey { type Error = ContentKeyError; - fn try_from(value: Vec) -> Result { + fn try_from(value: RawContentKey) -> Result { let Some((&selector, key)) = value.split_first() else { return Err(ContentKeyError::InvalidLength { received: value.len(), @@ -170,7 +172,7 @@ impl OverlayContentKey for BeaconContentKey { sha256.finalize().into() } - fn to_bytes(&self) -> Vec { + fn to_bytes(&self) -> RawContentKey { let mut bytes: Vec = Vec::new(); match self { @@ -196,7 +198,7 @@ impl OverlayContentKey for BeaconContentKey { } } - bytes + bytes.into() } } diff --git a/ethportal-api/src/types/content_key/history.rs b/ethportal-api/src/types/content_key/history.rs index 7658e0d35..d3b05064c 100644 --- a/ethportal-api/src/types/content_key/history.rs +++ b/ethportal-api/src/types/content_key/history.rs @@ -9,6 +9,7 @@ use std::{fmt, hash::Hash}; use crate::{ types::content_key::{error::ContentKeyError, overlay::OverlayContentKey}, utils::bytes::hex_encode_compact, + RawContentKey, }; // Prefixes for the different types of history content keys: @@ -44,6 +45,7 @@ impl HistoryContentKey { .choose(&mut rand::thread_rng()) .ok_or_else(|| anyhow::Error::msg("Failed to choose random prefix"))?; random_bytes.insert(0, *random_prefix); + let random_bytes: RawContentKey = random_bytes.into(); Self::try_from(random_bytes).map_err(anyhow::Error::msg) } } @@ -118,20 +120,20 @@ pub struct EpochAccumulatorKey { impl From<&HistoryContentKey> for Vec { fn from(val: &HistoryContentKey) -> Self { - val.to_bytes() + val.to_bytes().to_vec() } } impl From for Vec { fn from(val: HistoryContentKey) -> Self { - val.to_bytes() + val.to_bytes().to_vec() } } -impl TryFrom> for HistoryContentKey { +impl TryFrom for HistoryContentKey { type Error = ContentKeyError; - fn try_from(value: Vec) -> Result { + fn try_from(value: RawContentKey) -> Result { let Some((&selector, key)) = value.split_first() else { return Err(ContentKeyError::InvalidLength { received: value.len(), @@ -195,7 +197,7 @@ impl OverlayContentKey for HistoryContentKey { sha256.finalize().into() } - fn to_bytes(&self) -> Vec { + fn to_bytes(&self) -> RawContentKey { let mut bytes: Vec = Vec::new(); match self { @@ -217,7 +219,7 @@ impl OverlayContentKey for HistoryContentKey { } } - bytes + bytes.into() } } @@ -326,7 +328,7 @@ mod test { }); // round trip - let decoded = HistoryContentKey::try_from(key.to_bytes().to_vec()).unwrap(); + let decoded = HistoryContentKey::try_from(key.to_bytes()).unwrap(); assert_eq!(decoded, key); assert_eq!(key.to_bytes(), expected_content_key); diff --git a/ethportal-api/src/types/content_key/overlay.rs b/ethportal-api/src/types/content_key/overlay.rs index 5c88296ed..b811551ee 100644 --- a/ethportal-api/src/types/content_key/overlay.rs +++ b/ethportal-api/src/types/content_key/overlay.rs @@ -5,13 +5,13 @@ use quickcheck::{Arbitrary, Gen}; use crate::{ types::content_key::error::ContentKeyError, utils::bytes::{hex_decode, hex_encode, hex_encode_compact}, + RawContentKey, }; /// Types whose values represent keys to lookup content items in an overlay network. /// Keys are serializable. pub trait OverlayContentKey: - Into> - + TryFrom, Error = ContentKeyError> + TryFrom + Clone + fmt::Debug + fmt::Display @@ -25,7 +25,7 @@ pub trait OverlayContentKey: fn content_id(&self) -> [u8; 32]; /// Returns the bytes of the content key. - fn to_bytes(&self) -> Vec; + fn to_bytes(&self) -> RawContentKey; /// Returns the content key as a hex encoded "0x"-prefixed string. fn to_hex(&self) -> String { @@ -34,8 +34,8 @@ pub trait OverlayContentKey: /// Returns the content key from a hex encoded "0x"-prefixed string. fn from_hex(data: &str) -> anyhow::Result { - let bytes = hex_decode(&data.to_lowercase())?; - Ok(Self::try_from(bytes)?) + let bytes = hex_decode(data)?; + Ok(Self::try_from(bytes.into())?) } } @@ -67,10 +67,10 @@ impl Arbitrary for IdentityContentKey { } } -impl TryFrom> for IdentityContentKey { +impl TryFrom for IdentityContentKey { type Error = ContentKeyError; - fn try_from(value: Vec) -> Result { + fn try_from(value: RawContentKey) -> Result { // Require that length of input is equal to 32. if value.len() != 32 { return Err(ContentKeyError::InvalidLength { @@ -116,7 +116,7 @@ impl OverlayContentKey for IdentityContentKey { fn content_id(&self) -> [u8; 32] { self.value } - fn to_bytes(&self) -> Vec { - self.value.to_vec() + fn to_bytes(&self) -> RawContentKey { + self.value.to_vec().into() } } diff --git a/ethportal-api/src/types/content_key/state.rs b/ethportal-api/src/types/content_key/state.rs index 924a83a70..0382a56b7 100644 --- a/ethportal-api/src/types/content_key/state.rs +++ b/ethportal-api/src/types/content_key/state.rs @@ -8,7 +8,7 @@ use std::{fmt, hash::Hash}; use crate::{ types::{content_key::overlay::OverlayContentKey, state_trie::nibbles::Nibbles}, utils::bytes::hex_encode_compact, - ContentKeyError, + ContentKeyError, RawContentKey, }; // Prefixes for the different types of state content keys: @@ -70,7 +70,7 @@ impl OverlayContentKey for StateContentKey { sha256.finalize().into() } - fn to_bytes(&self) -> Vec { + fn to_bytes(&self) -> RawContentKey { let mut bytes: Vec = vec![]; match self { @@ -88,25 +88,25 @@ impl OverlayContentKey for StateContentKey { } } - bytes + bytes.into() } } impl From<&StateContentKey> for Vec { fn from(val: &StateContentKey) -> Self { - val.to_bytes() + val.to_bytes().to_vec() } } impl From for Vec { fn from(val: StateContentKey) -> Self { - val.to_bytes() + val.to_bytes().to_vec() } } -impl TryFrom> for StateContentKey { +impl TryFrom for StateContentKey { type Error = ContentKeyError; - fn try_from(value: Vec) -> Result { + fn try_from(value: RawContentKey) -> Result { let Some((&selector, key)) = value.split_first() else { return Err(ContentKeyError::from_decode_error( DecodeError::InvalidLengthPrefix { @@ -187,7 +187,7 @@ impl fmt::Display for StateContentKey { mod test { use std::{path::PathBuf, str::FromStr}; - use alloy_primitives::{keccak256, Address}; + use alloy_primitives::{bytes, keccak256, Address, Bytes}; use anyhow::Result; use rstest::rstest; use serde_yaml::Value; @@ -242,16 +242,20 @@ mod test { #[test] fn decode_empty_key_should_fail() { assert_eq!( - StateContentKey::try_from(vec![]).unwrap_err().to_string(), + StateContentKey::try_from(Bytes::new()) + .unwrap_err() + .to_string(), "Unable to decode key SSZ bytes 0x due to InvalidLengthPrefix { len: 0, expected: 1 }", ); } #[test] fn decode_key_with_invalid_selector_should_fail() { - let invalid_selector_content_key = "0x0024000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700005000000"; + let invalid_selector_content_key = bytes!( + "0024000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700005000000" + ); assert_eq!( - StateContentKey::try_from(hex_decode(invalid_selector_content_key).unwrap()) + StateContentKey::try_from(invalid_selector_content_key.clone()) .unwrap_err() .to_string(), format!("Unable to decode key SSZ bytes {invalid_selector_content_key} due to UnionSelectorInvalid(0)"), @@ -267,9 +271,9 @@ mod test { let yaml = yaml.as_mapping().unwrap(); let content_key_bytes = hex_decode(yaml["content_key"].as_str().unwrap())?; - let content_key = StateContentKey::try_from(content_key_bytes.clone())?; + let content_key = StateContentKey::try_from(Bytes::from(content_key_bytes.clone()))?; - assert_eq!(content_key.to_bytes(), content_key_bytes); + assert_eq!(content_key.to_bytes(), Bytes::from(content_key_bytes)); Ok(()) } @@ -300,7 +304,7 @@ mod test { let yaml = yaml.as_mapping().unwrap(); let content_key_bytes = hex_decode(yaml["content_key"].as_str().unwrap())?; - let content_key = StateContentKey::try_from(content_key_bytes)?; + let content_key = StateContentKey::try_from(Bytes::from(content_key_bytes))?; let expected_content_id = yaml_as_b256(&yaml["content_id"]); assert_eq!(B256::from(content_key.content_id()), expected_content_id); @@ -337,7 +341,7 @@ mod test { fn assert_content_key(value: &Value, expected_content_key: StateContentKey) -> Result<()> { assert_eq!( - StateContentKey::try_from(yaml_as_hex(value))?, + StateContentKey::try_from(Bytes::from(yaml_as_hex(value)))?, expected_content_key, "decoding from bytes {value:?} didn't match expected key {expected_content_key:?}" ); diff --git a/ethportal-api/src/types/portal_wire.rs b/ethportal-api/src/types/portal_wire.rs index 06729b91f..ba8f0e610 100644 --- a/ethportal-api/src/types/portal_wire.rs +++ b/ethportal-api/src/types/portal_wire.rs @@ -622,6 +622,7 @@ impl From for Value { #[allow(clippy::unwrap_used)] mod test { use super::*; + use alloy_primitives::bytes; use std::str::FromStr; use test_log::test; @@ -821,7 +822,7 @@ mod test { #[test] fn message_encoding_offer() { - let content_keys = vec![hex_decode("0x010203").unwrap().into()]; + let content_keys = vec![bytes!("010203")]; let offer = Offer { content_keys }; let offer = Message::Offer(offer); diff --git a/portalnet/src/find/query_info.rs b/portalnet/src/find/query_info.rs index 3f2f767e7..af6b4dd6c 100644 --- a/portalnet/src/find/query_info.rs +++ b/portalnet/src/find/query_info.rs @@ -73,7 +73,7 @@ impl QueryInfo { Request::FindNodes(FindNodes { distances }) } QueryType::FindContent { ref target, .. } => Request::FindContent(FindContent { - content_key: target.clone().into(), + content_key: target.clone().to_bytes().to_vec(), }), }; diff --git a/portalnet/src/gossip.rs b/portalnet/src/gossip.rs index 7686a36fa..7510a9b52 100644 --- a/portalnet/src/gossip.rs +++ b/portalnet/src/gossip.rs @@ -135,7 +135,7 @@ pub fn propagate_gossip_cross_thread( // change content keys to raw content keys let interested_content = interested_content .into_iter() - .map(|(key, value)| (key.into().into(), value)) + .map(|(key, value)| (key.to_bytes(), value)) .collect(); let offer_request = Request::PopulatedOffer(PopulatedOffer { content_items: interested_content, @@ -197,7 +197,7 @@ pub async fn trace_propagate_gossip_cross_thread for enr in interested_enrs.into_iter() { let (result_tx, mut result_rx) = tokio::sync::mpsc::unbounded_channel(); let offer_request = Request::PopulatedOfferWithResult(PopulatedOfferWithResult { - content_item: (content_key.clone().into().into(), data.clone()), + content_item: (content_key.clone().to_bytes(), data.clone()), result_tx, }); diff --git a/portalnet/src/overlay/protocol.rs b/portalnet/src/overlay/protocol.rs index 7c4b44c65..ddabec05f 100644 --- a/portalnet/src/overlay/protocol.rs +++ b/portalnet/src/overlay/protocol.rs @@ -94,7 +94,7 @@ impl< TStore: 'static + ContentStore + Send + Sync, > OverlayProtocol where - >>::Error: Debug + Display + Send, + >::Error: Debug + Display + Send, { pub async fn new( config: OverlayConfig, @@ -441,7 +441,7 @@ where let direction = RequestDirection::Outgoing { destination: enr.clone(), }; - let content_key = TContentKey::try_from(content_key).map_err(|err| { + let content_key = TContentKey::try_from(content_key.into()).map_err(|err| { OverlayRequestError::FailedValidation(format!( "Error decoding content key for received utp content: {err}" )) diff --git a/portalnet/src/overlay/service.rs b/portalnet/src/overlay/service.rs index 5067674b5..4c04e5cc9 100644 --- a/portalnet/src/overlay/service.rs +++ b/portalnet/src/overlay/service.rs @@ -165,7 +165,7 @@ impl< TStore: 'static + ContentStore + Send + Sync, > OverlayService where - >>::Error: Debug, + >::Error: Debug, { /// Spawns the overlay network service. /// @@ -192,7 +192,7 @@ where gossip_dropped: bool, ) -> UnboundedSender> where - >>::Error: Send, + >::Error: Send, { let (command_tx, command_rx) = mpsc::unbounded_channel(); let internal_command_tx = command_tx.clone(); @@ -756,7 +756,7 @@ where TMetric::distance(&node_id.raw(), &content_id) <= node.data_radius; if is_within_radius { let content_items: Vec<(RawContentKey, Vec)> = - vec![(content_key.clone().into().into(), content.clone())]; + vec![(content_key.clone().to_bytes(), content.clone())]; let offer_request = Request::PopulatedOffer(PopulatedOffer { content_items }); // if we have met the max outbound utp transfer limit continue the loop as we aren't @@ -933,7 +933,7 @@ where "Handling FindContent message", ); - let content_key = match (TContentKey::try_from)(request.content_key) { + let content_key = match (TContentKey::try_from)(request.content_key.into()) { Ok(key) => key, Err(_) => { return Err(OverlayRequestError::InvalidRequest( @@ -1030,7 +1030,7 @@ where let content_keys: Vec = request .content_keys .into_iter() - .map(|k| (TContentKey::try_from)(k.as_ssz_bytes())) + .map(|k| (TContentKey::try_from)(k.as_ssz_bytes().into())) .collect::, _>>() .map_err(|_| { OverlayRequestError::AcceptError( @@ -1654,7 +1654,7 @@ where } }; let request = Request::FindContent(FindContent { - content_key: content_key.clone().into(), + content_key: content_key.clone().to_bytes().to_vec(), }); let direction = RequestDirection::Outgoing { destination: fallback_peer.clone(), @@ -2022,7 +2022,7 @@ where let content_keys_offered: Result, TContentKey::Error> = content_keys_offered .into_iter() - .map(|key| TContentKey::try_from(key.as_ssz_bytes())) + .map(|key| TContentKey::try_from(key.as_ssz_bytes().into())) .collect(); let content_keys_offered: Vec = content_keys_offered diff --git a/trin-beacon/src/jsonrpc.rs b/trin-beacon/src/jsonrpc.rs index 03160f26a..9863bb839 100644 --- a/trin-beacon/src/jsonrpc.rs +++ b/trin-beacon/src/jsonrpc.rs @@ -289,7 +289,7 @@ async fn find_content( enr: discv5::enr::Enr, content_key: BeaconContentKey, ) -> Result { - match network.overlay.send_find_content(enr, content_key.into()).await { + match network.overlay.send_find_content(enr, content_key.to_bytes().to_vec()).await { Ok((content, utp_transfer)) => match content{ Content::ConnectionId(id) => Err(format!( "FindContent request returned a connection id ({id:?}) instead of conducting utp transfer." diff --git a/trin-beacon/src/storage.rs b/trin-beacon/src/storage.rs index e74b929c8..bf7448a79 100644 --- a/trin-beacon/src/storage.rs +++ b/trin-beacon/src/storage.rs @@ -1,3 +1,4 @@ +use alloy_primitives::Bytes; use ethportal_api::{ consensus::fork::ForkName, types::{ @@ -15,7 +16,7 @@ use ethportal_api::{ portal::PaginateLocalContentInfo, portal_wire::ProtocolId, }, - BeaconContentKey, OverlayContentKey, + BeaconContentKey, OverlayContentKey, RawContentKey, }; use r2d2::Pool; use r2d2_sqlite::{rusqlite, SqliteConnectionManager}; @@ -124,7 +125,7 @@ impl ContentStore for BeaconStorage { type Key = BeaconContentKey; fn get(&self, key: &Self::Key) -> Result>, ContentStoreError> { - let content_key: Vec = key.clone().into(); + let content_key: RawContentKey = key.clone().to_bytes(); let beacon_content_key = BeaconContentKey::try_from(content_key).map_err(|err| { ContentStoreError::InvalidData { message: format!("Error deserializing BeaconContentKey value: {err:?}"), @@ -216,7 +217,7 @@ impl ContentStore for BeaconStorage { &self, key: &Self::Key, ) -> Result { - let content_key: Vec = key.clone().into(); + let content_key: RawContentKey = key.clone().to_bytes(); let beacon_content_key = BeaconContentKey::try_from(content_key).map_err(|err| { ContentStoreError::InvalidData { message: format!("Error deserializing BeaconContentKey value: {err:?}"), @@ -378,7 +379,7 @@ impl BeaconStorage { value: &Vec, ) -> Result<(), ContentStoreError> { let content_id = key.content_id(); - let content_key: Vec = key.clone().into(); + let content_key: RawContentKey = key.clone().to_bytes(); match content_key.first() { Some(&LIGHT_CLIENT_BOOTSTRAP_KEY_PREFIX) => { @@ -597,11 +598,13 @@ impl BeaconStorage { let row: Vec = row.get(0)?; Ok(row) })? - .map(|row| BeaconContentKey::try_from(row?).map_err(ContentStoreError::ContentKey)) + .map(|row| { + BeaconContentKey::try_from(Bytes::from(row?)).map_err(ContentStoreError::ContentKey) + }) .collect(); match result?.first() { - Some(val) => Ok(Some(val.into())), + Some(val) => Ok(Some(val.to_bytes().to_vec())), None => Ok(None), } } diff --git a/trin-storage/src/versioned/id_indexed_v1/migration.rs b/trin-storage/src/versioned/id_indexed_v1/migration.rs index 9b0858f71..d06358f3c 100644 --- a/trin-storage/src/versioned/id_indexed_v1/migration.rs +++ b/trin-storage/src/versioned/id_indexed_v1/migration.rs @@ -109,7 +109,7 @@ mod tests { INSERT_QUERY_HISTORY, params![ content_id.as_slice(), - key, + key.to_vec(), value, distance_u32, content_size diff --git a/trin-storage/src/versioned/id_indexed_v1/store.rs b/trin-storage/src/versioned/id_indexed_v1/store.rs index 7e0417431..98c8b3580 100644 --- a/trin-storage/src/versioned/id_indexed_v1/store.rs +++ b/trin-storage/src/versioned/id_indexed_v1/store.rs @@ -202,7 +202,7 @@ impl IdIndexedV1Store { named_params! { ":content_id": content_id.to_vec() }, |row| { let bytes: Vec = row.get("content_key")?; - TContentKey::try_from(bytes).map_err(|e| { + TContentKey::try_from(bytes.into()).map_err(|e| { rusqlite::Error::FromSqlConversionFailure(0, Type::Blob, e.into()) }) }, @@ -256,7 +256,7 @@ impl IdIndexedV1Store { } let content_id = content_id.to_vec(); - let content_key = content_key.to_bytes(); + let content_key = content_key.to_bytes().to_vec(); let content_size = content_id.len() + content_key.len() + content_value.len(); let insert_timer = self.metrics.start_process_timer("insert"); @@ -337,7 +337,7 @@ impl IdIndexedV1Store { }, |row| { let bytes = row.get::<&str, Vec>("content_key")?; - TContentKey::try_from(bytes).map_err(|e| { + TContentKey::try_from(bytes.into()).map_err(|e| { rusqlite::Error::FromSqlConversionFailure(0, Type::Blob, e.into()) }) }, @@ -480,7 +480,7 @@ impl IdIndexedV1Store { let key_bytes: Vec = row.get("content_key")?; let value_bytes: Vec = row.get("content_value")?; let size: u64 = row.get("content_size")?; - TContentKey::try_from(key_bytes) + TContentKey::try_from(key_bytes.into()) .map(|key| (key, value_bytes, size)) .map_err(|e| { rusqlite::Error::FromSqlConversionFailure(0, Type::Blob, e.into()) @@ -611,7 +611,7 @@ mod tests { .get()? .execute(&sql::insert(&config.content_type), named_params! { ":content_id": id.as_slice(), - ":content_key": key.to_bytes(), + ":content_key": key.to_bytes().to_vec(), ":content_value": value, ":distance_short": config.distance_fn.distance(&config.node_id, &id).big_endian_u32(), ":content_size": content_size, diff --git a/trin-validation/src/header_validator.rs b/trin-validation/src/header_validator.rs index 03989e710..c994efdd4 100644 --- a/trin-validation/src/header_validator.rs +++ b/trin-validation/src/header_validator.rs @@ -223,7 +223,7 @@ mod test { use super::*; use std::{fs, str::FromStr}; - use alloy_primitives::{Address, Bloom, B256, U256}; + use alloy_primitives::{Address, Bloom, Bytes, B256, U256}; use alloy_rlp::Decodable; use rstest::*; use serde_json::{json, Value}; @@ -274,7 +274,7 @@ mod test { // Validate content_key decodes let raw_ck = obj.get("content_key").unwrap().as_str().unwrap(); let raw_ck = hex_decode(raw_ck).unwrap(); - let ck = HistoryContentKey::try_from(raw_ck).unwrap(); + let ck = HistoryContentKey::try_from(Bytes::from(raw_ck)).unwrap(); match ck { HistoryContentKey::BlockHeaderWithProof(_) => (), _ => panic!("Invalid test, content key decoded improperly"),