blobtx: fix some found issues; (#2383)

This commit is contained in:
GalaIO 2024-04-10 14:31:23 +08:00 committed by GitHub
parent 4e9f699068
commit 26f50099f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 124 additions and 4 deletions

@ -1,9 +1,12 @@
package core package core
import ( import (
"crypto/rand"
"math/big" "math/big"
"testing" "testing"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/crypto/kzg4844"
@ -247,6 +250,49 @@ func TestCheckDataAvailableInBatch(t *testing.T) {
} }
} }
func BenchmarkEmptySidecarDAChecking(b *testing.B) {
hr := NewMockDAHeaderReader(params.ParliaTestChainConfig)
block := types.NewBlockWithHeader(&types.Header{
Number: big.NewInt(1),
}).WithBody(types.Transactions{
createMockDATx(hr.Config(), emptySidecar()),
createMockDATx(hr.Config(), emptySidecar()),
createMockDATx(hr.Config(), emptySidecar()),
createMockDATx(hr.Config(), emptySidecar()),
createMockDATx(hr.Config(), emptySidecar()),
createMockDATx(hr.Config(), emptySidecar()),
}, nil)
block = block.WithSidecars(collectBlobsFromTxs(block.Header(), block.Transactions()))
b.ResetTimer()
for i := 0; i < b.N; i++ {
IsDataAvailable(hr, block)
}
}
func BenchmarkRandomSidecarDAChecking(b *testing.B) {
hr := NewMockDAHeaderReader(params.ParliaTestChainConfig)
const count = 10
blocks := make([]*types.Block, count)
for i := 0; i < len(blocks); i++ {
block := types.NewBlockWithHeader(&types.Header{
Number: big.NewInt(1),
}).WithBody(types.Transactions{
createMockDATx(hr.Config(), randomSidecar()),
createMockDATx(hr.Config(), randomSidecar()),
createMockDATx(hr.Config(), randomSidecar()),
createMockDATx(hr.Config(), randomSidecar()),
createMockDATx(hr.Config(), randomSidecar()),
createMockDATx(hr.Config(), randomSidecar()),
}, nil)
block = block.WithSidecars(collectBlobsFromTxs(block.Header(), block.Transactions()))
blocks[i] = block
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
IsDataAvailable(hr, blocks[i%count])
}
}
func collectBlobsFromTxs(header *types.Header, txs types.Transactions) types.BlobSidecars { func collectBlobsFromTxs(header *types.Header, txs types.Transactions) types.BlobSidecars {
sidecars := make(types.BlobSidecars, 0, len(txs)) sidecars := make(types.BlobSidecars, 0, len(txs))
for i, tx := range txs { for i, tx := range txs {
@ -348,3 +394,43 @@ func createMockDATx(config *params.ChainConfig, sidecar *types.BlobTxSidecar) *t
} }
return types.NewTx(tx) return types.NewTx(tx)
} }
func randFieldElement() [32]byte {
bytes := make([]byte, 32)
_, err := rand.Read(bytes)
if err != nil {
panic("failed to get random field element")
}
var r fr.Element
r.SetBytes(bytes)
return gokzg4844.SerializeScalar(r)
}
func randBlob() kzg4844.Blob {
var blob kzg4844.Blob
for i := 0; i < len(blob); i += gokzg4844.SerializedScalarSize {
fieldElementBytes := randFieldElement()
copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:])
}
return blob
}
func randomSidecar() *types.BlobTxSidecar {
blob := randBlob()
commitment, _ := kzg4844.BlobToCommitment(blob)
proof, _ := kzg4844.ComputeBlobProof(blob, commitment)
return &types.BlobTxSidecar{
Blobs: []kzg4844.Blob{blob},
Commitments: []kzg4844.Commitment{commitment},
Proofs: []kzg4844.Proof{proof},
}
}
func emptySidecar() *types.BlobTxSidecar {
return &types.BlobTxSidecar{
Blobs: []kzg4844.Blob{emptyBlob},
Commitments: []kzg4844.Commitment{emptyBlobCommit},
Proofs: []kzg4844.Proof{emptyBlobProof},
}
}

