Skip to content

Commit

Permalink
feat: add TransactionContext type (#5)
Browse files Browse the repository at this point in the history
* feat: add TransactionContext type

* Update src/tracing/js/mod.rs

Co-authored-by: Enrique <[email protected]>

---------

Co-authored-by: Enrique <[email protected]>
  • Loading branch information
mattsse and Evalir authored Jan 13, 2024
1 parent 5028bdb commit 29bb854
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 18 deletions.
16 changes: 6 additions & 10 deletions src/tracing/js/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::tracing::{
address_to_buf, bytes_to_address, bytes_to_hash, from_buf, to_bigint, to_buf,
to_buf_value,
},
JsDbRequest,
JsDbRequest, TransactionContext,
},
types::CallKind,
};
Expand Down Expand Up @@ -624,9 +624,7 @@ pub(crate) struct EvmContext {
pub(crate) output: Bytes,
/// Number, block number
pub(crate) time: String,
pub(crate) block_hash: Option<B256>,
pub(crate) tx_index: Option<usize>,
pub(crate) tx_hash: Option<B256>,
pub(crate) transaction_ctx: TransactionContext,
}

impl EvmContext {
Expand All @@ -644,9 +642,7 @@ impl EvmContext {
block,
output,
time,
block_hash,
tx_index,
tx_hash,
transaction_ctx,
} = self;
let obj = JsObject::default();

Expand All @@ -669,13 +665,13 @@ impl EvmContext {
obj.set("block", block, false, ctx)?;
obj.set("output", to_buf(output.to_vec(), ctx)?, false, ctx)?;
obj.set("time", time, false, ctx)?;
if let Some(block_hash) = block_hash {
if let Some(block_hash) = transaction_ctx.block_hash {
obj.set("blockHash", to_buf(block_hash.as_slice().to_vec(), ctx)?, false, ctx)?;
}
if let Some(tx_index) = tx_index {
if let Some(tx_index) = transaction_ctx.tx_index {
obj.set("txIndex", tx_index as u64, false, ctx)?;
}
if let Some(tx_hash) = tx_hash {
if let Some(tx_hash) = transaction_ctx.tx_hash {
obj.set("txHash", to_buf(tx_hash.as_slice().to_vec(), ctx)?, false, ctx)?;
}

Expand Down
85 changes: 77 additions & 8 deletions src/tracing/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ pub(crate) mod builtins;
pub struct JsInspector {
ctx: Context<'static>,
/// The javascript config provided to the inspector.
_config: JsValue,
_js_config_value: JsValue,
/// The input config object.
config: serde_json::Value,
/// The evaluated object that contains the inspector functions.
obj: JsObject,
/// The context of the transaction that is being inspected.
transaction_context: TransactionContext,

/// The javascript function that will be called when the result is requested.
result_fn: JsObject,
Expand Down Expand Up @@ -80,6 +84,19 @@ impl JsInspector {
code: String,
config: serde_json::Value,
to_db_service: mpsc::Sender<JsDbRequest>,
) -> Result<Self, JsInspectorError> {
Self::with_transaction_context(code, config, to_db_service, Default::default())
}

/// Creates a new inspector from a javascript code snippet. See also [Self::new].
///
/// This also accepts a [TransactionContext] that gives the JS code access to some contextual
/// transaction infos.
pub fn with_transaction_context(
code: String,
config: serde_json::Value,
to_db_service: mpsc::Sender<JsDbRequest>,
transaction_context: TransactionContext,
) -> Result<Self, JsInspectorError> {
// Instantiate the execution context
let mut ctx = Context::default();
Expand Down Expand Up @@ -116,7 +133,7 @@ impl JsInspector {
let exit_fn = obj.get("exit", &mut ctx)?.as_object().cloned().filter(|o| o.is_callable());
let step_fn = obj.get("step", &mut ctx)?.as_object().cloned().filter(|o| o.is_callable());

let config =
let _js_config_value =
JsValue::from_json(&config, &mut ctx).map_err(JsInspectorError::InvalidJsonConfig)?;

if let Some(setup_fn) = obj.get("setup", &mut ctx)?.as_object() {
Expand All @@ -126,14 +143,16 @@ impl JsInspector {

// call setup()
setup_fn
.call(&(obj.clone().into()), &[config.clone()], &mut ctx)
.call(&(obj.clone().into()), &[_js_config_value.clone()], &mut ctx)
.map_err(JsInspectorError::SetupCallFailed)?;
}

Ok(Self {
ctx,
_config: config,
_js_config_value,
config,
obj,
transaction_context,
result_fn,
fault_fn,
enter_fn,
Expand All @@ -145,6 +164,21 @@ impl JsInspector {
})
}

/// Returns the config object.
pub fn config(&self) -> &serde_json::Value {
&self.config
}

/// Returns the transaction context.
pub fn transaction_context(&self) -> &TransactionContext {
&self.transaction_context
}

/// Sets the transaction context.
pub fn set_transaction_context(&mut self, transaction_context: TransactionContext) {
self.transaction_context = transaction_context;
}

/// Calls the result function and returns the result as [serde_json::Value].
///
/// Note: This is supposed to be called after the inspection has finished.
Expand Down Expand Up @@ -199,11 +233,8 @@ impl JsInspector {
block: env.block.number.try_into().unwrap_or(u64::MAX),
output: output_bytes.unwrap_or_default(),
time: env.block.timestamp.to_string(),
// TODO: fill in the following fields
intrinsic_gas: 0,
block_hash: None,
tx_index: None,
tx_hash: None,
transaction_ctx: self.transaction_context.clone(),
};
let ctx = ctx.into_js_object(&mut self.ctx)?;
let db = db.into_js_object(&mut self.ctx)?;
Expand Down Expand Up @@ -510,6 +541,44 @@ where
}
}

/// Contains some contextual infos for a transaction execution that is made available to the JS
/// object.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct TransactionContext {
/// Hash of the block the tx is contained within.
///
/// `None` if this is a call.
pub block_hash: Option<B256>,
/// Index of the transaction within a block.
///
/// `None` if this is a call.
pub tx_index: Option<usize>,
/// Hash of the transaction being traced.
///
/// `None` if this is a call.
pub tx_hash: Option<B256>,
}

impl TransactionContext {
/// Sets the block hash.
pub fn with_block_hash(mut self, block_hash: B256) -> Self {
self.block_hash = Some(block_hash);
self
}

/// Sets the index of the transaction within a block.
pub fn with_tx_index(mut self, tx_index: usize) -> Self {
self.tx_index = Some(tx_index);
self
}

/// Sets the hash of the transaction.
pub fn with_tx_hash(mut self, tx_hash: B256) -> Self {
self.tx_hash = Some(tx_hash);
self
}
}

/// Request variants to be sent from the inspector to the database
#[derive(Debug, Clone)]
pub enum JsDbRequest {
Expand Down

0 comments on commit 29bb854

Please sign in to comment.