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

feat: support trace methods in provider #481

Merged
merged 1 commit into from
Oct 22, 2023
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
79 changes: 78 additions & 1 deletion starknet-providers/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use starknet_core::types::{
ContractClass, DeclareTransactionResult, DeployAccountTransactionResult, EventFilter,
EventsPage, FeeEstimate, FieldElement, FunctionCall, InvokeTransactionResult,
MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingStateUpdate,
MaybePendingTransactionReceipt, MsgFromL1, SyncStatusType, Transaction,
MaybePendingTransactionReceipt, MsgFromL1, SimulatedTransaction, SimulationFlag,
SyncStatusType, Transaction, TransactionTrace, TransactionTraceWithHash,
};

use crate::{
Expand Down Expand Up @@ -551,6 +552,82 @@ impl Provider for AnyProvider {
),
}
}

async fn trace_transaction<H>(
&self,
transaction_hash: H,
) -> Result<TransactionTrace, ProviderError<Self::Error>>
where
H: AsRef<FieldElement> + Send + Sync,
{
match self {
Self::JsonRpcHttp(inner) => Ok(
<JsonRpcClient<HttpTransport> as Provider>::trace_transaction(
inner,
transaction_hash,
)
.await?,
),
Self::SequencerGateway(inner) => Ok(
<SequencerGatewayProvider as Provider>::trace_transaction(inner, transaction_hash)
.await?,
),
}
}

async fn simulate_transactions<B, T, S>(
&self,
block_id: B,
transactions: T,
simulation_flags: S,
) -> Result<Vec<SimulatedTransaction>, ProviderError<Self::Error>>
where
B: AsRef<BlockId> + Send + Sync,
T: AsRef<[BroadcastedTransaction]> + Send + Sync,
S: AsRef<[SimulationFlag]> + Send + Sync,
{
match self {
Self::JsonRpcHttp(inner) => Ok(
<JsonRpcClient<HttpTransport> as Provider>::simulate_transactions(
inner,
block_id,
transactions,
simulation_flags,
)
.await?,
),
Self::SequencerGateway(inner) => Ok(
<SequencerGatewayProvider as Provider>::simulate_transactions(
inner,
block_id,
transactions,
simulation_flags,
)
.await?,
),
}
}

async fn trace_block_transactions<H>(
&self,
block_hash: H,
) -> Result<Vec<TransactionTraceWithHash>, ProviderError<Self::Error>>
where
H: AsRef<FieldElement> + Send + Sync,
{
match self {
Self::JsonRpcHttp(inner) => Ok(
<JsonRpcClient<HttpTransport> as Provider>::trace_block_transactions(
inner, block_hash,
)
.await?,
),
Self::SequencerGateway(inner) => Ok(
<SequencerGatewayProvider as Provider>::trace_block_transactions(inner, block_hash)
.await?,
),
}
}
}

impl From<ProviderError<<JsonRpcClient<HttpTransport> as Provider>::Error>>
Expand Down
83 changes: 82 additions & 1 deletion starknet-providers/src/jsonrpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use starknet_core::{
EventFilterWithPage, EventsPage, FeeEstimate, FieldElement, FunctionCall,
InvokeTransactionResult, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs,
MaybePendingStateUpdate, MaybePendingTransactionReceipt, MsgFromL1, ResultPageRequest,
StarknetError, SyncStatusType, Transaction,
SimulatedTransaction, SimulationFlag, StarknetError, SyncStatusType, Transaction,
TransactionTrace, TransactionTraceWithHash,
},
};

Expand Down Expand Up @@ -77,6 +78,12 @@ pub enum JsonRpcMethod {
AddDeclareTransaction,
#[serde(rename = "starknet_addDeployAccountTransaction")]
AddDeployAccountTransaction,
#[serde(rename = "starknet_traceTransaction")]
TraceTransaction,
#[serde(rename = "starknet_simulateTransactions")]
SimulateTransactions,
#[serde(rename = "starknet_traceBlockTransactions")]
TraceBlockTransactions,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -111,6 +118,9 @@ pub enum JsonRpcRequestData {
AddInvokeTransaction(AddInvokeTransactionRequest),
AddDeclareTransaction(AddDeclareTransactionRequest),
AddDeployAccountTransaction(AddDeployAccountTransactionRequest),
TraceTransaction(TraceTransactionRequest),
SimulateTransactions(SimulateTransactionsRequest),
TraceBlockTransactions(TraceBlockTransactionsRequest),
}

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -601,6 +611,65 @@ where
)
.await
}

/// For a given executed transaction, return the trace of its execution, including internal
/// calls
async fn trace_transaction<H>(
&self,
transaction_hash: H,
) -> Result<TransactionTrace, ProviderError<Self::Error>>
where
H: AsRef<FieldElement> + Send + Sync,
{
self.send_request(
JsonRpcMethod::TraceTransaction,
TraceTransactionRequestRef {
transaction_hash: transaction_hash.as_ref(),
},
)
.await
}

/// Simulate a given sequence of transactions on the requested state, and generate the execution
/// traces. If one of the transactions is reverted, raises CONTRACT_ERROR.
async fn simulate_transactions<B, TX, S>(
&self,
block_id: B,
transactions: TX,
simulation_flags: S,
) -> Result<Vec<SimulatedTransaction>, ProviderError<Self::Error>>
where
B: AsRef<BlockId> + Send + Sync,
TX: AsRef<[BroadcastedTransaction]> + Send + Sync,
S: AsRef<[SimulationFlag]> + Send + Sync,
{
self.send_request(
JsonRpcMethod::SimulateTransactions,
SimulateTransactionsRequestRef {
block_id: block_id.as_ref(),
transactions: transactions.as_ref(),
simulation_flags: simulation_flags.as_ref(),
},
)
.await
}

