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

core/types: add method to compute transaction intrinsic gas #31109

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

cedrickah
Copy link
Contributor

Resolves: #31058

Added an IntrinsicGas() method in core/types to compute transaction intrinsic gas.

@rjl493456442
Copy link
Member

Please use this method to prevent potential future expansion of the IntrinsicGas function in the core package.

if byt != 0 {
nz++
}
}
Copy link

Choose a reason for hiding this comment

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

While you're at it, you might as well change the loop to:

z := uint64(bytes.Count(data, []byte{0}))
nz := uint64(len(data)) - z

bytes.Count() uses an optimized assembly implementation to count bytes.

Copy link
Member

Choose a reason for hiding this comment

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

+1

@cedrickah
Copy link
Contributor Author

Please use this method to prevent potential future expansion of the IntrinsicGas function in the core package.

Hi @rjl493456442. Please, can you give me more details on what you mean?

@fjl
Copy link
Contributor

fjl commented Feb 6, 2025

He means the function core.IntrinsicGas should be removed.

@cedrickah
Copy link
Contributor Author

cedrickah commented Feb 6, 2025

He means the function core.IntrinsicGas should be removed.

Okay. I will push the changes.

@cedrickah
Copy link
Contributor Author

Please use this method to prevent potential future expansion of the IntrinsicGas function in the core package.

Hi @rjl493456442 Can you review the these changes please?

Data: data,
GasPrice: gasPrice,
})
gas, _ := tx0.IntrinsicGas(&rules)
Copy link
Contributor

Choose a reason for hiding this comment

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

Repeating the tx construction here is not great, and hightlights a shortcoming of having IntrinsicGas as a method of Transaction: you can't compute the intrinsic gas without creating the tx first, but it's often called to fill in the Gas of a new transaction. We need to think a bit harder how to solve this one. I have a hunch IntrinsicGas could be defined over types.TxData. But then we'd need to implement TxData in Transaction.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think TxData is already in Transaction as the inner field.

Copy link
Contributor

@fjl fjl Feb 8, 2025

Choose a reason for hiding this comment

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

OK, I've figured it out. What we need to do is, add a function IntrinsicGas(TxData, *params.Rules) to core/types. Keep the IntrinsicGas method on Transaction, and make it call this new function on tx.inner.

Copy link
Contributor Author

@cedrickah cedrickah Feb 8, 2025

Choose a reason for hiding this comment

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

OK. I wonder if the IntrinsicGas function could not have this signature instead: func (data []byte, accessList types.AccessList, authList []types.SetCodeAuthorization, isContractCreation, rules *params.Rules) (uint64, error).
It allows to pass fields in tx.inner instead of tx.inner, we can then do without a variable of type TxData if necessary. However, review the modifications please.

@fjl fjl added this to the 1.15.1 milestone Feb 11, 2025
@fjl fjl modified the milestones: 1.15.1, 1.15.2, 1.15.3 Feb 13, 2025
Copy link
Member

@lightclient lightclient left a comment

Choose a reason for hiding this comment

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

Left a few comments. Need to decide how to pass the txdata in state_transition.

Please rebase also when you can.

Gas: msg.GasLimit,
Data: msg.Data,
GasPrice: msg.GasPrice,
})
Copy link
Member

Choose a reason for hiding this comment

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

I think this isn't great.

By going tx -> msg -> back to tx we require ourselves to convert to msg correct and back correctly. TxData seems like the right thing to feed IntrinsicGas, but forcing stuff into a legacy tx when we don't exactly know the origin (or it isn't defined) isn't correct.

This currently fails to compute the intrinsic gas correctly for SetCode txs, because when converting from msg to a tx, the conversion is for a tx that does not have authorizations. Since SetCode seems like a perfect superset of all possible values which goes into InstrinsicGas, but if a new tx type comes along without auths and needs a new input to the IntrinsicGas computation, we'll have the same problem again.

Seems like there are two paths here:

  1. add new struct like GenericTxData that implements TxData and use this in places where we don't know the tx type

  2. add a new method on Message that infers the tx type and constructs the correct TxData

  3. is probably less code, but adds a weird export. 2) is more code, but still has the problem occasionally in other places outside core like tests where we want to generically compute some intrinsic gas.

I think I lean towards 1) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the review. I understand the problems posed. I'm going to look into the new GenericTxData structure. But I would also like to know if we should then put the IntrinsicGas method on TxData or leave it on Transaction.

