Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blobtx: fix some found issues; #2383

Merged
merged 4 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions core/data_availability_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package core

import (
"crypto/rand"
gokzg4844 "github.com/crate-crypto/go-kzg-4844"

Check failure on line 5 in core/data_availability_test.go

View workflow job for this annotation

GitHub Actions / golang-lint (1.21.x, ubuntu-latest)

File is not `goimports`-ed (goimports)
"math/big"
"testing"

"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
Expand Down Expand Up @@ -247,6 +250,49 @@
}
}

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 {
sidecars := make(types.BlobSidecars, 0, len(txs))
for i, tx := range txs {
Expand Down Expand Up @@ -348,3 +394,43 @@
}
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},
}
}
2 changes: 1 addition & 1 deletion core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ func WriteAncientBlocksWithBlobs(db ethdb.AncientWriter, blocks []*types.Block,
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 (
tdSum = new(big.Int).Set(td)
Expand Down
39 changes: 35 additions & 4 deletions core/rawdb/chain_freezer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package rawdb

import (
"errors"
"fmt"
"math/big"
"sync"
Expand All @@ -42,6 +43,10 @@ const (
freezerBatchLimit = 30000
)

var (
missFreezerEnvErr = errors.New("missing freezer env error")
)

// chainFreezer is a wrapper of freezer with additional chain freezing feature.
// The background thread will keep moving ancient chain segments from key-value
// database to flat files for saving space on live database.
Expand Down Expand Up @@ -119,6 +124,20 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
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.
hash := ReadHeadBlockHash(nfdb)
if hash == (common.Hash{}) {
Expand Down Expand Up @@ -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)
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 {
Expand All @@ -289,9 +308,6 @@ func getBlobExtraReserveFromEnv(env *ethdb.FreezerEnv) uint64 {
}

func (f *chainFreezer) freezeRangeWithBlobs(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) {
defer func() {
log.Info("freezeRangeWithBlobs", "from", number, "to", limit, "err", err)
}()
lastHash := ReadCanonicalHash(nfdb, limit)
if lastHash == (common.Hash{}) {
return nil, fmt.Errorf("canonical hash missing, can't freeze block %d", limit)
Expand Down Expand Up @@ -413,6 +429,21 @@ func (f *chainFreezer) SetupFreezerEnv(env *ethdb.FreezerEnv) error {
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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this condition means freezer env is missing? A blob can still freeze by default right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this condition means that env must be guaranteed to exist when the blob table already has data.

return missFreezerEnvErr
}
return nil
}

func isCancun(env *ethdb.FreezerEnv, num *big.Int, time uint64) bool {
if env == nil || env.ChainCfg == nil {
return false
Expand Down
2 changes: 1 addition & 1 deletion core/rawdb/freezer.go
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ func (f *Freezer) ResetTable(kind string, startAt uint64, onlyEmpty bool) error
f.frozen.Add(f.offset)
f.tail.Add(f.offset)
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
}

Expand Down
Loading