From 2464e1a529ca9501a62301ec4e3a25ee5597aa90 Mon Sep 17 00:00:00 2001 From: Danil Date: Tue, 24 Sep 2024 16:43:47 +0200 Subject: [PATCH] Update queries Signed-off-by: Danil --- ...c783b3710ee47f88edce1b17c2b8fa21dadd3.json | 22 ---- ...355e6aec05ba4af297a03169e3122a67ae53e.json | 28 +++++ core/lib/dal/src/transactions_dal.rs | 14 ++- core/lib/types/src/api/mod.rs | 52 ++++++++- core/lib/types/src/debug_flat_call.rs | 2 +- .../api_server/src/web3/namespaces/debug.rs | 101 ++++++++++-------- core/node/api_server/src/web3/tests/debug.rs | 23 ++-- core/node/api_server/src/web3/tests/vm.rs | 42 +++----- 8 files changed, 171 insertions(+), 113 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-b98e3790de305017c8fa5fba4c0c783b3710ee47f88edce1b17c2b8fa21dadd3.json create mode 100644 core/lib/dal/.sqlx/query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json diff --git a/core/lib/dal/.sqlx/query-b98e3790de305017c8fa5fba4c0c783b3710ee47f88edce1b17c2b8fa21dadd3.json b/core/lib/dal/.sqlx/query-b98e3790de305017c8fa5fba4c0c783b3710ee47f88edce1b17c2b8fa21dadd3.json deleted file mode 100644 index 81981683e895..000000000000 --- a/core/lib/dal/.sqlx/query-b98e3790de305017c8fa5fba4c0c783b3710ee47f88edce1b17c2b8fa21dadd3.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n protocol_version\n FROM\n transactions\n INNER JOIN miniblocks ON transactions.miniblock_number = miniblocks.number\n WHERE\n transactions.hash = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "protocol_version", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [ - "Bytea" - ] - }, - "nullable": [ - true - ] - }, - "hash": "b98e3790de305017c8fa5fba4c0c783b3710ee47f88edce1b17c2b8fa21dadd3" -} diff --git a/core/lib/dal/.sqlx/query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json b/core/lib/dal/.sqlx/query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json new file mode 100644 index 000000000000..0b1f56ef9f33 --- /dev/null +++ b/core/lib/dal/.sqlx/query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n protocol_version,\n index_in_block\n FROM\n transactions\n INNER JOIN miniblocks ON transactions.miniblock_number = miniblocks.number\n WHERE\n transactions.hash = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "protocol_version", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "index_in_block", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Bytea" + ] + }, + "nullable": [ + true, + true + ] + }, + "hash": "bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e" +} diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 2ec35c89ab01..408837d699e6 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -2113,11 +2113,12 @@ impl TransactionsDal<'_, '_> { Ok(data) } - pub async fn get_call_trace(&mut self, tx_hash: H256) -> DalResult> { + pub async fn get_call_trace(&mut self, tx_hash: H256) -> DalResult> { let row = sqlx::query!( r#" SELECT - protocol_version + protocol_version, + index_in_block FROM transactions INNER JOIN miniblocks ON transactions.miniblock_number = miniblocks.number @@ -2155,7 +2156,12 @@ impl TransactionsDal<'_, '_> { .with_arg("tx_hash", &tx_hash) .fetch_optional(self.storage) .await? - .map(|call_trace| parse_call_trace(&call_trace.call_trace, protocol_version))) + .map(|call_trace| { + ( + parse_call_trace(&call_trace.call_trace, protocol_version), + row.index_in_block.unwrap_or_default() as usize, + ) + })) } pub(crate) async fn get_tx_by_hash(&mut self, hash: H256) -> DalResult> { @@ -2227,7 +2233,7 @@ mod tests { .await .unwrap(); - let call_trace = conn + let (call_trace, _) = conn .transactions_dal() .get_call_trace(tx_hash) .await diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index f08d5852abbe..80cc2c3af15c 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -726,6 +726,17 @@ pub struct TracerConfig { pub tracer_config: CallTracerConfig, } +impl Default for TracerConfig { + fn default() -> Self { + TracerConfig { + tracer: SupportedTracers::CallTracer, + tracer_config: CallTracerConfig { + only_top_call: false, + }, + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum BlockStatus { @@ -741,12 +752,51 @@ pub enum CallTracerBlockResult { CallTrace(Vec), FlatCallTrace(Vec), } +impl CallTracerBlockResult { + pub fn unwrap_flatten(self) -> Vec { + match self { + Self::CallTrace(_) => { + unreachable!() + } + Self::FlatCallTrace(a) => a, + } + } + + pub fn unwrap_default(self) -> Vec { + match self { + Self::CallTrace(a) => a, + Self::FlatCallTrace(_) => { + unreachable!() + } + } + } +} #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(untagged)] pub enum CallTracerResult { CallTrace(DebugCall), - FlattCallTrace(Vec), + FlatCallTrace(Vec), +} + +impl CallTracerResult { + pub fn unwrap_flatten(self) -> Vec { + match self { + Self::CallTrace(_) => { + unreachable!() + } + Self::FlatCallTrace(a) => a, + } + } + + pub fn unwrap_default(self) -> DebugCall { + match self { + Self::CallTrace(a) => a, + Self::FlatCallTrace(_) => { + unreachable!() + } + } + } } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/core/lib/types/src/debug_flat_call.rs b/core/lib/types/src/debug_flat_call.rs index 318ca7be9ce1..89a008b5fb5f 100644 --- a/core/lib/types/src/debug_flat_call.rs +++ b/core/lib/types/src/debug_flat_call.rs @@ -9,7 +9,7 @@ pub struct DebugCallFlat { pub action: Action, pub result: Option, pub subtraces: usize, - pub traceaddress: Vec, + pub trace_address: Vec, pub transaction_position: usize, pub transaction_hash: H256, pub r#type: DebugCallType, diff --git a/core/node/api_server/src/web3/namespaces/debug.rs b/core/node/api_server/src/web3/namespaces/debug.rs index 5814a5ad8dae..68c7951cee45 100644 --- a/core/node/api_server/src/web3/namespaces/debug.rs +++ b/core/node/api_server/src/web3/namespaces/debug.rs @@ -49,30 +49,26 @@ impl DebugNamespace { call: Call, index: usize, transaction_hash: H256, - tracer_option: Option, + tracer_option: TracerConfig, ) -> CallTracerResult { - let (only_top_call, flatten) = tracer_option - .map(|options| { - ( - options.tracer_config.only_top_call, - matches!(options.tracer, SupportedTracers::FlatCallTracer), - ) - }) - .unwrap_or((false, false)); - if flatten { - let mut calls = vec![]; - let mut traces = vec![index]; - Self::map_flatten_call( + match tracer_option.tracer { + SupportedTracers::CallTracer => CallTracerResult::CallTrace(Self::map_default_call( call, - &mut calls, - &mut traces, - only_top_call, - index, - transaction_hash, - ); - CallTracerResult::FlattCallTrace(calls) - } else { - CallTracerResult::CallTrace(Self::map_default_call(call, only_top_call)) + tracer_option.tracer_config.only_top_call, + )), + SupportedTracers::FlatCallTracer => { + let mut calls = vec![]; + let mut traces = vec![index]; + Self::flatten_call( + call, + &mut calls, + &mut traces, + tracer_option.tracer_config.only_top_call, + index, + transaction_hash, + ); + CallTracerResult::FlatCallTrace(calls) + } } } pub(crate) fn map_default_call(call: Call, only_top_call: bool) -> DebugCall { @@ -104,7 +100,7 @@ impl DebugNamespace { } } - fn map_flatten_call( + fn flatten_call( call: Call, calls: &mut Vec, trace_address: &mut Vec, @@ -139,7 +135,7 @@ impl DebugNamespace { }, result, subtraces, - traceaddress: trace_address.clone(), // Clone the current trace address + trace_address: trace_address.clone(), // Clone the current trace address transaction_position, transaction_hash, r#type: DebugCallType::Call, @@ -148,7 +144,7 @@ impl DebugNamespace { if !only_top_call { for (number, call) in call.calls.into_iter().enumerate() { trace_address.push(number); - Self::map_flatten_call( + Self::flatten_call( call, calls, trace_address, @@ -187,20 +183,33 @@ impl DebugNamespace { .await .map_err(DalError::generalize)?; - let mut calls = vec![]; - let mut flat_calls = vec![]; - for (call_trace, hash, index) in call_traces { - match Self::map_call(call_trace, index, hash, options) { - CallTracerResult::CallTrace(call) => calls.push(ResultDebugCall { result: call }), - CallTracerResult::FlattCallTrace(mut call) => flat_calls.append(&mut call), + let options = options.unwrap_or_default(); + let result = match options.tracer { + SupportedTracers::CallTracer => CallTracerBlockResult::CallTrace( + call_traces + .into_iter() + .map(|(call, _, _)| ResultDebugCall { + result: Self::map_default_call(call, options.tracer_config.only_top_call), + }) + .collect(), + ), + SupportedTracers::FlatCallTracer => { + let mut flat_calls = vec![]; + for (call, tx_hash, tx_index) in call_traces { + let mut traces = vec![tx_index]; + Self::flatten_call( + call, + &mut flat_calls, + &mut traces, + options.tracer_config.only_top_call, + tx_index, + tx_hash, + ); + } + CallTracerBlockResult::FlatCallTrace(flat_calls) } - } - - if calls.is_empty() && !flat_calls.is_empty() { - Ok(CallTracerBlockResult::FlatCallTrace(flat_calls)) - } else { - Ok(CallTracerBlockResult::CallTrace(calls)) - } + }; + Ok(result) } pub async fn debug_trace_transaction_impl( @@ -214,7 +223,14 @@ impl DebugNamespace { .get_call_trace(tx_hash) .await .map_err(DalError::generalize)?; - Ok(call_trace.map(|call_trace| Self::map_call(call_trace, 0, tx_hash, options))) + Ok(call_trace.map(|(call_trace, index_in_block)| { + Self::map_call( + call_trace, + index_in_block, + tx_hash, + options.unwrap_or_default(), + ) + })) } pub async fn debug_trace_call_impl( @@ -226,10 +242,7 @@ impl DebugNamespace { let block_id = block_id.unwrap_or(BlockId::Number(BlockNumber::Pending)); self.current_method().set_block_id(block_id); - let only_top_call = options - .as_ref() - .map(|options| options.tracer_config.only_top_call) - .unwrap_or(false); + let options = options.unwrap_or_default(); let mut connection = self.state.acquire_connection().await?; let block_args = self @@ -264,7 +277,7 @@ impl DebugNamespace { // We don't need properly trace if we only need top call let tracing_params = OneshotTracingParams { - trace_calls: !only_top_call, + trace_calls: !options.tracer_config.only_top_call, }; let connection = self.state.acquire_connection().await?; diff --git a/core/node/api_server/src/web3/tests/debug.rs b/core/node/api_server/src/web3/tests/debug.rs index 3350ec7a0894..6e735d2eae4a 100644 --- a/core/node/api_server/src/web3/tests/debug.rs +++ b/core/node/api_server/src/web3/tests/debug.rs @@ -63,11 +63,9 @@ impl HttpTest for TraceBlockTest { let block_traces = match block_id { api::BlockId::Number(number) => client.trace_block_by_number(number, None).await?, api::BlockId::Hash(hash) => client.trace_block_by_hash(hash, None).await?, - }; + } + .unwrap_default(); - let CallTracerBlockResult::CallTrace(block_traces) = block_traces else { - unreachable!() - }; assert_eq!(block_traces.len(), tx_results.len()); // equals to the number of transactions in the block for (trace, tx_result) in block_traces.iter().zip(&tx_results) { let result = &trace.result; @@ -140,11 +138,8 @@ impl HttpTest for TraceBlockFlatTest { }, }), ) - .await?; - - let CallTracerBlockResult::FlatCallTrace(block_traces) = &block_traces else { - unreachable!() - }; + .await? + .unwrap_flatten(); // A transaction with 2 nested calls will convert into 3 Flattened calls. // Also in this test, all tx have the same # of nested calls @@ -155,10 +150,10 @@ impl HttpTest for TraceBlockFlatTest { // First tx has 2 nested calls, thus 2 sub-traces assert_eq!(block_traces[0].subtraces, 2); - assert_eq!(block_traces[0].traceaddress, [0]); + assert_eq!(block_traces[0].trace_address, [0]); // Second flat-call (fist nested call) do not have nested calls assert_eq!(block_traces[1].subtraces, 0); - assert_eq!(block_traces[1].traceaddress, [0, 0]); + assert_eq!(block_traces[1].trace_address, [0, 0]); let top_level_call_indexes = [0, 3, 6]; let top_level_traces = top_level_call_indexes @@ -231,13 +226,11 @@ impl HttpTest for TraceTransactionTest { .map(|call| DebugNamespace::map_default_call(call.clone(), false)) .collect(); - let CallTracerResult::CallTrace(result) = client + let result = client .trace_transaction(tx_results[0].hash, None) .await? .context("no transaction traces")? - else { - unreachable!() - }; + .unwrap_default(); assert_eq!(result.from, Address::zero()); assert_eq!(result.to, BOOTLOADER_ADDRESS); assert_eq!(result.gas, tx_results[0].transaction.gas_limit()); diff --git a/core/node/api_server/src/web3/tests/vm.rs b/core/node/api_server/src/web3/tests/vm.rs index f1fa7c86b745..5f62181da5dd 100644 --- a/core/node/api_server/src/web3/tests/vm.rs +++ b/core/node/api_server/src/web3/tests/vm.rs @@ -488,35 +488,30 @@ impl HttpTest for TraceCallTest { self.fee_input.expect_default(Self::FEE_SCALE); let call_request = CallTest::call_request(b"pending"); - let CallTracerResult::CallTrace(call_result) = - client.trace_call(call_request.clone(), None, None).await? - else { - unreachable!() - }; + let call_result = client + .trace_call(call_request.clone(), None, None) + .await? + .unwrap_default(); Self::assert_debug_call(&call_request, &call_result); let pending_block_number = api::BlockId::Number(api::BlockNumber::Pending); - let CallTracerResult::CallTrace(call_result) = client + let call_result = client .trace_call(call_request.clone(), Some(pending_block_number), None) .await? - else { - unreachable!() - }; + .unwrap_default(); Self::assert_debug_call(&call_request, &call_result); let latest_block_numbers = [api::BlockNumber::Latest, 1.into()]; let call_request = CallTest::call_request(b"latest"); for number in latest_block_numbers { self.fee_input.expect_for_block(number, Self::FEE_SCALE); - let CallTracerResult::CallTrace(call_result) = client + let call_result = client .trace_call( call_request.clone(), Some(api::BlockId::Number(number)), None, ) .await? - else { - unreachable!() - }; + .unwrap_default(); Self::assert_debug_call(&call_request, &call_result); } @@ -567,19 +562,16 @@ impl HttpTest for TraceCallTestAfterSnapshotRecovery { ) -> anyhow::Result<()> { self.fee_input.expect_default(TraceCallTest::FEE_SCALE); let call_request = CallTest::call_request(b"pending"); - let CallTracerResult::CallTrace(call_result) = - client.trace_call(call_request.clone(), None, None).await? - else { - unreachable!() - }; + let call_result = client + .trace_call(call_request.clone(), None, None) + .await? + .unwrap_default(); TraceCallTest::assert_debug_call(&call_request, &call_result); let pending_block_number = api::BlockId::Number(api::BlockNumber::Pending); - let CallTracerResult::CallTrace(call_result) = client + let call_result = client .trace_call(call_request.clone(), Some(pending_block_number), None) .await? - else { - unreachable!() - }; + .unwrap_default(); TraceCallTest::assert_debug_call(&call_request, &call_result); let first_local_l2_block = StorageInitialization::SNAPSHOT_RECOVERY_BLOCK + 1; @@ -599,12 +591,10 @@ impl HttpTest for TraceCallTestAfterSnapshotRecovery { self.fee_input .expect_for_block(number, TraceCallTest::FEE_SCALE); let number = api::BlockId::Number(number); - let CallTracerResult::CallTrace(call_result) = client + let call_result = client .trace_call(call_request.clone(), Some(number), None) .await? - else { - unreachable!() - }; + .unwrap_default(); TraceCallTest::assert_debug_call(&call_request, &call_result); } Ok(())