-
Notifications
You must be signed in to change notification settings - Fork 655
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
Refactor gas constants #1146
Comments
I'm 👍 on this. I have been thinking similarly about our opcodes. That all opcodes in |
Mmh...I'm not so sure about that one. After all, these are logic functions that even private chains may want to use. We already configure the opcodes per fork. py-evm/eth/vm/forks/constantinople/opcodes.py Lines 24 to 40 in bf1d3c2
But imagine you are implementing a private chain and want to use I can see the point though, chances are another fork wants to implement |
We could potentially anchor them in stub fork like |
As in |
When porting py-evm to Nim, we first used the same gas costs structure of Py-EVM but then refactored to isolate all gas costs and computation in a single file. See https://github.com/status-im/nimbus/pull/49 and the final implementation. In the end, we currently have on array per fork that maps the "name" to the gas cost from Yellow Paper Appendix G: # Generate the fork-specific gas costs tables
const
BaseGasFees: GasFeeSchedule = [
# Fee Schedule at for the initial Ethereum forks
GasZero: 0'i64,
GasBase: 2,
GasVeryLow: 3,
GasLow: 5,
GasMid: 8,
GasHigh: 10,
GasExtCode: 20, # Changed to 700 in Tangerine (EIP150)
GasBalance: 20, # Changed to 400 in Tangerine (EIP150)
GasSload: 50, # Changed to 200 in Tangerine (EIP150)
GasJumpDest: 1,
GasSset: 20_000,
GasSreset: 5_000,
RefundSclear: 15_000,
RefundSelfDestruct: 24_000,
GasSelfDestruct: 0, # Changed to 5000 in Tangerine (EIP150)
GasCreate: 32000,
GasCodeDeposit: 200,
GasCall: 40, # Changed to 700 in Tangerine (EIP150)
GasCallValue: 9000,
GasCallStipend: 2300,
GasNewAccount: 25_000,
GasExp: 10,
GasExpByte: 10, # Changed to 50 in Spurious Dragon (EIP160)
GasMemory: 3,
GasTXCreate: 32000,
GasTXDataZero: 4,
GasTXDataNonZero: 68,
GasTransaction: 21000,
GasLog: 375,
GasLogData: 8,
GasLogTopic: 375,
GasSha3: 30,
GasSha3Word: 6,
GasCopy: 3,
GasBlockhash: 20
# GasQuadDivisor: 100 # Unused, do not confuse with the quadratic coefficient 512 for memory expansion
]
# Create the schedule for each forks
func tangerineGasFees(previous_fees: GasFeeSchedule): GasFeeSchedule =
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md
result = previous_fees
result[GasSload] = 200
result[GasSelfDestruct] = 5000
result[GasBalance] = 400
result[GasCall] = 40
func spuriousGasFees(previous_fees: GasFeeSchedule): GasFeeSchedule =
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-160.md
result = previous_fees
result[GasExpByte] = 50
const
TangerineGasFees = BaseGasFees.tangerineGasFees
SpuriousGasFees = TangerineGasFees.spuriousGasFees
# Note that later forks are still WIP
# `gasCosts` is a macro that builds an array of gas cost functions
# It takes (Fee schedule, prefix of generated functions, result array of functions)
# as argument.
# The array is a property of vm forks.
gasCosts(BaseGasFees, base, BaseGasCosts)
gasCosts(TangerineGasFees, tangerine, TangerineGasCosts)
# Note that later forks are still WIP
proc forkToSchedule*(fork: Fork): GasCosts =
if fork < FkTangerine:
BaseGasCosts
else:
TangerineGasCosts
# Note that later forks are still WIP |
@mratsim thanks for chiming in here and sharing your code from the nimbus client 👍 As promised to @glaksmono in chat, here's me elaborating on the issue. Let's look at how the constants are used to day and the things that may be wrong with that. Let's consider Line 44 in 931e915
However, retrieving the balance doesn't actually cost
My initial reaction was: Let's clean up There are more generic constants such as And then there's another category. A constant such as With that in mind, let's try something else. Let's create a new class class BaseConstants:
GAS_LOW = 5
...
GAS_BALANCE = 20
... And then instead of the forks maintaining plain old constants in a separate file, let them have their inherited versions of the class TangerineWhistleConstants(BaseConstants):
GAS_BALANCE = 400 Instead of introducing a new, different constant to adjust the gas price of the balance opcode, the fork would just redefine With that in mind, let's derive some rules on how to use organize constants under that model.
@pipermerriam does that feel alright to you? |
My initial thought is 👎 with respect to the status-quo of just leaving things as they are. I already dislike how much inheritance we have in our current implementation and I'd like to move away from that. Using a class inheritance based approach feels like it just further contributes to the tangle of inherited class mechanics we have going. I'm inclined to shelve this idea but I'm open to alternatives. I'm currently in love with the concepts of composition but it isn't clear exactly how that would apply here. |
I'm a big fan of composition as well but this applies more to
functionality. This case is more about maintaining a extensible table of
static constants. We wouldn't ever have instances of these classes anyway.
…On Mon, Aug 20, 2018, 21:25 Piper Merriam ***@***.***> wrote:
My initial thought is 👎 with respect to the status-quo of just leaving
things as they are. I already dislike how much inheritance we have in our
current implementation and I'd like to move away from that.
I'm inclined to shelve this idea but I'm open to alternatives. I'm
currently in love with the concepts of composition but it isn't clear
exactly how that would apply here.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1146 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAfzlcaGNTw1WuOkCzXNlXGUEbhQzbq5ks5uSw1GgaJpZM4Vwha9>
.
|
instances and inheritance aside, I still don't see this as an improvement to the status quo. I think the only thing this cleans up is forks which have new opcodes which still use things like I'm not seeing the benefit. |
It basically boils down to the question: Do we prefer one fixed name per gas constant e.g. As I understand it Nimbus and I believe Geth also follow this "one table to rule them all" approach. But I'm fine to just stick to what we do if you aren't sharing the love 💕 |
While reading the nimbus issues they mentioned something about fully decoupling gas consumption from opcode logic. I think that our architecture fits that, except that we then re-couple them together with the As for the weird names, I actually like them as they are expressive in making it clear why the value is different, i.e. it's the EIP4711 value. |
To me, having one mapping table with fixed gas constants that just change in their value from fork to fork, sounds like a more maintainable thing compared to a potential explosion of different constants (depending on how often values change per constant). But I don't wanna be stubborn about it. We can close this issue for now and maybe revisit it in the future if we feel things are starting to hurt. |
What is wrong?
I noticed that our gas constants are a bit messy and should be reorganized.
Let's take
GAS_BALANCE
as an example which is defined as such:py-evm/eth/constants.py
Line 43 in bf1d3c2
For someone new to the code base this may seem as if retrieving the balance from some account has a fixed gas cost of
20
when in reality it is400
as specified with the tangerine whistle fork.py-evm/eth/vm/forks/tangerine_whistle/constants.py
Line 13 in bf1d3c2
How can it be fixed
My gut feeling says that only true constants™ belong into
eth.constants
and that all fork specific constants should live inevm.vm.forks.<fork_name>.constants
.The text was updated successfully, but these errors were encountered: