mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
core/rawdb/eradb: convert block receipts on access
This commit is contained in:
parent
477bbf1d18
commit
52464bffbe
4 changed files with 69 additions and 12 deletions
|
|
@ -18,6 +18,7 @@
|
||||||
package eradb
|
package eradb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
|
@ -27,6 +28,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
"github.com/ethereum/go-ethereum/internal/era"
|
"github.com/ethereum/go-ethereum/internal/era"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const openFileLimit = 64
|
const openFileLimit = 64
|
||||||
|
|
@ -125,7 +127,66 @@ func (db *Store) GetRawReceipts(number uint64) ([]byte, error) {
|
||||||
}
|
}
|
||||||
defer db.doneWithFile(epoch, entry)
|
defer db.doneWithFile(epoch, entry)
|
||||||
|
|
||||||
return entry.file.GetRawReceiptsByNumber(number)
|
data, err := entry.file.GetRawReceiptsByNumber(number)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return convertReceipts(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertReceipts transforms an encoded block receipts list from the format
|
||||||
|
// used by era1 into the 'storage' format used by the go-ethereum ancients database.
|
||||||
|
func convertReceipts(input []byte) ([]byte, error) {
|
||||||
|
var (
|
||||||
|
out bytes.Buffer
|
||||||
|
enc = rlp.NewEncoderBuffer(&out)
|
||||||
|
)
|
||||||
|
blockListIter, err := rlp.NewListIterator(input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid block receipts list: %v", err)
|
||||||
|
}
|
||||||
|
outerList := enc.List()
|
||||||
|
for i := 0; blockListIter.Next(); i++ {
|
||||||
|
kind, content, _, err := rlp.Split(blockListIter.Value())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("receipt %d invalid: %v", i, err)
|
||||||
|
}
|
||||||
|
var receiptData []byte
|
||||||
|
switch kind {
|
||||||
|
case rlp.Byte:
|
||||||
|
return nil, fmt.Errorf("receipt %d is single byte", i)
|
||||||
|
case rlp.String:
|
||||||
|
// Typed receipt - skip type.
|
||||||
|
receiptData = content[1:]
|
||||||
|
case rlp.List:
|
||||||
|
// Legacy receipt
|
||||||
|
receiptData = blockListIter.Value()
|
||||||
|
}
|
||||||
|
// Convert data list.
|
||||||
|
// Input is [status, gas-used, bloom, logs]
|
||||||
|
// Output is [status, gas-used, logs], i.e. we need to skip the bloom.
|
||||||
|
dataIter, err := rlp.NewListIterator(receiptData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("receipt %d has invalid data: %v", i, err)
|
||||||
|
}
|
||||||
|
innerList := enc.List()
|
||||||
|
for field := 0; dataIter.Next(); field++ {
|
||||||
|
if field == 2 {
|
||||||
|
continue // skip bloom
|
||||||
|
}
|
||||||
|
enc.Write(dataIter.Value())
|
||||||
|
}
|
||||||
|
enc.ListEnd(innerList)
|
||||||
|
if dataIter.Err() != nil {
|
||||||
|
return nil, fmt.Errorf("receipt %d iterator error: %v", i, dataIter.Err())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc.ListEnd(outerList)
|
||||||
|
if blockListIter.Err() != nil {
|
||||||
|
return nil, fmt.Errorf("block receipt list iterator error: %v", blockListIter.Err())
|
||||||
|
}
|
||||||
|
enc.Flush()
|
||||||
|
return out.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getEraByEpoch opens an era file or gets it from the cache.
|
// getEraByEpoch opens an era file or gets it from the cache.
|
||||||
|
|
@ -240,13 +301,11 @@ func (db *Store) openEraFile(epoch uint64) (*era.Era, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Assign an epoch to the table.
|
// Sanity-check start block.
|
||||||
if e.Count() != uint64(era.MaxEra1Size) {
|
|
||||||
return nil, fmt.Errorf("pre-merge era1 files must be full. Want: %d, have: %d", era.MaxEra1Size, e.Count())
|
|
||||||
}
|
|
||||||
if e.Start()%uint64(era.MaxEra1Size) != 0 {
|
if e.Start()%uint64(era.MaxEra1Size) != 0 {
|
||||||
return nil, fmt.Errorf("pre-merge era1 file has invalid boundary. %d %% %d != 0", e.Start(), era.MaxEra1Size)
|
return nil, fmt.Errorf("pre-merge era1 file has invalid boundary. %d %% %d != 0", e.Start(), era.MaxEra1Size)
|
||||||
}
|
}
|
||||||
|
log.Debug("Opened era1 file", "epoch", epoch)
|
||||||
return e, nil
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,27 +27,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEraDatabase(t *testing.T) {
|
func TestEraDatabase(t *testing.T) {
|
||||||
// Create the database
|
|
||||||
db, err := New("testdata")
|
db, err := New("testdata")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
r, err := db.GetRawBody(1024)
|
r, err := db.GetRawBody(175881)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
var body *types.Body
|
var body *types.Body
|
||||||
err = rlp.DecodeBytes(r, &body)
|
err = rlp.DecodeBytes(r, &body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, body, "block body not found")
|
require.NotNil(t, body, "block body not found")
|
||||||
assert.Equal(t, 0, len(body.Transactions))
|
assert.Equal(t, 3, len(body.Transactions))
|
||||||
|
|
||||||
// Get Receipts
|
r, err = db.GetRawReceipts(175881)
|
||||||
r, err = db.GetRawReceipts(1024)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
var receipts types.Receipts
|
var receipts []*types.ReceiptForStorage
|
||||||
err = rlp.DecodeBytes(r, &receipts)
|
err = rlp.DecodeBytes(r, &receipts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, receipts, "receipts not found")
|
require.NotNil(t, receipts, "receipts not found")
|
||||||
assert.Equal(t, 0, len(receipts), "receipts length mismatch")
|
assert.Equal(t, 3, len(receipts), "receipts length mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEraDatabaseConcurrentOpen(t *testing.T) {
|
func TestEraDatabaseConcurrentOpen(t *testing.T) {
|
||||||
|
|
|
||||||
Binary file not shown.
BIN
core/rawdb/eradb/testdata/sepolia-00021-b8814b14.era1
vendored
Normal file
BIN
core/rawdb/eradb/testdata/sepolia-00021-b8814b14.era1
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue