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

Implementation of 'eth_gasPrice' #2396

Merged
merged 8 commits into from
Nov 11, 2022
Merged

Implementation of 'eth_gasPrice' #2396

merged 8 commits into from
Nov 11, 2022

Conversation

rodrigoherrerai
Copy link
Contributor

Hi!

This implements 'eth_gasPrice'.

As discussed in issue #1114 , the implementation consists of the following:

If the chain is not 1559 compatible, it iterates over the last 20 blocks with a limit of 500 transactions. It then gets the average price of those transactions.

If the chain is 1559 compatible, it iterates over the last block to get the average priority fee and adds it to the next base fee.

@codecov
Copy link

codecov bot commented Nov 1, 2022

Codecov Report

Merging #2396 (038f7b4) into master (6d23fd0) will increase coverage by 0.05%.
The diff coverage is 83.01%.

Additional details and impacted files

Impacted file tree graph

Flag Coverage Δ
block 89.42% <ø> (ø)
blockchain 90.21% <ø> (ø)
client 87.53% <83.01%> (+0.04%) ⬆️
common 98.13% <ø> (ø)
devp2p 91.65% <ø> (+0.10%) ⬆️
ethash ∅ <ø> (∅)
evm 79.72% <ø> (ø)
rlp ?
statemanager 89.46% <ø> (ø)
trie 90.87% <ø> (+0.51%) ⬆️
tx 97.80% <ø> (ø)
util 83.89% <ø> (ø)
vm 85.41% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Copy link
Contributor

@acolytec3 acolytec3 left a comment

Choose a reason for hiding this comment

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

This looks great so far (left two specific comments on things I think need to be revised).

Also, can you add a test that runs 20 blocks and computes the gasPrice? Maybe run 21 blocks and validate the computation produces an average of only the last 20 (maybe put some astronomical gas fee in the first block that moves the average up and then make the gas fee just like 20 or something in the following 20) and then validate that the price returned by the RPC call is 20 and not 20 + some large number divided/# txns?

packages/client/lib/rpc/modules/eth.ts Outdated Show resolved Hide resolved
gasPrice = baseFee + priorityFee
} else {
// For chains that don't support EIP-1559 we iterate over the last 20
// blocks to get an average gas price. We cap the tx lookup to 500.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// blocks to get an average gas price. We cap the tx lookup to 500.
// blocks to get an average gas price. We cap the tx lookup per block to 500.

Not sure if you're actually intending to cap the transaction look up in the block or total transactions examined. If you're intending to do it as looking at a total number of transactions, you'll need to move the break in line 1030 after 1031. Otherwise, it will just break from the inner loop and not the outer one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The total tx lookup is 500 in total not per block. So I added the break in the inner and outer for loop so it doesn't exceed the transaction count.

Copy link
Member

Choose a reason for hiding this comment

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

@acolytec3 capping it per block makes no sense (unless I'm in the wrong here), we can get the entire block body from the LevelDB immediately so just getting the avg gas price should be super fast once we got the block from the DB. (This would ofc. be different if we would have to get tx-by-hash each time)

@rodrigoherrerai
Copy link
Contributor Author

Added the tests for 21 blocks !

const txGasPrice = (tx as Transaction).gasPrice
gasPrice += txGasPrice
txCount++
if (txCount >= 500) break
Copy link
Member

Choose a reason for hiding this comment

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

I really do not think we should do a per-block check, and I also do not think we need a tx cap limit. I might be wrong here, but the heaviest operation here is pulling the block body from the DB. Iterating over the txs should be much faster than that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this makes sense. I removed the tx cap.

Copy link
Member

@jochem-brouwer jochem-brouwer left a comment

Choose a reason for hiding this comment

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

I got some comments, but I am really happy to see that this one is being picked up on, thanks a lot! 😄

Copy link
Member

@holgerd77 holgerd77 left a comment

Choose a reason for hiding this comment

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

Short comment

*/
async gasPrice() {
let gasPrice = BigInt(0)
const latest = await this._chain.getCanonicalHeadHeader()
Copy link
Member

Choose a reason for hiding this comment

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

I generally wonder if we want to make this dependent from the synchronized status of the client this.client.config.synchronized? 🤔 it likely doesn't make sense to return anything (respectively: is not useful) if the client is still syncing and we are not calculating upon the latest blocks?

Not sure, maybe to test this in Geth what is responded in such a case?

Also, then: any reason to not also take the chain common object here for the 1559 check (below)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. Also, then: any reason to not also take the chain common object here for the 1559 check (below)?

->Made a change where the min gas price from the chain common object is now checked on both (1559 and non 1559) chains.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure, maybe to test this in Geth what is responded in such a case?

I checked this in geth and it does return a gas price even when syncing. Not sure where that gas price comes from but it's producing something. The spec doesn't give any specifics about how to calculate current gas price so I guess I would just we go with compute best gas price available based on the current view of the chain that we have (i.e. what is implemented here) and leave it to the consumer to validate the sync status of the client via the eth_syncing when evaluating gas price.

@acolytec3 acolytec3 mentioned this pull request Nov 8, 2022
13 tasks
Copy link
Member

@holgerd77 holgerd77 left a comment

Choose a reason for hiding this comment

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

Ok, this looks good now! 🙂 Thanks a lot @rodrigoherrerai for the additional iterations and the contribution in general! 💯 🙏

Will merge.

@holgerd77
Copy link
Member

Rebased this via UI.

Copy link
Member

@holgerd77 holgerd77 left a comment

Choose a reason for hiding this comment

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

LGTM

@holgerd77 holgerd77 merged commit 5a30031 into ethereumjs:master Nov 11, 2022
@rodrigoherrerai
Copy link
Contributor Author

Ok, this looks good now! 🙂 Thanks a lot @rodrigoherrerai for the additional iterations and the contribution in general! 💯 🙏

Will merge.

Great ! Is there any other are that you guys need help ? Would love to contribute more if possible :)

@acolytec3
Copy link
Contributor

Ok, this looks good now! slightly_smiling_face Thanks a lot @rodrigoherrerai for the additional iterations and the contribution in general! 100 pray
Will merge.

Great ! Is there any other are that you guys need help ? Would love to contribute more if possible :)

Definitely! If you're looking for another RPC endpoint to implement, the eth_feeHistory could be an interesting one. I opened an issue with initial comments/a proof of concept implementation (very incomplete) in #2359. If you're looking for something else, feel free to join our discord and we can discuss further on what makes the most sense!

@rodrigoherrerai
Copy link
Contributor Author

Ok, this looks good now! slightly_smiling_face Thanks a lot @rodrigoherrerai for the additional iterations and the contribution in general! 100 pray
Will merge.

Great ! Is there any other are that you guys need help ? Would love to contribute more if possible :)

Definitely! If you're looking for another RPC endpoint to implement, the eth_feeHistory could be an interesting one. I opened an issue with initial comments/a proof of concept implementation (very incomplete) in #2359. If you're looking for something else, feel free to join our discord and we can discuss further on what makes the most sense!

Perf! Can you provide the link to the discord ?

@acolytec3
Copy link
Contributor

https://discord.gg/aT78qk3u

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants