From eb535c8bf4f7f5d81571997a868507939d6a7779 Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Wed, 2 Oct 2024 23:26:50 +0100 Subject: [PATCH 1/7] update storage keys --- .../src/primitive/v1/asset/denom.rs | 32 ++- ...ests__storage_keys_have_not_changed-2.snap | 6 - .../src/accounts/state_ext.rs | 109 +++------- .../src/accounts/storage/keys.rs | 113 +++++++++++ .../src/accounts/storage/mod.rs | 1 + ...eys__tests__keys_should_not_change-2.snap} | 6 +- ...keys__tests__keys_should_not_change-3.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + .../astria-sequencer/src/address/state_ext.rs | 16 +- .../src/address/storage/keys.rs | 21 ++ .../src/address/storage/mod.rs | 1 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + ...ransaction_with_every_action_snapshot.snap | 56 +++--- ..._changes__app_finalize_block_snapshot.snap | 62 +++--- ...reaking_changes__app_genesis_snapshot.snap | 62 +++--- crates/astria-sequencer/src/app/state_ext.rs | 27 +-- .../astria-sequencer/src/app/storage/keys.rs | 35 ++++ .../astria-sequencer/src/app/storage/mod.rs | 1 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...keys__tests__keys_should_not_change-3.snap | 6 + ...keys__tests__keys_should_not_change-4.snap | 6 + ...keys__tests__keys_should_not_change-5.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + ...__tests__storage_keys_are_unchanged-2.snap | 5 - ...__tests__storage_keys_are_unchanged-3.snap | 5 - ...xt__tests__storage_keys_are_unchanged.snap | 5 - .../astria-sequencer/src/assets/state_ext.rs | 152 ++++---------- .../src/assets/storage/keys.rs | 118 +++++++++++ .../src/assets/storage/mod.rs | 1 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...keys__tests__keys_should_not_change-3.snap | 6 + ...keys__tests__keys_should_not_change-4.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + .../src/authority/state_ext.rs | 32 ++- .../src/authority/storage/keys.rs | 26 +++ .../src/authority/storage/mod.rs | 1 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...keys__tests__keys_should_not_change-3.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + ...ests__storage_keys_have_not_changed-2.snap | 6 - ...ests__storage_keys_have_not_changed-3.snap | 6 - ...ests__storage_keys_have_not_changed-4.snap | 6 - ..._tests__storage_keys_have_not_changed.snap | 6 - .../astria-sequencer/src/bridge/state_ext.rs | 189 ++++-------------- .../src/bridge/storage/keys.rs | 148 ++++++++++++++ .../src/bridge/storage/mod.rs | 1 + ...eys__tests__keys_should_not_change-10.snap | 6 + ...eys__tests__keys_should_not_change-11.snap | 6 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...keys__tests__keys_should_not_change-3.snap | 6 + ...keys__tests__keys_should_not_change-4.snap | 6 + ...keys__tests__keys_should_not_change-5.snap | 6 + ...keys__tests__keys_should_not_change-6.snap | 6 + ...keys__tests__keys_should_not_change-7.snap | 6 + ...keys__tests__keys_should_not_change-8.snap | 6 + ...keys__tests__keys_should_not_change-9.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + crates/astria-sequencer/src/grpc/state_ext.rs | 36 +--- .../astria-sequencer/src/grpc/storage/keys.rs | 63 ++++++ .../astria-sequencer/src/grpc/storage/mod.rs | 1 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...keys__tests__keys_should_not_change-3.snap | 6 + ...keys__tests__keys_should_not_change-4.snap | 6 + ...keys__tests__keys_should_not_change-5.snap | 6 + ...keys__tests__keys_should_not_change-6.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + ...ests__storage_keys_have_not_changed-2.snap | 5 - ..._tests__storage_keys_have_not_changed.snap | 5 - crates/astria-sequencer/src/ibc/state_ext.rs | 97 +++------ .../astria-sequencer/src/ibc/storage/keys.rs | 76 +++++++ .../astria-sequencer/src/ibc/storage/mod.rs | 1 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...keys__tests__keys_should_not_change-3.snap | 6 + ...keys__tests__keys_should_not_change-4.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + crates/astria-sequencer/src/lib.rs | 1 - .../src/sequence/state_ext.rs | 27 ++- .../src/sequence/storage/keys.rs | 22 ++ .../src/sequence/storage/mod.rs | 1 + ...keys__tests__keys_should_not_change-2.snap | 6 + ...__keys__tests__keys_should_not_change.snap | 6 + crates/astria-sequencer/src/storage/keys.rs | 101 ++++++++++ crates/astria-sequencer/src/storage/mod.rs | 1 + crates/astria-sequencer/src/storage_keys.rs | 60 ------ 85 files changed, 1273 insertions(+), 713 deletions(-) delete mode 100644 crates/astria-sequencer/src/accounts/snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed-2.snap create mode 100644 crates/astria-sequencer/src/accounts/storage/keys.rs rename crates/astria-sequencer/src/accounts/{snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed.snap => storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-2.snap} (50%) create mode 100644 crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-3.snap create mode 100644 crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change.snap create mode 100644 crates/astria-sequencer/src/address/storage/keys.rs create mode 100644 crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change.snap create mode 100644 crates/astria-sequencer/src/app/storage/keys.rs create mode 100644 crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-3.snap create mode 100644 crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-4.snap create mode 100644 crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-5.snap create mode 100644 crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change.snap delete mode 100644 crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-2.snap delete mode 100644 crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-3.snap delete mode 100644 crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged.snap create mode 100644 crates/astria-sequencer/src/assets/storage/keys.rs create mode 100644 crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-3.snap create mode 100644 crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-4.snap create mode 100644 crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change.snap create mode 100644 crates/astria-sequencer/src/authority/storage/keys.rs create mode 100644 crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-3.snap create mode 100644 crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change.snap delete mode 100644 crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-2.snap delete mode 100644 crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-3.snap delete mode 100644 crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-4.snap delete mode 100644 crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/keys.rs create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-10.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-11.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-3.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-4.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-5.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-6.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-7.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-8.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-9.snap create mode 100644 crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change.snap create mode 100644 crates/astria-sequencer/src/grpc/storage/keys.rs create mode 100644 crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-3.snap create mode 100644 crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-4.snap create mode 100644 crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-5.snap create mode 100644 crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-6.snap create mode 100644 crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change.snap delete mode 100644 crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed-2.snap delete mode 100644 crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed.snap create mode 100644 crates/astria-sequencer/src/ibc/storage/keys.rs create mode 100644 crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-3.snap create mode 100644 crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-4.snap create mode 100644 crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change.snap create mode 100644 crates/astria-sequencer/src/sequence/storage/keys.rs create mode 100644 crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change-2.snap create mode 100644 crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change.snap create mode 100644 crates/astria-sequencer/src/storage/keys.rs delete mode 100644 crates/astria-sequencer/src/storage_keys.rs diff --git a/crates/astria-core/src/primitive/v1/asset/denom.rs b/crates/astria-core/src/primitive/v1/asset/denom.rs index ec685dba7d..017c690ff9 100644 --- a/crates/astria-core/src/primitive/v1/asset/denom.rs +++ b/crates/astria-core/src/primitive/v1/asset/denom.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, collections::VecDeque, str::FromStr, }; @@ -140,6 +141,27 @@ impl<'a> From<&'a IbcPrefixed> for IbcPrefixed { } } +impl<'a> From<&'a IbcPrefixed> for Cow<'a, IbcPrefixed> { + fn from(ibc_prefixed: &'a IbcPrefixed) -> Self { + Cow::Borrowed(ibc_prefixed) + } +} + +impl<'a> From<&'a TracePrefixed> for Cow<'a, IbcPrefixed> { + fn from(trace_prefixed: &'a TracePrefixed) -> Self { + Cow::Owned(trace_prefixed.to_ibc_prefixed()) + } +} + +impl<'a> From<&'a Denom> for Cow<'a, IbcPrefixed> { + fn from(value: &'a Denom) -> Self { + match value { + Denom::TracePrefixed(trace_prefixed) => Cow::from(trace_prefixed), + Denom::IbcPrefixed(ibc_prefixed) => Cow::from(ibc_prefixed), + } + } +} + impl FromStr for Denom { type Err = ParseDenomError; @@ -543,20 +565,22 @@ pub struct IbcPrefixed { } impl IbcPrefixed { + pub const LENGTH: usize = 32; + #[must_use] - pub fn new(id: [u8; 32]) -> Self { + pub const fn new(id: [u8; Self::LENGTH]) -> Self { Self { id, } } #[must_use] - pub fn as_bytes(&self) -> &[u8; 32] { + pub const fn as_bytes(&self) -> &[u8; Self::LENGTH] { &self.id } #[must_use] - pub fn display_len(&self) -> usize { + pub const fn display_len(&self) -> usize { 68 // "ibc/" + 64 hex characters } } @@ -586,7 +610,7 @@ impl FromStr for IbcPrefixed { if segments.next().is_some() { return Err(ParseIbcPrefixedError::too_many_segments()); } - let id = <[u8; 32]>::from_hex(hex).map_err(Self::Err::hex)?; + let id = <[u8; Self::LENGTH]>::from_hex(hex).map_err(Self::Err::hex)?; Ok(Self { id, }) diff --git a/crates/astria-sequencer/src/accounts/snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed-2.snap b/crates/astria-sequencer/src/accounts/snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed-2.snap deleted file mode 100644 index 9b2ee0652b..0000000000 --- a/crates/astria-sequencer/src/accounts/snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed-2.snap +++ /dev/null @@ -1,6 +0,0 @@ ---- -source: crates/astria-sequencer/src/accounts/state_ext.rs -assertion_line: 855 -expression: nonce_storage_key(&address) ---- -accounts/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/nonce diff --git a/crates/astria-sequencer/src/accounts/state_ext.rs b/crates/astria-sequencer/src/accounts/state_ext.rs index 1aca12616c..c62fbc2d9d 100644 --- a/crates/astria-sequencer/src/accounts/state_ext.rs +++ b/crates/astria-sequencer/src/accounts/state_ext.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, fmt::Display, pin::Pin, task::{ @@ -27,44 +28,21 @@ use futures::Stream; use pin_project_lite::pin_project; use tracing::instrument; -use super::storage; +use super::storage::{ + self, + keys::{ + balance_key, + balance_prefix, + extract_asset_from_key, + nonce_key, + TRANSFER_BASE_FEE_KEY, + }, +}; use crate::{ accounts::AddressBytes, storage::StoredValue, }; -const ACCOUNTS_PREFIX: &str = "accounts"; -const TRANSFER_BASE_FEE_STORAGE_KEY: &str = "transferfee"; - -struct StorageKey<'a, T>(&'a T); -impl<'a, T: AddressBytes> std::fmt::Display for StorageKey<'a, T> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(ACCOUNTS_PREFIX)?; - f.write_str("/")?; - for byte in self.0.address_bytes() { - f.write_fmt(format_args!("{byte:02x}"))?; - } - Ok(()) - } -} - -fn balance_storage_key<'a, TAddress, TAsset>(address: &TAddress, asset: &'a TAsset) -> String -where - TAddress: AddressBytes, - asset::IbcPrefixed: From<&'a TAsset>, -{ - let asset: asset::IbcPrefixed = asset.into(); - format!( - "{}/balance/{}", - StorageKey(address), - crate::storage_keys::hunks::Asset::from(asset) - ) -} - -fn nonce_storage_key(address: &T) -> String { - format!("{}/nonce", StorageKey(address)) -} - pin_project! { /// A stream of IBC prefixed assets for a given account. pub(crate) struct AccountAssetsStream { @@ -141,15 +119,6 @@ where } } -fn extract_asset_from_key(s: &str) -> Result { - Ok(s.strip_prefix("accounts/") - .and_then(|s| s.split_once("/balance/").map(|(_, asset)| asset)) - .ok_or_eyre("failed to strip prefix from account balance key")? - .parse::() - .context("failed to parse storage key suffix as address hunk")? - .get()) -} - #[async_trait] pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { #[instrument(skip_all)] @@ -157,7 +126,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { &self, address: &T, ) -> AccountAssetsStream { - let prefix = format!("{}/balance/", StorageKey(address)); + let prefix = balance_prefix(address); AccountAssetsStream { underlying: self.prefix_keys(&prefix), } @@ -168,7 +137,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { &self, address: &T, ) -> AccountAssetBalancesStream { - let prefix = format!("{}/balance/", StorageKey(address)); + let prefix = balance_prefix(address); AccountAssetBalancesStream { underlying: self.prefix_raw(&prefix), } @@ -183,10 +152,10 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { where TAddress: AddressBytes, TAsset: Sync + Display, - asset::IbcPrefixed: From<&'a TAsset> + Send + Sync, + &'a TAsset: Into>, { let Some(bytes) = self - .get_raw(&balance_storage_key(address, asset)) + .get_raw(&balance_key(address, asset)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw account balance from state")? @@ -201,7 +170,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { #[instrument(skip_all)] async fn get_account_nonce(&self, address: &T) -> Result { let bytes = self - .get_raw(&nonce_storage_key(address)) + .get_raw(&nonce_key(address)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw account nonce from state")?; @@ -217,7 +186,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { #[instrument(skip_all)] async fn get_transfer_base_fee(&self) -> Result { let bytes = self - .get_raw(TRANSFER_BASE_FEE_STORAGE_KEY) + .get_raw(TRANSFER_BASE_FEE_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw transfer base fee from state")?; @@ -244,12 +213,12 @@ pub(crate) trait StateWriteExt: StateWrite { where TAddress: AddressBytes, TAsset: Display, - asset::IbcPrefixed: From<&'a TAsset> + Send, + &'a TAsset: Into>, { let bytes = StoredValue::from(storage::Balance::from(balance)) .serialize() .wrap_err("failed to serialize balance")?; - self.put_raw(balance_storage_key(address, asset), bytes); + self.put_raw(balance_key(address, asset), bytes); Ok(()) } @@ -258,7 +227,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Nonce::from(nonce)) .serialize() .wrap_err("failed to serialize nonce")?; - self.put_raw(nonce_storage_key(address), bytes); + self.put_raw(nonce_key(address), bytes); Ok(()) } @@ -272,7 +241,7 @@ pub(crate) trait StateWriteExt: StateWrite { where TAddress: AddressBytes, TAsset: Sync + Display, - asset::IbcPrefixed: From<&'a TAsset> + Send, + &'a TAsset: Into>, { let balance = self .get_account_balance(address, asset) @@ -299,7 +268,7 @@ pub(crate) trait StateWriteExt: StateWrite { where TAddress: AddressBytes, TAsset: Sync + Display, - asset::IbcPrefixed: From<&'a TAsset> + Send, + &'a TAsset: Into>, { let balance = self .get_account_balance(address, asset) @@ -321,7 +290,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .wrap_err("failed to serialize fee")?; - self.put_raw(TRANSFER_BASE_FEE_STORAGE_KEY.to_string(), bytes); + self.put_raw(TRANSFER_BASE_FEE_KEY.to_string(), bytes); Ok(()) } } @@ -330,17 +299,10 @@ impl StateWriteExt for T {} #[cfg(test)] mod tests { - use astria_core::primitive::v1::Address; use cnidarium::StateDelta; use futures::TryStreamExt as _; - use insta::assert_snapshot; - use super::{ - balance_storage_key, - nonce_storage_key, - StateReadExt as _, - StateWriteExt as _, - }; + use super::*; use crate::{ assets::{ StateReadExt as _, @@ -352,14 +314,15 @@ mod tests { }, }; - fn asset_0() -> astria_core::primitive::v1::asset::Denom { + fn asset_0() -> asset::Denom { "asset_0".parse().unwrap() } - fn asset_1() -> astria_core::primitive::v1::asset::Denom { + fn asset_1() -> asset::Denom { "asset_1".parse().unwrap() } - fn asset_2() -> astria_core::primitive::v1::asset::Denom { + + fn asset_2() -> asset::Denom { "asset_2".parse().unwrap() } @@ -834,20 +797,4 @@ mod tests { let retrieved_fee = state.get_transfer_base_fee().await.unwrap(); assert_eq!(retrieved_fee, 123); } - - #[test] - fn storage_keys_have_not_changed() { - let address: Address = "astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm" - .parse() - .unwrap(); - let asset = "an/asset/with/a/prefix" - .parse::() - .unwrap(); - assert_eq!( - balance_storage_key(&address, &asset), - balance_storage_key(&address, &asset.to_ibc_prefixed()) - ); - assert_snapshot!(balance_storage_key(&address, &asset)); - assert_snapshot!(nonce_storage_key(&address)); - } } diff --git a/crates/astria-sequencer/src/accounts/storage/keys.rs b/crates/astria-sequencer/src/accounts/storage/keys.rs new file mode 100644 index 0000000000..f3f1a90349 --- /dev/null +++ b/crates/astria-sequencer/src/accounts/storage/keys.rs @@ -0,0 +1,113 @@ +use std::borrow::Cow; + +use astria_core::primitive::v1::asset::IbcPrefixed; +use astria_eyre::eyre::{ + ContextCompat as _, + Result, + WrapErr as _, +}; + +use crate::{ + accounts::AddressBytes, + storage::keys::{ + AddressPrefixer, + Asset, + }, +}; + +pub(in crate::accounts) const TRANSFER_BASE_FEE_KEY: &str = "accounts/transfer_base_fee"; +const COMPONENT_PREFIX: &str = "accounts/"; +const BALANCE_PREFIX: &str = "balance/"; +const NONCE: &str = "nonce"; + +/// Example: `accounts/0101....0101/balance/`. +/// |40 hex chars| +pub(in crate::accounts) fn balance_prefix(address: &TAddress) -> String { + format!( + "{}/{BALANCE_PREFIX}", + AddressPrefixer::new(COMPONENT_PREFIX, address) + ) +} + +/// Example: `accounts/0101....0101/balance/0202....0202`. +/// |40 hex chars| |64 hex chars| +pub(in crate::accounts) fn balance_key<'a, TAddress, TAsset>( + address: &TAddress, + asset: &'a TAsset, +) -> String +where + TAddress: AddressBytes, + &'a TAsset: Into>, +{ + format!( + "{}/{BALANCE_PREFIX}{}", + AddressPrefixer::new(COMPONENT_PREFIX, address), + Asset::from(asset) + ) +} + +/// Example: `accounts/0101....0101/nonce`. +/// |40 hex chars| +pub(in crate::accounts) fn nonce_key(address: &TAddress) -> String { + format!( + "{}/{NONCE}", + AddressPrefixer::new(COMPONENT_PREFIX, address) + ) +} + +pub(in crate::accounts) fn extract_asset_from_key(key: &str) -> Result { + Ok(key + .strip_prefix(COMPONENT_PREFIX) + .and_then(|s| s.split_once(BALANCE_PREFIX).map(|(_, asset)| asset)) + .wrap_err("failed to strip prefix from account balance key")? + .parse::() + .wrap_err("failed to parse storage key suffix as address hunk")? + .get()) +} + +#[cfg(test)] +mod tests { + use astria_core::primitive::v1::{ + asset::Denom, + Address, + }; + + use super::*; + + fn address() -> Address { + "astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm" + .parse() + .unwrap() + } + + fn asset() -> Denom { + "an/asset/with/a/prefix".parse().unwrap() + } + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(TRANSFER_BASE_FEE_KEY); + insta::assert_snapshot!(balance_key(&address(), &asset())); + insta::assert_snapshot!(nonce_key(&address())); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(TRANSFER_BASE_FEE_KEY.starts_with(COMPONENT_PREFIX)); + assert!(balance_key(&address(), &asset()).starts_with(COMPONENT_PREFIX)); + assert!(nonce_key(&address()).starts_with(COMPONENT_PREFIX)); + } + + #[test] + fn balance_prefix_should_be_prefix_of_balance_key() { + assert!(balance_key(&address(), &asset()).starts_with(&balance_prefix(&address()))); + } + + #[test] + fn should_extract_asset_from_key() { + let asset = IbcPrefixed::new([2; 32]); + let key = balance_key(&[1; 20], &asset); + let recovered_asset = extract_asset_from_key(&key).unwrap(); + assert_eq!(asset, recovered_asset); + } +} diff --git a/crates/astria-sequencer/src/accounts/storage/mod.rs b/crates/astria-sequencer/src/accounts/storage/mod.rs index 5fb23de750..8d61ec9f93 100644 --- a/crates/astria-sequencer/src/accounts/storage/mod.rs +++ b/crates/astria-sequencer/src/accounts/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(crate) use values::Value; diff --git a/crates/astria-sequencer/src/accounts/snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed.snap b/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-2.snap similarity index 50% rename from crates/astria-sequencer/src/accounts/snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed.snap rename to crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-2.snap index 9125e1ba51..a22a1eff3a 100644 --- a/crates/astria-sequencer/src/accounts/snapshots/astria_sequencer__accounts__state_ext__tests__storage_keys_have_not_changed.snap +++ b/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-2.snap @@ -1,6 +1,6 @@ --- -source: crates/astria-sequencer/src/accounts/state_ext.rs -assertion_line: 854 -expression: "balance_storage_key(&address, &asset)" +source: crates/astria-sequencer/src/accounts/storage/keys.rs +assertion_line: 90 +expression: "balance_key(&address(), &asset())" --- accounts/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/balance/be429a02d00837245167a2616674a979a2ac6f9806468b48a975b156ad711320 diff --git a/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-3.snap b/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-3.snap new file mode 100644 index 0000000000..ad35152310 --- /dev/null +++ b/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change-3.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/accounts/storage/keys.rs +assertion_line: 91 +expression: nonce_key(&address()) +--- +accounts/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/nonce diff --git a/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..a57562a2da --- /dev/null +++ b/crates/astria-sequencer/src/accounts/storage/snapshots/astria_sequencer__accounts__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/accounts/storage/keys.rs +assertion_line: 79 +expression: TRANSFER_BASE_FEE_KEY +--- +accounts/transfer_base_fee diff --git a/crates/astria-sequencer/src/address/state_ext.rs b/crates/astria-sequencer/src/address/state_ext.rs index a0c074777b..6d1a4ea6d9 100644 --- a/crates/astria-sequencer/src/address/state_ext.rs +++ b/crates/astria-sequencer/src/address/state_ext.rs @@ -18,12 +18,15 @@ use cnidarium::{ }; use tracing::instrument; -use super::storage; +use super::storage::{ + self, + keys::{ + BASE_PREFIX_KEY, + IBC_COMPAT_PREFIX_KEY, + }, +}; use crate::storage::StoredValue; -const BASE_PREFIX_KEY: &str = "prefixes/base"; -const IBC_COMPAT_PREFIX_KEY: &str = "prefixes/ibc-compat"; - #[async_trait] pub(crate) trait StateReadExt: StateRead { async fn ensure_base_prefix(&self, address: &Address) -> Result<()> { @@ -111,10 +114,7 @@ impl StateWriteExt for T {} mod tests { use cnidarium::StateDelta; - use super::{ - StateReadExt as _, - StateWriteExt as _, - }; + use super::*; #[tokio::test] async fn put_and_get_base_prefix() { diff --git a/crates/astria-sequencer/src/address/storage/keys.rs b/crates/astria-sequencer/src/address/storage/keys.rs new file mode 100644 index 0000000000..84c2878629 --- /dev/null +++ b/crates/astria-sequencer/src/address/storage/keys.rs @@ -0,0 +1,21 @@ +pub(in crate::address) const BASE_PREFIX_KEY: &str = "address/prefixes/base"; +pub(in crate::address) const IBC_COMPAT_PREFIX_KEY: &str = "address/prefixes/ibc_compat"; + +#[cfg(test)] +mod tests { + use super::*; + + const COMPONENT_PREFIX: &str = "address/"; + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(BASE_PREFIX_KEY); + insta::assert_snapshot!(IBC_COMPAT_PREFIX_KEY); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(BASE_PREFIX_KEY.starts_with(COMPONENT_PREFIX)); + assert!(IBC_COMPAT_PREFIX_KEY.starts_with(COMPONENT_PREFIX)); + } +} diff --git a/crates/astria-sequencer/src/address/storage/mod.rs b/crates/astria-sequencer/src/address/storage/mod.rs index 9d97b02d12..66527bffe6 100644 --- a/crates/astria-sequencer/src/address/storage/mod.rs +++ b/crates/astria-sequencer/src/address/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(super) use values::AddressPrefix; diff --git a/crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..78e5051afb --- /dev/null +++ b/crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/address/storage/keys.rs +assertion_line: 11 +expression: IBC_COMPAT_PREFIX_KEY +--- +address/prefixes/ibc_compat diff --git a/crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..d0121e06ae --- /dev/null +++ b/crates/astria-sequencer/src/address/storage/snapshots/astria_sequencer__address__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/address/storage/keys.rs +assertion_line: 10 +expression: BASE_PREFIX_KEY +--- +address/prefixes/base diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_execute_transaction_with_every_action_snapshot.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_execute_transaction_with_every_action_snapshot.snap index ce1e424533..9a12120603 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_execute_transaction_with_every_action_snapshot.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_execute_transaction_with_every_action_snapshot.snap @@ -4,36 +4,36 @@ assertion_line: 350 expression: app.app_hash.as_bytes() --- [ - 152, - 102, + 46, + 84, + 67, 37, - 231, - 116, - 83, - 54, - 99, - 99, - 61, - 18, - 167, - 133, - 246, - 157, - 153, + 30, + 92, + 103, + 183, + 154, + 29, + 114, + 107, + 103, + 229, + 25, + 81, 240, - 12, - 160, - 204, - 116, - 164, - 109, - 125, - 163, - 141, - 253, + 121, + 107, 161, - 54, 116, - 76, - 131 + 132, + 237, + 185, + 19, + 131, + 158, + 123, + 159, + 135, + 225, + 49 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_finalize_block_snapshot.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_finalize_block_snapshot.snap index 991e89c41c..52747634df 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_finalize_block_snapshot.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_finalize_block_snapshot.snap @@ -1,39 +1,39 @@ --- source: crates/astria-sequencer/src/app/tests_breaking_changes.rs -assertion_line: 159 +assertion_line: 157 expression: app.app_hash.as_bytes() --- [ - 185, - 5, - 77, - 15, - 122, - 4, - 105, - 34, - 166, - 43, - 138, - 143, - 70, - 189, - 121, - 106, - 150, + 244, + 153, + 66, + 220, + 111, + 24, + 58, + 153, + 188, + 179, + 48, 128, - 112, - 142, - 173, - 98, - 148, - 152, - 2, - 3, - 100, + 150, + 160, + 50, + 71, + 140, + 9, + 221, + 209, 153, - 98, - 154, - 77, - 199 + 208, + 201, + 80, + 120, + 125, + 127, + 166, + 40, + 194, + 137, + 58 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_genesis_snapshot.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_genesis_snapshot.snap index 30a896d96f..d2d20d765a 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_genesis_snapshot.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_genesis_snapshot.snap @@ -1,39 +1,39 @@ --- source: crates/astria-sequencer/src/app/tests_breaking_changes.rs -assertion_line: 78 +assertion_line: 77 expression: app.app_hash.as_bytes() --- [ - 216, - 255, - 55, - 240, - 253, - 150, - 85, - 195, - 135, - 107, - 242, - 140, - 90, - 79, 175, - 169, - 15, - 89, - 132, - 159, - 196, - 65, - 113, - 174, - 207, - 46, - 107, + 8, + 235, 126, - 6, - 1, - 239, - 84 + 36, + 103, + 51, + 226, + 57, + 13, + 183, + 36, + 101, + 208, + 164, + 55, + 40, + 192, + 16, + 146, + 192, + 255, + 74, + 185, + 53, + 106, + 3, + 193, + 131, + 151, + 129, + 54 ] diff --git a/crates/astria-sequencer/src/app/state_ext.rs b/crates/astria-sequencer/src/app/state_ext.rs index cd51110c84..621fbb6db5 100644 --- a/crates/astria-sequencer/src/app/state_ext.rs +++ b/crates/astria-sequencer/src/app/state_ext.rs @@ -14,18 +14,18 @@ use cnidarium::{ use tendermint::Time; use tracing::instrument; -use super::storage; +use super::storage::{ + self, + keys::{ + storage_version_by_height_key, + BLOCK_HEIGHT_KEY, + BLOCK_TIMESTAMP_KEY, + CHAIN_ID_KEY, + REVISION_NUMBER_KEY, + }, +}; use crate::storage::StoredValue; -const CHAIN_ID_KEY: &str = "chain_id"; -const REVISION_NUMBER_KEY: &str = "revision_number"; -const BLOCK_HEIGHT_KEY: &str = "block_height"; -const BLOCK_TIMESTAMP_KEY: &str = "block_timestamp"; - -fn storage_version_by_height_key(height: u64) -> Vec { - format!("storage_version/{height}").into() -} - #[async_trait] pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] @@ -180,13 +180,8 @@ fn revision_number_from_chain_id(chain_id: &str) -> u64 { #[cfg(test)] mod tests { use cnidarium::StateDelta; - use tendermint::Time; - use super::{ - revision_number_from_chain_id, - StateReadExt as _, - StateWriteExt as _, - }; + use super::*; #[test] fn revision_number_from_chain_id_regex() { diff --git a/crates/astria-sequencer/src/app/storage/keys.rs b/crates/astria-sequencer/src/app/storage/keys.rs new file mode 100644 index 0000000000..45fe20f1a4 --- /dev/null +++ b/crates/astria-sequencer/src/app/storage/keys.rs @@ -0,0 +1,35 @@ +pub(in crate::app) const CHAIN_ID_KEY: &str = "app/chain_id"; +pub(in crate::app) const REVISION_NUMBER_KEY: &str = "app/revision_number"; +pub(in crate::app) const BLOCK_HEIGHT_KEY: &str = "app/block_height"; +pub(in crate::app) const BLOCK_TIMESTAMP_KEY: &str = "app/block_timestamp"; + +pub(in crate::app) fn storage_version_by_height_key(height: u64) -> Vec { + format!("app/storage_version/{height}").into_bytes() +} + +#[cfg(test)] +mod tests { + use telemetry::display::base64; + + use super::*; + + const COMPONENT_PREFIX: &str = "app/"; + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(CHAIN_ID_KEY); + insta::assert_snapshot!(REVISION_NUMBER_KEY); + insta::assert_snapshot!(BLOCK_HEIGHT_KEY); + insta::assert_snapshot!(BLOCK_TIMESTAMP_KEY); + insta::assert_snapshot!(base64(storage_version_by_height_key(42))); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(CHAIN_ID_KEY.starts_with(COMPONENT_PREFIX)); + assert!(REVISION_NUMBER_KEY.starts_with(COMPONENT_PREFIX)); + assert!(BLOCK_HEIGHT_KEY.starts_with(COMPONENT_PREFIX)); + assert!(BLOCK_TIMESTAMP_KEY.starts_with(COMPONENT_PREFIX)); + assert!(storage_version_by_height_key(42).starts_with(COMPONENT_PREFIX.as_bytes())); + } +} diff --git a/crates/astria-sequencer/src/app/storage/mod.rs b/crates/astria-sequencer/src/app/storage/mod.rs index 34b0d24cda..964bad6a6f 100644 --- a/crates/astria-sequencer/src/app/storage/mod.rs +++ b/crates/astria-sequencer/src/app/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(crate) use values::Value; diff --git a/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..5ef5391478 --- /dev/null +++ b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/app/storage/keys.rs +assertion_line: 21 +expression: REVISION_NUMBER_KEY +--- +app/revision_number diff --git a/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-3.snap b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-3.snap new file mode 100644 index 0000000000..4c70738ab6 --- /dev/null +++ b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-3.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/app/storage/keys.rs +assertion_line: 22 +expression: BLOCK_HEIGHT_KEY +--- +app/block_height diff --git a/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-4.snap b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-4.snap new file mode 100644 index 0000000000..ac8904c633 --- /dev/null +++ b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-4.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/app/storage/keys.rs +assertion_line: 23 +expression: BLOCK_TIMESTAMP_KEY +--- +app/block_timestamp diff --git a/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-5.snap b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-5.snap new file mode 100644 index 0000000000..0eb8b2d1f0 --- /dev/null +++ b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change-5.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/app/storage/keys.rs +assertion_line: 24 +expression: base64(storage_version_by_height_key(42)) +--- +YXBwL3N0b3JhZ2VfdmVyc2lvbi80Mg== diff --git a/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..d90a517589 --- /dev/null +++ b/crates/astria-sequencer/src/app/storage/snapshots/astria_sequencer__app__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/app/storage/keys.rs +assertion_line: 18 +expression: CHAIN_ID_KEY +--- +app/chain_id diff --git a/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-2.snap b/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-2.snap deleted file mode 100644 index 8c31993c79..0000000000 --- a/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-2.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/astria-sequencer/src/assets/state_ext.rs -expression: block_fees_key(&trace_prefixed) ---- -block_fees/ce072174ebc356c6ead681d61ab417ee72fdedd8155eb76478ece374bb04dc1d diff --git a/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-3.snap b/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-3.snap deleted file mode 100644 index a3e273ee76..0000000000 --- a/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged-3.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/astria-sequencer/src/assets/state_ext.rs -expression: fee_asset_key(trace_prefixed) ---- -fee_asset/ce072174ebc356c6ead681d61ab417ee72fdedd8155eb76478ece374bb04dc1d diff --git a/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged.snap b/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged.snap deleted file mode 100644 index 3ad210d6a2..0000000000 --- a/crates/astria-sequencer/src/assets/snapshots/astria_sequencer__assets__state_ext__tests__storage_keys_are_unchanged.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/astria-sequencer/src/assets/state_ext.rs -expression: asset_storage_key(asset) ---- -asset/be429a02d00837245167a2616674a979a2ac6f9806468b48a975b156ad711320 diff --git a/crates/astria-sequencer/src/assets/state_ext.rs b/crates/astria-sequencer/src/assets/state_ext.rs index a8cea703cd..9a3788d0b6 100644 --- a/crates/astria-sequencer/src/assets/state_ext.rs +++ b/crates/astria-sequencer/src/assets/state_ext.rs @@ -1,3 +1,8 @@ +use std::{ + borrow::Cow, + fmt::Display, +}; + use astria_core::primitive::v1::asset; use astria_eyre::{ anyhow_to_eyre, @@ -20,46 +25,23 @@ use tendermint::abci::{ }; use tracing::instrument; -use super::storage; +use super::storage::{ + self, + keys::{ + asset_key, + block_fees_key, + extract_asset_from_block_fees_key, + extract_asset_from_fee_asset_key, + fee_asset_key, + BLOCK_FEES_PREFIX, + FEE_ASSET_PREFIX, + NATIVE_ASSET_KEY, + }, +}; use crate::storage::StoredValue; -const BLOCK_FEES_PREFIX: &str = "block_fees/"; -const FEE_ASSET_PREFIX: &str = "fee_asset/"; -const NATIVE_ASSET_KEY: &str = "nativeasset"; - -fn asset_storage_key<'a, TAsset>(asset: &'a TAsset) -> String -where - asset::IbcPrefixed: From<&'a TAsset>, -{ - format!("asset/{}", crate::storage_keys::hunks::Asset::from(asset)) -} - -fn block_fees_key<'a, TAsset>(asset: &'a TAsset) -> String -where - asset::IbcPrefixed: From<&'a TAsset>, -{ - format!( - "{BLOCK_FEES_PREFIX}{}", - crate::storage_keys::hunks::Asset::from(asset) - ) -} - -fn fee_asset_key<'a, TAsset>(asset: &'a TAsset) -> String -where - asset::IbcPrefixed: From<&'a TAsset>, -{ - format!( - "{FEE_ASSET_PREFIX}{}", - crate::storage_keys::hunks::Asset::from(asset) - ) -} - /// Creates `abci::Event` of kind `tx.fees` for sequencer fee reporting -fn construct_tx_fee_event( - asset: &T, - fee_amount: u128, - action_type: String, -) -> Event { +fn construct_tx_fee_event(asset: &T, fee_amount: u128, action_type: String) -> Event { Event::new( "tx.fees", [ @@ -93,10 +75,10 @@ pub(crate) trait StateReadExt: StateRead { async fn has_ibc_asset<'a, TAsset>(&self, asset: &'a TAsset) -> Result where TAsset: Sync, - asset::IbcPrefixed: From<&'a TAsset>, + &'a TAsset: Into>, { Ok(self - .get_raw(&asset_storage_key(asset)) + .get_raw(&asset_key(asset)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw asset from state")? @@ -109,7 +91,7 @@ pub(crate) trait StateReadExt: StateRead { asset: &asset::IbcPrefixed, ) -> Result> { let Some(bytes) = self - .get_raw(&asset_storage_key(asset)) + .get_raw(&asset_key(asset)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw asset from state")? @@ -128,19 +110,10 @@ pub(crate) trait StateReadExt: StateRead { async fn get_block_fees(&self) -> Result> { let mut fees = Vec::new(); - let mut stream = - std::pin::pin!(self.nonverifiable_prefix_raw(BLOCK_FEES_PREFIX.as_bytes())); + let mut stream = std::pin::pin!(self.nonverifiable_prefix_raw(BLOCK_FEES_PREFIX)); while let Some(Ok((key, bytes))) = stream.next().await { - // if the key isn't of the form `block_fees/{asset_id}`, then we have a bug - // in `put_block_fees` - let suffix = key - .strip_prefix(BLOCK_FEES_PREFIX.as_bytes()) - .expect("prefix must always be present"); - let asset = std::str::from_utf8(suffix) - .wrap_err("key suffix was not utf8 encoded; this should not happen")? - .parse::() - .wrap_err("failed to parse storage key suffix as address hunk")? - .get(); + let asset = + extract_asset_from_block_fees_key(&key).wrap_err("failed to extract asset")?; let fee = StoredValue::deserialize(&bytes) .and_then(|value| storage::Fee::try_from(value).map(u128::from)) @@ -156,10 +129,10 @@ pub(crate) trait StateReadExt: StateRead { async fn is_allowed_fee_asset<'a, TAsset>(&self, asset: &'a TAsset) -> Result where TAsset: Sync, - asset::IbcPrefixed: From<&'a TAsset>, + &'a TAsset: Into>, { Ok(self - .nonverifiable_get_raw(fee_asset_key(asset).as_bytes()) + .nonverifiable_get_raw(&fee_asset_key(asset)) .await .map_err(anyhow_to_eyre) .wrap_err("failed to read raw fee asset from state")? @@ -170,18 +143,10 @@ pub(crate) trait StateReadExt: StateRead { async fn get_allowed_fee_assets(&self) -> Result> { let mut assets = Vec::new(); - let mut stream = std::pin::pin!(self.nonverifiable_prefix_raw(FEE_ASSET_PREFIX.as_bytes())); + let mut stream = std::pin::pin!(self.nonverifiable_prefix_raw(FEE_ASSET_PREFIX)); while let Some(Ok((key, _))) = stream.next().await { - // if the key isn't of the form `fee_asset/{asset_id}`, then we have a bug - // in `put_allowed_fee_asset` - let suffix = key - .strip_prefix(FEE_ASSET_PREFIX.as_bytes()) - .expect("prefix must always be present"); - let asset = std::str::from_utf8(suffix) - .wrap_err("key suffix was not utf8 encoded; this should not happen")? - .parse::() - .wrap_err("failed to parse storage key suffix as address hunk")? - .get(); + let asset = + extract_asset_from_fee_asset_key(&key).wrap_err("failed to extract asset")?; assets.push(asset); } @@ -204,7 +169,7 @@ pub(crate) trait StateWriteExt: StateWrite { #[instrument(skip_all)] fn put_ibc_asset(&mut self, asset: asset::TracePrefixed) -> Result<()> { - let key = asset_storage_key(&asset); + let key = asset_key(&asset); let bytes = StoredValue::from(storage::TracePrefixedDenom::from(&asset)) .serialize() .wrap_err("failed to serialize ibc asset")?; @@ -221,14 +186,14 @@ pub(crate) trait StateWriteExt: StateWrite { action_type: String, ) -> Result<()> where - TAsset: Sync + std::fmt::Display, - asset::IbcPrefixed: From<&'a TAsset>, + TAsset: Sync + Display, + &'a TAsset: Into>, { let tx_fee_event = construct_tx_fee_event(asset, amount, action_type); let block_fees_key = block_fees_key(asset); let current_amount = self - .nonverifiable_get_raw(block_fees_key.as_bytes()) + .nonverifiable_get_raw(&block_fees_key) .await .map_err(anyhow_to_eyre) .wrap_err("failed to read raw block fees from state")? @@ -246,7 +211,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(new_amount)) .serialize() .wrap_err("failed to serialize block fees")?; - self.nonverifiable_put_raw(block_fees_key.into(), bytes); + self.nonverifiable_put_raw(block_fees_key, bytes); self.record(tx_fee_event); @@ -255,8 +220,7 @@ pub(crate) trait StateWriteExt: StateWrite { #[instrument(skip_all)] async fn clear_block_fees(&mut self) { - let mut stream = - std::pin::pin!(self.nonverifiable_prefix_raw(BLOCK_FEES_PREFIX.as_bytes())); + let mut stream = std::pin::pin!(self.nonverifiable_prefix_raw(BLOCK_FEES_PREFIX)); while let Some(Ok((key, _))) = stream.next().await { self.nonverifiable_delete(key); } @@ -265,20 +229,20 @@ pub(crate) trait StateWriteExt: StateWrite { #[instrument(skip_all)] fn delete_allowed_fee_asset<'a, TAsset>(&mut self, asset: &'a TAsset) where - asset::IbcPrefixed: From<&'a TAsset>, + &'a TAsset: Into>, { - self.nonverifiable_delete(fee_asset_key(asset).into()); + self.nonverifiable_delete(fee_asset_key(asset)); } #[instrument(skip_all)] fn put_allowed_fee_asset<'a, TAsset>(&mut self, asset: &'a TAsset) -> Result<()> where - asset::IbcPrefixed: From<&'a TAsset>, + &'a TAsset: Into>, { let bytes = StoredValue::Unit .serialize() .context("failed to serialize unit for allowed fee asset")?; - self.nonverifiable_put_raw(fee_asset_key(asset).into(), bytes); + self.nonverifiable_put_raw(fee_asset_key(asset), bytes); Ok(()) } } @@ -289,16 +253,9 @@ impl StateWriteExt for T {} mod tests { use std::collections::HashSet; - use astria_core::primitive::v1::asset; use cnidarium::StateDelta; - use super::{ - asset_storage_key, - block_fees_key, - fee_asset_key, - StateReadExt as _, - StateWriteExt as _, - }; + use super::*; fn asset() -> asset::Denom { "asset".parse().unwrap() @@ -643,31 +600,4 @@ mod tests { "delete for allowed fee asset did not behave as expected" ); } - - #[test] - fn storage_keys_are_unchanged() { - let asset = "an/asset/with/a/prefix" - .parse::() - .unwrap(); - assert_eq!( - asset_storage_key(&asset), - asset_storage_key(&asset.to_ibc_prefixed()), - ); - insta::assert_snapshot!(asset_storage_key(&asset)); - - let trace_prefixed = "a/denom/with/a/prefix" - .parse::() - .unwrap(); - assert_eq!( - block_fees_key(&trace_prefixed), - block_fees_key(&trace_prefixed.to_ibc_prefixed()), - ); - insta::assert_snapshot!(block_fees_key(&trace_prefixed)); - - assert_eq!( - fee_asset_key(&trace_prefixed), - fee_asset_key(&trace_prefixed.to_ibc_prefixed()), - ); - insta::assert_snapshot!(fee_asset_key(&trace_prefixed)); - } } diff --git a/crates/astria-sequencer/src/assets/storage/keys.rs b/crates/astria-sequencer/src/assets/storage/keys.rs new file mode 100644 index 0000000000..85894de1d9 --- /dev/null +++ b/crates/astria-sequencer/src/assets/storage/keys.rs @@ -0,0 +1,118 @@ +use std::borrow::Cow; + +use astria_core::primitive::v1::asset::IbcPrefixed; +use astria_eyre::eyre::{ + bail, + ContextCompat, + Result, + WrapErr, +}; + +use crate::storage::keys::Asset; + +pub(in crate::assets) const NATIVE_ASSET_KEY: &str = "assets/native_asset"; +pub(in crate::assets) const BLOCK_FEES_PREFIX: &[u8] = b"assets/block_fees/"; +pub(in crate::assets) const FEE_ASSET_PREFIX: &[u8] = b"assets/fee_asset/"; + +/// Example: `assets/0101....0101`. +/// |64 hex chars| +pub(in crate::assets) fn asset_key<'a, TAsset>(asset: &'a TAsset) -> String +where + &'a TAsset: Into>, +{ + format!("assets/{}", Asset::from(asset)) +} + +pub(in crate::assets) fn fee_asset_key<'a, TAsset>(asset: &'a TAsset) -> Vec +where + &'a TAsset: Into>, +{ + [FEE_ASSET_PREFIX, Asset::from(asset).as_bytes()].concat() +} + +pub(in crate::assets) fn block_fees_key<'a, TAsset>(asset: &'a TAsset) -> Vec +where + &'a TAsset: Into>, +{ + [BLOCK_FEES_PREFIX, Asset::from(asset).as_bytes()].concat() +} + +pub(in crate::assets) fn extract_asset_from_fee_asset_key(key: &[u8]) -> Result { + extract_asset_from_key(key, FEE_ASSET_PREFIX) + .wrap_err("failed to extract asset from fee asset key") +} + +pub(in crate::assets) fn extract_asset_from_block_fees_key(key: &[u8]) -> Result { + extract_asset_from_key(key, BLOCK_FEES_PREFIX) + .wrap_err("failed to extract asset from fee asset key") +} + +fn extract_asset_from_key(key: &[u8], prefix: &[u8]) -> Result { + let suffix = key.strip_prefix(prefix).wrap_err_with(|| { + format!( + "key `{}` did not have prefix `{}`", + telemetry::display::hex(key), + telemetry::display::hex(prefix) + ) + })?; + if suffix.len() != IbcPrefixed::LENGTH { + bail!( + "suffix `{}` of key `{}` is not {} bytes", + telemetry::display::hex(suffix), + telemetry::display::hex(key), + IbcPrefixed::LENGTH + ); + } + let mut buffer = [0; IbcPrefixed::LENGTH]; + buffer.copy_from_slice(suffix); + Ok(IbcPrefixed::new(buffer)) +} + +#[cfg(test)] +mod tests { + use astria_core::primitive::v1::asset::Denom; + use telemetry::display::base64; + + use super::*; + + const COMPONENT_PREFIX: &str = "assets/"; + + fn asset() -> Denom { + "an/asset/with/a/prefix".parse().unwrap() + } + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(NATIVE_ASSET_KEY); + insta::assert_snapshot!(asset_key(&asset())); + insta::assert_snapshot!(base64(&fee_asset_key(&asset()))); + insta::assert_snapshot!(base64(&block_fees_key(&asset()))); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(NATIVE_ASSET_KEY.starts_with(COMPONENT_PREFIX)); + assert!(asset_key(&asset()).starts_with(COMPONENT_PREFIX)); + assert!(fee_asset_key(&asset()).starts_with(COMPONENT_PREFIX.as_bytes())); + assert!(block_fees_key(&asset()).starts_with(COMPONENT_PREFIX.as_bytes())); + } + + #[test] + fn prefixes_should_be_prefixes_of_relevant_keys() { + assert!(fee_asset_key(&asset()).starts_with(FEE_ASSET_PREFIX)); + assert!(block_fees_key(&asset()).starts_with(BLOCK_FEES_PREFIX)); + } + + #[test] + fn should_extract_asset_from_key() { + let asset = IbcPrefixed::new([1; 32]); + + let key = fee_asset_key(&asset); + let recovered_asset = extract_asset_from_fee_asset_key(&key).unwrap(); + assert_eq!(asset, recovered_asset); + + let key = block_fees_key(&asset); + let recovered_asset = extract_asset_from_block_fees_key(&key).unwrap(); + assert_eq!(asset, recovered_asset); + } +} diff --git a/crates/astria-sequencer/src/assets/storage/mod.rs b/crates/astria-sequencer/src/assets/storage/mod.rs index 84bbe13ac8..8551a44c91 100644 --- a/crates/astria-sequencer/src/assets/storage/mod.rs +++ b/crates/astria-sequencer/src/assets/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(crate) use values::Value; diff --git a/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..29c1e1d461 --- /dev/null +++ b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/assets/storage/keys.rs +assertion_line: 85 +expression: asset_key(&asset()) +--- +assets/be429a02d00837245167a2616674a979a2ac6f9806468b48a975b156ad711320 diff --git a/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-3.snap b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-3.snap new file mode 100644 index 0000000000..68d7ccdfdc --- /dev/null +++ b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-3.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/assets/storage/keys.rs +assertion_line: 86 +expression: base64(&fee_asset_key(&asset())) +--- +YXNzZXRzL2ZlZV9hc3NldC++QpoC0Ag3JFFnomFmdKl5oqxvmAZGi0ipdbFWrXETIA== diff --git a/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-4.snap b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-4.snap new file mode 100644 index 0000000000..02dec404d8 --- /dev/null +++ b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change-4.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/assets/storage/keys.rs +assertion_line: 87 +expression: base64(&block_fees_key(&asset())) +--- +YXNzZXRzL2Jsb2NrX2ZlZXMvvkKaAtAINyRRZ6JhZnSpeaKsb5gGRotIqXWxVq1xEyA= diff --git a/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..b7c28d8f3f --- /dev/null +++ b/crates/astria-sequencer/src/assets/storage/snapshots/astria_sequencer__assets__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/assets/storage/keys.rs +assertion_line: 84 +expression: NATIVE_ASSET_KEY +--- +assets/native_asset diff --git a/crates/astria-sequencer/src/authority/state_ext.rs b/crates/astria-sequencer/src/authority/state_ext.rs index 38df2f7c5b..575434c80d 100644 --- a/crates/astria-sequencer/src/authority/state_ext.rs +++ b/crates/astria-sequencer/src/authority/state_ext.rs @@ -17,7 +17,14 @@ use cnidarium::{ use tracing::instrument; use super::{ - storage, + storage::{ + self, + keys::{ + SUDO_KEY, + VALIDATOR_SET_KEY, + VALIDATOR_UPDATES_KEY, + }, + }, ValidatorSet, }; use crate::{ @@ -25,16 +32,12 @@ use crate::{ storage::StoredValue, }; -const SUDO_STORAGE_KEY: &str = "sudo"; -const VALIDATOR_SET_STORAGE_KEY: &str = "valset"; -const VALIDATOR_UPDATES_KEY: &[u8] = b"valupdates"; - #[async_trait] pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_sudo_address(&self) -> Result<[u8; ADDRESS_LEN]> { let Some(bytes) = self - .get_raw(SUDO_STORAGE_KEY) + .get_raw(SUDO_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw sudo key from state")? @@ -50,7 +53,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_validator_set(&self) -> Result { let Some(bytes) = self - .get_raw(VALIDATOR_SET_STORAGE_KEY) + .get_raw(VALIDATOR_SET_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw validator set from state")? @@ -89,7 +92,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::AddressBytes::from(&address)) .serialize() .wrap_err("failed to serialize sudo address")?; - self.put_raw(SUDO_STORAGE_KEY.to_string(), bytes); + self.put_raw(SUDO_KEY.to_string(), bytes); Ok(()) } @@ -98,7 +101,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::ValidatorSet::from(&validator_set)) .serialize() .wrap_err("failed to serialize validator set")?; - self.put_raw(VALIDATOR_SET_STORAGE_KEY.to_string(), bytes); + self.put_raw(VALIDATOR_SET_KEY.to_string(), bytes); Ok(()) } @@ -121,19 +124,12 @@ impl StateWriteExt for T {} #[cfg(test)] mod tests { - use astria_core::{ - primitive::v1::ADDRESS_LEN, - protocol::transaction::v1alpha1::action::ValidatorUpdate, - }; + use astria_core::protocol::transaction::v1alpha1::action::ValidatorUpdate; use cnidarium::StateDelta; - use super::{ - StateReadExt as _, - StateWriteExt as _, - }; + use super::*; use crate::{ address::StateWriteExt as _, - authority::ValidatorSet, test_utils::{ verification_key, ASTRIA_PREFIX, diff --git a/crates/astria-sequencer/src/authority/storage/keys.rs b/crates/astria-sequencer/src/authority/storage/keys.rs new file mode 100644 index 0000000000..e83bc957d1 --- /dev/null +++ b/crates/astria-sequencer/src/authority/storage/keys.rs @@ -0,0 +1,26 @@ +pub(in crate::authority) const SUDO_KEY: &str = "authority/sudo"; +pub(in crate::authority) const VALIDATOR_SET_KEY: &str = "authority/validator_set"; +pub(in crate::authority) const VALIDATOR_UPDATES_KEY: &[u8] = b"authority/validator_updates"; + +#[cfg(test)] +mod tests { + use telemetry::display::base64; + + use super::*; + + const COMPONENT_PREFIX: &str = "authority/"; + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(SUDO_KEY); + insta::assert_snapshot!(VALIDATOR_SET_KEY); + insta::assert_snapshot!(base64(VALIDATOR_UPDATES_KEY)); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(SUDO_KEY.starts_with(COMPONENT_PREFIX)); + assert!(VALIDATOR_SET_KEY.starts_with(COMPONENT_PREFIX)); + assert!(VALIDATOR_UPDATES_KEY.starts_with(COMPONENT_PREFIX.as_bytes())); + } +} diff --git a/crates/astria-sequencer/src/authority/storage/mod.rs b/crates/astria-sequencer/src/authority/storage/mod.rs index 9d81d20d1a..cb52a74a3d 100644 --- a/crates/astria-sequencer/src/authority/storage/mod.rs +++ b/crates/astria-sequencer/src/authority/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(crate) use values::Value; diff --git a/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..2bbd4fa8d0 --- /dev/null +++ b/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/authority/storage/keys.rs +assertion_line: 16 +expression: VALIDATOR_SET_STORAGE_KEY +--- +authority/validator_set diff --git a/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-3.snap b/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-3.snap new file mode 100644 index 0000000000..aab9cc3e2e --- /dev/null +++ b/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change-3.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/authority/storage/keys.rs +assertion_line: 17 +expression: base64(VALIDATOR_UPDATES_KEY) +--- +YXV0aG9yaXR5L3ZhbGlkYXRvcl91cGRhdGVz diff --git a/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..a046006094 --- /dev/null +++ b/crates/astria-sequencer/src/authority/storage/snapshots/astria_sequencer__authority__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/authority/storage/keys.rs +assertion_line: 15 +expression: SUDO_STORAGE_KEY +--- +authority/sudo diff --git a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-2.snap b/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-2.snap deleted file mode 100644 index ff90ccd2fd..0000000000 --- a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-2.snap +++ /dev/null @@ -1,6 +0,0 @@ ---- -source: crates/astria-sequencer/src/bridge/state_ext.rs -assertion_line: 812 -expression: asset_id_storage_key(&address) ---- -bridgeacc/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/assetid diff --git a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-3.snap b/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-3.snap deleted file mode 100644 index 0ce9c34aab..0000000000 --- a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-3.snap +++ /dev/null @@ -1,6 +0,0 @@ ---- -source: crates/astria-sequencer/src/bridge/state_ext.rs -assertion_line: 813 -expression: bridge_account_sudo_address_storage_key(&address) ---- -bsudo/1c0c490f1b5528d8173c5de46d131160e4b2c0c3 diff --git a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-4.snap b/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-4.snap deleted file mode 100644 index 408ac4f2d5..0000000000 --- a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed-4.snap +++ /dev/null @@ -1,6 +0,0 @@ ---- -source: crates/astria-sequencer/src/bridge/state_ext.rs -assertion_line: 814 -expression: bridge_account_withdrawer_address_storage_key(&address) ---- -bwithdrawer/1c0c490f1b5528d8173c5de46d131160e4b2c0c3 diff --git a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed.snap b/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed.snap deleted file mode 100644 index 8f75044410..0000000000 --- a/crates/astria-sequencer/src/bridge/snapshots/astria_sequencer__bridge__state_ext__tests__storage_keys_have_not_changed.snap +++ /dev/null @@ -1,6 +0,0 @@ ---- -source: crates/astria-sequencer/src/bridge/state_ext.rs -assertion_line: 811 -expression: rollup_id_storage_key(&address) ---- -bridgeacc/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/rollupid diff --git a/crates/astria-sequencer/src/bridge/state_ext.rs b/crates/astria-sequencer/src/bridge/state_ext.rs index 867ac9ecdd..7424131fdc 100644 --- a/crates/astria-sequencer/src/bridge/state_ext.rs +++ b/crates/astria-sequencer/src/bridge/state_ext.rs @@ -28,111 +28,28 @@ use tracing::{ instrument, }; -use super::storage; +use super::storage::{ + self, + keys::{ + asset_id_key, + bridge_account_sudo_address_key, + bridge_account_withdrawal_event_key, + bridge_account_withdrawer_address_key, + deposit_key, + last_transaction_id_for_bridge_account_key, + rollup_id_key, + BRIDGE_LOCK_BYTE_COST_MULTIPLIER_KEY, + BRIDGE_SUDO_CHANGE_FEE_KEY, + DEPOSITS_EPHEMERAL_KEY, + INIT_BRIDGE_ACCOUNT_BASE_FEE_KEY, + }, +}; use crate::{ accounts::AddressBytes, address, storage::StoredValue, }; -const BRIDGE_ACCOUNT_PREFIX: &str = "bridgeacc"; -const BRIDGE_ACCOUNT_SUDO_PREFIX: &str = "bsudo"; -const BRIDGE_ACCOUNT_WITHDRAWER_PREFIX: &str = "bwithdrawer"; -const DEPOSITS_EPHEMERAL_KEY: &str = "deposits"; -const DEPOSIT_PREFIX: &[u8] = b"deposit/"; -const INIT_BRIDGE_ACCOUNT_BASE_FEE_STORAGE_KEY: &str = "initbridgeaccfee"; -const BRIDGE_LOCK_BYTE_COST_MULTIPLIER_STORAGE_KEY: &str = "bridgelockmultiplier"; -const BRIDGE_SUDO_CHANGE_FEE_STORAGE_KEY: &str = "bridgesudofee"; - -struct BridgeAccountKey<'a, T> { - prefix: &'static str, - address: &'a T, -} - -impl<'a, T> std::fmt::Display for BridgeAccountKey<'a, T> -where - T: AddressBytes, -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.prefix)?; - f.write_str("/")?; - for byte in self.address.address_bytes() { - f.write_fmt(format_args!("{byte:02x}"))?; - } - Ok(()) - } -} - -fn rollup_id_storage_key(address: &T) -> String { - format!( - "{}/rollupid", - BridgeAccountKey { - prefix: BRIDGE_ACCOUNT_PREFIX, - address - } - ) -} - -fn asset_id_storage_key(address: &T) -> String { - format!( - "{}/assetid", - BridgeAccountKey { - prefix: BRIDGE_ACCOUNT_PREFIX, - address - } - ) -} - -fn deposit_storage_key(block_hash: &[u8; 32], rollup_id: &RollupId) -> Vec { - [DEPOSIT_PREFIX, block_hash, rollup_id.as_ref()].concat() -} - -fn bridge_account_sudo_address_storage_key(address: &T) -> String { - format!( - "{}", - BridgeAccountKey { - prefix: BRIDGE_ACCOUNT_SUDO_PREFIX, - address - } - ) -} - -fn bridge_account_withdrawer_address_storage_key(address: &T) -> String { - format!( - "{}", - BridgeAccountKey { - prefix: BRIDGE_ACCOUNT_WITHDRAWER_PREFIX, - address - } - ) -} - -fn bridge_account_withdrawal_event_storage_key( - address: &T, - withdrawal_event_id: &str, -) -> String { - format!( - "{}/withdrawalevent/{}", - BridgeAccountKey { - prefix: BRIDGE_ACCOUNT_PREFIX, - address - }, - withdrawal_event_id - ) -} - -fn last_transaction_id_for_bridge_account_storage_key(address: &T) -> Vec { - format!( - "{}/lasttx", - BridgeAccountKey { - prefix: BRIDGE_ACCOUNT_PREFIX, - address - } - ) - .as_bytes() - .to_vec() -} - #[async_trait] pub(crate) trait StateReadExt: StateRead + address::StateReadExt { #[instrument(skip_all)] @@ -147,7 +64,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { address: &T, ) -> Result> { let Some(bytes) = self - .get_raw(&rollup_id_storage_key(address)) + .get_raw(&rollup_id_key(address)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw account rollup ID from state")? @@ -169,7 +86,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { address: &T, ) -> Result { let bytes = self - .get_raw(&asset_id_storage_key(address)) + .get_raw(&asset_id_key(address)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw bridge account asset ID from state")? @@ -187,7 +104,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { bridge_address: &T, ) -> Result> { let Some(bytes) = self - .get_raw(&bridge_account_sudo_address_storage_key(bridge_address)) + .get_raw(&bridge_account_sudo_address_key(bridge_address)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw bridge account sudo address from state")? @@ -210,9 +127,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { bridge_address: &T, ) -> Result> { let Some(bytes) = self - .get_raw(&bridge_account_withdrawer_address_storage_key( - bridge_address, - )) + .get_raw(&bridge_account_withdrawer_address_key(bridge_address)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw bridge account withdrawer address from state")? @@ -241,7 +156,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { rollup_id: &RollupId, ) -> Result> { let Some(bytes) = self - .nonverifiable_get_raw(&deposit_storage_key(block_hash, rollup_id)) + .nonverifiable_get_raw(&deposit_key(block_hash, rollup_id)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw deposits from state")? @@ -256,7 +171,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { #[instrument(skip_all)] async fn get_init_bridge_account_base_fee(&self) -> Result { let bytes = self - .get_raw(INIT_BRIDGE_ACCOUNT_BASE_FEE_STORAGE_KEY) + .get_raw(INIT_BRIDGE_ACCOUNT_BASE_FEE_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw init bridge account base fee from state")? @@ -269,7 +184,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { #[instrument(skip_all)] async fn get_bridge_lock_byte_cost_multiplier(&self) -> Result { let bytes = self - .get_raw(BRIDGE_LOCK_BYTE_COST_MULTIPLIER_STORAGE_KEY) + .get_raw(BRIDGE_LOCK_BYTE_COST_MULTIPLIER_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw bridge lock byte cost multiplier from state")? @@ -282,7 +197,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { #[instrument(skip_all)] async fn get_bridge_sudo_change_base_fee(&self) -> Result { let bytes = self - .get_raw(BRIDGE_SUDO_CHANGE_FEE_STORAGE_KEY) + .get_raw(BRIDGE_SUDO_CHANGE_FEE_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw bridge sudo change fee from state")? @@ -298,7 +213,7 @@ pub(crate) trait StateReadExt: StateRead + address::StateReadExt { address: &T, ) -> Result> { let Some(bytes) = self - .nonverifiable_get_raw(&last_transaction_id_for_bridge_account_storage_key(address)) + .nonverifiable_get_raw(&last_transaction_id_for_bridge_account_key(address)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw last transaction hash for bridge account from state")? @@ -325,7 +240,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::RollupId::from(&rollup_id)) .serialize() .context("failed to serialize bridge account rollup id")?; - self.put_raw(rollup_id_storage_key(address), bytes); + self.put_raw(rollup_id_key(address), bytes); Ok(()) } @@ -343,7 +258,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::IbcPrefixedDenom::from(&ibc)) .serialize() .wrap_err("failed to serialize asset ids")?; - self.put_raw(asset_id_storage_key(address), bytes); + self.put_raw(asset_id_key(address), bytes); Ok(()) } @@ -360,10 +275,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::AddressBytes::from(&sudo_address)) .serialize() .context("failed to serialize bridge account sudo address")?; - self.put_raw( - bridge_account_sudo_address_storage_key(bridge_address), - bytes, - ); + self.put_raw(bridge_account_sudo_address_key(bridge_address), bytes); Ok(()) } @@ -380,10 +292,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::AddressBytes::from(&withdrawer_address)) .serialize() .context("failed to serialize bridge account sudo address")?; - self.put_raw( - bridge_account_withdrawer_address_storage_key(bridge_address), - bytes, - ); + self.put_raw(bridge_account_withdrawer_address_key(bridge_address), bytes); Ok(()) } @@ -394,7 +303,7 @@ pub(crate) trait StateWriteExt: StateWrite { withdrawal_event_id: &str, block_num: u64, ) -> Result<()> { - let key = bridge_account_withdrawal_event_storage_key(address, withdrawal_event_id); + let key = bridge_account_withdrawal_event_key(address, withdrawal_event_id); // Check if the withdrawal ID has already been used, if so return an error. let bytes = self @@ -438,7 +347,7 @@ pub(crate) trait StateWriteExt: StateWrite { all_deposits: HashMap>, ) -> Result<()> { for (rollup_id, deposits) in all_deposits { - let key = deposit_storage_key(block_hash, &rollup_id); + let key = deposit_key(block_hash, &rollup_id); let bytes = StoredValue::from(storage::Deposits::from(deposits.iter())) .serialize() .context("failed to serialize bridge deposit")?; @@ -452,7 +361,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .context("failed to serialize bridge account base fee")?; - self.put_raw(INIT_BRIDGE_ACCOUNT_BASE_FEE_STORAGE_KEY.to_string(), bytes); + self.put_raw(INIT_BRIDGE_ACCOUNT_BASE_FEE_KEY.to_string(), bytes); Ok(()) } @@ -461,10 +370,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .context("failed to serialize bridge lock byte cost multiplier")?; - self.put_raw( - BRIDGE_LOCK_BYTE_COST_MULTIPLIER_STORAGE_KEY.to_string(), - bytes, - ); + self.put_raw(BRIDGE_LOCK_BYTE_COST_MULTIPLIER_KEY.to_string(), bytes); Ok(()) } @@ -473,7 +379,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .context("failed to serialize bridge sudo change base fee")?; - self.put_raw(BRIDGE_SUDO_CHANGE_FEE_STORAGE_KEY.to_string(), bytes); + self.put_raw(BRIDGE_SUDO_CHANGE_FEE_KEY.to_string(), bytes); Ok(()) } @@ -486,10 +392,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::TransactionId::from(&tx_id)) .serialize() .context("failed to serialize transaction hash for bridge account")?; - self.nonverifiable_put_raw( - last_transaction_id_for_bridge_account_storage_key(address), - bytes, - ); + self.nonverifiable_put_raw(last_transaction_id_for_bridge_account_key(address), bytes); Ok(()) } } @@ -498,17 +401,7 @@ impl StateWriteExt for T {} #[cfg(test)] mod tests { - use astria_core::{ - primitive::v1::{ - asset, - Address, - RollupId, - TransactionId, - }, - sequencerblock::v1alpha1::block::Deposit, - }; use cnidarium::StateDelta; - use insta::assert_snapshot; use super::*; use crate::test_utils::astria_address; @@ -876,16 +769,4 @@ mod tests { .unwrap(); assert_eq!(retrieved_tx_hash, Some(tx_hash)); } - - #[test] - fn storage_keys_have_not_changed() { - let address: Address = "astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm" - .parse() - .unwrap(); - - assert_snapshot!(rollup_id_storage_key(&address)); - assert_snapshot!(asset_id_storage_key(&address)); - assert_snapshot!(bridge_account_sudo_address_storage_key(&address)); - assert_snapshot!(bridge_account_withdrawer_address_storage_key(&address)); - } } diff --git a/crates/astria-sequencer/src/bridge/storage/keys.rs b/crates/astria-sequencer/src/bridge/storage/keys.rs new file mode 100644 index 0000000000..1191b46b67 --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/keys.rs @@ -0,0 +1,148 @@ +use astria_core::primitive::v1::RollupId; + +use crate::{ + accounts::AddressBytes, + storage::keys::AddressPrefixer, +}; + +pub(in crate::bridge) const INIT_BRIDGE_ACCOUNT_BASE_FEE_KEY: &str = "bridge/init_account_fee"; +pub(in crate::bridge) const BRIDGE_LOCK_BYTE_COST_MULTIPLIER_KEY: &str = + "bridge/lock_byte_cost_multiplier"; +pub(in crate::bridge) const BRIDGE_SUDO_CHANGE_FEE_KEY: &str = "bridge/sudo_change_fee"; + +pub(in crate::bridge) const BRIDGE_ACCOUNT_PREFIX: &str = "bridge/account/"; +const BRIDGE_ACCOUNT_SUDO_PREFIX: &str = "bridge/sudo/"; +const BRIDGE_ACCOUNT_WITHDRAWER_PREFIX: &str = "bridge/withdrawer/"; + +pub(in crate::bridge) const DEPOSITS_EPHEMERAL_KEY: &str = "bridge/deposits"; +const DEPOSIT_PREFIX: &[u8] = b"bridge/deposit/"; + +/// Example: `bridge/account/0101....0101/rollup_id`. +/// |40 hex chars| +pub(in crate::bridge) fn rollup_id_key(address: &T) -> String { + format!( + "{}/rollup_id", + AddressPrefixer::new(BRIDGE_ACCOUNT_PREFIX, address) + ) +} + +/// Example: `bridge/account/0101....0101/asset_id`. +/// |40 hex chars| +pub(in crate::bridge) fn asset_id_key(address: &T) -> String { + format!( + "{}/asset_id", + AddressPrefixer::new(BRIDGE_ACCOUNT_PREFIX, address) + ) +} + +/// Example: `bridge/sudo/0101....0101`. +/// |40 hex chars| +pub(in crate::bridge) fn bridge_account_sudo_address_key(address: &T) -> String { + AddressPrefixer::new(BRIDGE_ACCOUNT_SUDO_PREFIX, address).to_string() +} + +/// Example: `bridge/withdrawer/0101....0101`. +/// |40 hex chars| +pub(in crate::bridge) fn bridge_account_withdrawer_address_key( + address: &T, +) -> String { + AddressPrefixer::new(BRIDGE_ACCOUNT_WITHDRAWER_PREFIX, address).to_string() +} + +/// Example: `bridge/account/0101....0101/withdrawal_event/`. +/// |40 hex chars| |UTF-8 chars| +pub(in crate::bridge) fn bridge_account_withdrawal_event_key( + address: &T, + withdrawal_event_id: &str, +) -> String { + format!( + "{}/withdrawal_event/{}", + AddressPrefixer::new(BRIDGE_ACCOUNT_PREFIX, address), + withdrawal_event_id + ) +} + +pub(in crate::bridge) fn deposit_key(block_hash: &[u8; 32], rollup_id: &RollupId) -> Vec { + [DEPOSIT_PREFIX, block_hash, rollup_id.as_ref()].concat() +} + +pub(in crate::bridge) fn last_transaction_id_for_bridge_account_key( + address: &T, +) -> Vec { + [ + BRIDGE_ACCOUNT_PREFIX.as_bytes(), + address.address_bytes(), + b"/last_tx", + ] + .concat() +} + +#[cfg(test)] +mod tests { + use astria_core::primitive::v1::Address; + use telemetry::display::base64; + + use super::*; + + const COMPONENT_PREFIX: &str = "bridge/"; + + fn address() -> Address { + "astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm" + .parse() + .unwrap() + } + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(INIT_BRIDGE_ACCOUNT_BASE_FEE_KEY); + insta::assert_snapshot!(BRIDGE_LOCK_BYTE_COST_MULTIPLIER_KEY); + insta::assert_snapshot!(BRIDGE_SUDO_CHANGE_FEE_KEY); + insta::assert_snapshot!(DEPOSITS_EPHEMERAL_KEY); + insta::assert_snapshot!(rollup_id_key(&address())); + insta::assert_snapshot!(asset_id_key(&address())); + insta::assert_snapshot!(bridge_account_sudo_address_key(&address())); + insta::assert_snapshot!(bridge_account_withdrawer_address_key(&address())); + insta::assert_snapshot!(bridge_account_withdrawal_event_key(&address(), "the-event")); + insta::assert_snapshot!(base64(&deposit_key(&[1; 32], &RollupId::new([2; 32])))); + insta::assert_snapshot!(base64(&last_transaction_id_for_bridge_account_key( + &address() + ))); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(INIT_BRIDGE_ACCOUNT_BASE_FEE_KEY.starts_with(COMPONENT_PREFIX)); + assert!(BRIDGE_LOCK_BYTE_COST_MULTIPLIER_KEY.starts_with(COMPONENT_PREFIX)); + assert!(BRIDGE_SUDO_CHANGE_FEE_KEY.starts_with(COMPONENT_PREFIX)); + assert!(DEPOSITS_EPHEMERAL_KEY.starts_with(COMPONENT_PREFIX)); + assert!(rollup_id_key(&address()).starts_with(COMPONENT_PREFIX)); + assert!(asset_id_key(&address()).starts_with(COMPONENT_PREFIX)); + assert!(bridge_account_sudo_address_key(&address()).starts_with(COMPONENT_PREFIX)); + assert!(bridge_account_withdrawer_address_key(&address()).starts_with(COMPONENT_PREFIX)); + assert!( + bridge_account_withdrawal_event_key(&address(), "the-event") + .starts_with(COMPONENT_PREFIX) + ); + assert!( + deposit_key(&[1; 32], &RollupId::new([2; 32])).starts_with(COMPONENT_PREFIX.as_bytes()) + ); + assert!( + last_transaction_id_for_bridge_account_key(&address()) + .starts_with(COMPONENT_PREFIX.as_bytes()) + ); + } + + #[test] + fn bridge_account_prefix_should_be_prefix_of_relevant_keys() { + assert!(rollup_id_key(&address()).starts_with(BRIDGE_ACCOUNT_PREFIX)); + assert!(asset_id_key(&address()).starts_with(BRIDGE_ACCOUNT_PREFIX)); + assert!( + bridge_account_withdrawal_event_key(&address(), "the-event") + .starts_with(BRIDGE_ACCOUNT_PREFIX) + ); + assert!( + last_transaction_id_for_bridge_account_key(&address()) + .starts_with(BRIDGE_ACCOUNT_PREFIX.as_bytes()) + ); + } +} diff --git a/crates/astria-sequencer/src/bridge/storage/mod.rs b/crates/astria-sequencer/src/bridge/storage/mod.rs index 8478b8c98f..c52ffe69e2 100644 --- a/crates/astria-sequencer/src/bridge/storage/mod.rs +++ b/crates/astria-sequencer/src/bridge/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(crate) use values::Value; diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-10.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-10.snap new file mode 100644 index 0000000000..74e2fa9ceb --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-10.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 104 +expression: "base64(&deposit_key(&[1; 32], &RollupId::new([2; 32])))" +--- +YnJpZGdlL2RlcG9zaXQvAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg== diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-11.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-11.snap new file mode 100644 index 0000000000..cb933280bd --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-11.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 105 +expression: base64(&last_transaction_id_for_bridge_account_key(&address())) +--- +YnJpZGdlL2FjY291bnQvHAxJDxtVKNgXPF3kbRMRYOSywMMvbGFzdF90eA== diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..8fdfb69d89 --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 96 +expression: BRIDGE_LOCK_BYTE_COST_MULTIPLIER_KEY +--- +bridge/lock_byte_cost_multiplier diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-3.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-3.snap new file mode 100644 index 0000000000..9b95261abd --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-3.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 97 +expression: BRIDGE_SUDO_CHANGE_FEE_KEY +--- +bridge/sudo_change_fee diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-4.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-4.snap new file mode 100644 index 0000000000..5be3e6da08 --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-4.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 98 +expression: DEPOSITS_EPHEMERAL_KEY +--- +bridge/deposits diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-5.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-5.snap new file mode 100644 index 0000000000..637e32bf92 --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-5.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 99 +expression: rollup_id_key(&address()) +--- +bridge/account/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/rollup_id diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-6.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-6.snap new file mode 100644 index 0000000000..5e82c62faf --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-6.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 100 +expression: asset_id_key(&address()) +--- +bridge/account/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/asset_id diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-7.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-7.snap new file mode 100644 index 0000000000..f0d5abc0d9 --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-7.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 101 +expression: bridge_account_sudo_address_key(&address()) +--- +bridge/sudo/1c0c490f1b5528d8173c5de46d131160e4b2c0c3 diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-8.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-8.snap new file mode 100644 index 0000000000..06df90828d --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-8.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 102 +expression: bridge_account_withdrawer_address_key(&address()) +--- +bridge/withdrawer/1c0c490f1b5528d8173c5de46d131160e4b2c0c3 diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-9.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-9.snap new file mode 100644 index 0000000000..bd9863249d --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change-9.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 103 +expression: "bridge_account_withdrawal_event_key(&address(), \"the-event\")" +--- +bridge/account/1c0c490f1b5528d8173c5de46d131160e4b2c0c3/withdrawal_event/the-event diff --git a/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..2ab66a494a --- /dev/null +++ b/crates/astria-sequencer/src/bridge/storage/snapshots/astria_sequencer__bridge__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/bridge/storage/keys.rs +assertion_line: 95 +expression: INIT_BRIDGE_ACCOUNT_BASE_FEE_KEY +--- +bridge/init_account_fee diff --git a/crates/astria-sequencer/src/grpc/state_ext.rs b/crates/astria-sequencer/src/grpc/state_ext.rs index fffc906d20..6d17282c18 100644 --- a/crates/astria-sequencer/src/grpc/state_ext.rs +++ b/crates/astria-sequencer/src/grpc/state_ext.rs @@ -22,33 +22,19 @@ use cnidarium::{ }; use tracing::instrument; -use super::storage; +use super::storage::{ + self, + keys::{ + block_hash_by_height_key, + rollup_data_by_hash_and_rollup_id_key, + rollup_ids_by_hash_key, + rollup_ids_proof_by_hash_key, + rollup_transactions_proof_by_hash_key, + sequencer_block_header_by_hash_key, + }, +}; use crate::storage::StoredValue; -fn block_hash_by_height_key(height: u64) -> Vec { - [b"blockhash/".as_slice(), &height.to_le_bytes()].concat() -} - -fn sequencer_block_header_by_hash_key(hash: &[u8; 32]) -> Vec { - [b"blockheader/", hash.as_slice()].concat() -} - -fn rollup_data_by_hash_and_rollup_id_key(hash: &[u8; 32], rollup_id: &RollupId) -> Vec { - [b"rollupdata/", hash.as_slice(), rollup_id.as_ref()].concat() -} - -fn rollup_ids_by_hash_key(hash: &[u8; 32]) -> Vec { - [b"rollupids/", hash.as_slice()].concat() -} - -fn rollup_transactions_proof_by_hash_key(hash: &[u8; 32]) -> Vec { - [b"rolluptxsproof/", hash.as_slice()].concat() -} - -fn rollup_ids_proof_by_hash_key(hash: &[u8; 32]) -> Vec { - [b"rollupidsproof/", hash.as_slice()].concat() -} - #[async_trait] pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] diff --git a/crates/astria-sequencer/src/grpc/storage/keys.rs b/crates/astria-sequencer/src/grpc/storage/keys.rs new file mode 100644 index 0000000000..684f929abb --- /dev/null +++ b/crates/astria-sequencer/src/grpc/storage/keys.rs @@ -0,0 +1,63 @@ +use astria_core::primitive::v1::RollupId; + +pub(in crate::grpc) fn block_hash_by_height_key(height: u64) -> Vec { + [b"grpc/block_hash/".as_slice(), &height.to_le_bytes()].concat() +} + +pub(in crate::grpc) fn sequencer_block_header_by_hash_key(hash: &[u8; 32]) -> Vec { + [b"grpc/block_header/", hash.as_slice()].concat() +} + +pub(in crate::grpc) fn rollup_data_by_hash_and_rollup_id_key( + hash: &[u8; 32], + rollup_id: &RollupId, +) -> Vec { + [b"grpc/rollup_data/", hash.as_slice(), rollup_id.as_ref()].concat() +} + +pub(in crate::grpc) fn rollup_ids_by_hash_key(hash: &[u8; 32]) -> Vec { + [b"grpc/rollup_ids/", hash.as_slice()].concat() +} + +pub(in crate::grpc) fn rollup_transactions_proof_by_hash_key(hash: &[u8; 32]) -> Vec { + [b"grpc/rollup_txs_proof/", hash.as_slice()].concat() +} + +pub(in crate::grpc) fn rollup_ids_proof_by_hash_key(hash: &[u8; 32]) -> Vec { + [b"grpc/rollup_ids_proof/", hash.as_slice()].concat() +} + +#[cfg(test)] +mod tests { + use telemetry::display::base64; + + use super::*; + + const COMPONENT_PREFIX: &[u8] = b"grpc/"; + const HASH: [u8; 32] = [1; 32]; + const ROLLUP_ID: RollupId = RollupId::new([2; 32]); + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(base64(&block_hash_by_height_key(42))); + insta::assert_snapshot!(base64(&sequencer_block_header_by_hash_key(&HASH))); + insta::assert_snapshot!(base64(&rollup_data_by_hash_and_rollup_id_key( + &HASH, &ROLLUP_ID + ))); + insta::assert_snapshot!(base64(&rollup_ids_by_hash_key(&HASH))); + insta::assert_snapshot!(base64(&rollup_transactions_proof_by_hash_key(&HASH))); + insta::assert_snapshot!(base64(&rollup_ids_proof_by_hash_key(&HASH))); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(block_hash_by_height_key(42).starts_with(COMPONENT_PREFIX)); + assert!(sequencer_block_header_by_hash_key(&HASH).starts_with(COMPONENT_PREFIX)); + assert!( + rollup_data_by_hash_and_rollup_id_key(&HASH, &ROLLUP_ID).starts_with(COMPONENT_PREFIX) + ); + assert!(rollup_ids_by_hash_key(&HASH).starts_with(COMPONENT_PREFIX)); + assert!(rollup_transactions_proof_by_hash_key(&HASH).starts_with(COMPONENT_PREFIX)); + assert!(rollup_ids_proof_by_hash_key(&HASH).starts_with(COMPONENT_PREFIX)); + } +} diff --git a/crates/astria-sequencer/src/grpc/storage/mod.rs b/crates/astria-sequencer/src/grpc/storage/mod.rs index 28d353e151..d1c28b1264 100644 --- a/crates/astria-sequencer/src/grpc/storage/mod.rs +++ b/crates/astria-sequencer/src/grpc/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(crate) use values::Value; diff --git a/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..731b93501a --- /dev/null +++ b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/grpc/storage/keys.rs +assertion_line: 40 +expression: base64(&sequencer_block_header_by_hash_key(&hash)) +--- +Z3JwYy9ibG9ja19oZWFkZXIvAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE= diff --git a/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-3.snap b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-3.snap new file mode 100644 index 0000000000..3e9136bfb0 --- /dev/null +++ b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-3.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/grpc/storage/keys.rs +assertion_line: 42 +expression: "base64(&rollup_data_by_hash_and_rollup_id_key(&hash, &rollup_id))" +--- +Z3JwYy9yb2xsdXBfZGF0YS8BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC diff --git a/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-4.snap b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-4.snap new file mode 100644 index 0000000000..69a6f2fd63 --- /dev/null +++ b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-4.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/grpc/storage/keys.rs +assertion_line: 45 +expression: base64(&rollup_ids_by_hash_key(&hash)) +--- +Z3JwYy9yb2xsdXBfaWRzLwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB diff --git a/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-5.snap b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-5.snap new file mode 100644 index 0000000000..7cea6e5b5f --- /dev/null +++ b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-5.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/grpc/storage/keys.rs +assertion_line: 46 +expression: base64(&rollup_transactions_proof_by_hash_key(&hash)) +--- +Z3JwYy9yb2xsdXBfdHhzX3Byb29mLwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB diff --git a/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-6.snap b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-6.snap new file mode 100644 index 0000000000..3b3a71ce19 --- /dev/null +++ b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change-6.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/grpc/storage/keys.rs +assertion_line: 47 +expression: base64(&rollup_ids_proof_by_hash_key(&hash)) +--- +Z3JwYy9yb2xsdXBfaWRzX3Byb29mLwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB diff --git a/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..7c789763b4 --- /dev/null +++ b/crates/astria-sequencer/src/grpc/storage/snapshots/astria_sequencer__grpc__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/grpc/storage/keys.rs +assertion_line: 38 +expression: base64(&block_hash_by_height_key(42)) +--- +Z3JwYy9ibG9ja19oYXNoLyoAAAAAAAAA diff --git a/crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed-2.snap b/crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed-2.snap deleted file mode 100644 index 7ba59bca3c..0000000000 --- a/crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed-2.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/astria-sequencer/src/ibc/state_ext.rs -expression: "channel_balance_storage_key(&channel, &asset)" ---- -ibc-data/channel-5/balance/be429a02d00837245167a2616674a979a2ac6f9806468b48a975b156ad711320 diff --git a/crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed.snap b/crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed.snap deleted file mode 100644 index 2358f2e37d..0000000000 --- a/crates/astria-sequencer/src/ibc/snapshots/astria_sequencer__ibc__state_ext__tests__storage_keys_have_not_changed.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/astria-sequencer/src/ibc/state_ext.rs -expression: "super::ibc_relayer_key(&address)" ---- -ibc-relayer/1c0c490f1b5528d8173c5de46d131160e4b2c0c3 diff --git a/crates/astria-sequencer/src/ibc/state_ext.rs b/crates/astria-sequencer/src/ibc/state_ext.rs index 4ec443a9c6..37c089b915 100644 --- a/crates/astria-sequencer/src/ibc/state_ext.rs +++ b/crates/astria-sequencer/src/ibc/state_ext.rs @@ -1,4 +1,7 @@ -use std::fmt::Display; +use std::{ + borrow::Cow, + fmt::Display, +}; use astria_core::primitive::v1::{ asset, @@ -24,42 +27,20 @@ use tracing::{ instrument, }; -use super::storage; +use super::storage::{ + self, + keys::{ + channel_balance_key, + ibc_relayer_key, + IBC_SUDO_KEY, + ICS20_WITHDRAWAL_BASE_FEE_KEY, + }, +}; use crate::{ accounts::AddressBytes, storage::StoredValue, }; -const IBC_SUDO_STORAGE_KEY: &str = "ibcsudo"; -const ICS20_WITHDRAWAL_BASE_FEE_STORAGE_KEY: &str = "ics20withdrawalfee"; - -struct IbcRelayerKey<'a, T>(&'a T); - -impl<'a, T: AddressBytes> std::fmt::Display for IbcRelayerKey<'a, T> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("ibc-relayer")?; - f.write_str("/")?; - for byte in self.0.address_bytes() { - f.write_fmt(format_args!("{byte:02x}"))?; - } - Ok(()) - } -} - -fn channel_balance_storage_key<'a, TAsset>(channel: &ChannelId, asset: &'a TAsset) -> String -where - asset::IbcPrefixed: From<&'a TAsset>, -{ - format!( - "ibc-data/{channel}/balance/{}", - crate::storage_keys::hunks::Asset::from(asset), - ) -} - -fn ibc_relayer_key(address: &T) -> String { - IbcRelayerKey(address).to_string() -} - #[async_trait] pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all, fields(%channel, %asset), err)] @@ -70,10 +51,10 @@ pub(crate) trait StateReadExt: StateRead { ) -> Result where TAsset: Sync + Display, - asset::IbcPrefixed: From<&'a TAsset>, + &'a TAsset: Into>, { let Some(bytes) = self - .get_raw(&channel_balance_storage_key(channel, asset)) + .get_raw(&channel_balance_key(channel, asset)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading ibc channel balance from state")? @@ -89,7 +70,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_ibc_sudo_address(&self) -> Result<[u8; ADDRESS_LEN]> { let Some(bytes) = self - .get_raw(IBC_SUDO_STORAGE_KEY) + .get_raw(IBC_SUDO_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw ibc sudo address from state")? @@ -115,7 +96,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_ics20_withdrawal_base_fee(&self) -> Result { let Some(bytes) = self - .get_raw(ICS20_WITHDRAWAL_BASE_FEE_STORAGE_KEY) + .get_raw(ICS20_WITHDRAWAL_BASE_FEE_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading ics20 withdrawal fee from state")? @@ -141,12 +122,12 @@ pub(crate) trait StateWriteExt: StateWrite { ) -> Result<()> where TAsset: Display, - asset::IbcPrefixed: From<&'a TAsset>, + &'a TAsset: Into>, { let bytes = StoredValue::from(storage::Balance::from(balance)) .serialize() .wrap_err("failed to serialize ibc channel balance")?; - self.put_raw(channel_balance_storage_key(channel, asset), bytes); + self.put_raw(channel_balance_key(channel, asset), bytes); Ok(()) } @@ -159,7 +140,7 @@ pub(crate) trait StateWriteExt: StateWrite { ) -> Result<()> where TAsset: Sync + Display, - asset::IbcPrefixed: From<&'a TAsset>, + &'a TAsset: Into>, { let old_balance = self .get_ibc_channel_balance(channel, asset) @@ -179,7 +160,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::AddressBytes::from(&address)) .serialize() .wrap_err("failed to serialize ibc sudo address")?; - self.put_raw(IBC_SUDO_STORAGE_KEY.to_string(), bytes); + self.put_raw(IBC_SUDO_KEY.to_string(), bytes); Ok(()) } @@ -202,7 +183,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .wrap_err("failed to serialize ics20 withdrawal base fee")?; - self.put_raw(ICS20_WITHDRAWAL_BASE_FEE_STORAGE_KEY.to_string(), bytes); + self.put_raw(ICS20_WITHDRAWAL_BASE_FEE_KEY.to_string(), bytes); Ok(()) } } @@ -211,21 +192,11 @@ impl StateWriteExt for T {} #[cfg(test)] mod tests { - use astria_core::primitive::v1::{ - asset, - Address, - }; use cnidarium::StateDelta; - use ibc_types::core::channel::ChannelId; - use insta::assert_snapshot; - use super::{ - StateReadExt as _, - StateWriteExt as _, - }; + use super::*; use crate::{ - address::StateWriteExt, - ibc::state_ext::channel_balance_storage_key, + address::StateWriteExt as _, test_utils::{ astria_address, ASTRIA_PREFIX, @@ -235,6 +206,7 @@ mod tests { fn asset_0() -> asset::Denom { "asset_0".parse().unwrap() } + fn asset_1() -> asset::Denom { "asset_1".parse().unwrap() } @@ -517,23 +489,4 @@ mod tests { let retrieved_fee = state.get_ics20_withdrawal_base_fee().await.unwrap(); assert_eq!(retrieved_fee, 123); } - - #[test] - fn storage_keys_have_not_changed() { - let channel = ChannelId::new(5); - let address: Address = "astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm" - .parse() - .unwrap(); - - assert_snapshot!(super::ibc_relayer_key(&address)); - - let asset = "an/asset/with/a/prefix" - .parse::() - .unwrap(); - assert_eq!( - channel_balance_storage_key(&channel, &asset), - channel_balance_storage_key(&channel, &asset.to_ibc_prefixed()), - ); - assert_snapshot!(channel_balance_storage_key(&channel, &asset)); - } } diff --git a/crates/astria-sequencer/src/ibc/storage/keys.rs b/crates/astria-sequencer/src/ibc/storage/keys.rs new file mode 100644 index 0000000000..7d5ac0bf5e --- /dev/null +++ b/crates/astria-sequencer/src/ibc/storage/keys.rs @@ -0,0 +1,76 @@ +use std::borrow::Cow; + +use astria_core::primitive::v1::asset::IbcPrefixed; +use ibc_types::core::channel::ChannelId; + +use crate::{ + accounts::AddressBytes, + storage::keys::{ + AddressPrefixer, + Asset, + }, +}; + +pub(in crate::ibc) const IBC_SUDO_KEY: &str = "ibc/sudo"; +pub(in crate::ibc) const ICS20_WITHDRAWAL_BASE_FEE_KEY: &str = "ibc/ics20_withdrawal_base_fee"; +const IBC_RELAYER_PREFIX: &str = "ibc/relayer/"; + +/// Example: `ibc/channel-xxx/balance/0101....0101`. +/// |int| |64 hex chars| +pub(in crate::ibc) fn channel_balance_key<'a, TAsset>( + channel: &ChannelId, + asset: &'a TAsset, +) -> String +where + &'a TAsset: Into>, +{ + format!("ibc/{channel}/balance/{}", Asset::from(asset)) +} + +/// Example: `ibc/relayer/0101....0101`. +/// |40 hex chars| +pub(in crate::ibc) fn ibc_relayer_key(address: &T) -> String { + AddressPrefixer::new(IBC_RELAYER_PREFIX, address).to_string() +} + +#[cfg(test)] +mod tests { + use astria_core::primitive::v1::{ + asset::Denom, + Address, + }; + + use super::*; + + const COMPONENT_PREFIX: &str = "ibc/"; + + fn channel_id() -> ChannelId { + ChannelId::new(5) + } + + fn address() -> Address { + "astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm" + .parse() + .unwrap() + } + + fn asset() -> Denom { + "an/asset/with/a/prefix".parse().unwrap() + } + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(IBC_SUDO_KEY); + insta::assert_snapshot!(ICS20_WITHDRAWAL_BASE_FEE_KEY); + insta::assert_snapshot!(channel_balance_key(&channel_id(), &asset())); + insta::assert_snapshot!(ibc_relayer_key(&address())); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(IBC_SUDO_KEY.starts_with(COMPONENT_PREFIX)); + assert!(ICS20_WITHDRAWAL_BASE_FEE_KEY.starts_with(COMPONENT_PREFIX)); + assert!(channel_balance_key(&channel_id(), &asset()).starts_with(COMPONENT_PREFIX)); + assert!(ibc_relayer_key(&address()).starts_with(COMPONENT_PREFIX)); + } +} diff --git a/crates/astria-sequencer/src/ibc/storage/mod.rs b/crates/astria-sequencer/src/ibc/storage/mod.rs index 2cda197b89..1f76fd5b36 100644 --- a/crates/astria-sequencer/src/ibc/storage/mod.rs +++ b/crates/astria-sequencer/src/ibc/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(crate) use values::Value; diff --git a/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..16047d71da --- /dev/null +++ b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/ibc/storage/keys.rs +assertion_line: 64 +expression: ICS20_WITHDRAWAL_BASE_FEE_KEY +--- +ibc/ics20_withdrawal_base_fee diff --git a/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-3.snap b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-3.snap new file mode 100644 index 0000000000..ac0a248a2a --- /dev/null +++ b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-3.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/ibc/storage/keys.rs +assertion_line: 65 +expression: "channel_balance_key(&channel_id(), &asset())" +--- +ibc/channel-5/balance/be429a02d00837245167a2616674a979a2ac6f9806468b48a975b156ad711320 diff --git a/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-4.snap b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-4.snap new file mode 100644 index 0000000000..6a6978da7d --- /dev/null +++ b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change-4.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/ibc/storage/keys.rs +assertion_line: 66 +expression: ibc_relayer_key(&address()) +--- +ibc/relayer/1c0c490f1b5528d8173c5de46d131160e4b2c0c3 diff --git a/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..c8f53e7af2 --- /dev/null +++ b/crates/astria-sequencer/src/ibc/storage/snapshots/astria_sequencer__ibc__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/ibc/storage/keys.rs +assertion_line: 63 +expression: IBC_SUDO_KEY +--- +ibc/sudo diff --git a/crates/astria-sequencer/src/lib.rs b/crates/astria-sequencer/src/lib.rs index 8322623b57..55bf2dfa5b 100644 --- a/crates/astria-sequencer/src/lib.rs +++ b/crates/astria-sequencer/src/lib.rs @@ -19,7 +19,6 @@ pub(crate) mod sequence; mod sequencer; pub(crate) mod service; pub(crate) mod storage; -pub(crate) mod storage_keys; #[cfg(any(test, feature = "benchmark"))] pub(crate) mod test_utils; pub(crate) mod transaction; diff --git a/crates/astria-sequencer/src/sequence/state_ext.rs b/crates/astria-sequencer/src/sequence/state_ext.rs index 2844abb2b2..f3ed8e921b 100644 --- a/crates/astria-sequencer/src/sequence/state_ext.rs +++ b/crates/astria-sequencer/src/sequence/state_ext.rs @@ -13,18 +13,21 @@ use cnidarium::{ }; use tracing::instrument; -use super::storage; +use super::storage::{ + self, + keys::{ + SEQUENCE_ACTION_BASE_FEE_KEY, + SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_KEY, + }, +}; use crate::storage::StoredValue; -const SEQUENCE_ACTION_BASE_FEE_STORAGE_KEY: &str = "seqbasefee"; -const SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_STORAGE_KEY: &str = "seqmultiplier"; - #[async_trait] pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_sequence_action_base_fee(&self) -> Result { let bytes = self - .get_raw(SEQUENCE_ACTION_BASE_FEE_STORAGE_KEY) + .get_raw(SEQUENCE_ACTION_BASE_FEE_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw sequence action base fee from state")? @@ -37,7 +40,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_sequence_action_byte_cost_multiplier(&self) -> Result { let bytes = self - .get_raw(SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_STORAGE_KEY) + .get_raw(SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_KEY) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw sequence action byte cost multiplier from state")? @@ -57,7 +60,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .context("failed to serialize sequence action base fee")?; - self.put_raw(SEQUENCE_ACTION_BASE_FEE_STORAGE_KEY.to_string(), bytes); + self.put_raw(SEQUENCE_ACTION_BASE_FEE_KEY.to_string(), bytes); Ok(()) } @@ -66,10 +69,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .context("failed to serialize sequence action byte cost multiplier")?; - self.put_raw( - SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_STORAGE_KEY.to_string(), - bytes, - ); + self.put_raw(SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_KEY.to_string(), bytes); Ok(()) } } @@ -80,10 +80,7 @@ impl StateWriteExt for T {} mod tests { use cnidarium::StateDelta; - use super::{ - StateReadExt as _, - StateWriteExt as _, - }; + use super::*; #[tokio::test] async fn sequence_action_base_fee() { diff --git a/crates/astria-sequencer/src/sequence/storage/keys.rs b/crates/astria-sequencer/src/sequence/storage/keys.rs new file mode 100644 index 0000000000..936c0017fb --- /dev/null +++ b/crates/astria-sequencer/src/sequence/storage/keys.rs @@ -0,0 +1,22 @@ +pub(in crate::sequence) const SEQUENCE_ACTION_BASE_FEE_KEY: &str = "sequence/base_fee"; +pub(in crate::sequence) const SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_KEY: &str = + "sequence/byte_cost_multiplier"; + +#[cfg(test)] +mod tests { + use super::*; + + const COMPONENT_PREFIX: &str = "sequence/"; + + #[test] + fn keys_should_not_change() { + insta::assert_snapshot!(SEQUENCE_ACTION_BASE_FEE_KEY); + insta::assert_snapshot!(SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_KEY); + } + + #[test] + fn keys_should_have_component_prefix() { + assert!(SEQUENCE_ACTION_BASE_FEE_KEY.starts_with(COMPONENT_PREFIX)); + assert!(SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_KEY.starts_with(COMPONENT_PREFIX)); + } +} diff --git a/crates/astria-sequencer/src/sequence/storage/mod.rs b/crates/astria-sequencer/src/sequence/storage/mod.rs index e6fee4261d..92e06f015f 100644 --- a/crates/astria-sequencer/src/sequence/storage/mod.rs +++ b/crates/astria-sequencer/src/sequence/storage/mod.rs @@ -1,3 +1,4 @@ +pub(super) mod keys; mod values; pub(super) use values::Fee; diff --git a/crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change-2.snap b/crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change-2.snap new file mode 100644 index 0000000000..1c2afa9bca --- /dev/null +++ b/crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change-2.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/sequence/storage/keys.rs +assertion_line: 14 +expression: SEQUENCE_ACTION_BYTE_COST_MULTIPLIER_KEY +--- +sequence/byte_cost_multiplier diff --git a/crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change.snap b/crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change.snap new file mode 100644 index 0000000000..d1d9fd3513 --- /dev/null +++ b/crates/astria-sequencer/src/sequence/storage/snapshots/astria_sequencer__sequence__storage__keys__tests__keys_should_not_change.snap @@ -0,0 +1,6 @@ +--- +source: crates/astria-sequencer/src/sequence/storage/keys.rs +assertion_line: 13 +expression: SEQUENCE_ACTION_BASE_FEE_KEY +--- +sequence/base_fee diff --git a/crates/astria-sequencer/src/storage/keys.rs b/crates/astria-sequencer/src/storage/keys.rs new file mode 100644 index 0000000000..fc8909f23a --- /dev/null +++ b/crates/astria-sequencer/src/storage/keys.rs @@ -0,0 +1,101 @@ +use std::{ + borrow::Cow, + fmt::{ + self, + Display, + Formatter, + }, + str::FromStr, +}; + +use astria_core::primitive::v1::asset::IbcPrefixed; + +use crate::accounts::AddressBytes; + +/// Helper struct whose `Display` impl outputs the prefix followed by the hex-encoded address. +pub(crate) struct AddressPrefixer<'a, T> { + prefix: &'static str, + address: &'a T, +} + +impl<'a, T> AddressPrefixer<'a, T> { + pub(crate) fn new(prefix: &'static str, address: &'a T) -> Self { + Self { + prefix, + address, + } + } +} + +impl<'a, T: AddressBytes> Display for AddressPrefixer<'a, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!( + f, + "{}{}", + self.prefix, + hex::encode(self.address.address_bytes()) + ) + } +} + +/// Helper struct whose `Display` impl outputs the hex-encoded ibc-prefixed address, and that can be +/// parsed from such a hex-encoded form. +#[cfg_attr(test, derive(Debug, PartialEq))] +pub(crate) struct Asset<'a>(Cow<'a, IbcPrefixed>); + +impl<'a> Asset<'a> { + pub(crate) fn get(self) -> IbcPrefixed { + self.0.into_owned() + } + + pub(crate) fn as_bytes(&self) -> &[u8; 32] { + self.0.as_bytes() + } +} + +impl<'a> Display for Asset<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str(&hex::encode(self.0.as_bytes())) + } +} + +impl<'a, T> From<&'a T> for Asset<'a> +where + &'a T: Into>, +{ + fn from(value: &'a T) -> Self { + Self(value.into()) + } +} + +#[derive(Debug, thiserror::Error)] +#[error("failed to parse input as asset key")] +pub(crate) struct ParseAssetKeyError { + #[from] + source: hex::FromHexError, +} + +impl<'a> FromStr for Asset<'a> { + type Err = ParseAssetKeyError; + + fn from_str(s: &str) -> Result { + use hex::FromHex as _; + let bytes = <[u8; IbcPrefixed::LENGTH]>::from_hex(s)?; + Ok(Self(Cow::Owned(IbcPrefixed::new(bytes)))) + } +} + +#[cfg(test)] +mod tests { + use super::Asset; + + #[test] + fn asset_key_to_string_parse_roundtrip() { + let asset = "an/asset/with/a/prefix" + .parse::() + .unwrap(); + let expected = Asset::from(&asset); + let actual = expected.to_string().parse::().unwrap(); + assert_eq!(expected, actual); + } +} diff --git a/crates/astria-sequencer/src/storage/mod.rs b/crates/astria-sequencer/src/storage/mod.rs index e3d45502e8..a4a1b61c98 100644 --- a/crates/astria-sequencer/src/storage/mod.rs +++ b/crates/astria-sequencer/src/storage/mod.rs @@ -1,3 +1,4 @@ +pub(crate) mod keys; mod stored_value; pub(crate) use stored_value::StoredValue; diff --git a/crates/astria-sequencer/src/storage_keys.rs b/crates/astria-sequencer/src/storage_keys.rs deleted file mode 100644 index 29bbe72f2a..0000000000 --- a/crates/astria-sequencer/src/storage_keys.rs +++ /dev/null @@ -1,60 +0,0 @@ -pub(crate) mod hunks { - use std::str::FromStr; - - use astria_core::primitive::v1::asset; - - #[derive(Clone, Copy, Debug, PartialEq)] - pub(crate) struct Asset(asset::IbcPrefixed); - - impl Asset { - pub(crate) fn get(self) -> asset::IbcPrefixed { - self.0 - } - } - - impl std::fmt::Display for Asset { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for byte in self.get().as_bytes() { - f.write_fmt(format_args!("{byte:02x}"))?; - } - Ok(()) - } - } - - impl> From for Asset { - fn from(value: T) -> Self { - Self(value.into()) - } - } - - #[derive(Debug, thiserror::Error)] - #[error("failed to parse input as asset key")] - pub(crate) struct ParseAssetKeyError { - #[from] - source: hex::FromHexError, - } - - impl FromStr for Asset { - type Err = ParseAssetKeyError; - - fn from_str(s: &str) -> std::result::Result { - use hex::FromHex as _; - let bytes = <[u8; 32]>::from_hex(s)?; - Ok(Self(asset::IbcPrefixed::new(bytes))) - } - } - - #[cfg(test)] - mod tests { - use super::Asset; - #[test] - fn asset_key_to_string_parse_roundtrip() { - let asset = "an/asset/with/a/prefix" - .parse::() - .unwrap(); - let expected = Asset::from(asset); - let actual = expected.to_string().parse::().unwrap(); - assert_eq!(expected, actual); - } - } -} From 6dff230972661693c60a62426e814886acc4b7bb Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Tue, 8 Oct 2024 14:56:37 +0100 Subject: [PATCH 2/7] rename storage keys --- .../src/primitive/v1/asset/denom.rs | 8 +- .../src/accounts/state_ext.rs | 21 ++--- .../src/accounts/storage/keys.rs | 30 +++--- .../astria-sequencer/src/address/state_ext.rs | 13 +-- .../src/address/storage/keys.rs | 12 +-- crates/astria-sequencer/src/app/state_ext.rs | 28 +++--- .../astria-sequencer/src/app/storage/keys.rs | 30 +++--- .../astria-sequencer/src/assets/state_ext.rs | 31 +++---- .../src/assets/storage/keys.rs | 40 ++++---- .../src/authority/state_ext.rs | 20 ++-- .../src/authority/storage/keys.rs | 18 ++-- .../astria-sequencer/src/bridge/state_ext.rs | 60 ++++++------ .../src/bridge/storage/keys.rs | 91 +++++++++---------- crates/astria-sequencer/src/grpc/state_ext.rs | 36 ++++---- .../astria-sequencer/src/grpc/storage/keys.rs | 38 ++++---- crates/astria-sequencer/src/ibc/state_ext.rs | 25 ++--- .../astria-sequencer/src/ibc/storage/keys.rs | 31 +++---- .../src/sequence/state_ext.rs | 16 ++-- .../src/sequence/storage/keys.rs | 12 +-- crates/astria-sequencer/src/storage/keys.rs | 8 +- 20 files changed, 260 insertions(+), 308 deletions(-) diff --git a/crates/astria-core/src/primitive/v1/asset/denom.rs b/crates/astria-core/src/primitive/v1/asset/denom.rs index 017c690ff9..6913f2321b 100644 --- a/crates/astria-core/src/primitive/v1/asset/denom.rs +++ b/crates/astria-core/src/primitive/v1/asset/denom.rs @@ -565,17 +565,17 @@ pub struct IbcPrefixed { } impl IbcPrefixed { - pub const LENGTH: usize = 32; + pub const ENCODED_HASH_LEN: usize = 32; #[must_use] - pub const fn new(id: [u8; Self::LENGTH]) -> Self { + pub const fn new(id: [u8; Self::ENCODED_HASH_LEN]) -> Self { Self { id, } } #[must_use] - pub const fn as_bytes(&self) -> &[u8; Self::LENGTH] { + pub const fn as_bytes(&self) -> &[u8; Self::ENCODED_HASH_LEN] { &self.id } @@ -610,7 +610,7 @@ impl FromStr for IbcPrefixed { if segments.next().is_some() { return Err(ParseIbcPrefixedError::too_many_segments()); } - let id = <[u8; Self::LENGTH]>::from_hex(hex).map_err(Self::Err::hex)?; + let id = <[u8; Self::ENCODED_HASH_LEN]>::from_hex(hex).map_err(Self::Err::hex)?; Ok(Self { id, }) diff --git a/crates/astria-sequencer/src/accounts/state_ext.rs b/crates/astria-sequencer/src/accounts/state_ext.rs index c62fbc2d9d..5348d0ee2d 100644 --- a/crates/astria-sequencer/src/accounts/state_ext.rs +++ b/crates/astria-sequencer/src/accounts/state_ext.rs @@ -31,11 +31,8 @@ use tracing::instrument; use super::storage::{ self, keys::{ - balance_key, - balance_prefix, + self, extract_asset_from_key, - nonce_key, - TRANSFER_BASE_FEE_KEY, }, }; use crate::{ @@ -126,7 +123,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { &self, address: &T, ) -> AccountAssetsStream { - let prefix = balance_prefix(address); + let prefix = keys::balance_prefix(address); AccountAssetsStream { underlying: self.prefix_keys(&prefix), } @@ -137,7 +134,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { &self, address: &T, ) -> AccountAssetBalancesStream { - let prefix = balance_prefix(address); + let prefix = keys::balance_prefix(address); AccountAssetBalancesStream { underlying: self.prefix_raw(&prefix), } @@ -155,7 +152,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { &'a TAsset: Into>, { let Some(bytes) = self - .get_raw(&balance_key(address, asset)) + .get_raw(&keys::balance(address, asset)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw account balance from state")? @@ -170,7 +167,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { #[instrument(skip_all)] async fn get_account_nonce(&self, address: &T) -> Result { let bytes = self - .get_raw(&nonce_key(address)) + .get_raw(&keys::nonce(address)) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw account nonce from state")?; @@ -186,7 +183,7 @@ pub(crate) trait StateReadExt: StateRead + crate::assets::StateReadExt { #[instrument(skip_all)] async fn get_transfer_base_fee(&self) -> Result { let bytes = self - .get_raw(TRANSFER_BASE_FEE_KEY) + .get_raw(keys::TRANSFER_BASE_FEE) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading raw transfer base fee from state")?; @@ -218,7 +215,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Balance::from(balance)) .serialize() .wrap_err("failed to serialize balance")?; - self.put_raw(balance_key(address, asset), bytes); + self.put_raw(keys::balance(address, asset), bytes); Ok(()) } @@ -227,7 +224,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Nonce::from(nonce)) .serialize() .wrap_err("failed to serialize nonce")?; - self.put_raw(nonce_key(address), bytes); + self.put_raw(keys::nonce(address), bytes); Ok(()) } @@ -290,7 +287,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::Fee::from(fee)) .serialize() .wrap_err("failed to serialize fee")?; - self.put_raw(TRANSFER_BASE_FEE_KEY.to_string(), bytes); + self.put_raw(keys::TRANSFER_BASE_FEE.to_string(), bytes); Ok(()) } } diff --git a/crates/astria-sequencer/src/accounts/storage/keys.rs b/crates/astria-sequencer/src/accounts/storage/keys.rs index f3f1a90349..d506f1ca15 100644 --- a/crates/astria-sequencer/src/accounts/storage/keys.rs +++ b/crates/astria-sequencer/src/accounts/storage/keys.rs @@ -10,12 +10,12 @@ use astria_eyre::eyre::{ use crate::{ accounts::AddressBytes, storage::keys::{ - AddressPrefixer, + AccountPrefixer, Asset, }, }; -pub(in crate::accounts) const TRANSFER_BASE_FEE_KEY: &str = "accounts/transfer_base_fee"; +pub(in crate::accounts) const TRANSFER_BASE_FEE: &str = "accounts/transfer_base_fee"; const COMPONENT_PREFIX: &str = "accounts/"; const BALANCE_PREFIX: &str = "balance/"; const NONCE: &str = "nonce"; @@ -25,13 +25,13 @@ const NONCE: &str = "nonce"; pub(in crate::accounts) fn balance_prefix(address: &TAddress) -> String { format!( "{}/{BALANCE_PREFIX}", - AddressPrefixer::new(COMPONENT_PREFIX, address) + AccountPrefixer::new(COMPONENT_PREFIX, address) ) } /// Example: `accounts/0101....0101/balance/0202....0202`. /// |40 hex chars| |64 hex chars| -pub(in crate::accounts) fn balance_key<'a, TAddress, TAsset>( +pub(in crate::accounts) fn balance<'a, TAddress, TAsset>( address: &TAddress, asset: &'a TAsset, ) -> String @@ -41,17 +41,17 @@ where { format!( "{}/{BALANCE_PREFIX}{}", - AddressPrefixer::new(COMPONENT_PREFIX, address), + AccountPrefixer::new(COMPONENT_PREFIX, address), Asset::from(asset) ) } /// Example: `accounts/0101....0101/nonce`. /// |40 hex chars| -pub(in crate::accounts) fn nonce_key(address: &TAddress) -> String { +pub(in crate::accounts) fn nonce(address: &TAddress) -> String { format!( "{}/{NONCE}", - AddressPrefixer::new(COMPONENT_PREFIX, address) + AccountPrefixer::new(COMPONENT_PREFIX, address) ) } @@ -86,27 +86,27 @@ mod tests { #[test] fn keys_should_not_change() { - insta::assert_snapshot!(TRANSFER_BASE_FEE_KEY); - insta::assert_snapshot!(balance_key(&address(), &asset())); - insta::assert_snapshot!(nonce_key(&address())); + insta::assert_snapshot!(TRANSFER_BASE_FEE); + insta::assert_snapshot!(balance(&address(), &asset())); + insta::assert_snapshot!(nonce(&address())); } #[test] fn keys_should_have_component_prefix() { - assert!(TRANSFER_BASE_FEE_KEY.starts_with(COMPONENT_PREFIX)); - assert!(balance_key(&address(), &asset()).starts_with(COMPONENT_PREFIX)); - assert!(nonce_key(&address()).starts_with(COMPONENT_PREFIX)); + assert!(TRANSFER_BASE_FEE.starts_with(COMPONENT_PREFIX)); + assert!(balance(&address(), &asset()).starts_with(COMPONENT_PREFIX)); + assert!(nonce(&address()).starts_with(COMPONENT_PREFIX)); } #[test] fn balance_prefix_should_be_prefix_of_balance_key() { - assert!(balance_key(&address(), &asset()).starts_with(&balance_prefix(&address()))); + assert!(balance(&address(), &asset()).starts_with(&balance_prefix(&address()))); } #[test] fn should_extract_asset_from_key() { let asset = IbcPrefixed::new([2; 32]); - let key = balance_key(&[1; 20], &asset); + let key = balance(&[1; 20], &asset); let recovered_asset = extract_asset_from_key(&key).unwrap(); assert_eq!(asset, recovered_asset); } diff --git a/crates/astria-sequencer/src/address/state_ext.rs b/crates/astria-sequencer/src/address/state_ext.rs index 6d1a4ea6d9..0f5cd5bf30 100644 --- a/crates/astria-sequencer/src/address/state_ext.rs +++ b/crates/astria-sequencer/src/address/state_ext.rs @@ -20,10 +20,7 @@ use tracing::instrument; use super::storage::{ self, - keys::{ - BASE_PREFIX_KEY, - IBC_COMPAT_PREFIX_KEY, - }, + keys, }; use crate::storage::StoredValue; @@ -57,7 +54,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all, err)] async fn get_base_prefix(&self) -> Result { let Some(bytes) = self - .get_raw(BASE_PREFIX_KEY) + .get_raw(keys::BASE_PREFIX) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading address base prefix from state")? @@ -72,7 +69,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all, err)] async fn get_ibc_compat_prefix(&self) -> Result { let Some(bytes) = self - .get_raw(IBC_COMPAT_PREFIX_KEY) + .get_raw(keys::IBC_COMPAT_PREFIX) .await .map_err(anyhow_to_eyre) .wrap_err("failed reading address ibc compat prefix from state")? @@ -94,7 +91,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::AddressPrefix::from(prefix.as_str())) .serialize() .context("failed to serialize base prefix")?; - self.put_raw(BASE_PREFIX_KEY.to_string(), bytes); + self.put_raw(keys::BASE_PREFIX.to_string(), bytes); Ok(()) } @@ -103,7 +100,7 @@ pub(crate) trait StateWriteExt: StateWrite { let bytes = StoredValue::from(storage::AddressPrefix::from(prefix.as_str())) .serialize() .context("failed to serialize ibc-compat prefix")?; - self.put_raw(IBC_COMPAT_PREFIX_KEY.to_string(), bytes); + self.put_raw(keys::IBC_COMPAT_PREFIX.to_string(), bytes); Ok(()) } } diff --git a/crates/astria-sequencer/src/address/storage/keys.rs b/crates/astria-sequencer/src/address/storage/keys.rs index 84c2878629..af58a1d79f 100644 --- a/crates/astria-sequencer/src/address/storage/keys.rs +++ b/crates/astria-sequencer/src/address/storage/keys.rs @@ -1,5 +1,5 @@ -pub(in crate::address) const BASE_PREFIX_KEY: &str = "address/prefixes/base"; -pub(in crate::address) const IBC_COMPAT_PREFIX_KEY: &str = "address/prefixes/ibc_compat"; +pub(in crate::address) const BASE_PREFIX: &str = "address/prefixes/base"; +pub(in crate::address) const IBC_COMPAT_PREFIX: &str = "address/prefixes/ibc_compat"; #[cfg(test)] mod tests { @@ -9,13 +9,13 @@ mod tests { #[test] fn keys_should_not_change() { - insta::assert_snapshot!(BASE_PREFIX_KEY); - insta::assert_snapshot!(IBC_COMPAT_PREFIX_KEY); + insta::assert_snapshot!(BASE_PREFIX); + insta::assert_snapshot!(IBC_COMPAT_PREFIX); } #[test] fn keys_should_have_component_prefix() { - assert!(BASE_PREFIX_KEY.starts_with(COMPONENT_PREFIX)); - assert!(IBC_COMPAT_PREFIX_KEY.starts_with(COMPONENT_PREFIX)); + assert!(BASE_PREFIX.starts_with(COMPONENT_PREFIX)); + assert!(IBC_COMPAT_PREFIX.starts_with(COMPONENT_PREFIX)); } } diff --git a/crates/astria-sequencer/src/app/state_ext.rs b/crates/astria-sequencer/src/app/state_ext.rs index 621fbb6db5..c3c1480991 100644 --- a/crates/astria-sequencer/src/app/state_ext.rs +++ b/crates/astria-sequencer/src/app/state_ext.rs @@ -16,13 +16,7 @@ use tracing::instrument; use super::storage::{ self, - keys::{ - storage_version_by_height_key, - BLOCK_HEIGHT_KEY, - BLOCK_TIMESTAMP_KEY, - CHAIN_ID_KEY, - REVISION_NUMBER_KEY, - }, + keys, }; use crate::storage::StoredValue; @@ -31,7 +25,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_chain_id(&self) -> Result { let Some(bytes) = self - .get_raw(CHAIN_ID_KEY) + .get_raw(keys::CHAIN_ID) .await .map_err(anyhow_to_eyre) .wrap_err("failed to read raw chain_id from state")? @@ -46,7 +40,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_revision_number(&self) -> Result { let Some(bytes) = self - .get_raw(REVISION_NUMBER_KEY) + .get_raw(keys::REVISION_NUMBER) .await .map_err(anyhow_to_eyre) .wrap_err("failed to read raw revision number from state")? @@ -61,7 +55,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_block_height(&self) -> Result { let Some(bytes) = self - .get_raw(BLOCK_HEIGHT_KEY) + .get_raw(keys::BLOCK_HEIGHT) .await .map_err(anyhow_to_eyre) .wrap_err("failed to read raw block_height from state")? @@ -76,7 +70,7 @@ pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] async fn get_block_timestamp(&self) -> Result