Copy link
Member

Choose a reason for hiding this comment

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

I think it should be on Transaction like you have it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also think we can have it on both Transaction and as a standalone function.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh, wait, I see the issue now. So we would need to implement TxData with Message somehow, but that's not possible because it's supposed to be a private interface. One thing we could do is making the intrinsic gas a part of Message as a field. Then we'd compute it earlier, like in ApplyTransaction. Just unsure how much of a ripple effect this has on other code.

Copy link
Member

Choose a reason for hiding this comment

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

Right. I kinda like this idea of precomputing earlier though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It will then remove the need for GenericTxData struct.

Copy link
Contributor Author

@cedrickah cedrickah Feb 22, 2025

Choose a reason for hiding this comment

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

Hello @fjl @lightclient. The effect is that the gas must be computed in Message before calling ApplyMessage wherever it is executed. Not just at the ApplyTransaction level. A method SetGas(tx types.TxData, rules *params.Rules) for Message can be useful for that.

if byt != 0 {
nz++
}
}
Copy link
Member

Choose a reason for hiding this comment

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

+1

Comment on lines 566 to 583
data = txdata.data()
accessList = txdata.accessList()
authList = txdata.setCodeAuthorizations()
Copy link
Member

Choose a reason for hiding this comment

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

I think these can be removed and use the txdata getter directly

    pick 9798c84 core/types: add method to compute transaction intrinsic gas
    pick 2c620ab core: replace core.IntrinsicGas() with types.IntrinsicGas()
    fixup 0aef175 removed unused commented code
    pick 989d560 core/types: add IntrinsicGas() function to compute tx intrinsic gas
@cedrickah cedrickah force-pushed the feature/add-compute-tx-intrinsic-gas-api-in-core-types branch from 97a96f3 to ac10896 Compare February 18, 2025 22:01
}

// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
func IntrinsicGas(txdata TxData, rules *params.Rules) (uint64, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It's annoying to have this function return an error. The only cases where it could return an error is for very large data, which is highly unlikely in practice. It should panic in these cases instead.

The function IntrinsicGas is supposed to be used when construction a new transaction. If we want to be even more safe, we could keep the error-returning variant as an internal function for use in Transaction.IntrinsicGas, since that one is used to validate transactions received over p2p.

@cedrickah cedrickah requested review from lightclient and fjl February 19, 2025 11:23
@s1na
Copy link
Contributor

s1na commented Feb 20, 2025

@cedrickah You force-pushed over my commit. Git must have warned about un-synced commits which you probably ignored. Please double check before force pushing.

I have now pushed it again. It fixes the TransactionTest in tests/. I meant to write a comment so you're aware but somehow it got away from me.

Btw after the latest refactor now many more tests are failing. Please look into them. You can see them on appveyor: https://ci.appveyor.com/project/ethereum/go-ethereum/builds/51553192 (it started another run now so wait a bit).

@cedrickah
Copy link
Contributor Author

@cedrickah You force-pushed over my commit. Git must have warned about un-synced commits which you probably ignored. Please double check before force pushing.

I have now pushed it again. It fixes the TransactionTest in tests/. I meant to write a comment so you're aware but somehow it got away from me.

Btw after the latest refactor now many more tests are failing. Please look into them. You can see them on appveyor: https://ci.appveyor.com/project/ethereum/go-ethereum/builds/51553192 (it started another run now so wait a bit).

Ooh sorry. I'll be more careful. I'm leaning towards tests.

@cedrickah
Copy link
Contributor Author

@cedrickah You force-pushed over my commit. Git must have warned about un-synced commits which you probably ignored. Please double check before force pushing.

I have now pushed it again. It fixes the TransactionTest in tests/. I meant to write a comment so you're aware but somehow it got away from me.

Btw after the latest refactor now many more tests are failing. Please look into them. You can see them on appveyor: https://ci.appveyor.com/project/ethereum/go-ethereum/builds/51553192 (it started another run now so wait a bit).

Hello @s1na . I saw the logs. As we are trying to computer gas in Message, the errors occured because ApplyMessage is called before the gas is precomputed in Mesage at locations. I'll take care of it.

@fjl fjl modified the milestones: 1.15.3, 1.15.4, 1.15.5 Feb 25, 2025
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.

core/types: add stable API to compute tx intrinsic gas
6 participants