@ -808,7 +808,7 @@ func WriteAncientBlocksWithBlobs(db ethdb.AncientWriter, blocks []*types.Block,
break break
} }
} }
log.Info("WriteAncientBlocks", "startAt", blocks[0].Number(), "cancunIndex", cancunIndex, "len", len(blocks)) log.Debug("WriteAncientBlocks", "startAt", blocks[0].Number(), "cancunIndex", cancunIndex, "len", len(blocks))
var ( var (
tdSum = new(big.Int).Set(td) tdSum = new(big.Int).Set(td)

@ -17,6 +17,7 @@
package rawdb package rawdb
import ( import (
"errors"
"fmt" "fmt"
"math/big" "math/big"
"sync" "sync"
@ -42,6 +43,10 @@ const (
freezerBatchLimit = 30000 freezerBatchLimit = 30000
) )
var (
missFreezerEnvErr = errors.New("missing freezer env error")
)
// chainFreezer is a wrapper of freezer with additional chain freezing feature. // chainFreezer is a wrapper of freezer with additional chain freezing feature.
// The background thread will keep moving ancient chain segments from key-value // The background thread will keep moving ancient chain segments from key-value
// database to flat files for saving space on live database. // database to flat files for saving space on live database.
@ -119,6 +124,20 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
return return
} }
} }
// check freezer env first, it must wait a while when the env is necessary
err := f.checkFreezerEnv()
if err == missFreezerEnvErr {
log.Warn("Freezer need related env, may wait for a while", "err", err)
backoff = true
continue
}
if err != nil {
log.Error("Freezer check FreezerEnv err", "err", err)
backoff = true
continue
}
// Retrieve the freezing threshold. // Retrieve the freezing threshold.
hash := ReadHeadBlockHash(nfdb) hash := ReadHeadBlockHash(nfdb)
if hash == (common.Hash{}) { if hash == (common.Hash{}) {
@ -278,7 +297,7 @@ func (f *chainFreezer) tryPruneBlobAncientTable(env *ethdb.FreezerEnv, num uint6
log.Error("Cannot prune blob ancient", "block", num, "expectTail", expectTail, "err", err) log.Error("Cannot prune blob ancient", "block", num, "expectTail", expectTail, "err", err)
return return
} }
log.Info("Chain freezer prune useless blobs, now ancient data is", "from", expectTail, "to", num, "cost", common.PrettyDuration(time.Since(start))) log.Debug("Chain freezer prune useless blobs, now ancient data is", "from", expectTail, "to", num, "cost", common.PrettyDuration(time.Since(start)))
} }
func getBlobExtraReserveFromEnv(env *ethdb.FreezerEnv) uint64 { func getBlobExtraReserveFromEnv(env *ethdb.FreezerEnv) uint64 {
@ -290,7 +309,7 @@ func getBlobExtraReserveFromEnv(env *ethdb.FreezerEnv) uint64 {
func (f *chainFreezer) freezeRangeWithBlobs(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) { func (f *chainFreezer) freezeRangeWithBlobs(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) {
defer func() { defer func() {
log.Info("freezeRangeWithBlobs", "from", number, "to", limit, "err", err) log.Debug("freezeRangeWithBlobs", "from", number, "to", limit, "err", err)
}() }()
lastHash := ReadCanonicalHash(nfdb, limit) lastHash := ReadCanonicalHash(nfdb, limit)
if lastHash == (common.Hash{}) { if lastHash == (common.Hash{}) {
@ -413,6 +432,21 @@ func (f *chainFreezer) SetupFreezerEnv(env *ethdb.FreezerEnv) error {
return nil return nil
} }
func (f *chainFreezer) checkFreezerEnv() error {
_, exist := f.freezeEnv.Load().(*ethdb.FreezerEnv)
if exist {
return nil
}
blobFrozen, err := f.TableAncients(ChainFreezerBlobSidecarTable)
if err != nil {
return err
}
if blobFrozen > 0 {
return missFreezerEnvErr
}
return nil
}
func isCancun(env *ethdb.FreezerEnv, num *big.Int, time uint64) bool { func isCancun(env *ethdb.FreezerEnv, num *big.Int, time uint64) bool {
if env == nil || env.ChainCfg == nil { if env == nil || env.ChainCfg == nil {
return false return false

@ -765,7 +765,7 @@ func (f *Freezer) ResetTable(kind string, startAt uint64, onlyEmpty bool) error
f.frozen.Add(f.offset) f.frozen.Add(f.offset)
f.tail.Add(f.offset) f.tail.Add(f.offset)
f.writeBatch = newFreezerBatch(f) f.writeBatch = newFreezerBatch(f)
log.Info("Reset Table", "kind", kind, "tail", f.tables[kind].itemHidden.Load(), "frozen", f.tables[kind].items.Load()) log.Debug("Reset Table", "kind", kind, "tail", f.tables[kind].itemHidden.Load(), "frozen", f.tables[kind].items.Load())
return nil return nil
} }