Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions consensus/misc/eip4844.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,6 @@ func CalcExcessDataGas(parentExcessDataGas *big.Int, newBlobs int) *big.Int {
return new(big.Int).Set(excessDataGas.Sub(excessDataGas, targetGas))
}

// fakeExponential approximates factor * e ** (num / denom) using a taylor expansion
// as described in the EIP-4844 spec.
func fakeExponential(factor, num, denom *big.Int) *big.Int {
output := new(big.Int)
numAccum := new(big.Int).Mul(factor, denom)
for i := 1; numAccum.Sign() > 0; i++ {
output.Add(output, numAccum)
numAccum.Mul(numAccum, num)
iBig := big.NewInt(int64(i))
numAccum.Div(numAccum, iBig.Mul(iBig, denom))
}
return output.Div(output, denom)
}

// CountBlobs returns the number of blob transactions in txs
func CountBlobs(txs []*types.Transaction) int {
var count int
Expand Down Expand Up @@ -101,11 +87,6 @@ func VerifyExcessDataGas(chainReader ChainReader, block *types.Block) error {
return nil
}

// GetDataGasPrice implements get_data_gas_price from EIP-4844
func GetDataGasPrice(excessDataGas *big.Int) *big.Int {
return fakeExponential(big.NewInt(params.MinDataGasPrice), excessDataGas, big.NewInt(params.DataGasPriceUpdateFraction))
}

// ChainReader defines a small collection of methods needed to access the local
// blockchain for EIP4844 block verifcation.
type ChainReader interface {
Expand Down
34 changes: 0 additions & 34 deletions consensus/misc/eip4844_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,6 @@ import (
"github.com/ethereum/go-ethereum/params"
)

func TestFakeExponential(t *testing.T) {
var tests = []struct {
factor, num, denom int64
want int64
}{
// When num==0 the return value should always equal the value of factor
{1, 0, 1, 1},
{38493, 0, 1000, 38493},
{0, 1234, 2345, 0}, // should be 0
{1, 2, 1, 6}, // approximate 7.389
{1, 4, 2, 6},
{1, 3, 1, 16}, // approximate 20.09
{1, 6, 2, 18},
{1, 4, 1, 49}, // approximate 54.60
{1, 8, 2, 50},
{10, 8, 2, 542}, // approximate 540.598
{11, 8, 2, 596}, // approximate 600.58
{1, 5, 1, 136}, // approximate 148.4
{1, 5, 2, 11}, // approximate 12.18
{2, 5, 2, 23}, // approximate 24.36
}

for _, tt := range tests {
factor := big.NewInt(tt.factor)
num := big.NewInt(tt.num)
denom := big.NewInt(tt.denom)
result := fakeExponential(factor, num, denom)
//t.Logf("%v*e^(%v/%v): %v", factor, num, denom, result)
if tt.want != result.Int64() {
t.Errorf("got %v want %v", result, tt.want)
}
}
}

func TestCalcExcessDataGas(t *testing.T) {
var tests = []struct {
parentExcessDataGas int64
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2050,7 +2050,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
// the processing of a block. These logs are later announced as deleted or reborn.
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), b.Transactions())
receipts.DeriveLogFields(b.Hash(), b.NumberU64(), b.Transactions())

var logs []*types.Log
for _, receipt := range receipts {
Expand Down
7 changes: 6 additions & 1 deletion core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,12 +638,17 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para
}
header := ReadHeader(db, hash, number)
var baseFee *big.Int
var parentExcessDataGas *big.Int
if header == nil {
baseFee = big.NewInt(0)
} else {
baseFee = header.BaseFee
parentHeader := ReadHeader(db, header.ParentHash, number-1)
if parentHeader != nil {
parentExcessDataGas = parentHeader.ExcessDataGas
}
}
if err := receipts.DeriveFields(config, hash, number, header.Time, baseFee, body.Transactions); err != nil {
if err := receipts.DeriveFields(config, hash, number, header.Time, baseFee, parentExcessDataGas, body.Transactions); err != nil {
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
return nil
}
Expand Down
7 changes: 3 additions & 4 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

"github.com/ethereum/go-ethereum/common"
cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
Expand Down Expand Up @@ -242,7 +241,7 @@ func (st *StateTransition) buyGas() error {
if st.evm.Context.ExcessDataGas == nil {
return fmt.Errorf("%w: sharding is active but ExcessDataGas is nil. Time: %v", ErrInternalFailure, st.evm.Context.Time)
}
dgval.Mul(misc.GetDataGasPrice(st.evm.Context.ExcessDataGas), new(big.Int).SetUint64(dataGasUsed))
dgval.Mul(types.GetDataGasPrice(st.evm.Context.ExcessDataGas), new(big.Int).SetUint64(dataGasUsed))
}

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

func (st *StateTransition) dataGasUsed() uint64 {
return uint64(len(st.msg.DataHashes)) * params.DataGasPerBlob
return types.GetDataGasUsed(len(st.msg.DataHashes))
}
32 changes: 31 additions & 1 deletion core/types/data_blob_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
"github.com/protolambda/ztyp/codec"
"github.com/protolambda/ztyp/conv"
. "github.com/protolambda/ztyp/view"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)

type ECDSASignature struct {
Expand Down Expand Up @@ -398,3 +400,31 @@ func (tx *SignedBlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.I
}
return tip.Add(tip, baseFee)
}

// fakeExponential approximates factor * e ** (num / denom) using a taylor expansion
// as described in the EIP-4844 spec.
func fakeExponential(factor, num, denom *big.Int) *big.Int {
output := new(big.Int)
numAccum := new(big.Int).Mul(factor, denom)
for i := 1; numAccum.Sign() > 0; i++ {
output.Add(output, numAccum)
numAccum.Mul(numAccum, num)
iBig := big.NewInt(int64(i))
numAccum.Div(numAccum, iBig.Mul(iBig, denom))
}
return output.Div(output, denom)
}

// GetDataGasPrice implements get_data_gas_price from EIP-4844
func GetDataGasPrice(excessDataGas *big.Int) *big.Int {
if excessDataGas == nil {
return nil
}
return fakeExponential(big.NewInt(params.MinDataGasPrice), excessDataGas, big.NewInt(params.DataGasPriceUpdateFraction))
}

// GetDataGasUsed returns the amount of datagas consumed by a transaction with the specified number
// of blobs
func GetDataGasUsed(blobs int) uint64 {
return uint64(blobs) * params.DataGasPerBlob
}
40 changes: 40 additions & 0 deletions core/types/data_blob_tx_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package types

import (
"math/big"
"testing"
)

func TestFakeExponential(t *testing.T) {
var tests = []struct {
factor, num, denom int64
want int64
}{
// When num==0 the return value should always equal the value of factor
{1, 0, 1, 1},
{38493, 0, 1000, 38493},
{0, 1234, 2345, 0}, // should be 0
{1, 2, 1, 6}, // approximate 7.389
{1, 4, 2, 6},
{1, 3, 1, 16}, // approximate 20.09
{1, 6, 2, 18},
{1, 4, 1, 49}, // approximate 54.60
{1, 8, 2, 50},
{10, 8, 2, 542}, // approximate 540.598
{11, 8, 2, 596}, // approximate 600.58
{1, 5, 1, 136}, // approximate 148.4
{1, 5, 2, 11}, // approximate 12.18
{2, 5, 2, 23}, // approximate 24.36
}

for _, tt := range tests {
factor := big.NewInt(tt.factor)
num := big.NewInt(tt.num)
denom := big.NewInt(tt.denom)
result := fakeExponential(factor, num, denom)
//t.Logf("%v*e^(%v/%v): %v", factor, num, denom, result)
if tt.want != result.Int64() {
t.Errorf("got %v want %v", result, tt.want)
}
}
}
20 changes: 16 additions & 4 deletions core/types/gen_receipt_json.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 33 additions & 12 deletions core/types/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,15 @@ type Receipt struct {
Logs []*Log `json:"logs" gencodec:"required"`

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

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

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

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

// Set data gas fields for blob-containing txs
if len(txs[i].DataHashes()) > 0 {
rs[i].DataGasUsed = GetDataGasUsed(len(txs[i].DataHashes()))
rs[i].DataGasPrice = GetDataGasPrice(parentExcessDataGas)
}
}
return rs.DeriveLogFields(hash, number, txs)
}

// DeriveLogFields fills the receipt logs with their computed fields based on consensus data and
// contextual infos like containing block and transactions.
func (rs Receipts) DeriveLogFields(hash common.Hash, number uint64, txs []*Transaction) error {
if len(txs) != len(rs) {
return errors.New("transaction and receipt count mismatch")
}
logIndex := uint(0)
for i, r := range rs {
// The derived log fields can simply be set from the block and transaction
for j := 0; j < len(rs[i].Logs); j++ {
rs[i].Logs[j].BlockNumber = number
rs[i].Logs[j].BlockHash = hash
rs[i].Logs[j].TxHash = rs[i].TxHash
rs[i].Logs[j].TxIndex = uint(i)
rs[i].Logs[j].Index = logIndex
for _, l := range r.Logs {
l.BlockNumber = number
l.BlockHash = hash
l.TxHash = txs[i].Hash()
l.TxIndex = uint(i)
l.Index = logIndex
logIndex++
}
}
Expand Down
Loading