Skip to content

Commit d75e28e

Browse files
committed
core, internal, miner, signer: convert legacy sidecar in Osaka fork
1 parent e9dca3b commit d75e28e

File tree

6 files changed

+150
-62
lines changed

6 files changed

+150
-62
lines changed

core/txpool/blobpool/blobpool.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1397,17 +1397,46 @@ func (p *BlobPool) AvailableBlobs(vhashes []common.Hash) int {
13971397
return available
13981398
}
13991399

1400+
// convertSidecar converts the legacy sidecar in the submitted transactions
1401+
// if osaka fork has been activated.
1402+
func (p *BlobPool) convertSidecar(txs []*types.Transaction) ([]*types.Transaction, []error) {
1403+
head := p.chain.CurrentBlock()
1404+
if !p.chain.Config().IsOsaka(head.Number, head.Time) {
1405+
return txs, make([]error, len(txs))
1406+
}
1407+
var errs []error
1408+
for _, tx := range txs {
1409+
sidecar := tx.BlobTxSidecar()
1410+
if sidecar == nil {
1411+
errs = append(errs, errors.New("missing sidecar in blob transaction"))
1412+
continue
1413+
}
1414+
if sidecar.Version == types.BlobSidecarVersion0 {
1415+
if err := sidecar.ToV1(); err != nil {
1416+
errs = append(errs, err)
1417+
continue
1418+
}
1419+
}
1420+
errs = append(errs, nil)
1421+
}
1422+
return txs, errs
1423+
}
1424+
14001425
// Add inserts a set of blob transactions into the pool if they pass validation (both
14011426
// consensus validity and pool restrictions).
14021427
//
14031428
// Note, if sync is set the method will block until all internal maintenance
14041429
// related to the add is finished. Only use this during tests for determinism.
14051430
func (p *BlobPool) Add(txs []*types.Transaction, sync bool) []error {
14061431
var (
1432+
errs []error
14071433
adds = make([]*types.Transaction, 0, len(txs))
1408-
errs = make([]error, len(txs))
14091434
)
1435+
txs, errs = p.convertSidecar(txs)
14101436
for i, tx := range txs {
1437+
if errs[i] != nil {
1438+
continue
1439+
}
14111440
errs[i] = p.add(tx)
14121441
if errs[i] == nil {
14131442
adds = append(adds, tx.WithoutBlobTxSidecar())

core/txpool/validation.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"math/big"
2323

2424
"github.com/ethereum/go-ethereum/common"
25-
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
2625
"github.com/ethereum/go-ethereum/core"
2726
"github.com/ethereum/go-ethereum/core/state"
2827
"github.com/ethereum/go-ethereum/core/types"
@@ -167,9 +166,8 @@ func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationO
167166
if len(hashes) == 0 {
168167
return errors.New("blobless blob transaction")
169168
}
170-
maxBlobs := eip4844.MaxBlobsPerBlock(opts.Config, head.Time)
171-
if len(hashes) > maxBlobs {
172-
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), maxBlobs)
169+
if len(hashes) > params.BlobTxMaxBlobs {
170+
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.BlobTxMaxBlobs)
173171
}
174172
if len(sidecar.Blobs) != len(hashes) {
175173
return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes))

internal/ethapi/api.go

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,8 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
14791479

