@@ -21,12 +21,10 @@ import (
2121 "container/heap"
2222 "errors"
2323 "fmt"
24- "maps"
2524 "math"
2625 "math/big"
2726 "os"
2827 "path/filepath"
29- "slices"
3028 "sort"
3129 "sync"
3230 "sync/atomic"
@@ -337,9 +335,8 @@ type BlobPool struct {
337335 stored uint64 // Useful data size of all transactions on disk
338336 limbo * limbo // Persistent data store for the non-finalized blobs
339337
340- signer types.Signer // Transaction signer to use for sender recovery
341- chain BlockChain // Chain object to access the state through
342- cQueue * conversionQueue // The queue for performing legacy sidecar conversion (TODO: remove after Osaka)
338+ signer types.Signer // Transaction signer to use for sender recovery
339+ chain BlockChain // Chain object to access the state through
343340
344341 head atomic.Pointer [types.Header ] // Current head of the chain
345342 state * state.StateDB // Current state at the head of the chain
@@ -368,7 +365,6 @@ func New(config Config, chain BlockChain, hasPendingAuth func(common.Address) bo
368365 hasPendingAuth : hasPendingAuth ,
369366 signer : types .LatestSigner (chain .Config ()),
370367 chain : chain ,
371- cQueue : newConversionQueue (), // Deprecate it after the osaka fork
372368 lookup : newLookup (),
373369 index : make (map [common.Address ][]* blobTxMeta ),
374370 spent : make (map [common.Address ]* uint256.Int ),
@@ -485,9 +481,6 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
485481
486482// Close closes down the underlying persistent store.
487483func (p * BlobPool ) Close () error {
488- // Terminate the conversion queue
489- p .cQueue .close ()
490-
491484 var errs []error
492485 if p .limbo != nil { // Close might be invoked due to error in constructor, before p,limbo is set
493486 if err := p .limbo .Close (); err != nil {
@@ -885,172 +878,6 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
885878 basefeeGauge .Update (int64 (basefee .Uint64 ()))
886879 blobfeeGauge .Update (int64 (blobfee .Uint64 ()))
887880 p .updateStorageMetrics ()
888-
889- // Perform the conversion logic at the fork boundary
890- if ! p .chain .Config ().IsOsaka (oldHead .Number , oldHead .Time ) && p .chain .Config ().IsOsaka (newHead .Number , newHead .Time ) {
891- // Deep copy all indexed transaction metadata.
892- var (
893- ids = make (map [common.Address ]map [uint64 ]uint64 )
894- txs = make (map [common.Address ]map [uint64 ]common.Hash )
895- )
896- for sender , list := range p .index {
897- ids [sender ] = make (map [uint64 ]uint64 )
898- txs [sender ] = make (map [uint64 ]common.Hash )
899- for _ , m := range list {
900- ids [sender ][m.nonce ] = m .id
901- txs [sender ][m.nonce ] = m .hash
902- }
903- }
904- // Initiate the background conversion thread.
905- p .cQueue .launchBillyConversion (func () {
906- p .convertLegacySidecars (ids , txs )
907- })
908- }
909- }
910-
911- // compareAndSwap checks if the specified transaction is still tracked in the pool
912- // and replace the metadata accordingly. It should only be used in the fork boundary
913- // bulk conversion. If it fails for some reason, the subsequent txs won't be dropped
914- // for simplicity which we assume it's very likely to happen.
915- //
916- // The returned flag indicates whether the replacement succeeded.
917- func (p * BlobPool ) compareAndSwap (address common.Address , hash common.Hash , blob []byte , oldID uint64 , oldStorageSize uint32 ) bool {
918- p .lock .Lock ()
919- defer p .lock .Unlock ()
920-
921- newId , err := p .store .Put (blob )
922- if err != nil {
923- log .Error ("Failed to store transaction" , "hash" , hash , "err" , err )
924- return false
925- }
926- newSize := uint64 (len (blob ))
927- newStorageSize := p .store .Size (newId )
928-
929- // Terminate the procedure if the transaction was already evicted. The
930- // newly added blob should be removed before return.
931- if ! p .lookup .update (hash , newId , newSize ) {
932- if derr := p .store .Delete (newId ); derr != nil {
933- log .Error ("Failed to delete the dangling blob tx" , "err" , derr )
934- } else {
935- log .Warn ("Deleted the dangling blob tx" , "id" , newId )
936- }
937- return false
938- }
939- // Update the metadata of blob transaction
940- for _ , meta := range p .index [address ] {
941- if meta .hash == hash {
942- meta .id = newId
943- meta .version = types .BlobSidecarVersion1
944- meta .storageSize = newStorageSize
945- meta .size = newSize
946-
947- p .stored += uint64 (newStorageSize )
948- p .stored -= uint64 (oldStorageSize )
949- break
950- }
951- }
952- if err := p .store .Delete (oldID ); err != nil {
953- log .Error ("Failed to delete the legacy transaction" , "hash" , hash , "id" , oldID , "err" , err )
954- }
955- return true
956- }
957-
958- // convertLegacySidecar fetches transaction data from the store, performs an
959- // on-the-fly conversion. This function is intended for use only during the
960- // Osaka fork transition period.
961- //
962- // The returned flag indicates whether the replacement succeeds or not.
963- func (p * BlobPool ) convertLegacySidecar (sender common.Address , hash common.Hash , id uint64 ) bool {
964- start := time .Now ()
965-
966- // Retrieves the legacy blob transaction from the underlying store with
967- // read lock held, preventing any potential data race around the slot
968- // specified by the id.
969- p .lock .RLock ()
970- data , err := p .store .Get (id )
971- if err != nil {
972- p .lock .RUnlock ()
973- // The transaction may have been evicted simultaneously, safe to skip conversion.
974- log .Debug ("Blob transaction is missing" , "hash" , hash , "id" , id , "err" , err )
975- return false
976- }
977- oldStorageSize := p .store .Size (id )
978- p .lock .RUnlock ()
979-
980- // Decode the transaction, the failure is not expected and report the error
981- // loudly if possible. If the blob transaction in this slot is corrupted,
982- // leave it in the store, it will be dropped during the next pool
983- // initialization.
984- var tx types.Transaction
985- if err = rlp .DecodeBytes (data , & tx ); err != nil {
986- log .Error ("Blob transaction is corrupted" , "hash" , hash , "id" , id , "err" , err )
987- return false
988- }
989-
990- // Skip conversion if the transaction does not match the expected hash, or if it was
991- // already converted. This can occur if the original transaction was evicted from the
992- // pool and the slot was reused by a new one.
993- if tx .Hash () != hash {
994- log .Warn ("Blob transaction was replaced" , "hash" , hash , "id" , id , "stored" , tx .Hash ())
995- return false
996- }
997- sc := tx .BlobTxSidecar ()
998- if sc .Version >= types .BlobSidecarVersion1 {
999- log .Debug ("Skipping conversion of blob tx" , "hash" , hash , "id" , id )
1000- return false
1001- }
1002-
1003- // Perform the sidecar conversion, the failure is not expected and report the error
1004- // loudly if possible.
1005- if err := tx .BlobTxSidecar ().ToV1 (); err != nil {
1006- log .Error ("Failed to convert blob transaction" , "hash" , hash , "err" , err )
1007- return false
1008- }
1009-
1010- // Encode the converted transaction, the failure is not expected and report
1011- // the error loudly if possible.
1012- blob , err := rlp .EncodeToBytes (& tx )
1013- if err != nil {
1014- log .Error ("Failed to encode blob transaction" , "hash" , tx .Hash (), "err" , err )
1015- return false
1016- }
1017-
1018- // Replace the legacy blob transaction with the converted format.
1019- if ! p .compareAndSwap (sender , hash , blob , id , oldStorageSize ) {
1020- log .Error ("Failed to replace the legacy transaction" , "hash" , hash )
1021- return false
1022- }
1023- log .Debug ("Converted legacy blob transaction" , "hash" , hash , "elapsed" , common .PrettyDuration (time .Since (start )))
1024- return true
1025- }
1026-
1027- // convertLegacySidecars converts all given transactions to sidecar version 1.
1028- //
1029- // If any of them fails to be converted, the subsequent transactions will still
1030- // be processed, as we assume the failure is very unlikely to happen. If happens,
1031- // these transactions will be stuck in the pool until eviction.
1032- func (p * BlobPool ) convertLegacySidecars (ids map [common.Address ]map [uint64 ]uint64 , txs map [common.Address ]map [uint64 ]common.Hash ) {
1033- var (
1034- start = time .Now ()
1035- success int
1036- failure int
1037- )
1038- for addr , list := range txs {
1039- // Transactions evicted from the pool must be contiguous, if in any case,
1040- // the transactions are gapped with each other, they will be discarded.
1041- nonces := slices .Collect (maps .Keys (list ))
1042- slices .Sort (nonces )
1043-
1044- // Convert the txs with nonce order
1045- for _ , nonce := range nonces {
1046- if p .convertLegacySidecar (addr , list [nonce ], ids [addr ][nonce ]) {
1047- success ++
1048- } else {
1049- failure ++
1050- }
1051- }
1052- }
1053- log .Info ("Completed blob transaction conversion" , "discarded" , failure , "injected" , success , "elapsed" , common .PrettyDuration (time .Since (start )))
1054881}
1055882
1056883// reorg assembles all the transactors and missing transactions between an old
@@ -1530,8 +1357,8 @@ func (p *BlobPool) GetMetadata(hash common.Hash) *txpool.TxMetadata {
15301357//
15311358// The version argument specifies the type of proofs to return, either the
15321359// blob proofs (version 0) or the cell proofs (version 1). Proofs conversion is
1533- // CPU intensive, so only done if explicitly requested with the convert flag .
1534- func (p * BlobPool ) GetBlobs (vhashes []common.Hash , version byte , convert bool ) ([]* kzg4844.Blob , []kzg4844.Commitment , [][]kzg4844.Proof , error ) {
1360+ // CPU intensive and prohibited in the blobpool explicitly .
1361+ func (p * BlobPool ) GetBlobs (vhashes []common.Hash , version byte ) ([]* kzg4844.Blob , []kzg4844.Commitment , [][]kzg4844.Proof , error ) {
15351362 var (
15361363 blobs = make ([]* kzg4844.Blob , len (vhashes ))
15371364 commitments = make ([]kzg4844.Commitment , len (vhashes ))
@@ -1582,7 +1409,7 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte, convert bool) (
15821409 }
15831410 // Mark hash as seen.
15841411 filled [hash ] = struct {}{}
1585- if sidecar .Version != version && ! convert {
1412+ if sidecar .Version != version {
15861413 // Skip blobs with incompatible version. Note we still track the blob hash
15871414 // in `filled` here, ensuring that we do not resolve this tx another time.
15881415 continue
@@ -1591,29 +1418,13 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte, convert bool) (
15911418 var pf []kzg4844.Proof
15921419 switch version {
15931420 case types .BlobSidecarVersion0 :
1594- if sidecar .Version == types .BlobSidecarVersion0 {
1595- pf = []kzg4844.Proof {sidecar .Proofs [i ]}
1596- } else {
1597- proof , err := kzg4844 .ComputeBlobProof (& sidecar .Blobs [i ], sidecar .Commitments [i ])
1598- if err != nil {
1599- return nil , nil , nil , err
1600- }
1601- pf = []kzg4844.Proof {proof }
1602- }
1421+ pf = []kzg4844.Proof {sidecar .Proofs [i ]}
16031422 case types .BlobSidecarVersion1 :
1604- if sidecar .Version == types .BlobSidecarVersion0 {
1605- cellProofs , err := kzg4844 .ComputeCellProofs (& sidecar .Blobs [i ])
1606- if err != nil {
1607- return nil , nil , nil , err
1608- }
1609- pf = cellProofs
1610- } else {
1611- cellProofs , err := sidecar .CellProofsAt (i )
1612- if err != nil {
1613- return nil , nil , nil , err
1614- }
1615- pf = cellProofs
1423+ cellProofs , err := sidecar .CellProofsAt (i )
1424+ if err != nil {
1425+ return nil , nil , nil , err
16161426 }
1427+ pf = cellProofs
16171428 }
16181429 for _ , index := range list {
16191430 blobs [index ] = & sidecar .Blobs [i ]
@@ -1640,45 +1451,26 @@ func (p *BlobPool) AvailableBlobs(vhashes []common.Hash) int {
16401451 return available
16411452}
16421453
1643- // preCheck performs the static validation upon the provided tx and converts
1644- // the legacy sidecars if Osaka fork has been activated with a short time window.
1454+ // preCheck performs the static validation upon the provided tx.
16451455//
16461456// This function is pure static and lock free.
16471457func (p * BlobPool ) preCheck (tx * types.Transaction ) error {
16481458 var (
1649- head = p .head .Load ()
1650- isOsaka = p .chain .Config ().IsOsaka (head .Number , head .Time )
1651- deadline time.Time
1459+ head = p .head .Load ()
1460+ version = types .BlobSidecarVersion0
16521461 )
1653- if isOsaka {
1654- deadline = time . Unix ( int64 ( * p . chain . Config (). OsakaTime ), 0 ). Add ( conversionTimeWindow )
1462+ if p . chain . Config (). IsOsaka ( head . Number , head . Time ) {
1463+ version = types . BlobSidecarVersion1
16551464 }
16561465 // Validate the transaction statically at first to avoid unnecessary
16571466 // conversion. This step doesn't require lock protection.
16581467 if err := p .ValidateTxBasics (tx ); err != nil {
16591468 return err
16601469 }
1661- // Before the Osaka fork, reject the blob txs with cell proofs
1662- if ! isOsaka {
1663- if tx .BlobTxSidecar ().Version == types .BlobSidecarVersion0 {
1664- return nil
1665- } else {
1666- return errors .New ("cell proof is not supported yet" )
1667- }
1668- }
1669- // After the Osaka fork, reject the legacy blob txs if the conversion
1670- // time window is passed.
1671- if tx .BlobTxSidecar ().Version == types .BlobSidecarVersion1 {
1672- return nil
1673- }
1674- if head .Time > uint64 (deadline .Unix ()) {
1675- return errors .New ("legacy blob tx is not supported" )
1470+ if tx .BlobTxSidecar ().Version != version {
1471+ return fmt .Errorf ("sidecar version is not supported, got: %d, want: %d" , tx .BlobTxSidecar ().Version , version )
16761472 }
1677- // Convert the legacy sidecar after Osaka fork. This could be a long
1678- // procedure which takes a few seconds, even minutes if there is a long
1679- // queue. Fortunately it will only block the routine of the source peer
1680- // announcing the tx, without affecting other parts.
1681- return p .cQueue .convert (tx )
1473+ return nil
16821474}
16831475
16841476// Add inserts a set of blob transactions into the pool if they pass validation (both
0 commit comments