Skip to content

Commit

Permalink
Update Trace API for 0.6
Browse files Browse the repository at this point in the history
  • Loading branch information
omerfirmak committed Nov 24, 2023
1 parent f5e2657 commit 629a99e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 52 deletions.
12 changes: 8 additions & 4 deletions rpc/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,10 @@ func (h *Handler) TraceTransaction(ctx context.Context, hash felt.Felt) (json.Ra
return h.traceTransaction(ctx, &hash, false)
}

// LegacyTraceTransaction returns the trace for a given executed transaction, including internal calls
//
// It follows the specification defined here:
// https://github.com/starkware-libs/starknet-specs/blob/1ae810e0137cc5d175ace4554892a4f43052be56/api/starknet_trace_api_openrpc.json#L11
func (h *Handler) LegacyTraceTransaction(ctx context.Context, hash felt.Felt) (json.RawMessage, *jsonrpc.Error) {
return h.traceTransaction(ctx, &hash, true)
}
Expand Down Expand Up @@ -1382,10 +1386,10 @@ func (h *Handler) TraceBlockTransactions(ctx context.Context, id BlockID) ([]Tra
return h.traceBlockTransactions(ctx, block, false)
}

func (h *Handler) LegacyTraceBlockTransactions(ctx context.Context, hash felt.Felt) ([]TracedBlockTransaction, *jsonrpc.Error) {
block, err := h.bcReader.BlockByHash(&hash)
if err != nil {
return nil, ErrInvalidBlockHash
func (h *Handler) LegacyTraceBlockTransactions(ctx context.Context, id BlockID) ([]TracedBlockTransaction, *jsonrpc.Error) {
block, err := h.blockByID(&id)
if block == nil || err != nil {
return nil, ErrBlockNotFound

Check warning on line 1392 in rpc/handlers.go

View check run for this annotation

Codecov / codecov/patch

rpc/handlers.go#L1389-L1392

Added lines #L1389 - L1392 were not covered by tests
}

return h.traceBlockTransactions(ctx, block, true)
Expand Down
31 changes: 11 additions & 20 deletions rpc/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ type ExecuteInvocation struct {
}

type OrderedEvent struct {
Order *uint64 `json:"order,omitempty"`
Order uint64 `json:"order"`
Event
}

type OrderedL2toL1Message struct {
Order *uint64 `json:"order,omitempty"`
Order uint64 `json:"order"`
MsgToL1
}

func adaptBlockTrace(block *BlockWithTxs, blockTrace *starknet.BlockTrace, legacyTrace bool) ([]TracedBlockTransaction, error) {
func adaptBlockTrace(block *BlockWithTxs, blockTrace *starknet.BlockTrace, _ bool) ([]TracedBlockTransaction, error) {
if blockTrace == nil {
return nil, nil
}
Expand All @@ -60,14 +60,12 @@ func adaptBlockTrace(block *BlockWithTxs, blockTrace *starknet.BlockTrace, legac
for index := range blockTrace.Traces {
feederTrace := &blockTrace.Traces[index]
trace := TransactionTrace{}
if !legacyTrace {
trace.Type = block.Transactions[index].Type
}
trace.Type = block.Transactions[index].Type

trace.FeeTransferInvocation = adaptFunctionInvocation(feederTrace.FeeTransferInvocation, legacyTrace)
trace.ValidateInvocation = adaptFunctionInvocation(feederTrace.ValidateInvocation, legacyTrace)
trace.FeeTransferInvocation = adaptFunctionInvocation(feederTrace.FeeTransferInvocation)
trace.ValidateInvocation = adaptFunctionInvocation(feederTrace.ValidateInvocation)

fnInvocation := adaptFunctionInvocation(feederTrace.FunctionInvocation, legacyTrace)
fnInvocation := adaptFunctionInvocation(feederTrace.FunctionInvocation)
switch block.Transactions[index].Type {
case TxnDeploy:
trace.ConstructorInvocation = fnInvocation
Expand Down Expand Up @@ -97,18 +95,11 @@ func adaptBlockTrace(block *BlockWithTxs, blockTrace *starknet.BlockTrace, legac
return traces, nil
}

func adaptFunctionInvocation(snFnInvocation *starknet.FunctionInvocation, legacyTrace bool) *FunctionInvocation {
func adaptFunctionInvocation(snFnInvocation *starknet.FunctionInvocation) *FunctionInvocation {
if snFnInvocation == nil {
return nil
}

orderPtr := func(o uint64) *uint64 {
if legacyTrace {
return nil
}
return &o
}

fnInvocation := FunctionInvocation{
ContractAddress: snFnInvocation.ContractAddress,
EntryPointSelector: snFnInvocation.Selector,
Expand All @@ -123,12 +114,12 @@ func adaptFunctionInvocation(snFnInvocation *starknet.FunctionInvocation, legacy
Messages: make([]OrderedL2toL1Message, 0, len(snFnInvocation.Messages)),
}
for index := range snFnInvocation.InternalCalls {
fnInvocation.Calls = append(fnInvocation.Calls, *adaptFunctionInvocation(&snFnInvocation.InternalCalls[index], legacyTrace))
fnInvocation.Calls = append(fnInvocation.Calls, *adaptFunctionInvocation(&snFnInvocation.InternalCalls[index]))
}
for index := range snFnInvocation.Events {
snEvent := &snFnInvocation.Events[index]
fnInvocation.Events = append(fnInvocation.Events, OrderedEvent{
Order: orderPtr(snEvent.Order),
Order: snEvent.Order,

Check warning on line 122 in rpc/trace.go

View check run for this annotation

Codecov / codecov/patch

rpc/trace.go#L122

Added line #L122 was not covered by tests
Event: Event{
Keys: utils.Map(snEvent.Keys, utils.Ptr[felt.Felt]),
Data: utils.Map(snEvent.Data, utils.Ptr[felt.Felt]),
Expand All @@ -138,7 +129,7 @@ func adaptFunctionInvocation(snFnInvocation *starknet.FunctionInvocation, legacy
for index := range snFnInvocation.Messages {
snMessage := &snFnInvocation.Messages[index]
fnInvocation.Messages = append(fnInvocation.Messages, OrderedL2toL1Message{
Order: orderPtr(snMessage.Order),
Order: snMessage.Order,
MsgToL1: MsgToL1{
Payload: utils.Map(snMessage.Payload, utils.Ptr[felt.Felt]),
To: common.HexToAddress(snMessage.ToAddr),
Expand Down
94 changes: 66 additions & 28 deletions vm/rust/src/jsonrpc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use blockifier;
use blockifier::execution::entry_point::CallType;
use blockifier::execution::call_info::OrderedL2ToL1Message;
use cairo_vm::vm::runners::builtin_runner::{
BITWISE_BUILTIN_NAME, EC_OP_BUILTIN_NAME, HASH_BUILTIN_NAME,
POSEIDON_BUILTIN_NAME, RANGE_CHECK_BUILTIN_NAME, SIGNATURE_BUILTIN_NAME, KECCAK_BUILTIN_NAME,
SEGMENT_ARENA_BUILTIN_NAME,
};
use blockifier::state::cached_state::TransactionalState;
use blockifier::state::errors::StateError;
use blockifier::state::state_api::{State, StateReader};
Expand All @@ -13,11 +18,11 @@ use starknet_api::transaction::{DeclareTransaction, Transaction as StarknetApiTr

use crate::juno_state_reader::JunoStateReader;

#[derive(Serialize)]
#[derive(Serialize, Default)]
#[serde(rename_all = "UPPERCASE")]
pub enum TransactionType {
// dummy type for implementing Default trait
Unknown,
#[default] Unknown,
Invoke,
Declare,
#[serde(rename = "DEPLOY_ACCOUNT")]
Expand All @@ -38,13 +43,11 @@ pub struct TransactionTrace {
constructor_invocation: Option<FunctionInvocation>,
#[serde(skip_serializing_if = "Option::is_none")]
function_invocation: Option<FunctionInvocation>,
#[serde(skip_serializing_if = "Option::is_none")]
r#type: Option<TransactionType>,
#[serde(skip_serializing_if = "Option::is_none")]
state_diff: Option<StateDiff>,
r#type: TransactionType,
state_diff: StateDiff,
}

#[derive(Serialize)]
#[derive(Serialize, Default)]
struct StateDiff {
storage_diffs: Vec<StorageDiff>,
nonces: Vec<Nonce>,
Expand Down Expand Up @@ -92,8 +95,6 @@ struct DeclaredClass {

impl TransactionTrace {
pub fn make_legacy(&mut self) {
self.state_diff = None;
self.r#type = None;
if let Some(invocation) = &mut self.validate_invocation {
invocation.make_legacy()
}
Expand Down Expand Up @@ -130,13 +131,13 @@ pub fn new_transaction_trace(
match tx {
StarknetApiTransaction::L1Handler(_) => {
trace.function_invocation = info.execute_call_info.map(|v| v.into());
trace.r#type = Some(TransactionType::L1Handler);
trace.r#type = TransactionType::L1Handler;
}
StarknetApiTransaction::DeployAccount(_) => {
trace.validate_invocation = info.validate_call_info.map(|v| v.into());
trace.constructor_invocation = info.execute_call_info.map(|v| v.into());
trace.fee_transfer_invocation = info.fee_transfer_call_info.map(|v| v.into());
trace.r#type = Some(TransactionType::DeployAccount);
trace.r#type = TransactionType::DeployAccount;
}
StarknetApiTransaction::Invoke(_) => {
trace.validate_invocation = info.validate_call_info.map(|v| v.into());
Expand All @@ -147,12 +148,12 @@ pub fn new_transaction_trace(
.map(|v| ExecuteInvocation::Ok(v.into())),
};
trace.fee_transfer_invocation = info.fee_transfer_call_info.map(|v| v.into());
trace.r#type = Some(TransactionType::Invoke);
trace.r#type = TransactionType::Invoke;
}
StarknetApiTransaction::Declare(declare_txn) => {
trace.validate_invocation = info.validate_call_info.map(|v| v.into());
trace.fee_transfer_invocation = info.fee_transfer_call_info.map(|v| v.into());
trace.r#type = Some(TransactionType::Declare);
trace.r#type = TransactionType::Declare;
deprecated_declared_class = if info.revert_error.is_none() {
match declare_txn {
DeclareTransaction::V0(_) => Some(declare_txn.class_hash()),
Expand All @@ -169,14 +170,13 @@ pub fn new_transaction_trace(
}
};

trace.state_diff = Some(make_state_diff(state, deprecated_declared_class)?);
trace.state_diff = make_state_diff(state, deprecated_declared_class)?;
Ok(trace)
}

#[derive(Serialize)]
pub struct OrderedEvent {
#[serde(skip_serializing_if = "Option::is_none")]
pub order: Option<usize>,
pub order: usize,
#[serde(flatten)]
pub event: EventContent,
}
Expand All @@ -185,12 +185,53 @@ use blockifier::execution::call_info::OrderedEvent as BlockifierOrderedEvent;
impl From<BlockifierOrderedEvent> for OrderedEvent {
fn from(val: BlockifierOrderedEvent) -> Self {
OrderedEvent {
order: Some(val.order),
order: val.order,
event: val.event,
}
}
}

#[derive(Serialize)]
pub struct ExecutionResources {
pub steps: usize,
pub memory_holes: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub range_check_builtin_applications: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pedersen_builtin_applications: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub poseidon_builtin_applications: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ec_op_builtin_applications: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ecdsa_builtin_applications: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bitwise_builtin_applications: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keccak_builtin_applications: Option<usize>,
// https://github.com/starkware-libs/starknet-specs/pull/167
#[serde(skip_serializing_if = "Option::is_none")]
pub segment_arena_builtin: Option<usize>,
}

use cairo_vm::vm::runners::cairo_runner::ExecutionResources as VmExecutionResources;
impl From<VmExecutionResources> for ExecutionResources {
fn from(val: VmExecutionResources) -> Self {
ExecutionResources {
steps: val.n_steps,
memory_holes: val.n_memory_holes,
range_check_builtin_applications: val.builtin_instance_counter.get(RANGE_CHECK_BUILTIN_NAME).cloned(),
pedersen_builtin_applications: val.builtin_instance_counter.get(HASH_BUILTIN_NAME).cloned(),
poseidon_builtin_applications: val.builtin_instance_counter.get(POSEIDON_BUILTIN_NAME).cloned(),
ec_op_builtin_applications: val.builtin_instance_counter.get(EC_OP_BUILTIN_NAME).cloned(),
ecdsa_builtin_applications: val.builtin_instance_counter.get(SIGNATURE_BUILTIN_NAME).cloned(),
bitwise_builtin_applications: val.builtin_instance_counter.get(BITWISE_BUILTIN_NAME).cloned(),
keccak_builtin_applications: val.builtin_instance_counter.get(KECCAK_BUILTIN_NAME).cloned(),
segment_arena_builtin: val.builtin_instance_counter.get(SEGMENT_ARENA_BUILTIN_NAME).cloned(),
}
}
}

#[derive(Serialize)]
pub struct FunctionInvocation {
#[serde(flatten)]
Expand All @@ -203,18 +244,15 @@ pub struct FunctionInvocation {
pub calls: Vec<FunctionInvocation>,
pub events: Vec<OrderedEvent>,
pub messages: Vec<OrderedMessage>,
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_resources: Option<ExecutionResources>,
}

impl FunctionInvocation {
fn make_legacy(&mut self) {
for indx in 0..self.events.len() {
self.events[indx].order = None;
}
for indx in 0..self.messages.len() {
self.messages[indx].order = None;
}
for indx in 0..self.calls.len() {
self.calls[indx].make_legacy();
self.execution_resources = None;
for call in self.calls.iter_mut() {
call.make_legacy();
}
}
}
Expand Down Expand Up @@ -249,6 +287,7 @@ impl From<BlockifierCallInfo> for FunctionInvocation {
ordered_message
})
.collect(),
execution_resources: Some(val.vm_resources.into()),
}
}
}
Expand All @@ -262,8 +301,7 @@ pub struct FunctionCall {

#[derive(Serialize)]
pub struct OrderedMessage {
#[serde(skip_serializing_if = "Option::is_none")]
pub order: Option<usize>,
pub order: usize,
pub from_address: ContractAddress,
pub to_address: EthAddress,
pub payload: L2ToL1Payload,
Expand All @@ -272,7 +310,7 @@ pub struct OrderedMessage {
impl From<OrderedL2ToL1Message> for OrderedMessage {
fn from(val: OrderedL2ToL1Message) -> Self {
OrderedMessage {
order: Some(val.order),
order: val.order,
from_address: ContractAddress(PatriciaKey::default()),
to_address: val.message.to_address,
payload: val.message.payload,
Expand Down

0 comments on commit 629a99e

Please sign in to comment.