Skip to content

Commit 8c9da8e

Browse files
eth/catalyst: add newPayloadV5 methods
1 parent d955653 commit 8c9da8e

34 files changed

+600
-99
lines changed

consensus/beacon/consensus.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,14 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
373373
return nil, errors.New("withdrawals set before Shanghai activation")
374374
}
375375
}
376+
if chain.Config().IsCancun(header.Number, header.Time) {
377+
var blobs int
378+
for _, tx := range txs {
379+
blobs += len(tx.BlobHashes())
380+
}
381+
blobGasUsed := uint64(blobs * params.BlobTxBlobGasPerBlob)
382+
header.BlobGasUsed = &blobGasUsed
383+
}
376384
// Finalize and assemble the block.
377385
beacon.Finalize(chain, header, state, txs, uncles, withdrawals)
378386

consensus/misc/eip4844/eip4844_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ func TestCalcExcessBlobGas(t *testing.T) {
4545
// The excess data gas should decrease by however much the target was
4646
// under-shot, capped at zero.
4747
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
48-
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxBlobGasPerBlob},
49-
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, 0},
48+
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 2 * params.BlobTxBlobGasPerBlob},
49+
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxBlobGasPerBlob},
5050
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
5151
}
5252
for _, tt := range tests {
@@ -64,8 +64,9 @@ func TestCalcBlobFee(t *testing.T) {
6464
}{
6565
{0, 1},
6666
{1542706, 1},
67-
{1542707, 2},
68-
{10 * 1024 * 1024, 111},
67+
{1542707, 1},
68+
{3085414, 2},
69+
{10 * 1024 * 1024, 23},
6970
}
7071
for i, tt := range tests {
7172
have := CalcBlobFee(tt.excessBlobGas)

core/genesis.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,14 @@ func (g *Genesis) ToBlock() *types.Block {
487487
}
488488
}
489489
}
490+
if g.Config != nil && g.Config.IsCancun(big.NewInt(int64(g.Number)), g.Timestamp) {
491+
if g.ExcessBlobGas == nil {
492+
var excessBlobGas uint64
493+
head.ExcessBlobGas = &excessBlobGas
494+
} else {
495+
head.ExcessBlobGas = g.ExcessBlobGas
496+
}
497+
}
490498
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)
491499
}
492500

core/state_transition.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ func (st *StateTransition) preCheck() error {
339339
}
340340
}
341341
}
342-
343342
return st.buyGas()
344343
}
345344

core/txpool/blobpool/blobpool.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,8 @@ func (p *BlobPool) reinject(addr common.Address, tx *types.Transaction) {
955955
}
956956
p.lookup[meta.hash] = meta.id
957957
p.stored += uint64(meta.size)
958+
959+
p.eventFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
958960
}
959961