14801480
// SendTransaction creates a transaction for the given argument, sign it and submit it to the
14811481
// transaction pool.
1482+
//
1483+
// This API is not capable for submitting blob transaction with sidecar.
14821484
func (api *TransactionAPI) SendTransaction(ctx context.Context, args TransactionArgs) (common.Hash, error) {
14831485
// Look up the wallet containing the requested signer
14841486
account := accounts.Account{Address: args.from()}
@@ -1499,7 +1501,10 @@ func (api *TransactionAPI) SendTransaction(ctx context.Context, args Transaction
14991501
}
15001502

15011503
// Set some sanity defaults and terminate on failure
1502-
if err := args.setDefaults(ctx, api.b, false); err != nil {
1504+
config := setDefaultConfig{
1505+
skipGasEstimation: false,
1506+
}
1507+
if err := args.setDefaults(ctx, api.b, config); err != nil {
15031508
return common.Hash{}, err
15041509
}
15051510
// Assemble the transaction and sign with the wallet
@@ -1516,10 +1521,20 @@ func (api *TransactionAPI) SendTransaction(ctx context.Context, args Transaction
15161521
// on a given unsigned transaction, and returns it to the caller for further
15171522
// processing (signing + broadcast).
15181523
func (api *TransactionAPI) FillTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
1519-
args.blobSidecarAllowed = true
1520-
15211524
// Set some sanity defaults and terminate on failure
1522-
if err := args.setDefaults(ctx, api.b, false); err != nil {
1525+
config := setDefaultConfig{
1526+
skipGasEstimation: false,
1527+
blobSidecarAllowed: true,
1528+
blobSidecarVersion: types.BlobSidecarVersion0,
1529+
}
1530+
if len(args.Blobs) > 0 {
1531+
chainHead := api.b.CurrentHeader()
1532+
isOsaka := api.b.ChainConfig().IsOsaka(chainHead.Number, chainHead.Time)
1533+
if isOsaka {
1534+
config.blobSidecarVersion = types.BlobSidecarVersion1
1535+
}
1536+
}
1537+
if err := args.setDefaults(ctx, api.b, config); err != nil {
15231538
return nil, err
15241539
}
15251540
// Assemble the transaction and obtain rlp
@@ -1576,8 +1591,6 @@ type SignTransactionResult struct {
15761591
// The node needs to have the private key of the account corresponding with
15771592
// the given from address and it needs to be unlocked.
15781593
func (api *TransactionAPI) SignTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
1579-
args.blobSidecarAllowed = true
1580-
15811594
if args.Gas == nil {
15821595
return nil, errors.New("gas not specified")
15831596
}
@@ -1587,7 +1600,21 @@ func (api *TransactionAPI) SignTransaction(ctx context.Context, args Transaction
15871600
if args.Nonce == nil {
15881601
return nil, errors.New("nonce not specified")
15891602
}
1590-
if err := args.setDefaults(ctx, api.b, false); err != nil {
1603+
config := setDefaultConfig{
1604+
skipGasEstimation: false,
1605+
blobSidecarAllowed: true,
1606+
}
1607+
sidecarVersion := types.BlobSidecarVersion0
1608+
if len(args.Blobs) > 0 {
1609+
chainHead := api.b.CurrentHeader()
1610+
isOsaka := api.b.ChainConfig().IsOsaka(chainHead.Number, chainHead.Time)
1611+
if isOsaka {
1612+
sidecarVersion = types.BlobSidecarVersion1
1613+
}
1614+
}
1615+
config.blobSidecarVersion = sidecarVersion
1616+
1617+
if err := args.setDefaults(ctx, api.b, config); err != nil {
15911618
return nil, err
15921619
}
15931620
// Before actually sign the transaction, ensure the transaction fee is reasonable.
@@ -1603,7 +1630,7 @@ func (api *TransactionAPI) SignTransaction(ctx context.Context, args Transaction
16031630
// no longer retains the blobs, only the blob hashes. In this step, we need
16041631
// to put back the blob(s).
16051632
if args.IsEIP4844() {
1606-
signed = signed.WithBlobTxSidecar(types.NewBlobTxSidecar(types.BlobSidecarVersion0, args.Blobs, args.Commitments, args.Proofs))
1633+
signed = signed.WithBlobTxSidecar(types.NewBlobTxSidecar(sidecarVersion, args.Blobs, args.Commitments, args.Proofs))
16071634
}
16081635
data, err := signed.MarshalBinary()
16091636
if err != nil {
@@ -1638,11 +1665,16 @@ func (api *TransactionAPI) PendingTransactions() ([]*RPCTransaction, error) {
16381665

16391666
// Resend accepts an existing transaction and a new gas price and limit. It will remove
16401667
// the given transaction from the pool and reinsert it with the new gas price and limit.
1668+
//
1669+
// This API is not capable for submitting blob transaction with sidecar.
16411670
func (api *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
16421671
if sendArgs.Nonce == nil {
16431672
return common.Hash{}, errors.New("missing transaction nonce in transaction spec")
16441673
}
1645-
if err := sendArgs.setDefaults(ctx, api.b, false); err != nil {
1674+
config := setDefaultConfig{
1675+
skipGasEstimation: false,
1676+
}
1677+
if err := sendArgs.setDefaults(ctx, api.b, config); err != nil {
16461678
return common.Hash{}, err
16471679
}
16481680
matchTx := sendArgs.ToTransaction(types.LegacyTxType)

internal/ethapi/transaction_args.go

Lines changed: 72 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ type TransactionArgs struct {
7070

7171
// For SetCodeTxType
7272
AuthorizationList []types.SetCodeAuthorization `json:"authorizationList"`
73-
74-
// This configures whether blobs are allowed to be passed.
75-
blobSidecarAllowed bool
7673
}
7774

7875
// from retrieves the transaction sender address.
@@ -94,9 +91,22 @@ func (args *TransactionArgs) data() []byte {
9491
return nil
9592
}
9693

94+
// setDefaultConfig defines the options for deriving missing fields of transactions.
95+
type setDefaultConfig struct {
96+
// This configures whether blobs are allowed to be passed and
97+
// the associated sidecar version should be attached.
98+
blobSidecarAllowed bool
99+
blobSidecarVersion byte
100+
101+
// skipGasEstimation is the flag whether the gas estimation is skipped.
102+
// this flag should only be used in the scenarios that a precise gas limit
103+
// is not critical, e.g., in non-transaction calls.
104+
skipGasEstimation bool
105+
}
106+
97107
// setDefaults fills in default values for unspecified tx fields.
98-
func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGasEstimation bool) error {
99-
if err := args.setBlobTxSidecar(ctx); err != nil {
108+
func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, config setDefaultConfig) error {
109+
if err := args.setBlobTxSidecar(ctx, config); err != nil {
100110
return err
101111
}
102112
if err := args.setFeeDefaults(ctx, b, b.CurrentHeader()); err != nil {
@@ -119,11 +129,10 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas
119129

120130
// BlobTx fields
121131
if args.BlobHashes != nil && len(args.BlobHashes) == 0 {
122-
return errors.New(`need at least 1 blob for a blob transaction`)
132+
return errors.New("need at least 1 blob for a blob transaction")
123133
}
124-
maxBlobs := eip4844.MaxBlobsPerBlock(b.ChainConfig(), b.CurrentHeader().Time)
125-
if args.BlobHashes != nil && len(args.BlobHashes) > maxBlobs {
126-
return fmt.Errorf(`too many blobs in transaction (have=%d, max=%d)`, len(args.BlobHashes), maxBlobs)
134+
if args.BlobHashes != nil && len(args.BlobHashes) > params.BlobTxMaxBlobs {
135+
return fmt.Errorf("too many blobs in transaction (have=%d, max=%d)", len(args.BlobHashes), params.BlobTxMaxBlobs)
127136
}
128137

129138
// create check
@@ -137,13 +146,13 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas
137146
}
138147

139148
if args.Gas == nil {
140-
if skipGasEstimation { // Skip gas usage estimation if a precise gas limit is not critical, e.g., in non-transaction calls.
149+
if config.skipGasEstimation {
141150
gas := hexutil.Uint64(b.RPCGasCap())
142151
if gas == 0 {
143152
gas = hexutil.Uint64(math.MaxUint64 / 2)
144153
}
145154
args.Gas = &gas
146-
} else { // Estimate the gas usage otherwise.
155+
} else {
147156
// These fields are immutable during the estimation, safe to
148157
// pass the pointer directly.
149158
data := args.data()
@@ -283,18 +292,17 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ
283292
}
284293

285294
// setBlobTxSidecar adds the blob tx
286-
func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context) error {
295+
func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context, config setDefaultConfig) error {
287296
// No blobs, we're done.
288297
if args.Blobs == nil {
289298
return nil
290299
}
291300

292301
// Passing blobs is not allowed in all contexts, only in specific methods.
293-
if !args.blobSidecarAllowed {
302+
if !config.blobSidecarAllowed {
294303
return errors.New(`"blobs" is not supported for this RPC method`)
295304
}
296305

297-
n := len(args.Blobs)
298306
// Assume user provides either only blobs (w/o hashes), or
299307
// blobs together with commitments and proofs.
300308
if args.Commitments == nil && args.Proofs != nil {
@@ -304,42 +312,73 @@ func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context) error {
304312
}
305313

306314
// len(blobs) == len(commitments) == len(proofs) == len(hashes)
315+
n := len(args.Blobs)
316+
if args.BlobHashes != nil && len(args.BlobHashes) != n {
317+
return fmt.Errorf("number of blobs and hashes mismatch (have=%d, want=%d)", len(args.BlobHashes), n)
318+
}
307319
if args.Commitments != nil && len(args.Commitments) != n {
308320
return fmt.Errorf("number of blobs and commitments mismatch (have=%d, want=%d)", len(args.Commitments), n)
309321
}
310-
if args.Proofs != nil && len(args.Proofs) != n {
311-
return fmt.Errorf("number of blobs and proofs mismatch (have=%d, want=%d)", len(args.Proofs), n)
322+
proofLen := n
323+
if config.blobSidecarVersion == types.BlobSidecarVersion1 {
324+
proofLen = n * kzg4844.CellProofsPerBlob
312325
}
313-
if args.BlobHashes != nil && len(args.BlobHashes) != n {
314-
return fmt.Errorf("number of blobs and hashes mismatch (have=%d, want=%d)", len(args.BlobHashes), n)
326+
if args.Proofs != nil && len(args.Proofs) != proofLen {
327+
if len(args.Proofs) != n {
328+
return fmt.Errorf("number of blobs and proofs mismatch (have=%d, want=%d)", len(args.Proofs), proofLen)
329+
}
330+
// Unset the commitments and proofs, as they may be submitted in the legacy format
331+
log.Debug("Unset legacy commitments and proofs", "blobs", n, "proofs", len(args.Proofs))
332+
args.Commitments, args.Proofs = nil, nil
315333
}
316334

335+
// Generate commitments and proofs if they are missing, or validate them if they
336+
// are provided.
317337
if args.Commitments == nil {
318-
// Generate commitment and proof.
319-
commitments := make([]kzg4844.Commitment, n)
320-
proofs := make([]kzg4844.Proof, n)
338+
var (
339+
commitments = make([]kzg4844.Commitment, n)
340+
proofs = make([]kzg4844.Proof, proofLen)
341+
)
321342
for i, b := range args.Blobs {
322343
c, err := kzg4844.BlobToCommitment(&b)
323344
if err != nil {
324345
return fmt.Errorf("blobs[%d]: error computing commitment: %v", i, err)
325346
}
326347
commitments[i] = c
327-
p, err := kzg4844.ComputeBlobProof(&b, c)
328-
if err != nil {
329-
return fmt.Errorf("blobs[%d]: error computing proof: %v", i, err)
348+
349+
switch config.blobSidecarVersion {
350+
case types.BlobSidecarVersion0:
351+
p, err := kzg4844.ComputeBlobProof(&b, c)
352+
if err != nil {
353+
return fmt.Errorf("blobs[%d]: error computing proof: %v", i, err)
354+
}
355+
proofs[i] = p
356+
case types.BlobSidecarVersion1:
357+
ps, err := kzg4844.ComputeCellProofs(&b)
358+
if err != nil {
359+
return fmt.Errorf("blobs[%d]: error computing cell proof: %v", i, err)
360+
}
361+
proofs = append(proofs, ps...)
330362
}
331-
proofs[i] = p
332363
}
333364
args.Commitments = commitments
334365
args.Proofs = proofs
335366
} else {
336-
for i, b := range args.Blobs {
337-
if err := kzg4844.VerifyBlobProof(&b, args.Commitments[i], args.Proofs[i]); err != nil {
338-
return fmt.Errorf("failed to verify blob proof: %v", err)
367+
switch config.blobSidecarVersion {
368+
case types.BlobSidecarVersion0:
369+
for i, b := range args.Blobs {
370+
if err := kzg4844.VerifyBlobProof(&b, args.Commitments[i], args.Proofs[i]); err != nil {
371+
return fmt.Errorf("failed to verify blob proof: %v", err)
372+
}
373+
}
374+
case types.BlobSidecarVersion1:
375+
if err := kzg4844.VerifyCellProofs(args.Blobs, args.Commitments, args.Proofs); err != nil {
376+
return fmt.Errorf("failed to verify blob cell proof: %v", err)
339377
}
340378
}
341379
}
342380

381+
// Generate blob hashes if they are missing, or validate them if they are provided.
343382
hashes := make([]common.Hash, n)
344383
hasher := sha256.New()
345384
for i, c := range args.Commitments {
@@ -527,8 +566,11 @@ func (args *TransactionArgs) ToTransaction(defaultType int) *types.Transaction {
527566
BlobFeeCap: uint256.MustFromBig((*big.Int)(args.BlobFeeCap)),
528567
}
529568
if args.Blobs != nil {
530-
// TODO(rjl493456442, marius) support V1
531-
data.(*types.BlobTx).Sidecar = types.NewBlobTxSidecar(types.BlobSidecarVersion0, args.Blobs, args.Commitments, args.Proofs)
569+
version := types.BlobSidecarVersion0
570+
if len(args.Proofs) == len(args.Blobs)*kzg4844.CellProofsPerBlob {
571+
version = types.BlobSidecarVersion1
572+
}
573+
data.(*types.BlobTx).Sidecar = types.NewBlobTxSidecar(version, args.Blobs, args.Commitments, args.Proofs)
532574
}
533575

534576
case types.DynamicFeeTxType:

miner/worker.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,6 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
344344

345345
func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error {
346346
var (
347-
isOsaka = miner.chainConfig.IsOsaka(env.header.Number, env.header.Time)
348347
isCancun = miner.chainConfig.IsCancun(env.header.Number, env.header.Time)
349348
gasLimit = env.header.GasLimit
350349
)
@@ -425,21 +424,6 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
425424
if !env.txFitsSize(tx) {
426425
break
427426
}
428-
429-
// Make sure all transactions after osaka have cell proofs
430-
if isOsaka {
431-
if sidecar := tx.BlobTxSidecar(); sidecar != nil {
432-
if sidecar.Version == types.BlobSidecarVersion0 {
433-
log.Info("Including blob tx with v0 sidecar, recomputing proofs", "hash", ltx.Hash)
434-
if err := sidecar.ToV1(); err != nil {
435-
txs.Pop()
436-
log.Warn("Failed to recompute cell proofs", "hash", ltx.Hash, "err", err)
437-
continue
438-
}
439-
}
440-
}
441-
}
442-
443427
// Error may be ignored here. The error has already been checked
444428
// during transaction acceptance in the transaction pool.
445429
from, _ := types.Sender(env.signer, tx)

0 commit comments

Comments
 (0)