fix: fix test error

This commit is contained in:
healthykim 2025-10-24 17:09:22 +09:00
parent c8e5daf85a
commit df81462230
4 changed files with 59 additions and 31 deletions

View file

@ -1101,7 +1101,7 @@ func (p *BlobPool) convertLegacySidecar(sender common.Address, hash common.Hash,
// loudly if possible. If the blob transaction in this slot is corrupted, // loudly if possible. If the blob transaction in this slot is corrupted,
// leave it in the store, it will be dropped during the next pool // leave it in the store, it will be dropped during the next pool
// initialization. // initialization.
var tx types.Transaction var tx pooledBlobTx
if err = rlp.DecodeBytes(data, &tx); err != nil { if err = rlp.DecodeBytes(data, &tx); err != nil {
log.Error("Blob transaction is corrupted", "hash", hash, "id", id, "err", err) log.Error("Blob transaction is corrupted", "hash", hash, "id", id, "err", err)
return false return false
@ -1110,11 +1110,11 @@ func (p *BlobPool) convertLegacySidecar(sender common.Address, hash common.Hash,
// Skip conversion if the transaction does not match the expected hash, or if it was // Skip conversion if the transaction does not match the expected hash, or if it was
// already converted. This can occur if the original transaction was evicted from the // already converted. This can occur if the original transaction was evicted from the
// pool and the slot was reused by a new one. // pool and the slot was reused by a new one.
if tx.Hash() != hash { if tx.Transaction.Hash() != hash {
log.Warn("Blob transaction was replaced", "hash", hash, "id", id, "stored", tx.Hash()) log.Warn("Blob transaction was replaced", "hash", hash, "id", id, "stored", tx.Transaction.Hash())
return false return false
} }
sc := tx.BlobTxSidecar() sc := tx.Sidecar
if sc.Version >= types.BlobSidecarVersion1 { if sc.Version >= types.BlobSidecarVersion1 {
log.Debug("Skipping conversion of blob tx", "hash", hash, "id", id) log.Debug("Skipping conversion of blob tx", "hash", hash, "id", id)
return false return false
@ -1122,7 +1122,7 @@ func (p *BlobPool) convertLegacySidecar(sender common.Address, hash common.Hash,
// Perform the sidecar conversion, the failure is not expected and report the error // Perform the sidecar conversion, the failure is not expected and report the error
// loudly if possible. // loudly if possible.
if err := tx.BlobTxSidecar().ToV1(); err != nil { if err := tx.Sidecar.ToV1(); err != nil {
log.Error("Failed to convert blob transaction", "hash", hash, "err", err) log.Error("Failed to convert blob transaction", "hash", hash, "err", err)
return false return false
} }
@ -1131,7 +1131,7 @@ func (p *BlobPool) convertLegacySidecar(sender common.Address, hash common.Hash,
// the error loudly if possible. // the error loudly if possible.
blob, err := rlp.EncodeToBytes(&tx) blob, err := rlp.EncodeToBytes(&tx)
if err != nil { if err != nil {
log.Error("Failed to encode blob transaction", "hash", tx.Hash(), "err", err) log.Error("Failed to encode blob transaction", "hash", tx.Transaction.Hash(), "err", err)
return false return false
} }
@ -1327,16 +1327,15 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
// this attack is financially inefficient to execute. // this attack is financially inefficient to execute.
head := p.head.Load() head := p.head.Load()
if p.chain.Config().IsOsaka(head.Number, head.Time) && pooledTx.Sidecar.Version == types.BlobSidecarVersion0 { if p.chain.Config().IsOsaka(head.Number, head.Time) && pooledTx.Sidecar.Version == types.BlobSidecarVersion0 {
tx, err := pooledTx.convert()
if err != nil { if err != nil {
log.Error("Failed to convert the pooledTx", "err", err) log.Error("Failed to convert the pooledTx", "err", err)
return err return err
} }
if err := tx.BlobTxSidecar().ToV1(); err != nil { if err := pooledTx.Sidecar.ToV1(); err != nil {
log.Error("Failed to convert the legacy sidecar", "err", err) log.Error("Failed to convert the legacy sidecar", "err", err)
return err return err
} }
log.Info("Legacy blob transaction is reorged", "hash", tx.Hash()) log.Info("Legacy blob transaction is reorged", "hash", pooledTx.Transaction.Hash())
} }
// Serialize the transaction back into the primary datastore. // Serialize the transaction back into the primary datastore.
blob, err := rlp.EncodeToBytes(pooledTx) blob, err := rlp.EncodeToBytes(pooledTx)
@ -1806,7 +1805,7 @@ func (p *BlobPool) AvailableBlobs(vhashes []common.Hash) int {
// the legacy sidecars if Osaka fork has been activated with a short time window. // the legacy sidecars if Osaka fork has been activated with a short time window.
// //
// This function is pure static and lock free. // This function is pure static and lock free.
func (p *BlobPool) preCheck(tx *types.Transaction) error { func (p *BlobPool) preCheck(tx *pooledBlobTx) error {
var ( var (
head = p.head.Load() head = p.head.Load()
isOsaka = p.chain.Config().IsOsaka(head.Number, head.Time) isOsaka = p.chain.Config().IsOsaka(head.Number, head.Time)
@ -1817,12 +1816,12 @@ func (p *BlobPool) preCheck(tx *types.Transaction) error {
} }
// Validate the transaction statically at first to avoid unnecessary // Validate the transaction statically at first to avoid unnecessary
// conversion. This step doesn't require lock protection. // conversion. This step doesn't require lock protection.
if err := p.ValidateTxBasics(tx); err != nil { if err := p.ValidateTxBasics(tx.Transaction); err != nil {
return err return err
} }
// Before the Osaka fork, reject the blob txs with cell proofs // Before the Osaka fork, reject the blob txs with cell proofs
if !isOsaka { if !isOsaka {
if tx.BlobTxSidecar().Version == types.BlobSidecarVersion0 { if tx.Sidecar.Version == types.BlobSidecarVersion0 {
return nil return nil
} else { } else {
return errors.New("cell proof is not supported yet") return errors.New("cell proof is not supported yet")
@ -1830,7 +1829,7 @@ func (p *BlobPool) preCheck(tx *types.Transaction) error {
} }
// After the Osaka fork, reject the legacy blob txs if the conversion // After the Osaka fork, reject the legacy blob txs if the conversion
// time window is passed. // time window is passed.
if tx.BlobTxSidecar().Version == types.BlobSidecarVersion1 { if tx.Sidecar.Version == types.BlobSidecarVersion1 {
return nil return nil
} }
if head.Time > uint64(deadline.Unix()) { if head.Time > uint64(deadline.Unix()) {
@ -1851,13 +1850,13 @@ func (p *BlobPool) Add(txs []*types.Transaction, sync bool) []error {
adds = make([]*types.Transaction, 0, len(txs)) adds = make([]*types.Transaction, 0, len(txs))
) )
for i, tx := range txs { for i, tx := range txs {
if errs[i] = p.preCheck(tx); errs[i] != nil {
continue
}
pooledTx, err := newPooledBlobTx(tx) pooledTx, err := newPooledBlobTx(tx)
if err != nil { if err != nil {
continue continue
} }
if errs[i] = p.preCheck(pooledTx); errs[i] != nil {
continue
}
errs[i] = p.add(pooledTx) errs[i] = p.add(pooledTx)
if errs[i] == nil { if errs[i] == nil {
adds = append(adds, tx.WithoutBlobTxSidecar()) adds = append(adds, tx.WithoutBlobTxSidecar())

View file

@ -23,7 +23,6 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
@ -34,7 +33,7 @@ const maxPendingConversionTasks = 2048
// txConvert represents a conversion task with an attached legacy blob transaction. // txConvert represents a conversion task with an attached legacy blob transaction.
type txConvert struct { type txConvert struct {
tx *types.Transaction // Legacy blob transaction tx *pooledBlobTx // Legacy blob transaction
done chan error // Channel for signaling back if the conversion succeeds done chan error // Channel for signaling back if the conversion succeeds
} }
@ -73,7 +72,7 @@ func newConversionQueue() *conversionQueue {
// for conversion. // for conversion.
// //
// This function may block for a long time until the transaction is processed. // This function may block for a long time until the transaction is processed.
func (q *conversionQueue) convert(tx *types.Transaction) error { func (q *conversionQueue) convert(tx *pooledBlobTx) error {
done := make(chan error, 1) done := make(chan error, 1)
select { select {
case q.tasks <- &txConvert{tx: tx, done: done}: case q.tasks <- &txConvert{tx: tx, done: done}:
@ -113,7 +112,7 @@ func (q *conversionQueue) run(tasks []*txConvert, done chan struct{}, interrupt
t.done <- errors.New("conversion is interrupted") t.done <- errors.New("conversion is interrupted")
continue continue
} }
sidecar := t.tx.BlobTxSidecar() sidecar := t.tx.Sidecar
if sidecar == nil { if sidecar == nil {
t.done <- errors.New("tx without sidecar") t.done <- errors.New("tx without sidecar")
continue continue
@ -122,7 +121,7 @@ func (q *conversionQueue) run(tasks []*txConvert, done chan struct{}, interrupt
start := time.Now() start := time.Now()
err := sidecar.ToV1() err := sidecar.ToV1()
t.done <- err t.done <- err
log.Trace("Converted legacy blob tx", "hash", t.tx.Hash(), "err", err, "elapsed", common.PrettyDuration(time.Since(start))) log.Trace("Converted legacy blob tx", "hash", t.tx.Transaction.Hash(), "err", err, "elapsed", common.PrettyDuration(time.Since(start)))
} }
} }

View file

@ -30,7 +30,7 @@ import (
) )
// createV1BlobTx creates a blob transaction with version 1 sidecar for testing. // createV1BlobTx creates a blob transaction with version 1 sidecar for testing.
func createV1BlobTx(nonce uint64, key *ecdsa.PrivateKey) *types.Transaction { func createV1BlobTx(nonce uint64, key *ecdsa.PrivateKey) *pooledBlobTx {
blob := &kzg4844.Blob{byte(nonce)} blob := &kzg4844.Blob{byte(nonce)}
commitment, _ := kzg4844.BlobToCommitment(blob) commitment, _ := kzg4844.BlobToCommitment(blob)
cellProofs, _ := kzg4844.ComputeCellProofs(blob) cellProofs, _ := kzg4844.ComputeCellProofs(blob)
@ -46,7 +46,9 @@ func createV1BlobTx(nonce uint64, key *ecdsa.PrivateKey) *types.Transaction {
Value: uint256.NewInt(100), Value: uint256.NewInt(100),
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion1, []kzg4844.Blob{*blob}, []kzg4844.Commitment{commitment}, cellProofs), Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion1, []kzg4844.Blob{*blob}, []kzg4844.Commitment{commitment}, cellProofs),
} }
return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx) tx := types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
pooledTx, _ := newPooledBlobTx(tx)
return pooledTx
} }
func TestConversionQueueBasic(t *testing.T) { func TestConversionQueueBasic(t *testing.T) {
@ -55,11 +57,12 @@ func TestConversionQueueBasic(t *testing.T) {
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
tx := makeTx(0, 1, 1, 1, key) tx := makeTx(0, 1, 1, 1, key)
if err := queue.convert(tx); err != nil { pooledTx, _ := newPooledBlobTx(tx)
if err := queue.convert(pooledTx); err != nil {
t.Fatalf("Expected successful conversion, got error: %v", err) t.Fatalf("Expected successful conversion, got error: %v", err)
} }
if tx.BlobTxSidecar().Version != types.BlobSidecarVersion1 { if pooledTx.Sidecar.Version != types.BlobSidecarVersion1 {
t.Errorf("Expected sidecar version to be %d, got %d", types.BlobSidecarVersion1, tx.BlobTxSidecar().Version) t.Errorf("Expected sidecar version to be %d, got %d", types.BlobSidecarVersion1, pooledTx.Sidecar.Version)
} }
} }
@ -69,14 +72,14 @@ func TestConversionQueueV1BlobTx(t *testing.T) {
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
tx := createV1BlobTx(0, key) tx := createV1BlobTx(0, key)
version := tx.BlobTxSidecar().Version version := tx.Sidecar.Version
err := queue.convert(tx) err := queue.convert(tx)
if err != nil { if err != nil {
t.Fatalf("Expected successful conversion, got error: %v", err) t.Fatalf("Expected successful conversion, got error: %v", err)
} }
if tx.BlobTxSidecar().Version != version { if tx.Sidecar.Version != version {
t.Errorf("Expected sidecar version to remain %d, got %d", version, tx.BlobTxSidecar().Version) t.Errorf("Expected sidecar version to remain %d, got %d", version, tx.Sidecar.Version)
} }
} }
@ -88,7 +91,8 @@ func TestConversionQueueClosed(t *testing.T) {
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
tx := makeTx(0, 1, 1, 1, key) tx := makeTx(0, 1, 1, 1, key)
err := queue.convert(tx) pooledTx, _ := newPooledBlobTx(tx)
err := queue.convert(pooledTx)
if err == nil { if err == nil {
t.Fatal("Expected error when converting on closed queue, got nil") t.Fatal("Expected error when converting on closed queue, got nil")
} }

View file

@ -207,6 +207,32 @@ func (c *BlobTxCellSidecar) ValidateBlobCommitmentHashes(hashes []common.Hash) e
return sc.ValidateBlobCommitmentHashes(hashes) return sc.ValidateBlobCommitmentHashes(hashes)
} }
// ToV1 converts the BlobSidecar to version 1, attaching the cell proofs.
// This function only available when we can recover the original blob with given cells
// TODO: duplication
func (sc *BlobTxCellSidecar) ToV1() error {
if sc.Version == BlobSidecarVersion1 {
return nil
}
blobs, err := kzg4844.RecoverBlobs(sc.Cells, sc.Custody.Indices())
if err != nil {
return err
}
if sc.Version == BlobSidecarVersion0 {
proofs := make([]kzg4844.Proof, 0, len(blobs)*kzg4844.CellProofsPerBlob)
for _, blob := range blobs {
cellProofs, err := kzg4844.ComputeCellProofs(&blob)
if err != nil {
return err
}
proofs = append(proofs, cellProofs...)
}
sc.Version = BlobSidecarVersion1
sc.Proofs = proofs
}
return nil
}
// blobTxWithBlobs represents blob tx with its corresponding sidecar. // blobTxWithBlobs represents blob tx with its corresponding sidecar.
// This is an interface because sidecars are versioned. // This is an interface because sidecars are versioned.
type blobTxWithBlobs interface { type blobTxWithBlobs interface {