Skip to content
Open
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 pkg/ethereum/execution/embedded_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func (n *EmbeddedNode) MarkReady(ctx context.Context) error {

for i, cb := range callbacks {
n.log.WithField("callback_index", i).Info("Executing OnReady callback")

if err := cb(ctx); err != nil {
n.log.WithError(err).Error("Failed to execute OnReady callback")

Expand Down
20 changes: 20 additions & 0 deletions pkg/processor/transaction/structlog/gas_cost.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,26 @@ func hasPrecomputedGasUsed(structlogs []execution.StructLog) bool {
return structlogs[0].GasUsed > 0
}

// hasPrecomputedCreateAddresses detects whether CREATE/CREATE2 addresses are pre-computed.
//
// In embedded mode, the tracer resolves CREATE addresses inline when the constructor
// returns, populating CallToAddress. In RPC mode, CallToAddress is nil for CREATE
// opcodes and must be computed post-hoc using ComputeCreateAddresses().
//
// Returns true if any CREATE/CREATE2 opcode has CallToAddress pre-populated.
func hasPrecomputedCreateAddresses(structlogs []execution.StructLog) bool {
for i := range structlogs {
op := structlogs[i].Op
if op == OpcodeCREATE || op == OpcodeCREATE2 {
// If any CREATE has CallToAddress populated, tracer pre-computed.
return structlogs[i].CallToAddress != nil
}
}

// No CREATE/CREATE2 opcodes found - doesn't matter, return false to use standard path.
return false
}

// ComputeGasUsed calculates the actual gas consumed for each structlog using
// the difference between consecutive gas values at the same depth level.
//
Expand Down
42 changes: 42 additions & 0 deletions pkg/processor/transaction/structlog/gas_cost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,48 @@ func TestHasPrecomputedGasUsed_WithoutGasUsed(t *testing.T) {
assert.False(t, hasPrecomputedGasUsed(structlogs))
}

// =============================================================================
// hasPrecomputedCreateAddresses Tests
// =============================================================================

func TestHasPrecomputedCreateAddresses_Empty(t *testing.T) {
assert.False(t, hasPrecomputedCreateAddresses(nil))
assert.False(t, hasPrecomputedCreateAddresses([]execution.StructLog{}))
}

func TestHasPrecomputedCreateAddresses_NoCreate(t *testing.T) {
structlogs := []execution.StructLog{
{Op: "PUSH1"},
{Op: "CALL"},
}
assert.False(t, hasPrecomputedCreateAddresses(structlogs))
}

func TestHasPrecomputedCreateAddresses_CreateWithAddress(t *testing.T) {
addr := "0x1234567890123456789012345678901234567890"
structlogs := []execution.StructLog{
{Op: "PUSH1"},
{Op: "CREATE", CallToAddress: &addr},
}
assert.True(t, hasPrecomputedCreateAddresses(structlogs))
}

func TestHasPrecomputedCreateAddresses_CreateWithoutAddress(t *testing.T) {
structlogs := []execution.StructLog{
{Op: "PUSH1"},
{Op: "CREATE", CallToAddress: nil},
}
assert.False(t, hasPrecomputedCreateAddresses(structlogs))
}

func TestHasPrecomputedCreateAddresses_Create2WithAddress(t *testing.T) {
addr := "0x1234567890123456789012345678901234567890"
structlogs := []execution.StructLog{
{Op: "CREATE2", CallToAddress: &addr},
}
assert.True(t, hasPrecomputedCreateAddresses(structlogs))
}

// =============================================================================
// ComputeGasUsed Tests
// =============================================================================
Expand Down
21 changes: 17 additions & 4 deletions pkg/processor/transaction/structlog/transaction_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,15 @@ func (p *Processor) ProcessTransaction(ctx context.Context, block execution.Bloc
// Initialize call frame tracker
callTracker := NewCallTracker()

// Pre-compute CREATE/CREATE2 addresses from trace stack
createAddresses := ComputeCreateAddresses(trace.Structlogs)
// Check if CREATE/CREATE2 addresses are pre-computed by the tracer (embedded mode).
// In embedded mode, skip the multi-pass ComputeCreateAddresses scan.
precomputedCreateAddresses := hasPrecomputedCreateAddresses(trace.Structlogs)

var createAddresses map[int]*string
if !precomputedCreateAddresses {
// Pre-compute CREATE/CREATE2 addresses from trace stack (RPC mode)
createAddresses = ComputeCreateAddresses(trace.Structlogs)
}

// Check if this is a big transaction and register if needed
if totalCount >= p.bigTxManager.GetThreshold() {
Expand Down Expand Up @@ -592,8 +599,14 @@ func (p *Processor) ExtractStructlogs(ctx context.Context, block execution.Block
// Initialize call frame tracker
callTracker := NewCallTracker()

// Pre-compute CREATE/CREATE2 addresses from trace stack
createAddresses := ComputeCreateAddresses(trace.Structlogs)
// Check if CREATE/CREATE2 addresses are pre-computed by the tracer (embedded mode).
precomputedCreateAddresses := hasPrecomputedCreateAddresses(trace.Structlogs)

var createAddresses map[int]*string
if !precomputedCreateAddresses {
// Pre-compute CREATE/CREATE2 addresses from trace stack (RPC mode)
createAddresses = ComputeCreateAddresses(trace.Structlogs)
}

// Pre-allocate slice for better memory efficiency
structlogs = make([]Structlog, 0, len(trace.Structlogs))
Expand Down