From 40ffc18739a9ff28a62a54d2318283ebc38f31f6 Mon Sep 17 00:00:00 2001 From: 0o-de-lally <1364012+0o-de-lally@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:27:22 -0400 Subject: [PATCH] can parse DiemAccountResource --- compatibility/src/version_five/event_v5.rs | 176 ++++++++++++++++----- 1 file changed, 140 insertions(+), 36 deletions(-) diff --git a/compatibility/src/version_five/event_v5.rs b/compatibility/src/version_five/event_v5.rs index b5b2603b7..0ca4e101d 100644 --- a/compatibility/src/version_five/event_v5.rs +++ b/compatibility/src/version_five/event_v5.rs @@ -1,40 +1,50 @@ -// Copyright © Diem Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. +// Copyright (c) The Diem Core Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::version_five::legacy_address_v5::LegacyAddressV5; -use serde::{Deserialize, Serialize}; -use std::fmt; +use hex::FromHex; +use serde::{de, ser, Deserialize, Serialize}; +use std::{ + convert::{TryFrom, TryInto}, + fmt, + str::FromStr, +}; + +use super::legacy_address_v5::LegacyAddressV5; /// A struct that represents a globally unique id for an Event stream that a user can listen to. /// By design, the lower part of EventKey is the same as account address. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct EventKey { - creation_number: u64, - account_address: LegacyAddressV5, -} +#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] + +pub struct EventKey([u8; EventKey::LENGTH]); impl EventKey { - pub fn new(creation_number: u64, account_address: LegacyAddressV5) -> Self { - Self { - creation_number, - account_address, - } + /// Construct a new EventKey from a byte array slice. + pub fn new(key: [u8; Self::LENGTH]) -> Self { + EventKey(key) + } + + /// The number of bytes in an EventKey. + pub const LENGTH: usize = LegacyAddressV5::LENGTH + 8; + + /// Get the byte representation of the event key. + pub fn as_bytes(&self) -> &[u8] { + &self.0 } /// Convert event key into a byte array. - pub fn to_bytes(&self) -> Vec { - bcs::to_bytes(&self).unwrap() + pub fn to_vec(&self) -> Vec { + self.0.to_vec() } /// Get the account address part in this event key pub fn get_creator_address(&self) -> LegacyAddressV5 { - self.account_address + LegacyAddressV5::try_from(&self.0[EventKey::LENGTH - LegacyAddressV5::LENGTH..]) + .expect("get_creator_address failed") } /// If this is the `ith` EventKey` created by `get_creator_address()`, return `i` pub fn get_creation_number(&self) -> u64 { - self.creation_number + u64::from_le_bytes(self.0[0..8].try_into().unwrap()) } // #[cfg(any(test, feature = "fuzzing"))] @@ -42,14 +52,18 @@ impl EventKey { // pub fn random() -> Self { // let mut rng = OsRng; // let salt = rng.next_u64(); - // EventKey::new(salt, AccountAddress::random()) + // EventKey::new_from_address(&AccountAddress::random(), salt) // } - pub fn size(&self) -> usize { - 8 /* u64 */ + 32 /* address */ + /// Create a unique handle by using an AccountAddress and a counter. + pub fn new_from_address(addr: &LegacyAddressV5, salt: u64) -> Self { + let mut output_bytes = [0; Self::LENGTH]; + let (lhs, rhs) = output_bytes.split_at_mut(8); + lhs.copy_from_slice(&salt.to_le_bytes()); + rhs.copy_from_slice(addr.as_ref()); + EventKey(output_bytes) } - /* pub fn from_hex>(hex: T) -> Result { <[u8; Self::LENGTH]>::from_hex(hex) .map_err(|_| EventKeyParseError) @@ -61,10 +75,8 @@ impl EventKey { .map_err(|_| EventKeyParseError) .map(Self) } - */ } -/* impl FromStr for EventKey { type Err = EventKeyParseError; @@ -72,9 +84,7 @@ impl FromStr for EventKey { EventKey::from_hex(s) } } -*/ -/* impl From for [u8; EventKey::LENGTH] { fn from(event_key: EventKey) -> Self { event_key.0 @@ -86,7 +96,44 @@ impl From<&EventKey> for [u8; EventKey::LENGTH] { event_key.0 } } -*/ + +impl ser::Serialize for EventKey { + fn serialize(&self, serializer: S) -> Result + where + S: ser::Serializer, + { + if serializer.is_human_readable() { + self.to_string().serialize(serializer) + } else { + // In order to preserve the Serde data model and help analysis tools, + // make sure to wrap our value in a container with the same name + // as the original type. + serializer.serialize_newtype_struct("EventKey", serde_bytes::Bytes::new(&self.0)) + } + } +} + +impl<'de> de::Deserialize<'de> for EventKey { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + use serde::de::Error; + + if deserializer.is_human_readable() { + let s = ::deserialize(deserializer)?; + EventKey::from_hex(s).map_err(D::Error::custom) + } else { + // See comment in serialize. + #[derive(::serde::Deserialize)] + #[serde(rename = "EventKey")] + struct Value<'a>(&'a [u8]); + + let value = Value::deserialize(deserializer)?; + Self::try_from(value.0).map_err(D::Error::custom) + } + } +} impl fmt::LowerHex for EventKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -94,7 +141,7 @@ impl fmt::LowerHex for EventKey { write!(f, "0x")?; } - for byte in self.to_bytes() { + for byte in &self.0 { write!(f, "{:02x}", byte)?; } @@ -108,7 +155,12 @@ impl fmt::Display for EventKey { } } -/* +impl fmt::Debug for EventKey { + fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result { + write!(f, "EventKey({:x})", self) + } +} + impl TryFrom<&[u8]> for EventKey { type Error = EventKeyParseError; @@ -117,7 +169,6 @@ impl TryFrom<&[u8]> for EventKey { Self::from_bytes(bytes) } } -*/ #[derive(Clone, Copy, Debug)] pub struct EventKeyParseError; @@ -156,16 +207,69 @@ impl EventHandleV5 { } // #[cfg(any(test, feature = "fuzzing"))] - // /// Create a random event key for testing - // pub fn random(count: u64) -> Self { + // pub fn count_mut(&mut self) -> &mut u64 { + // &mut self.count + // } + + // #[cfg(any(test, feature = "fuzzing"))] + // /// Create a random event handle for testing + // pub fn random_handle(count: u64) -> Self { // Self { // key: EventKey::random(), // count, // } // } - #[cfg(any(test, feature = "fuzzing"))] - pub fn count_mut(&mut self) -> &mut u64 { - &mut self.count + // #[cfg(any(test, feature = "fuzzing"))] + // /// Derive a unique handle by using an AccountAddress and a counter. + // pub fn new_from_address(addr: &AccountAddress, salt: u64) -> Self { + // Self { + // key: EventKey::new_from_address(addr, salt), + // count: 0, + // } + // } +} +#[cfg(test)] +mod tests { + use super::EventKey; + + #[test] + fn test_display_impls() { + let hex = "1000000000000000ca843279e3427144cead5e4d5999a3d0"; + + let key = EventKey::from_hex(hex).unwrap(); + + assert_eq!(format!("{}", key), hex); + assert_eq!(format!("{:x}", key), hex); + + assert_eq!(format!("{:#x}", key), format!("0x{}", hex)); + } + + #[test] + fn test_invalid_length() { + let bytes = vec![1; 123]; + EventKey::from_bytes(bytes).unwrap_err(); + } + + // #[test] + // fn test_deserialize_from_json_value() { + // let key = EventKey::random(); + // let json_value = serde_json::to_value(key).unwrap(); + // let key2: EventKey = serde_json::from_value(json_value).unwrap(); + // assert_eq!(key, key2); + // } + + #[test] + fn test_serde_json() { + let hex = "1000000000000000ca843279e3427144cead5e4d5999a3d0"; + let json_hex = "\"1000000000000000ca843279e3427144cead5e4d5999a3d0\""; + + let key = EventKey::from_hex(hex).unwrap(); + + let json = serde_json::to_string(&key).unwrap(); + let json_key: EventKey = serde_json::from_str(json_hex).unwrap(); + + assert_eq!(json, json_hex); + assert_eq!(key, json_key); } }