Skip to content

Commit

Permalink
chore(sequencer)!: put blocks and deposits to non-verified storage (E…
Browse files Browse the repository at this point in the history
…NG-812) (#1525)

## Summary
This changes where sequencer blocks and the `TracePrefixed` native asset
are stored, and also persists `Deposit`s to non-verifiable storage.

## Background
Sequencer blocks are currently written to verified storage, which is
unnecessary as all of their constituent data is already available there.

We want to avoid the cost of storing full blocks in verified storage,
but still have the ability to provide a third party with a full block if
requested. To further assist with this, deposits will also be written to
non-verified storage.

It also seemed appropriate to store the `TracePrefixed` native asset in
verified storage, since this is something which all validators should
reach consensus over.

## Changes
- `SequencerBlock`s are now stored in non-verifiable storage.
- `Deposit`s are now stored in non-verifiable storage.
- The native asset is now stored in verifiable storage.

## Testing
Existing unit tests have been updated as required to assert these
changes.

## Breaking Changelist
- The set of data being written to verified storage has changed, which
is a breaking change in terms of on-disk data and generation of state
root hashes. Otherwise no APIs have changed.

## Related Issues
Closes #1493.
  • Loading branch information
Fraser999 authored Sep 26, 2024
1 parent 2da3a48 commit bda4ffc
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 749 deletions.
63 changes: 32 additions & 31 deletions crates/astria-sequencer/src/api_state_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,28 @@ use cnidarium::{
use prost::Message;
use tracing::instrument;

fn block_hash_by_height_key(height: u64) -> String {
format!("blockhash/{height}")
fn block_hash_by_height_key(height: u64) -> Vec<u8> {
[b"blockhash/".as_slice(), &height.to_le_bytes()].concat()
}

fn sequencer_block_header_by_hash_key(hash: &[u8]) -> String {
format!("blockheader/{}", crate::utils::Hex(hash))
fn sequencer_block_header_by_hash_key(hash: &[u8]) -> Vec<u8> {
[b"blockheader/", hash].concat()
}

fn rollup_data_by_hash_and_rollup_id_key(hash: &[u8], rollup_id: &RollupId) -> String {
format!("rollupdata/{}/{}", crate::utils::Hex(hash), rollup_id)
fn rollup_data_by_hash_and_rollup_id_key(hash: &[u8], rollup_id: &RollupId) -> Vec<u8> {
[b"rollupdata/", hash, rollup_id.as_ref()].concat()
}

fn rollup_ids_by_hash_key(hash: &[u8]) -> String {
format!("rollupids/{}", crate::utils::Hex(hash))
fn rollup_ids_by_hash_key(hash: &[u8]) -> Vec<u8> {
[b"rollupids/", hash].concat()
}

fn rollup_transactions_proof_by_hash_key(hash: &[u8]) -> String {
format!("rolluptxsproof/{}", crate::utils::Hex(hash))
fn rollup_transactions_proof_by_hash_key(hash: &[u8]) -> Vec<u8> {
[b"rolluptxsproof/", hash].concat()
}

fn rollup_ids_proof_by_hash_key(hash: &[u8]) -> String {
format!("rollupidsproof/{}", crate::utils::Hex(hash))
fn rollup_ids_proof_by_hash_key(hash: &[u8]) -> Vec<u8> {
[b"rollupidsproof/", hash].concat()
}

#[derive(BorshSerialize, BorshDeserialize)]
Expand Down Expand Up @@ -139,7 +139,7 @@ pub(crate) trait StateReadExt: StateRead {
async fn get_block_hash_by_height(&self, height: u64) -> Result<[u8; 32]> {
let key = block_hash_by_height_key(height);
let Some(hash) = self
.get_raw(&key)
.nonverifiable_get_raw(&key)
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read block hash by height from state")?
Expand All @@ -160,7 +160,7 @@ pub(crate) trait StateReadExt: StateRead {
) -> Result<SequencerBlockHeader> {
let key = sequencer_block_header_by_hash_key(hash);
let Some(header_bytes) = self
.get_raw(&key)
.nonverifiable_get_raw(&key)
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read raw sequencer block from state")?
Expand All @@ -179,7 +179,7 @@ pub(crate) trait StateReadExt: StateRead {
async fn get_rollup_ids_by_block_hash(&self, hash: &[u8]) -> Result<Vec<RollupId>> {
let key = rollup_ids_by_hash_key(hash);
let Some(rollup_ids_bytes) = self
.get_raw(&key)
.nonverifiable_get_raw(&key)
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read rollup IDs by block hash from state")?
Expand All @@ -195,7 +195,7 @@ pub(crate) trait StateReadExt: StateRead {
#[instrument(skip_all)]
async fn get_sequencer_block_by_hash(&self, hash: &[u8]) -> Result<SequencerBlock> {
let Some(header_bytes) = self
.get_raw(&sequencer_block_header_by_hash_key(hash))
.nonverifiable_get_raw(&sequencer_block_header_by_hash_key(hash))
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read raw sequencer block from state")?
Expand All @@ -214,10 +214,11 @@ pub(crate) trait StateReadExt: StateRead {
let mut rollup_transactions = Vec::with_capacity(rollup_ids.len());
for id in &rollup_ids {
let key = rollup_data_by_hash_and_rollup_id_key(hash, id);
let raw =
self.get_raw(&key).await.map_err(anyhow_to_eyre).wrap_err(
"failed to read rollup data by block hash and rollup ID from state",
)?;
let raw = self
.nonverifiable_get_raw(&key)
.await
.map_err(anyhow_to_eyre)
.context("failed to read rollup data by block hash and rollup ID from state")?;
if let Some(raw) = raw {
let raw = raw.as_slice();
let rollup_data = raw::RollupTransactions::decode(raw)
Expand All @@ -227,7 +228,7 @@ pub(crate) trait StateReadExt: StateRead {
}

let Some(rollup_transactions_proof) = self
.get_raw(&rollup_transactions_proof_by_hash_key(hash))
.nonverifiable_get_raw(&rollup_transactions_proof_by_hash_key(hash))
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read rollup transactions proof by block hash from state")?
Expand All @@ -240,7 +241,7 @@ pub(crate) trait StateReadExt: StateRead {
.wrap_err("failed to decode rollup transactions proof from raw bytes")?;

let Some(rollup_ids_proof) = self
.get_raw(&rollup_ids_proof_by_hash_key(hash))
.nonverifiable_get_raw(&rollup_ids_proof_by_hash_key(hash))
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read rollup IDs proof by block hash from state")?
Expand Down Expand Up @@ -284,7 +285,7 @@ pub(crate) trait StateReadExt: StateRead {
) -> Result<RollupTransactions> {
let key = rollup_data_by_hash_and_rollup_id_key(hash, rollup_id);
let Some(bytes) = self
.get_raw(&key)
.nonverifiable_get_raw(&key)
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read rollup data by block hash and rollup ID from state")?
Expand All @@ -306,7 +307,7 @@ pub(crate) trait StateReadExt: StateRead {
hash: &[u8],
) -> Result<(primitiveRaw::Proof, primitiveRaw::Proof)> {
let Some(rollup_transactions_proof) = self
.get_raw(&rollup_transactions_proof_by_hash_key(hash))
.nonverifiable_get_raw(&rollup_transactions_proof_by_hash_key(hash))
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read rollup transactions proof by block hash from state")?
Expand All @@ -319,7 +320,7 @@ pub(crate) trait StateReadExt: StateRead {
.wrap_err("failed to decode rollup transactions proof from raw bytes")?;

let Some(rollup_ids_proof) = self
.get_raw(&rollup_ids_proof_by_hash_key(hash))
.nonverifiable_get_raw(&rollup_ids_proof_by_hash_key(hash))
.await
.map_err(anyhow_to_eyre)
.wrap_err("failed to read rollup IDs proof by block hash from state")?
Expand Down Expand Up @@ -348,7 +349,7 @@ pub(crate) trait StateWriteExt: StateWrite {
// 6. block hash to rollup IDs proof

let key = block_hash_by_height_key(block.height().into());
self.put_raw(key, block.block_hash().to_vec());
self.nonverifiable_put_raw(key, block.block_hash().to_vec());

let rollup_ids = block
.rollup_transactions()
Expand All @@ -359,7 +360,7 @@ pub(crate) trait StateWriteExt: StateWrite {

let key = rollup_ids_by_hash_key(&block.block_hash());

self.put_raw(
self.nonverifiable_put_raw(
key,
borsh::to_vec(&RollupIdSeq(rollup_ids))
.wrap_err("failed to serialize rollup IDs list")?,
Expand All @@ -374,18 +375,18 @@ pub(crate) trait StateWriteExt: StateWrite {
rollup_ids_proof,
} = block.into_parts();
let header = header.into_raw();
self.put_raw(key, header.encode_to_vec());
self.nonverifiable_put_raw(key, header.encode_to_vec());

for (id, rollup_data) in rollup_transactions {
let key = rollup_data_by_hash_and_rollup_id_key(&block_hash, &id);
self.put_raw(key, rollup_data.into_raw().encode_to_vec());
self.nonverifiable_put_raw(key, rollup_data.into_raw().encode_to_vec());
}

let key = rollup_transactions_proof_by_hash_key(&block_hash);
self.put_raw(key, rollup_transactions_proof.into_raw().encode_to_vec());
self.nonverifiable_put_raw(key, rollup_transactions_proof.into_raw().encode_to_vec());

let key = rollup_ids_proof_by_hash_key(&block_hash);
self.put_raw(key, rollup_ids_proof.into_raw().encode_to_vec());
self.nonverifiable_put_raw(key, rollup_ids_proof.into_raw().encode_to_vec());

Ok(())
}
Expand Down
31 changes: 9 additions & 22 deletions crates/astria-sequencer/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,7 @@ impl App {
self.metrics
.record_proposal_transactions(signed_txs_included.len());

let deposits = self
.state
.get_block_deposits()
.await
.wrap_err("failed to get block deposits in prepare_proposal")?;
let deposits = self.state.get_cached_block_deposits();
self.metrics.record_proposal_deposits(deposits.len());

// generate commitment to sequence::Actions and deposits and commitment to the rollup IDs
Expand Down Expand Up @@ -444,11 +440,7 @@ impl App {
);
self.metrics.record_proposal_transactions(signed_txs.len());

let deposits = self
.state
.get_block_deposits()
.await
.wrap_err("failed to get block deposits in process_proposal")?;
let deposits = self.state.get_cached_block_deposits();
self.metrics.record_proposal_deposits(deposits.len());

let GeneratedCommitments {
Expand Down Expand Up @@ -871,21 +863,16 @@ impl App {

let end_block = self.end_block(height.value(), sudo_address).await?;

// get and clear block deposits from state
// get deposits for this block from state's ephemeral cache and put them to storage.
let mut state_tx = StateDelta::new(self.state.clone());
let deposits = self
.state
.get_block_deposits()
.await
.wrap_err("failed to get block deposits in end_block")?;
state_tx
.clear_block_deposits()
.await
.wrap_err("failed to clear block deposits")?;
let deposits_in_this_block = self.state.get_cached_block_deposits();
debug!(
deposits = %telemetry::display::json(&deposits),
deposits = %telemetry::display::json(&deposits_in_this_block),
"got block deposits from state"
);
state_tx
.put_deposits(&block_hash, deposits_in_this_block.clone())
.wrap_err("failed to put deposits to state")?;

let sequencer_block = SequencerBlock::try_from_block_info_and_data(
block_hash,
Expand All @@ -898,7 +885,7 @@ impl App {
.into_iter()
.map(std::convert::Into::into)
.collect(),
deposits,
deposits_in_this_block,
)
.wrap_err("failed to convert block info and data to SequencerBlock")?;
state_tx
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
---
source: crates/astria-sequencer/src/app/tests_breaking_changes.rs
assertion_line: 308
expression: app.app_hash.as_bytes()
---
[
237,
67,
124,
63,
240,
228,
62,
229,
45,
207,
78,
64,
191,
89,
84,
121,
150,
21,
207,
248,
173,
132,
77,
247,
126,
148,
252,
239,
251,
224,
244,
97,
68,
46,
184,
181,
205,
86,
212,
153,
66,
146,
179,
120,
206,
95,
76,
11,
0,
184,
137,
173
104,
130,
55,
201,
32,
57,
167,
215,
228
]
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
---
source: crates/astria-sequencer/src/app/tests_breaking_changes.rs
assertion_line: 157
expression: app.app_hash.as_bytes()
---
[
111,
25,
76,
238,
112,
77,
102,
234,
8,
97,
24,
100,
73,
128,
228,
106,
82,
255,
119,
93,
248,
7,
224,
51,
239,
115,
58,
9,
149,
86,
23,
113,
195,
128,
219,
248,
114
198,
108,
251,
204,
202,
182,
150,
203,
69,
213,
169,
101,
228,
90,
61,
94,
59,
180,
251,
59,
119,
37,
42,
216
]
Loading

0 comments on commit bda4ffc

Please sign in to comment.