Skip to content

Commit

Permalink
fix: ensure transaction executions are stored with fork and db provid…
Browse files Browse the repository at this point in the history
…ers (#1852)

* fix: ensure transaction executions are stored with fork and db providers

* feat: add implementation for TxExecutions into mdbx

* fix: ensure tests now include TxExecInfo and add missing implementations

* tests: add empty block testing

* fix: rename TxExecutions to TxTraces

* fix: use consistent naming to access tables

* fix: use 0 as default transaction hash for empty testing

* fix: enhance readability of iter with zip

* fix: use `Range` implementation

Co-authored-by: Ammar Arif <[email protected]>

---------

Co-authored-by: Ammar Arif <[email protected]>
  • Loading branch information
glihm and kariy authored Apr 22, 2024
1 parent 010444f commit f6510d5
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 43 deletions.
8 changes: 6 additions & 2 deletions crates/katana/core/src/backend/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ mod tests {
use katana_primitives::genesis::Genesis;
use katana_primitives::receipt::{InvokeTxReceipt, Receipt};
use katana_primitives::state::StateUpdatesWithDeclaredClasses;
use katana_primitives::trace::TxExecInfo;
use katana_primitives::transaction::{InvokeTx, Tx, TxWithHash};
use katana_primitives::FieldElement;
use katana_provider::providers::in_memory::InMemoryProvider;
Expand All @@ -154,7 +155,7 @@ mod tests {
HeaderProvider,
};
use katana_provider::traits::state::StateFactoryProvider;
use katana_provider::traits::transaction::TransactionProvider;
use katana_provider::traits::transaction::{TransactionProvider, TransactionTraceProvider};
use starknet::macros::felt;

use super::Blockchain;
Expand Down Expand Up @@ -254,7 +255,7 @@ mod tests {
dummy_block.clone(),
StateUpdatesWithDeclaredClasses::default(),
vec![Receipt::Invoke(InvokeTxReceipt::default())],
vec![],
vec![TxExecInfo::default()],
)
.unwrap();

Expand Down Expand Up @@ -310,11 +311,14 @@ mod tests {
.unwrap();

let tx = blockchain.provider().transaction_by_hash(dummy_tx.hash).unwrap().unwrap();
let tx_exec =
blockchain.provider().transaction_execution(dummy_tx.hash).unwrap().unwrap();

assert_eq!(block_hash, dummy_block.block.header.hash);
assert_eq!(block_number, dummy_block.block.header.header.number);
assert_eq!(block, dummy_block.block.unseal());
assert_eq!(tx, dummy_tx);
assert_eq!(tx_exec, TxExecInfo::default());
}
}
}
37 changes: 20 additions & 17 deletions crates/katana/storage/db/src/tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub enum TableType {
DupSort,
}

pub const NUM_TABLES: usize = 22;
pub const NUM_TABLES: usize = 23;

