Skip to content
This repository has been archived by the owner on Aug 2, 2024. It is now read-only.

Commit

Permalink
feat: add rpc traceBlock (#1416)
Browse files Browse the repository at this point in the history
  • Loading branch information
tdelabro authored Feb 9, 2024
1 parent e717451 commit a3101a4
Show file tree
Hide file tree
Showing 30 changed files with 882 additions and 232 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
- fix: get_block_by_block_hash then default rather than error
- feat(rpc): added `get_state_update` real values from DA db
- feat: add transparent representation to `Felt252Wrapper`
- feat(rpc/trace_api): add `trace_block_transaction`
- chore(db): changed the way hashes are encoded

## v0.7.0

Expand Down Expand Up @@ -80,7 +82,7 @@
- feat: fixing getNonce Rpc Call and adding a new test
- refactor: use Zaun crate for Starknet core contract bindings
- refactor: use Anvil sandbox from Zaun crate
- feat(rpc) : estimateMessageFee RPC call implementation
- feat(rpc): estimateMessageFee RPC call implementation

## v0.6.0

Expand Down
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 5 additions & 8 deletions crates/client/db/src/da_db.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::marker::PhantomData;
use std::sync::Arc;

// Substrate
use parity_scale_codec::{Decode, Encode};
use sp_database::Database;
use sp_runtime::traits::Block as BlockT;
// Starknet
use starknet_api::block::BlockHash;
use starknet_api::hash::StarkFelt;
Expand All @@ -14,17 +12,16 @@ use uuid::Uuid;
use crate::{DbError, DbHash};

// The fact db stores DA facts that need to be written to L1
pub struct DaDb<B: BlockT> {
pub struct DaDb {
pub(crate) db: Arc<dyn Database<DbHash>>,
pub(crate) _marker: PhantomData<B>,
}

// TODO: purge old cairo job keys
impl<B: BlockT> DaDb<B> {
pub fn state_diff(&self, block_hash: &BlockHash) -> Result<ThinStateDiff, String> {
impl DaDb {
pub fn state_diff(&self, block_hash: &BlockHash) -> Result<ThinStateDiff, DbError> {
match self.db.get(crate::columns::DA, block_hash.0.bytes()) {
Some(raw) => Ok(ThinStateDiff::decode(&mut &raw[..]).map_err(|e| format!("{:?}", e))?),
None => Err(String::from("can't write state diff")),
Some(raw) => Ok(ThinStateDiff::decode(&mut &raw[..])?),
None => Err(DbError::ValueNotInitialized(crate::columns::DA, block_hash.to_string())),
}
}

Expand Down
39 changes: 39 additions & 0 deletions crates/client/db/src/l1_handler_tx_fee.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::sync::Arc;

use parity_scale_codec::Encode;
use sp_database::Database;
use starknet_api::hash::StarkFelt;
use starknet_api::transaction::Fee;

use crate::{DbError, DbHash};

pub struct L1HandlerTxFeeDb {
pub(crate) db: Arc<dyn Database<DbHash>>,
}

impl L1HandlerTxFeeDb {
/// Store the fee paid on l1 for a specific L1Handler transaction
pub fn store_fee_paid_for_l1_handler_tx(&self, tx_hash: StarkFelt, fee: Fee) -> Result<(), DbError> {
let mut transaction = sp_database::Transaction::new();

transaction.set(crate::columns::L1_HANDLER_PAID_FEE, &tx_hash.encode(), &fee.0.to_le_bytes());

self.db.commit(transaction)?;

Ok(())
}

/// Return the stored fee paid on l1 for a specific L1Handler transaction
pub fn get_fee_paid_for_l1_handler_tx(&self, tx_hash: StarkFelt) -> Result<Fee, DbError> {
if let Some(bytes) = self.db.get(crate::columns::L1_HANDLER_PAID_FEE, &tx_hash.encode()) {
let mut buff = [0u8; 16];

buff.copy_from_slice(&bytes);
let fee = u128::from_le_bytes(buff);

Ok(Fee(fee))
} else {
Err(DbError::ValueNotInitialized(crate::columns::L1_HANDLER_PAID_FEE, tx_hash.to_string()))
}
}
}
32 changes: 22 additions & 10 deletions crates/client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ mod db_opening_utils;
mod messaging_db;
mod sierra_classes_db;
pub use messaging_db::LastSyncedEventBlock;
mod l1_handler_tx_fee;
mod meta_db;

use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use da_db::DaDb;
use l1_handler_tx_fee::L1HandlerTxFeeDb;
use mapping_db::MappingDb;
use messaging_db::MessagingDb;
use meta_db::MetaDb;
Expand All @@ -51,7 +53,7 @@ pub(crate) mod columns {
// ===== /!\ ===================================================================================
// MUST BE INCREMENTED WHEN A NEW COLUMN IN ADDED
// ===== /!\ ===================================================================================
pub const NUM_COLUMNS: u32 = 8;
pub const NUM_COLUMNS: u32 = 9;

pub const META: u32 = 0;
pub const BLOCK_MAPPING: u32 = 1;
Expand All @@ -70,6 +72,9 @@ pub(crate) mod columns {

/// This column contains the Sierra contract classes
pub const SIERRA_CONTRACT_CLASSES: u32 = 7;

/// This column stores the fee paid on l1 for L1Handler transactions
pub const L1_HANDLER_PAID_FEE: u32 = 8;
}

pub mod static_keys {
Expand All @@ -86,9 +91,10 @@ pub mod static_keys {
pub struct Backend<B: BlockT> {
meta: Arc<MetaDb<B>>,
mapping: Arc<MappingDb<B>>,
da: Arc<DaDb<B>>,
messaging: Arc<MessagingDb<B>>,
sierra_classes: Arc<SierraClassesDb<B>>,
da: Arc<DaDb>,
messaging: Arc<MessagingDb>,
sierra_classes: Arc<SierraClassesDb>,
l1_handler_paid_fee: Arc<L1HandlerTxFeeDb>,
}

/// Returns the Starknet database directory.
Expand Down Expand Up @@ -128,9 +134,10 @@ impl<B: BlockT> Backend<B> {
Ok(Self {
mapping: Arc::new(MappingDb::new(db.clone(), cache_more_things)),
meta: Arc::new(MetaDb { db: db.clone(), _marker: PhantomData }),
da: Arc::new(DaDb { db: db.clone(), _marker: PhantomData }),
messaging: Arc::new(MessagingDb { db: db.clone(), _marker: PhantomData }),
sierra_classes: Arc::new(SierraClassesDb { db: db.clone(), _marker: PhantomData }),
da: Arc::new(DaDb { db: db.clone() }),
messaging: Arc::new(MessagingDb { db: db.clone() }),
sierra_classes: Arc::new(SierraClassesDb { db: db.clone() }),
l1_handler_paid_fee: Arc::new(L1HandlerTxFeeDb { db: db.clone() }),
})
}

Expand All @@ -145,20 +152,25 @@ impl<B: BlockT> Backend<B> {
}

/// Return the da database manager
pub fn da(&self) -> &Arc<DaDb<B>> {
pub fn da(&self) -> &Arc<DaDb> {
&self.da
}

/// Return the da database manager
pub fn messaging(&self) -> &Arc<MessagingDb<B>> {
pub fn messaging(&self) -> &Arc<MessagingDb> {
&self.messaging
}

/// Return the sierra classes database manager
pub fn sierra_classes(&self) -> &Arc<SierraClassesDb<B>> {
pub fn sierra_classes(&self) -> &Arc<SierraClassesDb> {
&self.sierra_classes
}

/// Return l1 handler tx paid fee database manager
pub fn l1_handler_paid_fee(&self) -> &Arc<L1HandlerTxFeeDb> {
&self.l1_handler_paid_fee
}

/// In the future, we will compute the block global state root asynchronously in the client,
/// using the Starknet-Bonzai-trie.
/// That what replaces it for now :)
Expand Down
21 changes: 12 additions & 9 deletions crates/client/db/src/mapping_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ use std::sync::{Arc, Mutex};

// Substrate
use parity_scale_codec::{Decode, Encode};
use sp_core::H256;
use sp_database::Database;
use sp_runtime::traits::Block as BlockT;
use starknet_api::hash::StarkHash;

use crate::{DbError, DbHash};

/// The mapping to write in db
#[derive(Debug)]
pub struct MappingCommitment<B: BlockT> {
pub block_hash: B::Hash,
pub starknet_block_hash: H256,
pub starknet_transaction_hashes: Vec<H256>,
pub starknet_block_hash: StarkHash,
pub starknet_transaction_hashes: Vec<StarkHash>,
}

/// Allow interaction with the mapping db
Expand Down Expand Up @@ -44,7 +44,7 @@ impl<B: BlockT> MappingDb<B> {
///
/// Under some circumstances it can return multiples blocks hashes, meaning that the result has
/// to be checked against the actual blockchain state in order to find the good one.
pub fn block_hash(&self, starknet_block_hash: &H256) -> Result<Option<Vec<B::Hash>>, DbError> {
pub fn block_hash(&self, starknet_block_hash: StarkHash) -> Result<Option<Vec<B::Hash>>, DbError> {
match self.db.get(crate::columns::BLOCK_MAPPING, &starknet_block_hash.encode()) {
Some(raw) => Ok(Some(Vec::<B::Hash>::decode(&mut &raw[..])?)),
None => Ok(None),
Expand All @@ -70,7 +70,7 @@ impl<B: BlockT> MappingDb<B> {

let mut transaction = sp_database::Transaction::new();

let substrate_hashes = match self.block_hash(&commitment.starknet_block_hash) {
let substrate_hashes = match self.block_hash(commitment.starknet_block_hash) {
Ok(Some(mut data)) => {
data.push(commitment.block_hash);
log::warn!(
Expand Down Expand Up @@ -121,7 +121,7 @@ impl<B: BlockT> MappingDb<B> {
/// * `transaction_hash` - the transaction hash to search for. H256 is used here because it's a
/// native type of substrate, and we are sure it's SCALE encoding is optimized and will not
/// change.
pub fn block_hash_from_transaction_hash(&self, transaction_hash: H256) -> Result<Option<B::Hash>, DbError> {
pub fn block_hash_from_transaction_hash(&self, transaction_hash: StarkHash) -> Result<Option<B::Hash>, DbError> {
match self.db.get(crate::columns::TRANSACTION_MAPPING, &transaction_hash.encode()) {
Some(raw) => Ok(Some(<B::Hash>::decode(&mut &raw[..])?)),
None => Ok(None),
Expand All @@ -142,14 +142,17 @@ impl<B: BlockT> MappingDb<B> {
///
/// - The cache is disabled.
/// - The provided `starknet_hash` is not present in the cache.
pub fn cached_transaction_hashes_from_block_hash(&self, starknet_hash: H256) -> Result<Option<Vec<H256>>, DbError> {
pub fn cached_transaction_hashes_from_block_hash(
&self,
starknet_block_hash: StarkHash,
) -> Result<Option<Vec<StarkHash>>, DbError> {
if !self.cache_more_things {
// The cache is not enabled, no need to even touch the database.
return Ok(None);
}

match self.db.get(crate::columns::STARKNET_TRANSACTION_HASHES_CACHE, &starknet_hash.encode()) {
Some(raw) => Ok(Some(Vec::<H256>::decode(&mut &raw[..])?)),
match self.db.get(crate::columns::STARKNET_TRANSACTION_HASHES_CACHE, &starknet_block_hash.encode()) {
Some(raw) => Ok(Some(Vec::<StarkHash>::decode(&mut &raw[..])?)),
None => Ok(None),
}
}
Expand Down
7 changes: 2 additions & 5 deletions crates/client/db/src/messaging_db.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use std::marker::PhantomData;
use std::sync::Arc;

// Substrate
use parity_scale_codec::{Decode, Encode};
use sp_database::Database;
use sp_runtime::traits::Block as BlockT;

use crate::error::DbError;
use crate::DbHash;

pub struct MessagingDb<B: BlockT> {
pub struct MessagingDb {
pub(crate) db: Arc<dyn Database<DbHash>>,
pub(crate) _marker: PhantomData<B>,
}

#[derive(Encode, Decode)]
Expand All @@ -26,7 +23,7 @@ impl LastSyncedEventBlock {
}
}

impl<B: BlockT> MessagingDb<B> {
impl MessagingDb {
pub fn last_synced_l1_block_with_event(&self) -> Result<LastSyncedEventBlock, DbError> {
match self.db.get(crate::columns::MESSAGING, crate::static_keys::LAST_SYNCED_L1_EVENT_BLOCK) {
Some(raw) => Ok(LastSyncedEventBlock::decode(&mut &raw[..])?),
Expand Down
13 changes: 5 additions & 8 deletions crates/client/db/src/sierra_classes_db.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
use std::marker::PhantomData;
use std::sync::Arc;

use parity_scale_codec::{Decode, Encode};
use sp_database::Database;
use sp_runtime::traits::Block as BlockT;
use starknet_api::hash::StarkFelt;
use starknet_api::api_core::ClassHash;
use starknet_api::state::ContractClass;

use crate::{DbError, DbHash};

/// Allow interaction with the sierra classes db
pub struct SierraClassesDb<B: BlockT> {
pub struct SierraClassesDb {
pub(crate) db: Arc<dyn Database<DbHash>>,
pub(crate) _marker: PhantomData<B>,
}

impl<B: BlockT> SierraClassesDb<B> {
pub fn store_sierra_class(&self, class_hash: StarkFelt, class: ContractClass) -> Result<(), DbError> {
impl SierraClassesDb {
pub fn store_sierra_class(&self, class_hash: ClassHash, class: ContractClass) -> Result<(), DbError> {
let mut transaction = sp_database::Transaction::new();

transaction.set(crate::columns::SIERRA_CONTRACT_CLASSES, &class_hash.encode(), &class.encode());
Expand All @@ -26,7 +23,7 @@ impl<B: BlockT> SierraClassesDb<B> {
Ok(())
}

pub fn get_sierra_class(&self, class_hash: StarkFelt) -> Result<Option<ContractClass>, DbError> {
pub fn get_sierra_class(&self, class_hash: ClassHash) -> Result<Option<ContractClass>, DbError> {
let opt_contract_class = self
.db
.get(crate::columns::SIERRA_CONTRACT_CLASSES, &class_hash.encode())
Expand Down
3 changes: 1 addition & 2 deletions crates/client/mapping-sync/src/sync_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use pallet_starknet_runtime_api::StarknetRuntimeApi;
use sc_client_api::backend::{Backend, StorageProvider};
use sp_api::ProvideRuntimeApi;
use sp_blockchain::{Backend as _, HeaderBackend};
use sp_core::H256;
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero};

fn sync_block<B: BlockT, C, BE, H>(client: &C, backend: &mc_db::Backend<B>, header: &B::Header) -> anyhow::Result<()>
Expand Down Expand Up @@ -46,7 +45,7 @@ where
starknet_transaction_hashes: digest_starknet_block
.transactions()
.iter()
.map(|tx| H256::from(tx.compute_hash::<H>(chain_id, false)))
.map(|tx| tx.compute_hash::<H>(chain_id, false).into())
.collect(),
};

Expand Down
5 changes: 5 additions & 0 deletions crates/client/rpc-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use starknet_core::types::{
DeployAccountTransactionResult, EventFilterWithPage, EventsPage, FeeEstimate, FieldElement, FunctionCall,
InvokeTransactionResult, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingTransactionReceipt,
MsgFromL1, SimulatedTransaction, SimulationFlag, StateUpdate, SyncStatusType, Transaction,
TransactionTraceWithHash,
};

#[serde_as]
Expand Down Expand Up @@ -178,4 +179,8 @@ pub trait StarknetTraceRpcApi {
transactions: Vec<BroadcastedTransaction>,
simulation_flags: Vec<SimulationFlag>,
) -> RpcResult<Vec<SimulatedTransaction>>;

#[method(name = "traceBlockTransactions")]
/// Returns the execution traces of all transactions included in the given block
async fn trace_block_transactions(&self, block_id: BlockId) -> RpcResult<Vec<TransactionTraceWithHash>>;
}
Loading

0 comments on commit a3101a4

Please sign in to comment.