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

eth/tracers: check the parent callframe's length before removing precompile call #27290

Closed
wants to merge 1 commit into from

Conversation

minh-bq
Copy link
Contributor

@minh-bq minh-bq commented May 17, 2023

When using flat call tracer, by default, we remove the call to precompile. However, we should check the length of parent's callframe before doing that because when OnlyTopCall option is provided the call tracer's CaptureExit does not push the child's callframe to parent's callframe. As a result, the parent's callframe is empty, trying to remove the precompile call leads to index out of range. This commit checks the length of parent's callframe before removing precompile call.

…ompile call

When using flat call tracer, by default, we remove the call to precompile.
However, we should check the length of parent's callframe before doing that
because when OnlyTopCall option is provided the call tracer's CaptureExit does
not push the child's callframe to parent's callframe. As a result, the parent's
callframe is empty, trying to remove the precompile call leads to index out of
range. This commit checks the length of parent's callframe before removing
precompile call.
@minh-bq minh-bq requested a review from s1na as a code owner May 17, 2023 10:19
@s1na
Copy link
Contributor

s1na commented May 17, 2023

Good find!

I'm a bit torn on this. I feel like we should clear the config for the flat call tracer. For example WithLogs is also not implemented yet. For that we'll have to change the format and add in logs.

Do you need OnlyTopCall for the flatCallTracer? or discovered this by accident?

@minh-bq
Copy link
Contributor Author

minh-bq commented May 18, 2023

Yes, I also feel that call tracer configs are not intended to be used when flat call tracer is used. Our team does not use the OnlyTopCall for flatCallTracer, just find it during testing.

So, do you prefer this solution, not pass the config from flat call tracer down to inner call tracer?

diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go
index a9c056f27..1334b8baa 100644
--- a/eth/tracers/native/call_flat.go
+++ b/eth/tracers/native/call_flat.go
@@ -129,6 +129,7 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace
                }
        }
 
+       cfg, _ = json.Marshal(callTracerConfig{})
        tracer, err := tracers.DefaultDirectory.New("callTracer", ctx, cfg)
        if err != nil {
                return nil, err

@ziogaschr
Copy link
Contributor

Nice find!
There is a possibility that the OnlyTopCall is not useful for flatCallTracer. Though it might be preferably to keep it in, as flatCallTracer is a proxy tracer that mostly formats the output of callTracer.

For some stuff, I wouldn't suggest touching the base formatting as this might be useful for endusers consuming the Parity tracer in past. On the other hand, extending on top of this tracer feels welcoming, and OnlyTopCall can be easily kept.

About the WithLogs, we can ignore it in the config by passing a false value in the CallTracer, and why not later add support for it.

I think it makes sense to have all the logic and base functionality coming from the CallTracer and having flatCallTracer only doing the formatting and needed changes.

@s1na
Copy link
Contributor

s1na commented May 18, 2023

Honestly I'd prefer to clear the config for now and only allow those options if someone asks for it. The reason we added the flatCallTracer is to have compatibility with other clients. I'd say if we want to e.g. add logs we should consult with them and do it together.

@minh-bq that patch looks good!

@ziogaschr
Copy link
Contributor

@s1na yes that a valid point. It's wiser to do this in discussion with other clients when needed.

// When OnlyTopCall is provided, the call tracer CaptureExit does
// not push the child's callframe to parent's callframe so we don't
// need to remove the call to precompile.
if len(t.tracer.callstack[len(t.tracer.callstack)-1].Calls) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think the suggestion below will miss any edge cases in case the CallTracer.CaptureExit gets modified? Probably the way you coded it is more safe.

Suggested change
if len(t.tracer.callstack[len(t.tracer.callstack)-1].Calls) == 0 {
if t.tracer.config.OnlyTopCall {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggestion looks good to me

@minh-bq
Copy link
Contributor Author

minh-bq commented May 19, 2023

Look like we prefer to clear the config passed to inner call tracer, don't want to edit this PR description and title for reference, I create another PR: #27304 for that implementation.

@minh-bq minh-bq closed this May 19, 2023
@vinioleg2015zem vinioleg2015zem linked an issue May 21, 2023 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

> content://media/external/downloads/1000000694
3 participants