Skip to content

Commit e9dca3b

Browse files
eth/catalyst: avoid load the same blob tx multi times (#32190)
- If all the `vhashes` are in the same `sidecar`, then it will load the same blob tx many times. This PR aims to upgrade this. --------- Co-authored-by: Gary Rong <[email protected]>
1 parent cf50026 commit e9dca3b

File tree

3 files changed

+301
-119
lines changed

3 files changed

+301
-119
lines changed

core/txpool/blobpool/blobpool.go

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/ethereum/go-ethereum/core/state"
3737
"github.com/ethereum/go-ethereum/core/txpool"
3838
"github.com/ethereum/go-ethereum/core/types"
39+
"github.com/ethereum/go-ethereum/crypto/kzg4844"
3940
"github.com/ethereum/go-ethereum/event"
4041
"github.com/ethereum/go-ethereum/log"
4142
"github.com/ethereum/go-ethereum/metrics"
@@ -1299,32 +1300,86 @@ func (p *BlobPool) GetMetadata(hash common.Hash) *txpool.TxMetadata {
12991300
// GetBlobs returns a number of blobs and proofs for the given versioned hashes.
13001301
// This is a utility method for the engine API, enabling consensus clients to
13011302
// retrieve blobs from the pools directly instead of the network.
1302-
func (p *BlobPool) GetBlobs(vhashes []common.Hash) []*types.BlobTxSidecar {
1303-
sidecars := make([]*types.BlobTxSidecar, len(vhashes))
1304-
for idx, vhash := range vhashes {
1305-
// Retrieve the datastore item (in a short lock)
1306-
p.lock.RLock()
1307-
id, exists := p.lookup.storeidOfBlob(vhash)
1308-
if !exists {
1309-
p.lock.RUnlock()
1303+
func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte) ([]*kzg4844.Blob, []kzg4844.Commitment, [][]kzg4844.Proof, error) {
1304+
var (
1305+
blobs = make([]*kzg4844.Blob, len(vhashes))
1306+
commitments = make([]kzg4844.Commitment, len(vhashes))
1307+
proofs = make([][]kzg4844.Proof, len(vhashes))
1308+
1309+
indices = make(map[common.Hash][]int)
1310+
filled = make(map[common.Hash]struct{})
1311+
)
1312+
for i, h := range vhashes {
1313+
indices[h] = append(indices[h], i)
1314+
}
1315+
for _, vhash := range vhashes {
1316+
// Skip duplicate vhash that was already resolved in a previous iteration
1317+
if _, ok := filled[vhash]; ok {
13101318
continue
13111319
}
1312-
data, err := p.store.Get(id)
1320+
// Retrieve the corresponding blob tx with the vhash
1321+
p.lock.RLock()
1322+
txID, exists := p.lookup.storeidOfBlob(vhash)
13131323
p.lock.RUnlock()
1314-
1315-
// After releasing the lock, try to fill any blobs requested
1324+
if !exists {
1325+
return nil, nil, nil, fmt.Errorf("blob with vhash %x is not found", vhash)
1326+
}
1327+
data, err := p.store.Get(txID)
13161328
if err != nil {
1317-
log.Error("Tracked blob transaction missing from store", "id", id, "err", err)
1318-
continue
1329+
return nil, nil, nil, err
13191330
}
1320-
item := new(types.Transaction)
1321-
if err = rlp.DecodeBytes(data, item); err != nil {
1322-
log.Error("Blobs corrupted for traced transaction", "id", id, "err", err)
1323-
continue
1331+
1332+
// Decode the blob transaction
1333+
tx := new(types.Transaction)
1334+
if err := rlp.DecodeBytes(data, tx); err != nil {
1335+
return nil, nil, nil, err
1336+
}
1337+
sidecar := tx.BlobTxSidecar()
1338+
if sidecar == nil {
1339+
return nil, nil, nil, fmt.Errorf("blob tx without sidecar %x", tx.Hash())
1340+
}
1341+
// Traverse the blobs in the transaction
1342+
for i, hash := range tx.BlobHashes() {
1343+
list, ok := indices[hash]
1344+
if !ok {
1345+
continue // non-interesting blob
1346+
}
1347+
var pf []kzg4844.Proof
1348+
switch version {
1349+
case types.BlobSidecarVersion0:
1350+
if sidecar.Version == types.BlobSidecarVersion0 {
1351+
pf = []kzg4844.Proof{sidecar.Proofs[i]}
1352+
} else {
1353+
proof, err := kzg4844.ComputeBlobProof(&sidecar.Blobs[i], sidecar.Commitments[i])
1354+
if err != nil {
1355+
return nil, nil, nil, err
1356+
}
1357+
pf = []kzg4844.Proof{proof}
1358+
}
1359+
case types.BlobSidecarVersion1:
1360+
if sidecar.Version == types.BlobSidecarVersion0 {
1361+
cellProofs, err := kzg4844.ComputeCellProofs(&sidecar.Blobs[i])
1362+
if err != nil {
1363+
return nil, nil, nil, err
1364+
}
1365+
pf = cellProofs
1366+
} else {
1367+
cellProofs, err := sidecar.CellProofsAt(i)
1368+
if err != nil {
1369+
return nil, nil, nil, err
1370+
}
1371+
pf = cellProofs
1372+
}
1373+
}
1374+
for _, index := range list {
1375+
blobs[index] = &sidecar.Blobs[i]
1376+
commitments[index] = sidecar.Commitments[i]
1377+
proofs[index] = pf
1378+
}
1379+
filled[hash] = struct{}{}
13241380
}
1325-
sidecars[idx] = item.BlobTxSidecar()
13261381
}
1327-
return sidecars
1382+
return blobs, commitments, proofs, nil
13281383
}
13291384

13301385
// AvailableBlobs returns the number of blobs that are available in the subpool.

0 commit comments

Comments
 (0)