mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-25 16:06:18 +00:00
core/txpool: drop support for v0 blob sidecar (#35191)
This PR drops support for v0 blob sidecar in blobpool. Since the osaka fork activation time has passed, these code paths are now unused. It is assumed that only v1 transactions exist in the blobpool.
This commit is contained in:
parent
af7bf37b53
commit
eea629b9b3
11 changed files with 69 additions and 304 deletions
|
|
@ -1013,11 +1013,11 @@ func makeSidecar(data ...byte) *types.BlobTxSidecar {
|
|||
for i := range blobs {
|
||||
blobs[i][0] = data[i]
|
||||
c, _ := kzg4844.BlobToCommitment(&blobs[i])
|
||||
p, _ := kzg4844.ComputeBlobProof(&blobs[i], c)
|
||||
cellProofs, _ := kzg4844.ComputeCellProofs(&blobs[i])
|
||||
commitments = append(commitments, c)
|
||||
proofs = append(proofs, p)
|
||||
proofs = append(proofs, cellProofs...)
|
||||
}
|
||||
return types.NewBlobTxSidecar(types.BlobSidecarVersion0, blobs, commitments, proofs)
|
||||
return types.NewBlobTxSidecar(types.BlobSidecarVersion1, blobs, commitments, proofs)
|
||||
}
|
||||
|
||||
func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) {
|
||||
|
|
|
|||
|
|
@ -228,22 +228,17 @@ func encodeForNetwork(storedRLP []byte) ([]byte, error) {
|
|||
|
||||
// 2. Find the version of sidecar.
|
||||
version, _, err := rlp.SplitUint64(elems[1])
|
||||
if err != nil || version > 255 {
|
||||
if err != nil || version > 255 || version == 0 {
|
||||
return nil, fmt.Errorf("invalid version: %w", err)
|
||||
}
|
||||
versionByte := byte(version)
|
||||
// 3. Extract sidecar elements.
|
||||
commitmentsRLP := elems[2]
|
||||
proofsRLP := elems[3]
|
||||
blobsRLP := elems[4]
|
||||
|
||||
// 4. Reconstruct into the network format.
|
||||
var outer [][]byte
|
||||
if versionByte == types.BlobSidecarVersion0 {
|
||||
outer = [][]byte{txRLP, blobsRLP, commitmentsRLP, proofsRLP}
|
||||
} else {
|
||||
outer = [][]byte{txRLP, elems[1], blobsRLP, commitmentsRLP, proofsRLP}
|
||||
}
|
||||
outer := [][]byte{txRLP, elems[1], blobsRLP, commitmentsRLP, proofsRLP}
|
||||
|
||||
body, err := rlp.MergeListValues(outer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -555,7 +550,7 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
|
|||
p.state = state
|
||||
|
||||
// Create new slotter for pre-Osaka blob configuration.
|
||||
slotter := newSlotter(params.BlobTxMaxBlobs)
|
||||
slotter := newSlotterEIP7594(params.BlobTxMaxBlobs)
|
||||
|
||||
// See if we need to migrate the queue blob store after fusaka
|
||||
slotter, err = tryMigrate(p.chain.Config(), slotter, queuedir)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ import (
|
|||
var (
|
||||
testBlobs []*kzg4844.Blob
|
||||
testBlobCommits []kzg4844.Commitment
|
||||
testBlobProofs []kzg4844.Proof
|
||||
testBlobCellProofs [][]kzg4844.Proof
|
||||
testBlobVHashes [][32]byte
|
||||
testBlobIndices = make(map[[32]byte]int)
|
||||
|
|
@ -69,9 +68,6 @@ func init() {
|
|||
testBlobCommit, _ := kzg4844.BlobToCommitment(testBlob)
|
||||
testBlobCommits = append(testBlobCommits, testBlobCommit)
|
||||
|
||||
testBlobProof, _ := kzg4844.ComputeBlobProof(testBlob, testBlobCommit)
|
||||
testBlobProofs = append(testBlobProofs, testBlobProof)
|
||||
|
||||
testBlobCellProof, _ := kzg4844.ComputeCellProofs(testBlob)
|
||||
testBlobCellProofs = append(testBlobCellProofs, testBlobCellProof)
|
||||
|
||||
|
|
@ -243,7 +239,7 @@ func encodeForPool(tx *types.Transaction) []byte {
|
|||
|
||||
// makeMultiBlobTx is a utility method to construct a random blob tx with
|
||||
// certain number of blobs in its sidecar.
|
||||
func makeMultiBlobTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64, blobCount int, blobOffset int, key *ecdsa.PrivateKey, version byte) *types.Transaction {
|
||||
func makeMultiBlobTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64, blobCount int, blobOffset int, key *ecdsa.PrivateKey) *types.Transaction {
|
||||
var (
|
||||
blobs []kzg4844.Blob
|
||||
blobHashes []common.Hash
|
||||
|
|
@ -253,12 +249,8 @@ func makeMultiBlobTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCa
|
|||
for i := 0; i < blobCount; i++ {
|
||||
blobs = append(blobs, *testBlobs[blobOffset+i])
|
||||
commitments = append(commitments, testBlobCommits[blobOffset+i])
|
||||
if version == types.BlobSidecarVersion0 {
|
||||
proofs = append(proofs, testBlobProofs[blobOffset+i])
|
||||
} else {
|
||||
cellProofs, _ := kzg4844.ComputeCellProofs(testBlobs[blobOffset+i])
|
||||
proofs = append(proofs, cellProofs...)
|
||||
}
|
||||
cellProofs, _ := kzg4844.ComputeCellProofs(testBlobs[blobOffset+i])
|
||||
proofs = append(proofs, cellProofs...)
|
||||
blobHashes = append(blobHashes, testBlobVHashes[blobOffset+i])
|
||||
}
|
||||
blobtx := &types.BlobTx{
|
||||
|
|
@ -270,7 +262,7 @@ func makeMultiBlobTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCa
|
|||
BlobFeeCap: uint256.NewInt(blobFeeCap),
|
||||
BlobHashes: blobHashes,
|
||||
Value: uint256.NewInt(100),
|
||||
Sidecar: types.NewBlobTxSidecar(version, blobs, commitments, proofs),
|
||||
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion1, blobs, commitments, proofs),
|
||||
}
|
||||
return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
|
||||
}
|
||||
|
|
@ -293,7 +285,7 @@ func makeUnsignedTxWithTestBlob(nonce uint64, gasTipCap uint64, gasFeeCap uint64
|
|||
BlobFeeCap: uint256.NewInt(blobFeeCap),
|
||||
BlobHashes: []common.Hash{testBlobVHashes[blobIdx]},
|
||||
Value: uint256.NewInt(100),
|
||||
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion0, []kzg4844.Blob{*testBlobs[blobIdx]}, []kzg4844.Commitment{testBlobCommits[blobIdx]}, []kzg4844.Proof{testBlobProofs[blobIdx]}),
|
||||
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion1, []kzg4844.Blob{*testBlobs[blobIdx]}, []kzg4844.Commitment{testBlobCommits[blobIdx]}, testBlobCellProofs[blobIdx]),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,36 +432,18 @@ func verifyBlobRetrievals(t *testing.T, pool *BlobPool) {
|
|||
hashes = append(hashes, tx.vhashes...)
|
||||
}
|
||||
}
|
||||
blobs1, _, proofs1, err := pool.getBlobs(hashes, types.BlobSidecarVersion0)
|
||||
blobs, _, proofs, err := pool.getBlobs(hashes, types.BlobSidecarVersion1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
blobs2, _, proofs2, err := pool.getBlobs(hashes, types.BlobSidecarVersion1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Cross validate what we received vs what we wanted
|
||||
if len(blobs1) != len(hashes) || len(proofs1) != len(hashes) {
|
||||
t.Errorf("retrieved blobs/proofs size mismatch: have %d/%d, want %d", len(blobs1), len(proofs1), len(hashes))
|
||||
return
|
||||
}
|
||||
if len(blobs2) != len(hashes) || len(proofs2) != len(hashes) {
|
||||
t.Errorf("retrieved blobs/proofs size mismatch: have %d/%d, want blobs %d, want proofs: %d", len(blobs2), len(proofs2), len(hashes), len(hashes))
|
||||
if len(blobs) != len(hashes) || len(proofs) != len(hashes) {
|
||||
t.Errorf("retrieved blobs/proofs size mismatch: have %d/%d, want blobs %d, want proofs: %d", len(blobs), len(proofs), len(hashes), len(hashes))
|
||||
return
|
||||
}
|
||||
for i, hash := range hashes {
|
||||
// If an item is missing from both, but shouldn't, error
|
||||
if (blobs1[i] == nil || proofs1[i] == nil) && (blobs2[i] == nil || proofs2[i] == nil) {
|
||||
t.Errorf("tracked blob retrieval failed: item %d, hash %x", i, hash)
|
||||
continue
|
||||
}
|
||||
// Item retrieved, make sure it matches the expectation
|
||||
index := testBlobIndices[hash]
|
||||
if blobs1[i] != nil && (*blobs1[i] != *testBlobs[index] || proofs1[i][0] != testBlobProofs[index]) {
|
||||
t.Errorf("retrieved blob or proof mismatch: item %d, hash %x", i, hash)
|
||||
continue
|
||||
}
|
||||
if blobs2[i] != nil && (*blobs2[i] != *testBlobs[index] || !slices.Equal(proofs2[i], testBlobCellProofs[index])) {
|
||||
if blobs[i] != nil && (*blobs[i] != *testBlobs[index] || !slices.Equal(proofs[i], testBlobCellProofs[index])) {
|
||||
t.Errorf("retrieved blob or proof mismatch: item %d, hash %x", i, hash)
|
||||
continue
|
||||
}
|
||||
|
|
@ -503,7 +477,7 @@ func TestOpenDrops(t *testing.T) {
|
|||
storage := t.TempDir()
|
||||
|
||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotterEIP7594(testMaxBlobsPerBlock), nil)
|
||||
|
||||
// Insert a malformed transaction to verify that decoding errors (or format
|
||||
// changes) are handled gracefully (case 1)
|
||||
|
|
@ -825,7 +799,7 @@ func TestOpenIndex(t *testing.T) {
|
|||
storage := t.TempDir()
|
||||
|
||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotterEIP7594(testMaxBlobsPerBlock), nil)
|
||||
|
||||
// Insert a sequence of transactions with varying price points to check that
|
||||
// the cumulative minimum will be maintained.
|
||||
|
|
@ -913,7 +887,7 @@ func TestOpenHeap(t *testing.T) {
|
|||
storage := t.TempDir()
|
||||
|
||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotterEIP7594(testMaxBlobsPerBlock), nil)
|
||||
|
||||
// Insert a few transactions from a few accounts. To remove randomness from
|
||||
// the heap initialization, use a deterministic account/tx/priority ordering.
|
||||
|
|
@ -1088,7 +1062,7 @@ func TestChangingSlotterSize(t *testing.T) {
|
|||
storage := t.TempDir()
|
||||
|
||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(6), nil)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotterEIP7594(6), nil)
|
||||
|
||||
// Create transactions from a few accounts.
|
||||
var (
|
||||
|
|
@ -1100,9 +1074,9 @@ func TestChangingSlotterSize(t *testing.T) {
|
|||
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1, types.BlobSidecarVersion0)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, 0, key2, types.BlobSidecarVersion0)
|
||||
tx3 = makeMultiBlobTx(0, 1, 800, 110, 24, 0, key3, types.BlobSidecarVersion0)
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, 0, key2)
|
||||
tx3 = makeMultiBlobTx(0, 1, 800, 110, 24, 0, key3)
|
||||
|
||||
blob1 = encodeForPool(tx1)
|
||||
blob2 = encodeForPool(tx2)
|
||||
|
|
@ -1203,9 +1177,9 @@ func TestBillyMigration(t *testing.T) {
|
|||
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1, types.BlobSidecarVersion0)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, 0, key2, types.BlobSidecarVersion0)
|
||||
tx3 = makeMultiBlobTx(0, 1, 800, 110, 24, 0, key3, types.BlobSidecarVersion0)
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, 0, key2)
|
||||
tx3 = makeMultiBlobTx(0, 1, 800, 110, 24, 0, key3)
|
||||
|
||||
blob1 = encodeForPool(tx1)
|
||||
blob2 = encodeForPool(tx2)
|
||||
|
|
@ -1299,7 +1273,7 @@ func TestLegacyTxConversion(t *testing.T) {
|
|||
// Initialize the pending store with two blob transactions encoded in the
|
||||
// legacy format.
|
||||
queuedir := filepath.Join(storage, pendingTransactionStore)
|
||||
store, err := billy.Open(billy.Options{Path: queuedir}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||
store, err := billy.Open(billy.Options{Path: queuedir}, newSlotterEIP7594(testMaxBlobsPerBlock), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open billy: %v", err)
|
||||
}
|
||||
|
|
@ -1309,8 +1283,8 @@ func TestLegacyTxConversion(t *testing.T) {
|
|||
addr1 := crypto.PubkeyToAddress(key1.PublicKey)
|
||||
addr2 := crypto.PubkeyToAddress(key2.PublicKey)
|
||||
|
||||
tx1 := makeMultiBlobTx(0, 1, 1000, 100, 2, 0, key1, types.BlobSidecarVersion0)
|
||||
tx2 := makeMultiBlobTx(0, 1, 1000, 100, 2, 2, key2, types.BlobSidecarVersion0)
|
||||
tx1 := makeMultiBlobTx(0, 1, 1000, 100, 2, 0, key1)
|
||||
tx2 := makeMultiBlobTx(0, 1, 1000, 100, 2, 2, key2)
|
||||
|
||||
for _, tx := range []*types.Transaction{tx1, tx2} {
|
||||
legacy, err := rlp.EncodeToBytes(tx)
|
||||
|
|
@ -1408,8 +1382,8 @@ func TestBlobCountLimit(t *testing.T) {
|
|||
|
||||
// Attempt to add transactions.
|
||||
var (
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1, types.BlobSidecarVersion0)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 7, 0, key2, types.BlobSidecarVersion0)
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 7, 0, key2)
|
||||
)
|
||||
errs := pool.Add([]*types.Transaction{tx1, tx2}, true)
|
||||
|
||||
|
|
@ -1811,7 +1785,7 @@ func TestAdd(t *testing.T) {
|
|||
storage := filepath.Join(t.TempDir(), fmt.Sprintf("test-%d", i))
|
||||
|
||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotterEIP7594(testMaxBlobsPerBlock), nil)
|
||||
|
||||
// Insert the seed transactions for the pool startup
|
||||
var (
|
||||
|
|
@ -1922,7 +1896,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
storage := t.TempDir()
|
||||
|
||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(params.BlobTxMaxBlobs), nil)
|
||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotterEIP7594(params.BlobTxMaxBlobs), nil)
|
||||
|
||||
// Create transactions from a few accounts.
|
||||
var (
|
||||
|
|
@ -1934,9 +1908,9 @@ func TestGetBlobs(t *testing.T) {
|
|||
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1, types.BlobSidecarVersion0) // [0, 6)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, 6, key2, types.BlobSidecarVersion1) // [6, 12)
|
||||
tx3 = makeMultiBlobTx(0, 1, 800, 110, 6, 12, key3, types.BlobSidecarVersion0) // [12, 18)
|
||||
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1) // [0, 6)
|
||||
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, 6, key2) // [6, 12)
|
||||
tx3 = makeMultiBlobTx(0, 1, 800, 110, 6, 12, key3) // [12, 18)
|
||||
|
||||
blob1 = encodeForPool(tx1)
|
||||
blob2 = encodeForPool(tx2)
|
||||
|
|
@ -2004,7 +1978,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
start: 0, limit: 6,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 6,
|
||||
|
|
@ -2012,7 +1986,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
},
|
||||
{
|
||||
start: 0, limit: 6, fillRandom: true,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 6, fillRandom: true,
|
||||
|
|
@ -2020,7 +1994,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
},
|
||||
{
|
||||
start: 3, limit: 9,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 3, limit: 9,
|
||||
|
|
@ -2028,7 +2002,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
},
|
||||
{
|
||||
start: 3, limit: 9, fillRandom: true,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 3, limit: 9, fillRandom: true,
|
||||
|
|
@ -2036,7 +2010,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
},
|
||||
{
|
||||
start: 3, limit: 15,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 3, limit: 15,
|
||||
|
|
@ -2044,7 +2018,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
},
|
||||
{
|
||||
start: 3, limit: 15, fillRandom: true,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 3, limit: 15, fillRandom: true,
|
||||
|
|
@ -2052,7 +2026,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
},
|
||||
{
|
||||
start: 0, limit: 18,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 18,
|
||||
|
|
@ -2060,7 +2034,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
},
|
||||
{
|
||||
start: 0, limit: 18, fillRandom: true,
|
||||
version: types.BlobSidecarVersion0,
|
||||
version: types.BlobSidecarVersion1,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 18, fillRandom: true,
|
||||
|
|
@ -2114,7 +2088,7 @@ func TestGetBlobs(t *testing.T) {
|
|||
if blobs[j] == nil || proofs[j] == nil {
|
||||
// This is only an error if there was no version mismatch
|
||||
if (c.version == types.BlobSidecarVersion1 && 6 <= testBlobIndex && testBlobIndex < 12) ||
|
||||
(c.version == types.BlobSidecarVersion0 && (testBlobIndex < 6 || 12 <= testBlobIndex)) {
|
||||
(c.version == types.BlobSidecarVersion1 && (testBlobIndex < 6 || 12 <= testBlobIndex)) {
|
||||
t.Errorf("tracked blob retrieval failed: item %d, hash %x", j, vhashes[j])
|
||||
}
|
||||
continue
|
||||
|
|
@ -2125,15 +2099,9 @@ func TestGetBlobs(t *testing.T) {
|
|||
continue
|
||||
}
|
||||
// Item retrieved, make sure the proof matches the expectation
|
||||
if c.version == types.BlobSidecarVersion0 {
|
||||
if proofs[j][0] != testBlobProofs[testBlobIndex] {
|
||||
t.Errorf("retrieved proof mismatch: item %d, hash %x", j, vhashes[j])
|
||||
}
|
||||
} else {
|
||||
want, _ := kzg4844.ComputeCellProofs(blobs[j])
|
||||
if !reflect.DeepEqual(want, proofs[j]) {
|
||||
t.Errorf("retrieved proof mismatch: item %d, hash %x", j, vhashes[j])
|
||||
}
|
||||
want, _ := kzg4844.ComputeCellProofs(blobs[j])
|
||||
if !reflect.DeepEqual(want, proofs[j]) {
|
||||
t.Errorf("retrieved proof mismatch: item %d, hash %x", j, vhashes[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2143,13 +2111,12 @@ func TestGetBlobs(t *testing.T) {
|
|||
// TestEncodeForNetwork verifies that encodeForNetwork produces output identical
|
||||
// to rlp.EncodeToBytes on the original transaction, for both V0 and V1 sidecars.
|
||||
func TestEncodeForNetwork(t *testing.T) {
|
||||
t.Run("v0", func(t *testing.T) { testEncodeForNetwork(t, types.BlobSidecarVersion0) })
|
||||
t.Run("v1", func(t *testing.T) { testEncodeForNetwork(t, types.BlobSidecarVersion1) })
|
||||
t.Run("v1", func(t *testing.T) { testEncodeForNetwork(t) })
|
||||
}
|
||||
|
||||
func testEncodeForNetwork(t *testing.T, version byte) {
|
||||
func testEncodeForNetwork(t *testing.T) {
|
||||
key, _ := crypto.GenerateKey()
|
||||
tx := makeMultiBlobTx(0, 1, 1, 1, 1, 0, key, version)
|
||||
tx := makeMultiBlobTx(0, 1, 1, 1, 1, 0, key)
|
||||
|
||||
wantRLP, err := rlp.EncodeToBytes(tx)
|
||||
if err != nil {
|
||||
|
|
@ -2162,7 +2129,7 @@ func testEncodeForNetwork(t *testing.T, version byte) {
|
|||
t.Fatalf("encodeForNetwork failed: %v", err)
|
||||
}
|
||||
if !bytes.Equal(gotRLP, wantRLP) {
|
||||
t.Fatalf("network encoding mismatch (version %d): got %d bytes, want %d bytes", version, len(gotRLP), len(wantRLP))
|
||||
t.Fatalf("network encoding mismatch: got %d bytes, want %d bytes", len(gotRLP), len(wantRLP))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -343,22 +343,15 @@ func (c *Cache) update(want []common.Hash) {
|
|||
if _, exists := c.entries[v]; exists {
|
||||
continue // recompute only new entries
|
||||
}
|
||||
var pf []kzg4844.Proof
|
||||
switch sidecar.Version {
|
||||
case types.BlobSidecarVersion0:
|
||||
pf = []kzg4844.Proof{sidecar.Proofs[i]}
|
||||
case types.BlobSidecarVersion1:
|
||||
cellProofs, err := sidecar.CellProofsAt(i)
|
||||
if err != nil {
|
||||
log.Error("Failed to get cell proofs", "txhash", ptx.Tx.Hash(), "err", err)
|
||||
continue
|
||||
}
|
||||
pf = cellProofs
|
||||
cellProofs, err := sidecar.CellProofsAt(i)
|
||||
if err != nil {
|
||||
log.Error("Failed to get cell proofs", "txhash", ptx.Tx.Hash(), "err", err)
|
||||
continue
|
||||
}
|
||||
c.entries[v] = &cachedBlob{
|
||||
blob: &sidecar.Blobs[i],
|
||||
commitment: sidecar.Commitments[i],
|
||||
proofs: pf,
|
||||
proofs: cellProofs,
|
||||
version: sidecar.Version,
|
||||
}
|
||||
cacheBlobsGauge.Inc(1)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func newTestCache(t *testing.T, txConfig []txSpec) *testCache {
|
|||
if err := os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700); err != nil {
|
||||
t.Fatalf("mkdir: %v", err)
|
||||
}
|
||||
store, err := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(params.BlobTxMaxBlobs), nil)
|
||||
store, err := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotterEIP7594(params.BlobTxMaxBlobs), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("billy open: %v", err)
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ func newTestCache(t *testing.T, txConfig []txSpec) *testCache {
|
|||
)
|
||||
for _, s := range txConfig {
|
||||
key, _ := crypto.GenerateKey()
|
||||
tx := makeMultiBlobTx(0, s.tip, 1_000_000, 1_000_000, s.blobs, offset, key, types.BlobSidecarVersion1)
|
||||
tx := makeMultiBlobTx(0, s.tip, 1_000_000, 1_000_000, s.blobs, offset, key)
|
||||
if _, err := store.Put(encodeForPool(tx)); err != nil {
|
||||
t.Fatalf("store put: %v", err)
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ func newTestCache(t *testing.T, txConfig []txSpec) *testCache {
|
|||
func (tc *testCache) inject(t *testing.T, spec txSpec) []common.Hash {
|
||||
t.Helper()
|
||||
key, _ := crypto.GenerateKey()
|
||||
tx := makeMultiBlobTx(0, spec.tip, 1_000_000, 1_000_000, spec.blobs, tc.offset, key, types.BlobSidecarVersion1)
|
||||
tx := makeMultiBlobTx(0, spec.tip, 1_000_000, 1_000_000, spec.blobs, tc.offset, key)
|
||||
tc.offset += spec.blobs
|
||||
|
||||
ptx := newBlobTxForPool(tx)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func newLimbo(config *params.ChainConfig, datadir string) (*limbo, error) {
|
|||
}
|
||||
|
||||
// Create new slotter for pre-Osaka blob configuration.
|
||||
slotter := newSlotter(params.BlobTxMaxBlobs)
|
||||
slotter := newSlotterEIP7594(params.BlobTxMaxBlobs)
|
||||
|
||||
// See if we need to migrate the limbo after fusaka.
|
||||
slotter, err := tryMigrate(config, slotter, datadir)
|
||||
|
|
|
|||
|
|
@ -58,27 +58,6 @@ func tryMigrate(config *params.ChainConfig, slotter billy.SlotSizeFn, datadir st
|
|||
return slotter, nil
|
||||
}
|
||||
|
||||
// newSlotter creates a helper method for the Billy datastore that returns the
|
||||
// individual shelf sizes used to store transactions in.
|
||||
//
|
||||
// The slotter will create shelves for each possible blob count + some tx metadata
|
||||
// wiggle room, up to the max permitted limits.
|
||||
//
|
||||
// The slotter also creates a shelf for 0-blob transactions. Whilst those are not
|
||||
// allowed in the current protocol, having an empty shelf is not a relevant use
|
||||
// of resources, but it makes stress testing with junk transactions simpler.
|
||||
func newSlotter(maxBlobsPerTransaction int) billy.SlotSizeFn {
|
||||
slotsize := uint32(txAvgSize)
|
||||
slotsize -= uint32(blobSize) // underflows, it's ok, will overflow back in the first return
|
||||
|
||||
return func() (size uint32, done bool) {
|
||||
slotsize += blobSize
|
||||
finished := slotsize > uint32(maxBlobsPerTransaction)*blobSize+txMaxSize
|
||||
|
||||
return slotsize, finished
|
||||
}
|
||||
}
|
||||
|
||||
// newSlotterEIP7594 creates a different slotter for EIP-7594 transactions.
|
||||
// EIP-7594 (PeerDAS) changes the average transaction size which means the current
|
||||
// static 4KB average size is not enough anymore.
|
||||
|
|
|
|||
|
|
@ -20,47 +20,6 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
// Tests that the slotter creates the expected database shelves.
|
||||
func TestNewSlotter(t *testing.T) {
|
||||
// Generate the database shelve sizes
|
||||
slotter := newSlotter(6)
|
||||
|
||||
var shelves []uint32
|
||||
for {
|
||||
shelf, done := slotter()
|
||||
shelves = append(shelves, shelf)
|
||||
if done {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Compare the database shelves to the expected ones
|
||||
want := []uint32{
|
||||
0*blobSize + txAvgSize, // 0 blob + some expected tx infos
|
||||
1*blobSize + txAvgSize, // 1 blob + some expected tx infos
|
||||
2*blobSize + txAvgSize, // 2 blob + some expected tx infos (could be fewer blobs and more tx data)
|
||||
3*blobSize + txAvgSize, // 3 blob + some expected tx infos (could be fewer blobs and more tx data)
|
||||
4*blobSize + txAvgSize, // 4 blob + some expected tx infos (could be fewer blobs and more tx data)
|
||||
5*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
6*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
7*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
8*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
9*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
10*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
11*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
12*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
13*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
|
||||
14*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size
|
||||
}
|
||||
if len(shelves) != len(want) {
|
||||
t.Errorf("shelves count mismatch: have %d, want %d", len(shelves), len(want))
|
||||
}
|
||||
for i := 0; i < len(shelves) && i < len(want); i++ {
|
||||
if shelves[i] != want[i] {
|
||||
t.Errorf("shelf %d mismatch: have %d, want %d", i, shelves[i], want[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that the slotter creates the expected database shelves.
|
||||
func TestNewSlotterEIP7594(t *testing.T) {
|
||||
// Generate the database shelve sizes
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
|
|||
return fmt.Errorf("%w: gas tip cap %v, minimum needed %v", ErrTxGasPriceTooLow, tx.GasTipCap(), opts.MinTip)
|
||||
}
|
||||
if tx.Type() == types.BlobTxType {
|
||||
return validateBlobTx(tx, head, opts)
|
||||
return validateBlobTx(tx)
|
||||
}
|
||||
if tx.Type() == types.SetCodeTxType {
|
||||
if len(tx.SetCodeAuthorizations()) == 0 {
|
||||
|
|
@ -165,19 +165,14 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
|
|||
}
|
||||
|
||||
// validateBlobTx implements the blob-transaction specific validations.
|
||||
func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationOptions) error {
|
||||
func validateBlobTx(tx *types.Transaction) error {
|
||||
sidecar := tx.BlobTxSidecar()
|
||||
if sidecar == nil {
|
||||
return errors.New("missing sidecar in blob transaction")
|
||||
}
|
||||
// Ensure the sidecar is constructed with the correct version, consistent
|
||||
// with the current fork.
|
||||
version := types.BlobSidecarVersion0
|
||||
if opts.Config.IsOsaka(head.Number, head.Time) {
|
||||
version = types.BlobSidecarVersion1
|
||||
}
|
||||
if sidecar.Version != version {
|
||||
return fmt.Errorf("unexpected sidecar version, want: %d, got: %d", version, sidecar.Version)
|
||||
// Ensure the sidecar is constructed with the correct version
|
||||
if sidecar.Version != types.BlobSidecarVersion1 {
|
||||
return fmt.Errorf("unexpected sidecar version, want: %d, got: %d", types.BlobSidecarVersion1, sidecar.Version)
|
||||
}
|
||||
// Ensure the blob fee cap satisfies the minimum blob gas price
|
||||
if tx.BlobGasFeeCapIntCmp(blobTxMinBlobGasPrice) < 0 {
|
||||
|
|
@ -198,26 +193,8 @@ func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationO
|
|||
if err := sidecar.ValidateBlobCommitmentHashes(hashes); err != nil {
|
||||
return err
|
||||
}
|
||||
// Fork-specific sidecar checks, including proof verification.
|
||||
if sidecar.Version == types.BlobSidecarVersion1 {
|
||||
return validateBlobSidecarOsaka(sidecar, hashes)
|
||||
} else {
|
||||
return validateBlobSidecarLegacy(sidecar, hashes)
|
||||
}
|
||||
return validateBlobSidecarOsaka(sidecar, hashes)
|
||||
}
|
||||
|
||||
func validateBlobSidecarLegacy(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
|
||||
if len(sidecar.Proofs) != len(hashes) {
|
||||
return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes))
|
||||
}
|
||||
for i := range sidecar.Blobs {
|
||||
if err := kzg4844.VerifyBlobProof(&sidecar.Blobs[i], sidecar.Commitments[i], sidecar.Proofs[i]); err != nil {
|
||||
return fmt.Errorf("%w: invalid blob proof: %v", ErrKZGVerificationError, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateBlobSidecarOsaka(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
|
||||
if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob {
|
||||
return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes)*kzg4844.CellProofsPerBlob)
|
||||
|
|
|
|||
|
|
@ -1917,111 +1917,6 @@ func newGetBlobEnv(t testing.TB, version byte) (*node.Node, *ConsensusAPI) {
|
|||
api := newConsensusAPIWithoutHeartbeat(ethServ)
|
||||
return n, api
|
||||
}
|
||||
|
||||
func TestGetBlobsV1(t *testing.T) {
|
||||
n, api := newGetBlobEnv(t, 0)
|
||||
defer n.Close()
|
||||
|
||||
suites := []struct {
|
||||
start int
|
||||
limit int
|
||||
fillRandom bool
|
||||
}{
|
||||
{
|
||||
start: 0, limit: 1,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 1, fillRandom: true,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 2,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 2, fillRandom: true,
|
||||
},
|
||||
{
|
||||
start: 1, limit: 3,
|
||||
},
|
||||
{
|
||||
start: 1, limit: 3, fillRandom: true,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 6,
|
||||
},
|
||||
{
|
||||
start: 0, limit: 6, fillRandom: true,
|
||||
},
|
||||
{
|
||||
start: 1, limit: 5,
|
||||
},
|
||||
{
|
||||
start: 1, limit: 5, fillRandom: true,
|
||||
},
|
||||
}
|
||||
for i, suite := range suites {
|
||||
// Fill the request for retrieving blobs
|
||||
var (
|
||||
vhashes []common.Hash
|
||||
expect engine.BlobAndProofListV1
|
||||
)
|
||||
// fill missing blob at the beginning
|
||||
if suite.fillRandom {
|
||||
vhashes = append(vhashes, testrand.Hash())
|
||||
expect = append(expect, nil)
|
||||
}
|
||||
for j := suite.start; j < suite.limit; j++ {
|
||||
vhashes = append(vhashes, testBlobVHashes[j])
|
||||
expect = append(expect, &engine.BlobAndProofV1{
|
||||
Blob: testBlobs[j][:],
|
||||
Proof: testBlobProofs[j][:],
|
||||
})
|
||||
|
||||
// fill missing blobs in the middle
|
||||
if suite.fillRandom && rand.Intn(2) == 0 {
|
||||
vhashes = append(vhashes, testrand.Hash())
|
||||
expect = append(expect, nil)
|
||||
}
|
||||
}
|
||||
// fill missing blobs at the end
|
||||
if suite.fillRandom {
|
||||
vhashes = append(vhashes, testrand.Hash())
|
||||
expect = append(expect, nil)
|
||||
}
|
||||
result, err := api.GetBlobsV1(context.Background(), vhashes)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error for case %d, %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(result, expect) {
|
||||
t.Fatalf("Unexpected result for case %d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBlobsV1AfterOsakaFork(t *testing.T) {
|
||||
genesis := &core.Genesis{
|
||||
Config: params.MergedTestChainConfig,
|
||||
Alloc: types.GenesisAlloc{testAddr: {Balance: testBalance}},
|
||||
Difficulty: common.Big0,
|
||||
Timestamp: 1, // Timestamp > 0 to ensure Osaka fork is active
|
||||
}
|
||||
n, ethServ := startEthService(t, genesis, nil)
|
||||
defer n.Close()
|
||||
|
||||
var engineErr *engine.EngineAPIError
|
||||
api := newConsensusAPIWithoutHeartbeat(ethServ)
|
||||
_, err := api.GetBlobsV1(context.Background(), []common.Hash{testrand.Hash()})
|
||||
if !errors.As(err, &engineErr) {
|
||||
t.Fatalf("Unexpected error: %T", err)
|
||||
} else {
|
||||
if engineErr.ErrorCode() != -38005 {
|
||||
t.Fatalf("Expected error code -38005, got %d", engineErr.ErrorCode())
|
||||
}
|
||||
if engineErr.Error() != "Unsupported fork" {
|
||||
t.Fatalf("Expected error message 'Unsupported fork', got '%s'", engineErr.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBlobsV2And3(t *testing.T) {
|
||||
n, api := newGetBlobEnv(t, 1)
|
||||
defer n.Close()
|
||||
|
|
|
|||
|
|
@ -858,7 +858,7 @@ func testGetPooledTransaction(t *testing.T, blobTx bool) {
|
|||
emptyBlob = kzg4844.Blob{}
|
||||
emptyBlobs = []kzg4844.Blob{emptyBlob}
|
||||
emptyBlobCommit, _ = kzg4844.BlobToCommitment(&emptyBlob)
|
||||
emptyBlobProof, _ = kzg4844.ComputeBlobProof(&emptyBlob, emptyBlobCommit)
|
||||
emptyCellProof, _ = kzg4844.ComputeCellProofs(&emptyBlob)
|
||||
emptyBlobHash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit)
|
||||
)
|
||||
backend := newTestBackendWithGenerator(0, true, true, nil)
|
||||
|
|
@ -882,7 +882,7 @@ func testGetPooledTransaction(t *testing.T, blobTx bool) {
|
|||
To: testAddr,
|
||||
BlobHashes: []common.Hash{emptyBlobHash},
|
||||
BlobFeeCap: uint256.MustFromBig(common.Big1),
|
||||
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion0, emptyBlobs, []kzg4844.Commitment{emptyBlobCommit}, []kzg4844.Proof{emptyBlobProof}),
|
||||
Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion1, emptyBlobs, []kzg4844.Commitment{emptyBlobCommit}, emptyCellProof),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
Loading…
Reference in a new issue