-
Notifications
You must be signed in to change notification settings - Fork 20.5k
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
accounts/abi/bind/backend: SimulatedBackend
options to always honour vm.Config
#25072
Conversation
@gballet and @MariusVanDerWijden can you please take a look when you get a chance? I've also sent over #25055 but if you've only got time for one review, please focus on this one. |
Hey @aschlosberg, thank you for the PR and sorry for taking so long to look at it. Generally the idea of having a way to modify the |
Hey @MariusVanDerWijden, not a problem re the delay, this is low priority :) thanks for the feedback. What would your suggested approach look like for Which bit is too complicated for you? The introduction of sim := backends.NewSimulatedBackend(…)
cfg := sim.Blockchain().GetVMConfig()
… // modify cfg
sim.CloneVMConfigOnCall(true) is pretty similar to:
but tx vs call configs gets messy: sim := backends.NewSimulatedBackend(…)
txConfig := sim.Blockchain().GetVMConfig()
… // modify txConfig
sim.SetVMConfigForCalls(txConfig) // same config? different one? txConfig is a pointer so do we clone it here? |
@MariusVanDerWijden I've opted to simplify the entire process by just exposing the flag struct that was previously unexported, reverting all of the |
Wouldn't it be simpler to just copy the config on every call? Why should that be optional? |
Another idea: add a method Edit: @MariusVanDerWijden already figured that out 17 days ago :) |
That would be ideal, but it introduces a breaking change into an exported API. Unfortunately the historical behaviour might be relied on by someone so I don't think we should change it, which is why there's otherwise unnecessary complexity.
Would this also be copied to the config held by |
IMO we should just add a new constructor, where you pass in the config you want to use. That way, it also gets passed into the blockchain. It becomes 'weird' if the backend has one config, and the internal blockchain has another. It also gets weird if you try to SetConfig at arbitrary points in time, and things like the extra eips get changed.
I still think that would be the simplest solution. |
Thanks @holiman. Just to confirm that we weren't talking about different things, I meant a We'd then have
I'm not suggesting it should, which is why I'd like to clarify in my first paragraph. |
Yes, that's what I meant. Re the constructors, I'm not sure I have a preference. I mean, we could just clobber them as |
@MariusVanDerWijden originally felt the options were too complicated, but that was only when we were considering adding @MariusVanDerWijden would you be ok with the following? type Option …
func NewSimulatedBackend(core.GenesisAlloc, uint64, ...Option) *SimulatedBackend
// WithDatabase configures a SimulatedBackend to use the specified database.
func WithDatabase(ethdb.Database) Option
// WithVMConfig configures a SimulatedBackend to use the specified VM config, which is used for transactions and calls.
func WithVMConfig(vm.Config) Option
// NewSimulatedBackendWithDatabase creates a new binding backend based on the given database and uses a simulated blockchain for testing purposes. A simulated backend always uses chainID 1337.
// DEPRECATED: use NewSimulatedBackend(WithDatabase()).
func NewSimulatedBackendWithDatabase(ethdb.Database, core.GenesisAlloc, gasLimit) *SimulatedBackend I can push the DB Option to a later PR if you'd like, but I'm sure we all want to see this whole thing wrapped up sooner. |
We discussed that we like the big long clunky constructor better than the variadic methods. So just adding |
818dcd9
to
49a3eb5
Compare
Both done, with backwards compatibility maintained. Anyone who uses the original constructors and directly modifies the |
We are reworking the simulated backend in #28202 so this doesn't really apply anymore. |
backends.SimulatedBackend
has an internal methodcallContract()
that is common to each ofCallContract()
,PendingCallContract()
andEstimateGas()
. In cloning the EVM to run the calls, it fails to to copy anyvm.Config
held by the underlying*core.Blockchain
. This makes it impossible to, for example, trace static calls in testing*.This PR introduces variadic configuration
Option
s to override the default functionality in a backwards-compatible manner by not changing the effective function signature for existing code. The alternative of a config struct with aNew() *SimulatedBackend
method makes for a more cumbersome API, hence theOption
pattern.The options
CloneVMConfigOnCall()
,CloneVMConfigOnPendingCall()
,ClondeVMConfigOnEstimateGas()
, andAlwaysCloneVMConfig()
do as they say on the tin. Internally, they simply switch flags in a new struct inSimulatedBackend
. TheNoBaseFee
field ofvm.Config
is always set to true, in keeping with historical behaviour.*This isn't just a hypothetical situation: I discovered it after writing a trace-based coverage analysis tool for Solidity contracts, which is blocked by this PR.