From ca1f2e4d38f4e94676981bb9251239a5d490b004 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Fri, 24 Jul 2026 16:50:20 +0800 Subject: [PATCH] core: fix tx size calculation (#35406) This PR fixes the incorrect size calculation for blob sidecar. The original formula is for legacy sidecar without the version tag. As the legacy version has been deprecated and no longer supported by the Geth's blobPool, the size calculation should also be flipped to sidecar v1. --- core/txpool/blobpool/blobpool.go | 20 ++++++++++++++++---- core/types/tx_blob.go | 6 +++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index c013b7b1e3..1debf6efa0 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -171,8 +171,11 @@ func (ptx *BlobTxForPool) sidecar() (*types.BlobTxSidecar, error) { return types.NewBlobTxSidecar(sidecar.Version, blobs, sidecar.Commitments, sidecar.Proofs), nil } -// TxSize returns the transaction size on the network without -// reconstructing the transaction. +// txSize returns the network size of the transaction without reconstructing it. +// +// The blobpool only holds v1 (cell-proof) sidecars: legacy v0 sidecars are no longer +// accepted into the pool, nor served over the wire protocol. The size therefore assumes +// the v1 wire form [tx, version, blobs, commitments, proofs]. func (ptx *BlobTxForPool) txSize() uint64 { sidecar := ptx.CellSidecar @@ -185,9 +188,17 @@ func (ptx *BlobTxForPool) txSize() uint64 { } var blob kzg4844.Blob blobs := uint64(len(sidecar.Commitments)) * rlp.BytesSize(blob[:]) - return ptx.Tx.Size() + rlp.ListSize(rlp.ListSize(blobs)+rlp.ListSize(commitments)+rlp.ListSize(proofs)) + + version := uint64(rlp.IntSize(uint64(sidecar.Version))) + return ptx.Tx.Size() + rlp.ListSize(version+rlp.ListSize(blobs)+rlp.ListSize(commitments)+rlp.ListSize(proofs)) } +// txSizeWithoutBlob returns the eth/72 network size, where the blob payload is dropped +// to an empty list and fetched separately via GetCells. +// +// Like txSize, this assumes the v1 wire form: only v1 sidecars live in the pool (v0 is +// no longer accepted or served), so the version byte is always present, only the blob +// payload becomes an empty list [tx, version, [], commitments, proofs]. func (ptx *BlobTxForPool) txSizeWithoutBlob() uint64 { sidecar := ptx.CellSidecar @@ -198,7 +209,8 @@ func (ptx *BlobTxForPool) txSizeWithoutBlob() uint64 { for i := range sidecar.Proofs { proofs += rlp.BytesSize(sidecar.Proofs[i][:]) } - return ptx.Tx.Size() + rlp.ListSize(rlp.ListSize(0)+rlp.ListSize(commitments)+rlp.ListSize(proofs)) + version := uint64(rlp.IntSize(uint64(sidecar.Version))) + return ptx.Tx.Size() + rlp.ListSize(version+rlp.ListSize(0)+rlp.ListSize(commitments)+rlp.ListSize(proofs)) } // ToTx reconstructs a full Transaction with the sidecar attached. diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go index b5789eea32..d06d103a95 100644 --- a/core/types/tx_blob.go +++ b/core/types/tx_blob.go @@ -144,7 +144,11 @@ func (sc *BlobTxSidecar) encodedSize() uint64 { for i := range sc.Proofs { proofs += rlp.BytesSize(sc.Proofs[i][:]) } - return rlp.ListSize(blobs) + rlp.ListSize(commitments) + rlp.ListSize(proofs) + size := rlp.ListSize(blobs) + rlp.ListSize(commitments) + rlp.ListSize(proofs) + if sc.Version != BlobSidecarVersion0 { + size += uint64(rlp.IntSize(uint64(sc.Version))) + } + return size } // ValidateBlobCommitmentHashes checks whether the given hashes correspond to the