/// Macro to declare `libmdbx` tables.
#[macro_export]
Expand Down Expand Up @@ -153,6 +153,7 @@ define_tables_enum! {[
(TxNumbers, TableType::Table),
(TxBlocks, TableType::Table),
(TxHashes, TableType::Table),
(TxTraces, TableType::Table),
(Transactions, TableType::Table),
(Receipts, TableType::Table),
(CompiledClassHashes, TableType::Table),
Expand Down Expand Up @@ -189,8 +190,8 @@ tables! {
Transactions: (TxNumber) => Tx,
/// Stores the block number of a transaction.
TxBlocks: (TxNumber) => BlockNumber,
/// Stores the transaction's execution info.
TxExecutions: (TxNumber) => TxExecInfo,
/// Stores the transaction's traces.
TxTraces: (TxNumber) => TxExecInfo,
/// Store transaction receipts
Receipts: (TxNumber) => Receipt,
/// Store compiled classes
Expand Down Expand Up @@ -242,20 +243,21 @@ mod tests {
assert_eq!(Tables::ALL[5].name(), TxNumbers::NAME);
assert_eq!(Tables::ALL[6].name(), TxBlocks::NAME);
assert_eq!(Tables::ALL[7].name(), TxHashes::NAME);
assert_eq!(Tables::ALL[8].name(), Transactions::NAME);
assert_eq!(Tables::ALL[9].name(), Receipts::NAME);
assert_eq!(Tables::ALL[10].name(), CompiledClassHashes::NAME);
assert_eq!(Tables::ALL[11].name(), CompiledClasses::NAME);
assert_eq!(Tables::ALL[12].name(), SierraClasses::NAME);
assert_eq!(Tables::ALL[13].name(), ContractInfo::NAME);
assert_eq!(Tables::ALL[14].name(), ContractStorage::NAME);
assert_eq!(Tables::ALL[15].name(), ClassDeclarationBlock::NAME);
assert_eq!(Tables::ALL[16].name(), ClassDeclarations::NAME);
assert_eq!(Tables::ALL[17].name(), ContractInfoChangeSet::NAME);
assert_eq!(Tables::ALL[18].name(), NonceChangeHistory::NAME);
assert_eq!(Tables::ALL[19].name(), ClassChangeHistory::NAME);
assert_eq!(Tables::ALL[20].name(), StorageChangeHistory::NAME);
assert_eq!(Tables::ALL[21].name(), StorageChangeSet::NAME);
assert_eq!(Tables::ALL[8].name(), TxTraces::NAME);
assert_eq!(Tables::ALL[9].name(), Transactions::NAME);
assert_eq!(Tables::ALL[10].name(), Receipts::NAME);
assert_eq!(Tables::ALL[11].name(), CompiledClassHashes::NAME);
assert_eq!(Tables::ALL[12].name(), CompiledClasses::NAME);
assert_eq!(Tables::ALL[13].name(), SierraClasses::NAME);
assert_eq!(Tables::ALL[14].name(), ContractInfo::NAME);
assert_eq!(Tables::ALL[15].name(), ContractStorage::NAME);
assert_eq!(Tables::ALL[16].name(), ClassDeclarationBlock::NAME);
assert_eq!(Tables::ALL[17].name(), ClassDeclarations::NAME);
assert_eq!(Tables::ALL[18].name(), ContractInfoChangeSet::NAME);
assert_eq!(Tables::ALL[19].name(), NonceChangeHistory::NAME);
assert_eq!(Tables::ALL[20].name(), ClassChangeHistory::NAME);
assert_eq!(Tables::ALL[21].name(), StorageChangeHistory::NAME);
assert_eq!(Tables::ALL[22].name(), StorageChangeSet::NAME);

assert_eq!(Tables::Headers.table_type(), TableType::Table);
assert_eq!(Tables::BlockHashes.table_type(), TableType::Table);
Expand All @@ -265,6 +267,7 @@ mod tests {
assert_eq!(Tables::TxNumbers.table_type(), TableType::Table);
assert_eq!(Tables::TxBlocks.table_type(), TableType::Table);
assert_eq!(Tables::TxHashes.table_type(), TableType::Table);
assert_eq!(Tables::TxTraces.table_type(), TableType::Table);
assert_eq!(Tables::Transactions.table_type(), TableType::Table);
assert_eq!(Tables::Receipts.table_type(), TableType::Table);
assert_eq!(Tables::CompiledClassHashes.table_type(), TableType::Table);
Expand Down
4 changes: 4 additions & 0 deletions crates/katana/storage/provider/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ pub enum ProviderError {
#[error("Missing transaction receipt for tx number {0}")]
MissingTxReceipt(TxNumber),

/// Error when a transaction execution info is not found but the transaction exists.
#[error("Missing transaction execution for tx number {0}")]
MissingTxExecution(TxNumber),

/// Error when a compiled class hash is not found but the class hash exists.
#[error("Missing compiled class hash for class hash {0:#x}")]
MissingCompiledClassHash(ClassHash),
Expand Down
56 changes: 44 additions & 12 deletions crates/katana/storage/provider/src/providers/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,25 +492,49 @@ impl TransactionStatusProvider for DbProvider {
}

impl TransactionTraceProvider for DbProvider {
fn transaction_execution(&self, _hash: TxHash) -> ProviderResult<Option<TxExecInfo>> {
todo!()
fn transaction_execution(&self, hash: TxHash) -> ProviderResult<Option<TxExecInfo>> {
let db_tx = self.0.tx()?;
if let Some(num) = db_tx.get::<tables::TxNumbers>(hash)? {
let execution = db_tx
.get::<tables::TxTraces>(num)?
.ok_or(ProviderError::MissingTxExecution(num))?;

db_tx.commit()?;
Ok(Some(execution))
} else {
Ok(None)
}
}

fn transactions_executions_by_block(
&self,
_block_id: BlockHashOrNumber,
block_id: BlockHashOrNumber,
) -> ProviderResult<Option<Vec<TxExecInfo>>> {
todo!()
if let Some(indices) = self.block_body_indices(block_id)? {
let db_tx = self.0.tx()?;
let mut executions = Vec::with_capacity(indices.tx_count as usize);

let range = Range::from(indices);
for i in range {
if let Some(execution) = db_tx.get::<tables::TxTraces>(i)? {
executions.push(execution);
}
}

db_tx.commit()?;
Ok(Some(executions))
} else {
Ok(None)
}
}
}

impl ReceiptProvider for DbProvider {
fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Receipt>> {
let db_tx = self.0.tx()?;
if let Some(num) = db_tx.get::<tables::TxNumbers>(hash)? {
let receipt = db_tx
.get::<katana_db::tables::Receipts>(num)?
.ok_or(ProviderError::MissingTxReceipt(num))?;
let receipt =
db_tx.get::<tables::Receipts>(num)?.ok_or(ProviderError::MissingTxReceipt(num))?;

db_tx.commit()?;
Ok(Some(receipt))
Expand Down Expand Up @@ -561,7 +585,7 @@ impl BlockWriter for DbProvider {
block: SealedBlockWithStatus,
states: StateUpdatesWithDeclaredClasses,
receipts: Vec<Receipt>,
_executions: Vec<TxExecInfo>,
executions: Vec<TxExecInfo>,
) -> ProviderResult<()> {
self.0.update(move |db_tx| -> ProviderResult<()> {
let block_hash = block.block.header.hash;
Expand All @@ -581,7 +605,13 @@ impl BlockWriter for DbProvider {
db_tx.put::<tables::Headers>(block_number, block_header)?;
db_tx.put::<tables::BlockBodyIndices>(block_number, block_body_indices)?;

for (i, (transaction, receipt)) in transactions.into_iter().zip(receipts).enumerate() {
for (i, (transaction, receipt, execution)) in transactions
.into_iter()
.zip(receipts.into_iter())
.zip(executions.into_iter())
.map(|((transaction, receipt), execution)| (transaction, receipt, execution))
.enumerate()
{
let tx_number = tx_offset + i as u64;
let tx_hash = transaction.hash;

Expand All @@ -590,6 +620,7 @@ impl BlockWriter for DbProvider {
db_tx.put::<tables::TxBlocks>(tx_number, block_number)?;
db_tx.put::<tables::Transactions>(tx_number, transaction.transaction)?;
db_tx.put::<tables::Receipts>(tx_number, receipt)?;
db_tx.put::<tables::TxTraces>(tx_number, execution)?;
}

// insert classes
Expand Down Expand Up @@ -727,6 +758,7 @@ mod tests {
use katana_primitives::contract::ContractAddress;
use katana_primitives::receipt::Receipt;
use katana_primitives::state::{StateUpdates, StateUpdatesWithDeclaredClasses};
use katana_primitives::trace::TxExecInfo;
use katana_primitives::transaction::{InvokeTx, Tx, TxHash, TxWithHash};
use starknet::macros::felt;

Expand Down Expand Up @@ -812,7 +844,7 @@ mod tests {
block.clone(),
state_updates,
vec![Receipt::Invoke(Default::default())],
vec![],
vec![TxExecInfo::default()],
)
.expect("failed to insert block");

Expand Down Expand Up @@ -890,7 +922,7 @@ mod tests {
block.clone(),
state_updates1,
vec![Receipt::Invoke(Default::default())],
vec![],
vec![TxExecInfo::default()],
)
.expect("failed to insert block");

Expand All @@ -900,7 +932,7 @@ mod tests {
block,
state_updates2,
vec![Receipt::Invoke(Default::default())],
vec![],
vec![TxExecInfo::default()],
)
.expect("failed to insert block");

Expand Down
3 changes: 2 additions & 1 deletion crates/katana/storage/provider/src/providers/fork/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ impl BlockWriter for ForkedProvider {
block: SealedBlockWithStatus,
states: StateUpdatesWithDeclaredClasses,
receipts: Vec<Receipt>,
_executions: Vec<TxExecInfo>,
executions: Vec<TxExecInfo>,
) -> ProviderResult<()> {
let mut storage = self.storage.write();

Expand Down Expand Up @@ -494,6 +494,7 @@ impl BlockWriter for ForkedProvider {
storage.transaction_numbers.extend(txs_num);
storage.transaction_block.extend(txs_block);
storage.receipts.extend(receipts);
storage.transactions_executions.extend(executions);

storage.state_update.insert(block_number, states.state_updates.clone());

Expand Down
Loading

0 comments on commit f6510d5

Please sign in to comment.