960962
// SetGasTip implements txpool.SubPool, allowing the blob pool's gas requirements
@@ -1037,7 +1039,6 @@ func (p *BlobPool) validateTx(tx *types.Transaction, blobs []kzg4844.Blob, commi
10371039
// Ensure the transaction adheres to the stateful pool filters (nonce, balance)
10381040
stateOpts := &txpool.ValidationOptionsWithState{
10391041
State: p.state,
1040-
10411042
FirstNonceGap: func(addr common.Address) uint64 {
10421043
// Nonce gaps are not permitted in the blob pool, the first gap will
10431044
// be the next nonce shifted by however many transactions we already
@@ -1303,6 +1304,7 @@ func (p *BlobPool) add(tx *types.Transaction, blobs []kzg4844.Blob, commits []kz
13031304
}
13041305
p.updateStorageMetrics()
13051306

1307+
p.eventFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
13061308
return nil
13071309
}
13081310

core/txpool/subpool.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ type Transaction struct {
3737
BlobTxProofs []kzg4844.Proof // Proofs needed by the blob pool
3838
}
3939

40+
func (t *Transaction) Size() uint64 {
41+
size := t.Tx.Size()
42+
if len(t.BlobTxBlobs) > 0 {
43+
size += uint64(len(t.BlobTxBlobs) * len(t.BlobTxBlobs[0]))
44+
size += uint64(len(t.BlobTxCommits) * len(t.BlobTxCommits[0]))
45+
size += uint64(len(t.BlobTxProofs) * len(t.BlobTxProofs[0]))
46+
}
47+
return size
48+
}
49+
4050
// LazyTransaction contains a small subset of the transaction properties that is
4151
// enough for the miner and other APIs to handle large batches of transactions;
4252
// and supports pulling up the entire transaction when really needed.

core/types/receipt.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu
355355
rs[i].GasUsed = rs[i].CumulativeGasUsed - rs[i-1].CumulativeGasUsed
356356
}
357357

358+
if len(txs[i].BlobHashes()) != 0 {
359+
rs[i].BlobGasUsed = uint64(len(txs[i].BlobHashes()) * params.BlobTxBlobGasPerBlob)
360+
rs[i].BlobGasPrice = blobGasPrice
361+
}
362+
358363
// The derived log fields can simply be set from the block and transaction
359364
for j := 0; j < len(rs[i].Logs); j++ {
360365
rs[i].Logs[j].BlockNumber = number

core/types/transaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ func (tx *Transaction) BlobGas() uint64 { return tx.inner.blobGas() }
294294
// BlobGasFeeCap returns the data gas fee cap per data gas of the transaction for blob transactions, nil otherwise.
295295
func (tx *Transaction) BlobGasFeeCap() *big.Int { return tx.inner.blobGasFeeCap() }
296296

297-
// BlobHashes returns the hases of the blob commitments for blob transactions, nil otherwise.
297+
// BlobHashes returns the hashes of the blob commitments for blob transactions, nil otherwise.
298298
func (tx *Transaction) BlobHashes() []common.Hash { return tx.inner.blobHashes() }
299299

300300
// Value returns the ether amount of the transaction.

core/types/tx_blob_with_blob.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package types
2+
3+
import (
4+
"bytes"
5+
"io"
6+
7+
"github.com/ethereum/go-ethereum/crypto/kzg4844"
8+
"github.com/ethereum/go-ethereum/rlp"
9+
)
10+
11+
type BlobTxWithBlobs struct {
12+
*Transaction
13+
Blobs []kzg4844.Blob
14+
Commitments []kzg4844.Commitment
15+
Proofs []kzg4844.Proof
16+
}
17+
18+
func NewBlobTxWithBlobs(tx *Transaction, blobs []kzg4844.Blob, commitments []kzg4844.Commitment, proofs []kzg4844.Proof) *BlobTxWithBlobs {
19+
if tx == nil {
20+
return nil
21+
}
22+
return &BlobTxWithBlobs{
23+
Transaction: tx,
24+
Blobs: blobs,
25+
Commitments: commitments,
26+
Proofs: proofs,
27+
}
28+
}
29+
30+
type innerType struct {
31+
BlobTx *BlobTx
32+
Blobs []kzg4844.Blob
33+
Commitments []kzg4844.Commitment
34+
Proofs []kzg4844.Proof
35+
}
36+
37+
func (tx *BlobTxWithBlobs) DecodeRLP(s *rlp.Stream) error {
38+
tx.Transaction = new(Transaction)
39+
kind, _, err := s.Kind()
40+
switch {
41+
case err != nil:
42+
return err
43+
case kind == rlp.List:
44+
return tx.Transaction.DecodeRLP(s)
45+
default:
46+
b, err := s.Bytes()
47+
if err != nil {
48+
return err
49+
}
50+
return tx.UnmarshalBinary(b)
51+
}
52+
}
53+
54+
func (tx *BlobTxWithBlobs) EncodeRLP(w io.Writer) error {
55+
blobTx, ok := tx.Transaction.inner.(*BlobTx)
56+
if !ok {
57+
// For non-blob transactions, the encoding is just the transaction.
58+
return tx.Transaction.EncodeRLP(w)
59+
}
60+
61+
// For blob transactions, the encoding is the transaction together with the blobs.
62+
// Use temporary buffer from pool.
63+
buf := encodeBufferPool.Get().(*bytes.Buffer)
64+
defer encodeBufferPool.Put(buf)
65+
buf.Reset()
66+
67+
buf.WriteByte(BlobTxType)
68+
innerValue := &innerType{
69+
BlobTx: blobTx,
70+
Blobs: tx.Blobs,
71+
Commitments: tx.Commitments,
72+
Proofs: tx.Proofs,
73+
}
74+
err := rlp.Encode(buf, innerValue)
75+
if err != nil {
76+
return err
77+
}
78+
return rlp.Encode(w, buf.Bytes())
79+
}
80+
81+
func (tx *BlobTxWithBlobs) UnmarshalBinary(b []byte) error {
82+
tx.Transaction = new(Transaction)
83+
if len(b) < 1 {
84+
return errShortTypedTx
85+
}
86+
if b[0] == BlobTxType {
87+
var blobTypedTx innerType
88+
if err := rlp.DecodeBytes(b[1:], &blobTypedTx); err != nil {
89+
return err
90+
}
91+
tx.Transaction = NewTx(blobTypedTx.BlobTx)
92+
tx.Blobs = blobTypedTx.Blobs
93+
tx.Commitments = blobTypedTx.Commitments
94+
tx.Proofs = blobTypedTx.Proofs
95+
return nil
96+
}
97+
return tx.Transaction.UnmarshalBinary(b)
98+
}
99+
100+
func (tx *BlobTxWithBlobs) MarshalBinary() ([]byte, error) {
101+
blobTx, ok := tx.Transaction.inner.(*BlobTx)
102+
if !ok {
103+
// For non-blob transactions, the encoding is just the transaction.
104+
return tx.Transaction.MarshalBinary()
105+
}
106+
var buf bytes.Buffer
107+
buf.WriteByte(BlobTxType)
108+
innerValue := &innerType{
109+
BlobTx: blobTx,
110+
Blobs: tx.Blobs,
111+
Commitments: tx.Commitments,
112+
Proofs: tx.Proofs,
113+
}
114+
err := rlp.Encode(&buf, innerValue)
115+
return buf.Bytes(), err
116+
}

core/types/types_test.go

Lines changed: 57 additions & 1 deletion
Large diffs are not rendered by default.

eth/api_backend.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/ethereum/go-ethereum/core/txpool"
3434
"github.com/ethereum/go-ethereum/core/types"
3535
"github.com/ethereum/go-ethereum/core/vm"
36+
"github.com/ethereum/go-ethereum/crypto/kzg4844"
3637
"github.com/ethereum/go-ethereum/eth/gasprice"
3738
"github.com/ethereum/go-ethereum/eth/tracers"
3839
"github.com/ethereum/go-ethereum/ethdb"
@@ -297,6 +298,10 @@ func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
297298
return b.eth.txPool.Add([]*txpool.Transaction{{Tx: signedTx}}, true, false)[0]
298299
}
299300

301+
func (b *EthAPIBackend) SendBlobTx(ctx context.Context, signedTx *types.Transaction, blobTxBlobs []kzg4844.Blob, blobTxCommits []kzg4844.Commitment, blobTxProofs []kzg4844.Proof) error {
302+
return b.eth.txPool.Add([]*txpool.Transaction{&txpool.Transaction{Tx: signedTx, BlobTxBlobs: blobTxBlobs, BlobTxCommits: blobTxCommits, BlobTxProofs: blobTxProofs}}, true, false)[0]
303+
}
304+
300305
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
301306
pending := b.eth.txPool.Pending(false)
302307
var txs types.Transactions

eth/fetcher/tx_fetcher.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
261261
// and the fetcher. This method may be called by both transaction broadcasts and
262262
// direct request replies. The differentiation is important so the fetcher can
263263
// re-schedule missing transactions as soon as possible.
264-
func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool) error {
264+
func (f *TxFetcher) Enqueue(peer string, txs []*types.BlobTxWithBlobs, direct bool) error {
265265
var (
266266
inMeter = txReplyInMeter
267267
knownMeter = txReplyKnownMeter
@@ -297,7 +297,7 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
297297

298298
wrapped := make([]*txpool.Transaction, len(batch))
299299
for j, tx := range batch {
300-
wrapped[j] = &txpool.Transaction{Tx: tx}
300+
wrapped[j] = &txpool.Transaction{Tx: tx.Transaction, BlobTxBlobs: tx.Blobs, BlobTxCommits: tx.Commitments, BlobTxProofs: tx.Proofs}
301301
}
302302
for j, err := range f.addTxs(wrapped) {
303303
// Track the transaction hash if the price is too low for us.

eth/fetcher/tx_fetcher_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1287,7 +1287,11 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
12871287
}
12881288

12891289
case doTxEnqueue:
1290-
if err := fetcher.Enqueue(step.peer, step.txs, step.direct); err != nil {
1290+
var txs []*types.BlobTxWithBlobs
1291+
for _, tx := range step.txs {
1292+
txs = append(txs, types.NewBlobTxWithBlobs(tx, nil, nil, nil))
1293+
}
1294+
if err := fetcher.Enqueue(step.peer, txs, step.direct); err != nil {
12911295
t.Errorf("step %d: %v", i, err)
12921296
}
12931297
<-wait // Fetcher needs to process this, wait until it's done

eth/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
623623
peers := h.peers.peersWithoutTransaction(tx.Hash())
624624

625625
var numDirect int
626-
if tx.Size() <= txMaxBroadcastSize {
626+
if tx.Size() <= txMaxBroadcastSize && tx.Type() != types.BlobTxType {
627627
numDirect = int(math.Sqrt(float64(len(peers))))
628628
}
629629
// Send the tx unconditionally to a subset of our peers

eth/handler_eth.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
7373
return h.txFetcher.Notify(peer.ID(), packet.Hashes)
7474

7575
case *eth.TransactionsPacket:
76-
return h.txFetcher.Enqueue(peer.ID(), *packet, false)
76+
var txs []*types.BlobTxWithBlobs
77+
for _, tx := range *packet {
78+
txs = append(txs, types.NewBlobTxWithBlobs(tx, nil, nil, nil))
79+
}
80+
return h.txFetcher.Enqueue(peer.ID(), txs, false)
7781

7882
case *eth.PooledTransactionsPacket:
7983
return h.txFetcher.Enqueue(peer.ID(), *packet, true)

0 commit comments

Comments
 (0)