/// Retrieve traces for all transactions in the given block.
async fn trace_block_transactions<H>(
&self,
block_hash: H,
) -> Result<Vec<TransactionTraceWithHash>, ProviderError<Self::Error>>
where
H: AsRef<FieldElement> + Send + Sync,
{
self.send_request(
JsonRpcMethod::TraceBlockTransactions,
TraceBlockTransactionsRequestRef {
block_hash: block_hash.as_ref(),
},
)
.await
}
}

impl<'de> Deserialize<'de> for JsonRpcRequest {
Expand Down Expand Up @@ -725,6 +794,18 @@ impl<'de> Deserialize<'de> for JsonRpcRequest {
.map_err(error_mapper)?,
)
}
JsonRpcMethod::TraceTransaction => JsonRpcRequestData::TraceTransaction(
serde_json::from_value::<TraceTransactionRequest>(raw_request.params)
.map_err(error_mapper)?,
),
JsonRpcMethod::SimulateTransactions => JsonRpcRequestData::SimulateTransactions(
serde_json::from_value::<SimulateTransactionsRequest>(raw_request.params)
.map_err(error_mapper)?,
),
JsonRpcMethod::TraceBlockTransactions => JsonRpcRequestData::TraceBlockTransactions(
serde_json::from_value::<TraceBlockTransactionsRequest>(raw_request.params)
.map_err(error_mapper)?,
),
};

Ok(Self {
Expand Down
61 changes: 60 additions & 1 deletion starknet-providers/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use starknet_core::types::{
ContractClass, DeclareTransactionResult, DeployAccountTransactionResult, EventFilter,
EventsPage, FeeEstimate, FieldElement, FunctionCall, InvokeTransactionResult,
MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingStateUpdate,
MaybePendingTransactionReceipt, MsgFromL1, StarknetError, SyncStatusType, Transaction,
MaybePendingTransactionReceipt, MsgFromL1, SimulatedTransaction, SimulationFlag, StarknetError,
SyncStatusType, Transaction, TransactionTrace, TransactionTraceWithHash,
};
use std::error::Error;

Expand Down Expand Up @@ -202,6 +203,36 @@ pub trait Provider {
where
D: AsRef<BroadcastedDeployAccountTransaction> + Send + Sync;

/// For a given executed transaction, return the trace of its execution, including internal
/// calls
async fn trace_transaction<H>(
&self,
transaction_hash: H,
) -> Result<TransactionTrace, ProviderError<Self::Error>>
where
H: AsRef<FieldElement> + Send + Sync;

/// Simulate a given sequence of transactions on the requested state, and generate the execution
/// traces. If one of the transactions is reverted, raises CONTRACT_ERROR.
async fn simulate_transactions<B, T, S>(
&self,
block_id: B,
transactions: T,
simulation_flags: S,
) -> Result<Vec<SimulatedTransaction>, ProviderError<Self::Error>>
where
B: AsRef<BlockId> + Send + Sync,
T: AsRef<[BroadcastedTransaction]> + Send + Sync,
S: AsRef<[SimulationFlag]> + Send + Sync;

/// Retrieve traces for all transactions in the given block.
async fn trace_block_transactions<H>(
&self,
block_hash: H,
) -> Result<Vec<TransactionTraceWithHash>, ProviderError<Self::Error>>
where
H: AsRef<FieldElement> + Send + Sync;

/// Same as [estimate_fee], but only with one estimate.
async fn estimate_fee_single<R, B>(
&self,
Expand All @@ -223,6 +254,34 @@ pub trait Provider {
Err(ProviderError::ArrayLengthMismatch)
}
}

/// Same as [simulate_transactions], but only with one simulation.
async fn simulate_transaction<B, T, S>(
&self,
block_id: B,
transaction: T,
simulation_flags: S,
) -> Result<SimulatedTransaction, ProviderError<Self::Error>>
where
B: AsRef<BlockId> + Send + Sync,
T: AsRef<BroadcastedTransaction> + Send + Sync,
S: AsRef<[SimulationFlag]> + Send + Sync,
{
let mut result = self
.simulate_transactions(
block_id,
[transaction.as_ref().to_owned()],
simulation_flags,
)
.await?;

if result.len() == 1 {
// Unwrapping here is safe becuase we already checked length
Ok(result.pop().unwrap())
} else {
Err(ProviderError::ArrayLengthMismatch)
}
}
}

#[derive(Debug, thiserror::Error)]
Expand Down
6 changes: 6 additions & 0 deletions starknet-providers/src/sequencer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ pub enum GatewayClientError {
/// Model conversion error (only when using as [Provider])
#[error("unable to convert gateway models to jsonrpc types")]
ModelConversionError,
/// Simulating multiple transactions is not supported (only when using as [Provider])
#[error("simulating multiple transactions not supported")]
BulkSimulationNotSupported,
/// At least one of the simulation flags is not supported (only when using as [Provider])
#[error("unsupported simulation flag")]
UnsupportedSimulationFlag,
}

#[derive(Debug, thiserror::Error, Deserialize)]
Expand Down
Loading
Loading