Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

store events #106

Merged
merged 7 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next release

- feat: store events in block, return events in call get_transaction_receipt
- feat: types in `mp-transactions` impl a method to get their version
- feat: make L1 gas price a `const` of the `RuntimeConfig`
- fix: broken class hashes and contracts in genesis
Expand Down
16 changes: 11 additions & 5 deletions crates/client/deoxys/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@ pub fn block(block: &p::Block) -> mp_block::Block {
extra_data: block.block_hash.map(|h| sp_core::U256::from_big_endian(&h.to_bytes_be())),
};

mp_block::Block::new(header, transactions)
let ordered_events: Vec<mp_block::OrderedEvents> = block
.transaction_receipts
.iter()
.enumerate()
.filter(|(_, r)| r.events.len() > 0)
.map(|(i, r)| mp_block::OrderedEvents::new(i as u128, r.events.iter().map(event).collect()))
.collect();

mp_block::Block::new(header, transactions, ordered_events)
}

fn transactions(txs: &[p::TransactionType]) -> Vec<mp_transactions::Transaction> {
Expand Down Expand Up @@ -141,14 +149,12 @@ fn l1_handler_transaction(tx: &p::L1HandlerTransaction) -> mp_transactions::Hand
/// Converts a starknet version string to a felt value.
/// If the string contains more than 31 bytes, the function panics.
fn starknet_version(version: &Option<String>) -> Felt252Wrapper {
let ret = match version {
match version {
Some(version) => {
Felt252Wrapper::try_from(version.as_bytes()).expect("Failed to convert version to felt: string is too long")
}
None => Felt252Wrapper::ZERO,
};
println!("Starknet version: {}", ret.from_utf8().unwrap());
ret
}
}

fn fee(felt: starknet_ff::FieldElement) -> u128 {
Expand Down
9 changes: 5 additions & 4 deletions crates/client/deoxys/src/state_updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,11 @@ impl Decode for StateUpdateWrapper {

// // for contract in &state_update.state_diff.deployed_contracts {
// // let contract_address =
// ContractAddress(PatriciaKey(contract.address.try_into().map_err(|_| // BuildCommitmentStateDiffError::ConversionError)?
// )); let class_hash = // ClassHash(contract.class_hash.try_into().map_err(|_|
// // BuildCommitmentStateDiffError::ConversionError)?); let compiled_class_hash:
// // CompiledClassHash = calculate_compiled_class_hash(&class_hash);
// ContractAddress(PatriciaKey(contract.address.try_into().map_err(|_| //
// BuildCommitmentStateDiffError::ConversionError)? )); let class_hash = //
// ClassHash(contract.class_hash.try_into().map_err(|_| //
// BuildCommitmentStateDiffError::ConversionError)? ); let compiled_class_hash: //
// CompiledClassHash = calculate_compiled_class_hash(&class_hash);

// // commitment_state_diff.address_to_class_hash.insert(contract_address, class_hash);
// // commitment_state_diff.class_hash_to_compiled_class_hash.insert(class_hash,
Expand Down
162 changes: 55 additions & 107 deletions crates/client/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1350,66 +1350,23 @@ where
&self,
transaction_hash: FieldElement,
) -> RpcResult<MaybePendingTransactionReceipt> {
async fn wait_for_tx_inclusion<B: sp_api::BlockT>(
madara_backend: Arc<MadaraBackend<B>>,
transaction_hash: FieldElement,
) -> Result<<B as BlockT>::Hash, StarknetRpcApiError> {
let substrate_block_hash;

loop {
let substrate_block_hash_from_db = madara_backend
.mapping()
.block_hash_from_transaction_hash(H256::from(transaction_hash.to_bytes_be()))
.map_err(|e| {
error!("Failed to interact with db backend error: {e}");
StarknetRpcApiError::InternalServerError
})?;

match substrate_block_hash_from_db {
Some(block_hash) => {
substrate_block_hash = block_hash;
break;
}
None => {
// TODO: hardcoded to match the blocktime; make it dynamic
tokio::time::sleep(std::time::Duration::from_millis(6000)).await;
continue;
}
};
}

Ok(substrate_block_hash)
}

let substrate_block_hash = match tokio::time::timeout(
std::time::Duration::from_millis(60000),
wait_for_tx_inclusion(self.backend.clone(), transaction_hash),
)
.await
{
Err(_) => {
error!("did not receive tx hash within 1 minute");
return Err(StarknetRpcApiError::TxnHashNotFound.into());
}
Ok(res) => res,
}?;
let substrate_block_hash = self
.backend
.mapping()
.block_hash_from_transaction_hash(H256::from(transaction_hash.to_bytes_be()))
.map_err(|e| {
error!("Failed to interact with db backend error: {e}");
StarknetRpcApiError::InternalServerError
})?
.ok_or(StarknetRpcApiError::TxnHashNotFound)?;

let starknet_block: mp_block::Block =
get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default();
let block_header = starknet_block.header();
let block_hash = block_header.hash::<H>().into();
let block_hash: Felt252Wrapper = block_header.hash::<H>().into();
let block_number = block_header.block_number;

let block_extrinsics = self
.client
.block_body(substrate_block_hash)
.map_err(|e| {
error!("Failed to get block body. Substrate block hash: {substrate_block_hash}, error: {e}");
StarknetRpcApiError::InternalServerError
})?
.ok_or(StarknetRpcApiError::BlockNotFound)?;

let chain_id = self.chain_id()?.0.into();
let chain_id = self.chain_id()?.0;

let starknet_version = starknet_block.header().protocol_version;

Expand All @@ -1419,31 +1376,39 @@ where
StarknetRpcApiError::InternalServerError
})?;

let (tx_index, transaction) = self
.client
.runtime_api()
.get_index_and_tx_for_tx_hash(substrate_block_hash, block_extrinsics, chain_id, transaction_hash.into())
.map_err(|e| {
error!(
"Failed to get index for transaction hash. Substrate block hash: {substrate_block_hash}, \
transaction hash: {transaction_hash}, error: {e}"
);
StarknetRpcApiError::InternalServerError
})?
.expect("the transaction should be present in the substrate extrinsics"); // not reachable
let block_txs_hashes: Vec<_> = if let Some(tx_hashes) = self.get_cached_transaction_hashes(block_hash.into()) {
tx_hashes
.into_iter()
.map(|h| {
h256_to_felt(h)
.map_err(|e| {
CallError::Failed(anyhow::anyhow!(
"The hash cached for block with hash {block_hash:?} is an invalid felt: '{h}'. The \
caching db has probably been tempered"
))
})
.unwrap()
})
.collect()
} else {
starknet_block
.transactions_hashes::<H>(chain_id.into(), Some(starknet_block.header().block_number))
.map(FieldElement::from)
.collect()
};

let events = self
.client
.runtime_api()
.get_events_for_tx_by_index(substrate_block_hash, tx_index)
.map_err(|e| {
error!(
"Failed to get events for transaction index. Substrate block hash: {substrate_block_hash}, \
transaction idx: {tx_index}, error: {e}"
);
StarknetRpcApiError::InternalServerError
})?
.expect("the transaction should be present in the substrate extrinsics"); // not reachable
let (tx_index, _) =
block_txs_hashes.into_iter().enumerate().find(|(_, hash)| hash == &transaction_hash.into()).unwrap().into();

let transaction = starknet_block.transactions().get(tx_index).unwrap();

let events = starknet_block
.events()
.into_iter()
.filter(|event| event.index == tx_index as u128)
.flat_map(|event| event.events.clone())
.map(event_conversion)
.collect();

let execution_result = {
let revert_error = self
Expand Down Expand Up @@ -1476,24 +1441,7 @@ where
}
}

let events_converted: Vec<starknet_core::types::Event> =
events.clone().into_iter().map(event_conversion).collect();

let actual_fee = if fee_disabled {
FieldElement::ZERO
} else {
// Event {
// from_address: fee_token_address,
// keys: [selector("Transfer")],
// data: [
// send_from_address, // account_contract_address
// send_to_address, // to (sequencer address)
// expected_fee_value_low, // transfer amount (fee)
// expected_fee_value_high,
// ]},
// fee transfer must be the last event, except enabled disable-transaction-fee feature
events_converted.last().unwrap().data[2]
};
let actual_fee = FieldElement::ZERO;

let actual_status = if starknet_block.header().block_number
<= mc_deoxys::l1::ETHEREUM_STATE_UPDATE.lock().unwrap().block_number.0
Expand Down Expand Up @@ -1524,13 +1472,13 @@ where
// TODO: use actual execution ressources
let receipt = match transaction {
mp_transactions::Transaction::Declare(_) => TransactionReceipt::Declare(DeclareTransactionReceipt {
transaction_hash,
transaction_hash: transaction_hash.into(),
actual_fee,
finality_status: actual_status,
block_hash,
block_hash: block_hash.into(),
block_number,
messages_sent: messages.into_iter().map(message_conversion).collect(),
events: events_converted,
events,
execution_result,
execution_resources: ExecutionResources {
steps: 0,
Expand All @@ -1549,10 +1497,10 @@ where
transaction_hash,
actual_fee,
finality_status: actual_status,
block_hash,
block_hash: block_hash.into(),
block_number,
messages_sent: messages.into_iter().map(message_conversion).collect(),
events: events_converted,
events,
contract_address: tx.get_account_address(),
execution_result,
execution_resources: ExecutionResources {
Expand All @@ -1572,10 +1520,10 @@ where
transaction_hash,
actual_fee,
finality_status: actual_status,
block_hash,
block_hash: block_hash.into(),
block_number,
messages_sent: Default::default(),
events: events_converted,
events,
contract_address: tx.get_account_address(),
execution_result,
execution_resources: ExecutionResources {
Expand All @@ -1594,10 +1542,10 @@ where
transaction_hash,
actual_fee,
finality_status: actual_status,
block_hash,
block_hash: block_hash.into(),
block_number,
messages_sent: messages.into_iter().map(message_conversion).collect(),
events: events_converted,
events,
execution_result,
execution_resources: ExecutionResources {
steps: 0,
Expand All @@ -1616,10 +1564,10 @@ where
transaction_hash,
actual_fee,
finality_status: actual_status,
block_hash,
block_hash: block_hash.into(),
block_number,
messages_sent: messages.into_iter().map(message_conversion).collect(),
events: events_converted,
events,
execution_result,
execution_resources: ExecutionResources {
steps: 0,
Expand Down
3 changes: 3 additions & 0 deletions crates/pallets/starknet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,8 @@ impl<T: Config> Pallet<T> {
let extra_data = None;
let l1_gas_price = T::L1GasPrice::get();

let ordered_events = vec![];

let block = StarknetBlock::new(
StarknetHeader::new(
parent_block_hash.into(),
Expand All @@ -1046,6 +1048,7 @@ impl<T: Config> Pallet<T> {
extra_data,
),
transactions,
ordered_events,
);
// Save the block number <> hash mapping.
let blockhash = block.header().hash::<T::SystemHash>();
Expand Down
20 changes: 16 additions & 4 deletions crates/primitives/block/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@
#[doc(hidden)]
pub extern crate alloc;

use alloc::vec::Vec;

mod header;
mod ordered_events;
pub mod state_update;

use alloc::vec::Vec;

pub use header::*;
use mp_felt::Felt252Wrapper;
use mp_hashers::HasherT;
use mp_transactions::compute_hash::ComputeTransactionHash;
use mp_transactions::Transaction;
pub use ordered_events::*;

/// Block Transactions
pub type BlockTransactions = Vec<Transaction>;

/// Block Events
pub type BlockEvents = Vec<OrderedEvents>;

/// Block tag.
///
/// A tag specifying a dynamic reference to a block.
Expand Down Expand Up @@ -50,6 +55,8 @@ pub struct Block {
header: Header,
/// The block transactions.
transactions: BlockTransactions,
/// The block events.
events: BlockEvents,
}

impl Block {
Expand All @@ -59,8 +66,8 @@ impl Block {
///
/// * `header` - The block header.
/// * `transactions` - The block transactions.
pub fn new(header: Header, transactions: BlockTransactions) -> Self {
Self { header, transactions }
pub fn new(header: Header, transactions: BlockTransactions, events: BlockEvents) -> Self {
Self { header, transactions, events }
}

/// Return a reference to the block header
Expand All @@ -73,6 +80,11 @@ impl Block {
&self.transactions
}

// Return a reference to all events
pub fn events(&self) -> &BlockEvents {
&self.events
}

/// Returns an iterator that iterates over all transaction hashes.
///
/// Those transactions are computed using the given `chain_id`.
Expand Down
Loading
Loading