Skip to content

Commit fcc5f10

Browse files
add UsedDataGas and DataGasPrice to the receipt
1 parent ea43bc1 commit fcc5f10

File tree

12 files changed

+179
-79
lines changed

12 files changed

+179
-79
lines changed

consensus/misc/eip4844.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,6 @@ func CalcExcessDataGas(parentExcessDataGas *big.Int, newBlobs int) *big.Int {
4242
return new(big.Int).Set(excessDataGas.Sub(excessDataGas, targetGas))
4343
}
4444

45-
// fakeExponential approximates factor * e ** (num / denom) using a taylor expansion
46-
// as described in the EIP-4844 spec.
47-
func fakeExponential(factor, num, denom *big.Int) *big.Int {
48-
output := new(big.Int)
49-
numAccum := new(big.Int).Mul(factor, denom)
50-
for i := 1; numAccum.Sign() > 0; i++ {
51-
output.Add(output, numAccum)
52-
numAccum.Mul(numAccum, num)
53-
iBig := big.NewInt(int64(i))
54-
numAccum.Div(numAccum, iBig.Mul(iBig, denom))
55-
}
56-
return output.Div(output, denom)
57-
}
58-
5945
// CountBlobs returns the number of blob transactions in txs
6046
func CountBlobs(txs []*types.Transaction) int {
6147
var count int
@@ -101,11 +87,6 @@ func VerifyExcessDataGas(chainReader ChainReader, block *types.Block) error {
10187
return nil
10288
}
10389

104-
// GetDataGasPrice implements get_data_gas_price from EIP-4844
105-
func GetDataGasPrice(excessDataGas *big.Int) *big.Int {
106-
return fakeExponential(big.NewInt(params.MinDataGasPrice), excessDataGas, big.NewInt(params.DataGasPriceUpdateFraction))
107-
}
108-
10990
// ChainReader defines a small collection of methods needed to access the local
11091
// blockchain for EIP4844 block verifcation.
11192
type ChainReader interface {

consensus/misc/eip4844_test.go

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,40 +23,6 @@ import (
2323
"github.com/ethereum/go-ethereum/params"
2424
)
2525

26-
func TestFakeExponential(t *testing.T) {
27-
var tests = []struct {
28-
factor, num, denom int64
29-
want int64
30-
}{
31-
// When num==0 the return value should always equal the value of factor
32-
{1, 0, 1, 1},
33-
{38493, 0, 1000, 38493},
34-
{0, 1234, 2345, 0}, // should be 0
35-
{1, 2, 1, 6}, // approximate 7.389
36-
{1, 4, 2, 6},
37-
{1, 3, 1, 16}, // approximate 20.09
38-
{1, 6, 2, 18},
39-
{1, 4, 1, 49}, // approximate 54.60
40-
{1, 8, 2, 50},
41-
{10, 8, 2, 542}, // approximate 540.598
42-
{11, 8, 2, 596}, // approximate 600.58
43-
{1, 5, 1, 136}, // approximate 148.4
44-
{1, 5, 2, 11}, // approximate 12.18
45-
{2, 5, 2, 23}, // approximate 24.36
46-
}
47-
48-
for _, tt := range tests {
49-
factor := big.NewInt(tt.factor)
50-
num := big.NewInt(tt.num)
51-
denom := big.NewInt(tt.denom)
52-
result := fakeExponential(factor, num, denom)
53-
//t.Logf("%v*e^(%v/%v): %v", factor, num, denom, result)
54-
if tt.want != result.Int64() {
55-
t.Errorf("got %v want %v", result, tt.want)
56-
}
57-
}
58-
}
59-
6026
func TestCalcExcessDataGas(t *testing.T) {
6127
var tests = []struct {
6228
parentExcessDataGas int64

core/blockchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2050,7 +2050,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
20502050
// the processing of a block. These logs are later announced as deleted or reborn.
20512051
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
20522052
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
2053-
receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), b.Transactions())
2053+
receipts.DeriveLogFields(b.Hash(), b.NumberU64(), b.Transactions())
20542054

20552055
var logs []*types.Log
20562056
for _, receipt := range receipts {

core/rawdb/accessors_chain.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,12 +638,17 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para
638638
}
639639
header := ReadHeader(db, hash, number)
640640
var baseFee *big.Int
641+
var parentExcessDataGas *big.Int
641642
if header == nil {
642643
baseFee = big.NewInt(0)
643644
} else {
644645
baseFee = header.BaseFee
646+
parentHeader := ReadHeader(db, header.ParentHash, number-1)
647+
if parentHeader != nil {
648+
parentExcessDataGas = parentHeader.ExcessDataGas
649+
}
645650
}
646-
if err := receipts.DeriveFields(config, hash, number, header.Time, baseFee, body.Transactions); err != nil {
651+
if err := receipts.DeriveFields(config, hash, number, header.Time, baseFee, parentExcessDataGas, body.Transactions); err != nil {
647652
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
648653
return nil
649654
}

core/state_transition.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323

2424
"github.com/ethereum/go-ethereum/common"
2525
cmath "github.com/ethereum/go-ethereum/common/math"
26-
"github.com/ethereum/go-ethereum/consensus/misc"
2726
"github.com/ethereum/go-ethereum/core/types"
2827
"github.com/ethereum/go-ethereum/core/vm"
2928
"github.com/ethereum/go-ethereum/params"
@@ -242,7 +241,7 @@ func (st *StateTransition) buyGas() error {
242241
if st.evm.Context.ExcessDataGas == nil {
243242
return fmt.Errorf("%w: sharding is active but ExcessDataGas is nil. Time: %v", ErrInternalFailure, st.evm.Context.Time)
244243
}
245-
dgval.Mul(misc.GetDataGasPrice(st.evm.Context.ExcessDataGas), new(big.Int).SetUint64(dataGasUsed))
244+
dgval.Mul(types.GetDataGasPrice(st.evm.Context.ExcessDataGas), new(big.Int).SetUint64(dataGasUsed))
246245
}
247246

248247
// perform the required user balance checks
@@ -325,7 +324,7 @@ func (st *StateTransition) preCheck() error {
325324
}
326325
}
327326
if st.dataGasUsed() > 0 && st.evm.ChainConfig().IsSharding(st.evm.Context.Time) {
328-
dataGasPrice := misc.GetDataGasPrice(st.evm.Context.ExcessDataGas)
327+
dataGasPrice := types.GetDataGasPrice(st.evm.Context.ExcessDataGas)
329328
if dataGasPrice.Cmp(st.msg.MaxFeePerDataGas) > 0 {
330329
return fmt.Errorf("%w: address %v, maxFeePerDataGas: %v dataGasPrice: %v, excessDataGas: %v",
331330
ErrMaxFeePerDataGas,
@@ -466,5 +465,5 @@ func (st *StateTransition) gasUsed() uint64 {
466465
}
467466

468467
func (st *StateTransition) dataGasUsed() uint64 {
469-
return uint64(len(st.msg.DataHashes)) * params.DataGasPerBlob
468+
return types.GetDataGasUsed(len(st.msg.DataHashes))
470469
}

core/types/data_blob_tx.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import (
66
"fmt"
77
"math/big"
88

9-
"github.com/ethereum/go-ethereum/common"
109
"github.com/holiman/uint256"
1110
"github.com/protolambda/ztyp/codec"
1211
"github.com/protolambda/ztyp/conv"
1312
. "github.com/protolambda/ztyp/view"
13+
14+
"github.com/ethereum/go-ethereum/common"
15+
"github.com/ethereum/go-ethereum/params"
1416
)
1517

1618
type ECDSASignature struct {
@@ -398,3 +400,31 @@ func (tx *SignedBlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.I
398400
}
399401
return tip.Add(tip, baseFee)
400402
}
403+
404+
// fakeExponential approximates factor * e ** (num / denom) using a taylor expansion
405+
// as described in the EIP-4844 spec.
406+
func fakeExponential(factor, num, denom *big.Int) *big.Int {
407+
output := new(big.Int)
408+
numAccum := new(big.Int).Mul(factor, denom)
409+
for i := 1; numAccum.Sign() > 0; i++ {
410+
output.Add(output, numAccum)
411+
numAccum.Mul(numAccum, num)
412+
iBig := big.NewInt(int64(i))
413+
numAccum.Div(numAccum, iBig.Mul(iBig, denom))
414+
}
415+
return output.Div(output, denom)
416+
}
417+
418+
// GetDataGasPrice implements get_data_gas_price from EIP-4844
419+
func GetDataGasPrice(excessDataGas *big.Int) *big.Int {
420+
if excessDataGas == nil {
421+
return nil
422+
}
423+
return fakeExponential(big.NewInt(params.MinDataGasPrice), excessDataGas, big.NewInt(params.DataGasPriceUpdateFraction))
424+
}
425+
426+
// GetDataGasUsed returns the amount of datagas consumed by a transaction with the specified number
427+
// of blobs
428+
func GetDataGasUsed(blobs int) uint64 {
429+
return uint64(blobs) * params.DataGasPerBlob
430+
}

core/types/data_blob_tx_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package types
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
)
7+
8+
func TestFakeExponential(t *testing.T) {
9+
var tests = []struct {
10+
factor, num, denom int64
11+
want int64
12+
}{
13+
// When num==0 the return value should always equal the value of factor
14+
{1, 0, 1, 1},
15+
{38493, 0, 1000, 38493},
16+
{0, 1234, 2345, 0}, // should be 0
17+
{1, 2, 1, 6}, // approximate 7.389
18+
{1, 4, 2, 6},
19+
{1, 3, 1, 16}, // approximate 20.09
20+
{1, 6, 2, 18},
21+
{1, 4, 1, 49}, // approximate 54.60
22+
{1, 8, 2, 50},
23+
{10, 8, 2, 542}, // approximate 540.598
24+
{11, 8, 2, 596}, // approximate 600.58
25+
{1, 5, 1, 136}, // approximate 148.4
26+
{1, 5, 2, 11}, // approximate 12.18
27+
{2, 5, 2, 23}, // approximate 24.36
28+
}
29+
30+
for _, tt := range tests {
31+
factor := big.NewInt(tt.factor)
32+
num := big.NewInt(tt.num)
33+
denom := big.NewInt(tt.denom)
34+
result := fakeExponential(factor, num, denom)
35+
//t.Logf("%v*e^(%v/%v): %v", factor, num, denom, result)
36+
if tt.want != result.Int64() {
37+
t.Errorf("got %v want %v", result, tt.want)
38+
}
39+
}
40+
}

core/types/gen_receipt_json.go

Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/types/receipt.go

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,15 @@ type Receipt struct {
5959
Logs []*Log `json:"logs" gencodec:"required"`
6060

6161
// Implementation fields: These fields are added by geth when processing a transaction.
62-
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
63-
ContractAddress common.Address `json:"contractAddress"`
64-
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
65-
EffectiveGasPrice *big.Int `json:"effectiveGasPrice"`
62+
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
63+
ContractAddress common.Address `json:"contractAddress"`
64+
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
65+
// TODO: EffectiveGasPrice should be a required field:
66+
// https://github.com/ethereum/execution-apis/blob/af82a989bead35e2325ecc49a9023df39c548756/src/schemas/receipt.yaml#L49
67+
// Changing it to required is currently breaking cmd/evm/t8n_test.go, so leaving as omitempty for now.
68+
EffectiveGasPrice *big.Int `json:"effectiveGasPrice,omitempty"`
69+
DataGasUsed uint64 `json:"dataGasUsed,omitempty"`
70+
DataGasPrice *big.Int `json:"dataGasPrice,omitempty"`
6671

6772
// Inclusion information: These fields provide information about the inclusion of the
6873
// transaction corresponding to this receipt.
@@ -318,10 +323,9 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
318323

319324
// DeriveFields fills the receipts with their computed fields based on consensus
320325
// data and contextual infos like containing block and transactions.
321-
func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, txs []*Transaction) error {
326+
func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, parentExcessDataGas *big.Int, txs []*Transaction) error {
322327
signer := MakeSigner(config, new(big.Int).SetUint64(number), time)
323328

324-
logIndex := uint(0)
325329
if len(txs) != len(rs) {
326330
return errors.New("transaction and receipt count mismatch")
327331
}
@@ -353,13 +357,30 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu
353357
rs[i].GasUsed = rs[i].CumulativeGasUsed - rs[i-1].CumulativeGasUsed
354358
}
355359

360+
// Set data gas fields for blob-containing txs
361+
if len(txs[i].DataHashes()) > 0 {
362+
rs[i].DataGasUsed = GetDataGasUsed(len(txs[i].DataHashes()))
363+
rs[i].DataGasPrice = GetDataGasPrice(parentExcessDataGas)
364+
}
365+
}
366+
return rs.DeriveLogFields(hash, number, txs)
367+
}
368+
369+
// DeriveLogFields fills the receipt logs with their computed fields based on consensus data and
370+
// contextual infos like containing block and transactions.
371+
func (rs Receipts) DeriveLogFields(hash common.Hash, number uint64, txs []*Transaction) error {
372+
if len(txs) != len(rs) {
373+
return errors.New("transaction and receipt count mismatch")
374+
}
375+
logIndex := uint(0)
376+
for i, r := range rs {
356377
// The derived log fields can simply be set from the block and transaction
357-
for j := 0; j < len(rs[i].Logs); j++ {
358-
rs[i].Logs[j].BlockNumber = number
359-
rs[i].Logs[j].BlockHash = hash
360-
rs[i].Logs[j].TxHash = rs[i].TxHash
361-
rs[i].Logs[j].TxIndex = uint(i)
362-
rs[i].Logs[j].Index = logIndex
378+
for _, l := range r.Logs {
379+
l.BlockNumber = number
380+
l.BlockHash = hash
381+
l.TxHash = txs[i].Hash()
382+
l.TxIndex = uint(i)
383+
l.Index = logIndex
363384
logIndex++
364385
}
365386
}

0 commit comments

Comments
 (0)