mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 11:46:44 +00:00
added all changes from comments
This commit is contained in:
parent
fc4c76a1cb
commit
e475a30421
3 changed files with 210 additions and 199 deletions
|
|
@ -70,16 +70,16 @@ const (
|
|||
headerSize uint64 = 8
|
||||
)
|
||||
|
||||
type variant uint16
|
||||
|
||||
// temporary buffer for writing blocks until Finalize is called
|
||||
type buffer struct {
|
||||
headers [][]byte
|
||||
bodies [][]byte
|
||||
receipts [][]byte
|
||||
proofs [][]byte
|
||||
tds [][]byte
|
||||
tds []*big.Int
|
||||
}
|
||||
|
||||
// offsets holds the offsets of the different block components in the e2store file
|
||||
type offsets struct {
|
||||
headers []uint64
|
||||
bodys []uint64
|
||||
|
|
@ -89,50 +89,30 @@ type offsets struct {
|
|||
}
|
||||
|
||||
type Builder struct {
|
||||
w *e2store.Writer
|
||||
buf *bytes.Buffer
|
||||
sn *snappy.Writer
|
||||
w *e2store.Writer
|
||||
buf *bytes.Buffer
|
||||
snappy *snappy.Writer
|
||||
|
||||
buff buffer
|
||||
off offsets
|
||||
|
||||
prooftype variant
|
||||
tdsint []*big.Int
|
||||
hashes []common.Hash
|
||||
startNum *uint64
|
||||
writtenBytes uint64
|
||||
hashes []common.Hash
|
||||
startNum *uint64
|
||||
written uint64
|
||||
}
|
||||
|
||||
// NewBuilder returns a new Builder instance.
|
||||
func NewBuilder(w io.Writer) *Builder {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
return &Builder{
|
||||
w: e2store.NewWriter(w),
|
||||
buf: buf,
|
||||
sn: snappy.NewBufferedWriter(buf),
|
||||
w: e2store.NewWriter(w),
|
||||
buf: buf,
|
||||
snappy: snappy.NewBufferedWriter(buf),
|
||||
}
|
||||
}
|
||||
|
||||
// Add writes a block entry, its reciepts, and optionally its proofs as well into the e2store file.
|
||||
func (b *Builder) Add(header types.Header, body types.Body, receipts types.Receipts, td *big.Int, proof Proof) error {
|
||||
pv := variantOf(proof) // variant code (or proofNone)
|
||||
var ep []byte // encoded proof payload
|
||||
|
||||
if proof != nil {
|
||||
var buf bytes.Buffer
|
||||
if err := proof.EncodeRLP(&buf); err != nil {
|
||||
return fmt.Errorf("encode proof: %w", err)
|
||||
}
|
||||
ep = buf.Bytes()
|
||||
}
|
||||
|
||||
if len(b.buff.headers) == 0 {
|
||||
b.prooftype = pv
|
||||
} else if pv != b.prooftype {
|
||||
return fmt.Errorf("cannot mix proof variants: first=%d now=%d",
|
||||
b.prooftype, pv)
|
||||
}
|
||||
|
||||
eh, err := rlp.EncodeToBytes(&header)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode header: %w", err)
|
||||
|
|
@ -146,6 +126,22 @@ func (b *Builder) Add(header types.Header, body types.Body, receipts types.Recei
|
|||
return fmt.Errorf("encode receipts: %w", err)
|
||||
}
|
||||
|
||||
var ep []byte
|
||||
var buffer bytes.Buffer
|
||||
|
||||
if proof != nil {
|
||||
if err := proof.EncodeRLP(&buffer); err != nil {
|
||||
return fmt.Errorf("encode proof: %w", err)
|
||||
}
|
||||
ep = buffer.Bytes()
|
||||
} else {
|
||||
noProof := &NoProof{}
|
||||
if err := noProof.EncodeRLP(&buffer); err != nil {
|
||||
return fmt.Errorf("encode no proof: %w", err)
|
||||
}
|
||||
ep = buffer.Bytes()
|
||||
}
|
||||
|
||||
return b.AddRLP(
|
||||
eh, eb, er, ep,
|
||||
header.Number.Uint64(),
|
||||
|
|
@ -162,27 +158,26 @@ func (b *Builder) AddRLP(headerRLP []byte, bodyRLP []byte, receipts []byte, proo
|
|||
b.buff.headers = append(b.buff.headers, headerRLP)
|
||||
b.buff.bodies = append(b.buff.bodies, bodyRLP)
|
||||
b.buff.receipts = append(b.buff.receipts, receipts)
|
||||
b.buff.tds = append(b.buff.tds, uint256LE(td))
|
||||
b.tdsint = append(b.tdsint, new(big.Int).Set(td))
|
||||
b.buff.tds = append(b.buff.tds, new(big.Int).Set(td))
|
||||
b.hashes = append(b.hashes, blockHash)
|
||||
if proof != nil {
|
||||
b.buff.proofs = append(b.buff.proofs, proof)
|
||||
}
|
||||
|
||||
//Write Era2 version before writing any blocks.
|
||||
// Write Era2 version before writing any blocks.
|
||||
if b.startNum == nil {
|
||||
b.startNum = new(uint64)
|
||||
*b.startNum = blockNum
|
||||
if n, err := b.w.Write(TypeVersion, nil); err != nil {
|
||||
return fmt.Errorf("write version entry: %w", err)
|
||||
} else {
|
||||
b.writtenBytes += uint64(n)
|
||||
b.written += uint64(n)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Finalize flushes all entries present in cache to the underlying e2store file.
|
||||
// Finalize writes all header entries, followed by all body entries, followed by all receipt entries.
|
||||
func (b *Builder) Finalize() (common.Hash, error) {
|
||||
if b.startNum == nil {
|
||||
return common.Hash{}, errors.New("no blocks added, cannot finalize")
|
||||
|
|
@ -213,7 +208,8 @@ func (b *Builder) Finalize() (common.Hash, error) {
|
|||
|
||||
if len(b.buff.tds) > 0 {
|
||||
for _, data := range b.buff.tds {
|
||||
off, err := b.addEntry(TypeTotalDifficulty, data, false)
|
||||
littleEndian := uint256LE(data)
|
||||
off, err := b.addEntry(TypeTotalDifficulty, littleEndian, false)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("total-difficulty: %w", err)
|
||||
}
|
||||
|
|
@ -221,7 +217,7 @@ func (b *Builder) Finalize() (common.Hash, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if b.prooftype != ProofNone {
|
||||
if len(b.buff.proofs) > 0 {
|
||||
for _, data := range b.buff.proofs {
|
||||
off, err := b.addEntry(TypeProof, data, true)
|
||||
if err != nil {
|
||||
|
|
@ -234,14 +230,14 @@ func (b *Builder) Finalize() (common.Hash, error) {
|
|||
var accRoot common.Hash
|
||||
if len(b.hashes) > 0 {
|
||||
var err error
|
||||
accRoot, err = ComputeAccumulator(b.hashes, b.tdsint)
|
||||
accRoot, err = ComputeAccumulator(b.hashes, b.buff.tds)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("compute accumulator: %w", err)
|
||||
}
|
||||
if n, err := b.w.Write(TypeAccumulatorRoot, accRoot[:]); err != nil {
|
||||
return common.Hash{}, fmt.Errorf("write accumulator: %w", err)
|
||||
} else {
|
||||
b.writtenBytes += uint64(n)
|
||||
b.written += uint64(n)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,18 +257,18 @@ func uint256LE(v *big.Int) []byte {
|
|||
func (b *Builder) snappyWrite(typ uint16, in []byte) error {
|
||||
var (
|
||||
buf = b.buf
|
||||
s = b.sn
|
||||
s = b.snappy
|
||||
)
|
||||
buf.Reset()
|
||||
s.Reset(buf)
|
||||
if _, err := b.sn.Write(in); err != nil {
|
||||
if _, err := b.snappy.Write(in); err != nil {
|
||||
return fmt.Errorf("error snappy encoding: %w", err)
|
||||
}
|
||||
if err := s.Flush(); err != nil {
|
||||
return fmt.Errorf("error flushing snappy encoding: %w", err)
|
||||
}
|
||||
n, err := b.w.Write(typ, b.buf.Bytes())
|
||||
b.writtenBytes += uint64(n)
|
||||
b.written += uint64(n)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing e2store entry: %w", err)
|
||||
}
|
||||
|
|
@ -280,10 +276,10 @@ func (b *Builder) snappyWrite(typ uint16, in []byte) error {
|
|||
}
|
||||
|
||||
// Add entry takes the e2store object and writes it into the file
|
||||
func (b *Builder) addEntry(typ uint16, payload []byte, snappyIt bool) (uint64, error) {
|
||||
offset := b.writtenBytes
|
||||
func (b *Builder) addEntry(typ uint16, payload []byte, compressed bool) (uint64, error) {
|
||||
offset := b.written
|
||||
var err error
|
||||
if snappyIt {
|
||||
if compressed {
|
||||
if err = b.snappyWrite(typ, payload); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -292,12 +288,12 @@ func (b *Builder) addEntry(typ uint16, payload []byte, snappyIt bool) (uint64, e
|
|||
if n, err = b.w.Write(typ, payload); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
b.writtenBytes += uint64(n)
|
||||
b.written += uint64(n)
|
||||
}
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
// write index takes all the offset table and writes it to the file
|
||||
// writeIndex takes all the offset table and writes it to the file
|
||||
// the index table contains all offsets to specific block entries
|
||||
func (b *Builder) writeIndex() error {
|
||||
count := uint64(len(b.off.headers))
|
||||
|
|
@ -309,9 +305,9 @@ func (b *Builder) writeIndex() error {
|
|||
componentCount++
|
||||
}
|
||||
|
||||
index := make([]byte, 8+count*8*componentCount+16) //8 for start block, 8 per property per block, 16 for the number of properties and the number of blocks
|
||||
index := make([]byte, 8+count*8*componentCount+16) // 8 for start block, 8 per property per block, 16 for the number of properties and the number of blocks
|
||||
binary.LittleEndian.PutUint64(index, *b.startNum)
|
||||
base := int64(b.writtenBytes)
|
||||
base := int64(b.written)
|
||||
rel := func(abs uint64) uint64 { return uint64(int64(abs) - base) }
|
||||
for i := uint64(0); i < count; i++ {
|
||||
basePosition := 8 + i*componentCount*8
|
||||
|
|
@ -329,14 +325,14 @@ func (b *Builder) writeIndex() error {
|
|||
binary.LittleEndian.PutUint64(index[basePosition+pos:], rel(b.off.proofoffsets[i]))
|
||||
}
|
||||
}
|
||||
indexEnd := 8 + count*componentCount*8
|
||||
end := 8 + count*componentCount*8
|
||||
|
||||
binary.LittleEndian.PutUint64(index[indexEnd+0:], componentCount)
|
||||
binary.LittleEndian.PutUint64(index[indexEnd+8:], count)
|
||||
binary.LittleEndian.PutUint64(index[end+0:], componentCount)
|
||||
binary.LittleEndian.PutUint64(index[end+8:], count)
|
||||
if n, err := b.w.Write(TypeBlockIndex, index); err != nil {
|
||||
return err
|
||||
} else {
|
||||
b.writtenBytes += uint64(n)
|
||||
b.written += uint64(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/klauspost/compress/snappy"
|
||||
)
|
||||
|
||||
// metadata contains the information about the era file that is written into the file.
|
||||
type metadata struct {
|
||||
start uint64 // start block number
|
||||
count uint64 // number of blocks in the era
|
||||
|
|
@ -37,97 +38,17 @@ type metadata struct {
|
|||
length int64 // length of the file in bytes
|
||||
}
|
||||
|
||||
const (
|
||||
ProofNone variant = iota
|
||||
proofHHA
|
||||
proofRoots
|
||||
proofCapella
|
||||
proofDeneb
|
||||
)
|
||||
// the types of components that can be present in the era file.
|
||||
type componentType int
|
||||
|
||||
const (
|
||||
compHeader = 0
|
||||
compBody = 1
|
||||
compReceipts = 2
|
||||
compTD = 3
|
||||
compProof = 4
|
||||
componentHeader componentType = iota
|
||||
componentBody
|
||||
componentReceipts
|
||||
componentTD
|
||||
componentProof
|
||||
)
|
||||
|
||||
type BlockProofHistoricalHashesAccumulator [15]common.Hash // 15 * 32 = 480 bytes
|
||||
|
||||
// BlockProofHistoricalRoots – Altair / Bellatrix historical_roots branch.
|
||||
type BlockProofHistoricalRoots struct {
|
||||
BeaconBlockProof [14]common.Hash // 448
|
||||
BeaconBlockRoot common.Hash // 32
|
||||
ExecutionBlockProof [11]common.Hash // 352
|
||||
Slot uint64 // 8 => 840 bytes
|
||||
}
|
||||
|
||||
// BlockProofHistoricalSummariesCapella – Capella historical_summaries branch.
|
||||
type BlockProofHistoricalSummariesCapella struct {
|
||||
BeaconBlockProof [13]common.Hash // 416
|
||||
BeaconBlockRoot common.Hash // 32
|
||||
ExecutionBlockProof [11]common.Hash // 352
|
||||
Slot uint64 // 8 => 808 bytes
|
||||
}
|
||||
|
||||
// BlockProofHistoricalSummariesDeneb – Deneb historical_summaries branch.
|
||||
type BlockProofHistoricalSummariesDeneb struct {
|
||||
BeaconBlockProof [13]common.Hash // 416
|
||||
BeaconBlockRoot common.Hash // 32
|
||||
ExecutionBlockProof [12]common.Hash // 384
|
||||
Slot uint64 // 8 => 840 bytes
|
||||
}
|
||||
|
||||
type Proof interface {
|
||||
EncodeRLP(w io.Writer) error
|
||||
DecodeRlP(s *rlp.Stream) error
|
||||
Variant() variant
|
||||
}
|
||||
|
||||
type hhaAlias BlockProofHistoricalHashesAccumulator // alias ⇒ no EncodeRLP method
|
||||
|
||||
func (p *BlockProofHistoricalHashesAccumulator) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofHHA), hhaAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (p *BlockProofHistoricalHashesAccumulator) Variant() variant { return proofHHA }
|
||||
|
||||
type rootsAlias BlockProofHistoricalRoots
|
||||
|
||||
func (p *BlockProofHistoricalRoots) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofRoots), rootsAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (*BlockProofHistoricalRoots) Variant() variant { return proofRoots }
|
||||
|
||||
type capellaAlias BlockProofHistoricalSummariesCapella
|
||||
|
||||
func (p *BlockProofHistoricalSummariesCapella) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofCapella), capellaAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (*BlockProofHistoricalSummariesCapella) Variant() variant { return proofCapella }
|
||||
|
||||
type denebAlias BlockProofHistoricalSummariesDeneb
|
||||
|
||||
func (p *BlockProofHistoricalSummariesDeneb) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofDeneb), denebAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (*BlockProofHistoricalSummariesDeneb) Variant() variant { return proofDeneb }
|
||||
|
||||
func variantOf(p Proof) variant {
|
||||
if p == nil {
|
||||
return ProofNone
|
||||
}
|
||||
return p.Variant()
|
||||
}
|
||||
|
||||
type ReadAtSeekCloser interface {
|
||||
io.ReaderAt
|
||||
io.Seeker
|
||||
|
|
@ -135,19 +56,17 @@ type ReadAtSeekCloser interface {
|
|||
}
|
||||
|
||||
type Era struct {
|
||||
f ReadAtSeekCloser
|
||||
s *e2store.Reader
|
||||
m metadata // metadata for the Era file
|
||||
indstart int64
|
||||
rootheader uint64 // offset of the root header in the file if present
|
||||
f ReadAtSeekCloser
|
||||
s *e2store.Reader
|
||||
m metadata // metadata for the Era file
|
||||
}
|
||||
|
||||
// Returns a recognizable filename for erae file
|
||||
// Filename returns a recognizable filename for erae file
|
||||
func Filename(network string, epoch int, root common.Hash) string {
|
||||
return fmt.Sprintf("%s-%05d-%s.erae", network, epoch, root.Hex()[2:10])
|
||||
}
|
||||
|
||||
// Opens era file
|
||||
// Open opens the era file
|
||||
func Open(path string) (*Era, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
@ -161,7 +80,7 @@ func Open(path string) (*Era, error) {
|
|||
return e, nil
|
||||
}
|
||||
|
||||
// Closes era file
|
||||
// Close closes the era file
|
||||
func (e *Era) Close() error {
|
||||
if e.f == nil {
|
||||
return nil
|
||||
|
|
@ -171,17 +90,17 @@ func (e *Era) Close() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// retrieves starting block number
|
||||
// Start retrieves the starting block number
|
||||
func (e *Era) Start() uint64 {
|
||||
return e.m.start
|
||||
}
|
||||
|
||||
// retrieves count of blocks present
|
||||
// Count retrieves the count of blocks present
|
||||
func (e *Era) Count() uint64 {
|
||||
return e.m.count
|
||||
}
|
||||
|
||||
// retrieves the block if present within the era file
|
||||
// GetBlockByNumber retrieves the block if present within the era file
|
||||
func (e *Era) GetBlockByNumber(blockNum uint64) (*types.Block, error) {
|
||||
h, err := e.GetHeader(blockNum)
|
||||
if err != nil {
|
||||
|
|
@ -194,7 +113,7 @@ func (e *Era) GetBlockByNumber(blockNum uint64) (*types.Block, error) {
|
|||
return types.NewBlockWithHeader(h).WithBody(*b), nil
|
||||
}
|
||||
|
||||
// retrieves header from era file through the cached offset table
|
||||
// GetHeader retrieves the header from the era file through the cached offset table
|
||||
func (e *Era) GetHeader(num uint64) (*types.Header, error) {
|
||||
off, err := e.headerOff(num)
|
||||
if err != nil {
|
||||
|
|
@ -211,7 +130,7 @@ func (e *Era) GetHeader(num uint64) (*types.Header, error) {
|
|||
return &h, rlp.Decode(r, &h)
|
||||
}
|
||||
|
||||
// retrieves body from era file through cached offset table
|
||||
// GetBody retrieves the body from the era file through cached offset table
|
||||
func (e *Era) GetBody(num uint64) (*types.Body, error) {
|
||||
off, err := e.bodyOff(num)
|
||||
if err != nil {
|
||||
|
|
@ -228,7 +147,7 @@ func (e *Era) GetBody(num uint64) (*types.Body, error) {
|
|||
return &b, rlp.Decode(r, &b)
|
||||
}
|
||||
|
||||
// retrieves td from era file through cached offset table
|
||||
// getTD retrieves the td from the era file through cached offset table
|
||||
func (e *Era) getTD(blockNum uint64) (*big.Int, error) {
|
||||
off, err := e.tdOff(blockNum)
|
||||
if err != nil {
|
||||
|
|
@ -243,7 +162,7 @@ func (e *Era) getTD(blockNum uint64) (*big.Int, error) {
|
|||
return td, nil
|
||||
}
|
||||
|
||||
// retrieves the raw body frame in bytes of a specific block
|
||||
// GetRawBodyFrameByNumber retrieves the raw body frame in bytes of a specific block
|
||||
func (e *Era) GetRawBodyFrameByNumber(blockNum uint64) ([]byte, error) {
|
||||
off, err := e.bodyOff(blockNum)
|
||||
if err != nil {
|
||||
|
|
@ -256,9 +175,9 @@ func (e *Era) GetRawBodyFrameByNumber(blockNum uint64) ([]byte, error) {
|
|||
return io.ReadAll(r)
|
||||
}
|
||||
|
||||
// retrieves the raw receipts frame in bytes of a specific block
|
||||
// GetRawReceiptsFrameByNumber retrieves the raw receipts frame in bytes of a specific block.
|
||||
func (e *Era) GetRawReceiptsFrameByNumber(blockNum uint64) ([]byte, error) {
|
||||
off, err := e.rcptOff(blockNum)
|
||||
off, err := e.receiptOff(blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -269,7 +188,7 @@ func (e *Era) GetRawReceiptsFrameByNumber(blockNum uint64) ([]byte, error) {
|
|||
return io.ReadAll(r)
|
||||
}
|
||||
|
||||
// retrieves the raw proof frame in bytes of a specific block proof
|
||||
// GetRawProofFrameByNumber retrieves the raw proof frame in bytes of a specific block proof
|
||||
func (e *Era) GetRawProofFrameByNumber(blockNum uint64) ([]byte, error) {
|
||||
off, err := e.proofOff(blockNum)
|
||||
if err != nil {
|
||||
|
|
@ -282,7 +201,7 @@ func (e *Era) GetRawProofFrameByNumber(blockNum uint64) ([]byte, error) {
|
|||
return io.ReadAll(r)
|
||||
}
|
||||
|
||||
// loads in the index table containing all offsets and caches it
|
||||
// loadIndex loads in the index table containing all offsets and caches it
|
||||
func (e *Era) loadIndex() error {
|
||||
var err error
|
||||
e.m.length, err = e.f.Seek(0, io.SeekEnd)
|
||||
|
|
@ -299,65 +218,43 @@ func (e *Era) loadIndex() error {
|
|||
|
||||
payloadlen := 8 + 8*e.m.count*e.m.components + 16 // 8 for start block, 8 per property per block, 16 for the number of properties and the number of blocks
|
||||
tlvstart := e.m.length - int64(payloadlen) - 8
|
||||
e.indstart = tlvstart
|
||||
|
||||
_, err = e.f.ReadAt(b[:8], tlvstart+8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.m.start = binary.LittleEndian.Uint64(b[:8])
|
||||
num := int(e.m.components)
|
||||
|
||||
totaloffsets := num * int(e.m.count)
|
||||
offBytes := make([]byte, totaloffsets*8)
|
||||
offsetArea := tlvstart + 8 + 8 // 8 for the header size, 8 for the start number
|
||||
_, err = e.f.ReadAt(offBytes, offsetArea)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var off int64 = 0 // start at byte-0 of file
|
||||
|
||||
for off < e.indstart { // never enter the Block-Index TLV
|
||||
typ, length, err := e.s.ReadMetadataAt(off)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading TLV at offset %d: %w", off, err)
|
||||
}
|
||||
if typ == TypeAccumulatorRoot {
|
||||
e.rootheader = uint64(off) // remember absolute header offset
|
||||
break // found
|
||||
}
|
||||
off += 8 + int64(length) // headersize plus length to jump to next TLV header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Getter methods to calculate offset of a specific component in the file.
|
||||
func (e *Era) headerOff(num uint64) (uint64, error) { return e.indexOffset(num, compHeader) }
|
||||
func (e *Era) bodyOff(num uint64) (uint64, error) { return e.indexOffset(num, compBody) }
|
||||
func (e *Era) rcptOff(num uint64) (uint64, error) { return e.indexOffset(num, compReceipts) }
|
||||
func (e *Era) tdOff(num uint64) (uint64, error) { return e.indexOffset(num, compTD) }
|
||||
func (e *Era) proofOff(num uint64) (uint64, error) { return e.indexOffset(num, compProof) }
|
||||
func (e *Era) headerOff(num uint64) (uint64, error) { return e.indexOffset(num, componentHeader) }
|
||||
func (e *Era) bodyOff(num uint64) (uint64, error) { return e.indexOffset(num, componentBody) }
|
||||
func (e *Era) receiptOff(num uint64) (uint64, error) { return e.indexOffset(num, componentReceipts) }
|
||||
func (e *Era) tdOff(num uint64) (uint64, error) { return e.indexOffset(num, componentTD) }
|
||||
func (e *Era) proofOff(num uint64) (uint64, error) { return e.indexOffset(num, componentProof) }
|
||||
|
||||
// calculates offset to a certain component for a block number within a file.
|
||||
func (e *Era) indexOffset(n uint64, comp int) (uint64, error) {
|
||||
// indexOffset calculates offset to a certain component for a block number within a file.
|
||||
func (e *Era) indexOffset(n uint64, component componentType) (uint64, error) {
|
||||
if n < e.m.start || n >= e.m.start+e.m.count {
|
||||
return 0, fmt.Errorf("block %d out of range [%d,%d)", n, e.m.start, e.m.start+e.m.count)
|
||||
}
|
||||
if comp >= int(e.m.components) {
|
||||
return 0, fmt.Errorf("component %d not present", comp)
|
||||
if int(component) >= int(e.m.components) {
|
||||
return 0, fmt.Errorf("component %d not present", component)
|
||||
}
|
||||
|
||||
rec := (n-e.m.start)*e.m.components + uint64(comp)
|
||||
pos := e.indstart + 8 + 8 + int64(rec*8)
|
||||
payloadlen := 8 + 8*e.m.count*e.m.components + 16 // 8 for start block, 8 per property per block, 16 for the number of properties and the number of blocks
|
||||
indstart := e.m.length - int64(payloadlen) - 8
|
||||
|
||||
rec := (n-e.m.start)*e.m.components + uint64(component)
|
||||
pos := indstart + 8 + 8 + int64(rec*8)
|
||||
|
||||
var buf [8]byte
|
||||
if _, err := e.f.ReadAt(buf[:], pos); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rel := binary.LittleEndian.Uint64(buf[:])
|
||||
return uint64(int64(rel) + e.indstart), nil
|
||||
return uint64(int64(rel) + indstart), nil
|
||||
}
|
||||
|
||||
// GetHeaders returns RLP-decoded headers.
|
||||
|
|
@ -430,7 +327,7 @@ func (e *Era) GetReceipts(first, count uint64) ([]types.Receipts, error) {
|
|||
out := make([]types.Receipts, count)
|
||||
for i := uint64(0); i < count; i++ {
|
||||
n := first + i
|
||||
off, err := e.rcptOff(n)
|
||||
off, err := e.receiptOff(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
118
internal/era2/proof.go
Normal file
118
internal/era2/proof.go
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
// Copyright 2025 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
package era2
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
type variant uint16
|
||||
|
||||
const (
|
||||
proofNone variant = iota
|
||||
proofHistoricalHashesAccumulator
|
||||
proofHistoricalRoots
|
||||
proofCapella
|
||||
proofDeneb
|
||||
)
|
||||
|
||||
type BlockProofHistoricalHashesAccumulator [15]common.Hash // 15 * 32 = 480 bytes
|
||||
|
||||
// BlockProofHistoricalRoots – Altair / Bellatrix historical_roots branch.
|
||||
type BlockProofHistoricalRoots struct {
|
||||
BeaconBlockProof [14]common.Hash // 448
|
||||
BeaconBlockRoot common.Hash // 32
|
||||
ExecutionBlockProof [11]common.Hash // 352
|
||||
Slot uint64 // 8 => 840 bytes
|
||||
}
|
||||
|
||||
// BlockProofHistoricalSummariesCapella – Capella historical_summaries branch.
|
||||
type BlockProofHistoricalSummariesCapella struct {
|
||||
BeaconBlockProof [13]common.Hash // 416
|
||||
BeaconBlockRoot common.Hash // 32
|
||||
ExecutionBlockProof [11]common.Hash // 352
|
||||
Slot uint64 // 8 => 808 bytes
|
||||
}
|
||||
|
||||
// BlockProofHistoricalSummariesDeneb – Deneb historical_summaries branch.
|
||||
type BlockProofHistoricalSummariesDeneb struct {
|
||||
BeaconBlockProof [13]common.Hash // 416
|
||||
BeaconBlockRoot common.Hash // 32
|
||||
ExecutionBlockProof [12]common.Hash // 384
|
||||
Slot uint64 // 8 => 840 bytes
|
||||
}
|
||||
|
||||
type NoProof struct{}
|
||||
|
||||
type Proof interface {
|
||||
EncodeRLP(w io.Writer) error
|
||||
DecodeRlP(s *rlp.Stream) error
|
||||
Variant() variant
|
||||
}
|
||||
|
||||
type hhaAlias BlockProofHistoricalHashesAccumulator // alias ⇒ no EncodeRLP method
|
||||
|
||||
func (p *BlockProofHistoricalHashesAccumulator) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofHistoricalHashesAccumulator), hhaAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (p *BlockProofHistoricalHashesAccumulator) Variant() variant {
|
||||
return proofHistoricalHashesAccumulator
|
||||
}
|
||||
|
||||
type rootsAlias BlockProofHistoricalRoots
|
||||
|
||||
func (p *BlockProofHistoricalRoots) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofHistoricalRoots), rootsAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (*BlockProofHistoricalRoots) Variant() variant { return proofHistoricalRoots }
|
||||
|
||||
type capellaAlias BlockProofHistoricalSummariesCapella
|
||||
|
||||
func (p *BlockProofHistoricalSummariesCapella) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofCapella), capellaAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (*BlockProofHistoricalSummariesCapella) Variant() variant { return proofCapella }
|
||||
|
||||
type denebAlias BlockProofHistoricalSummariesDeneb
|
||||
|
||||
func (p *BlockProofHistoricalSummariesDeneb) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofDeneb), denebAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
type NoProofAlias NoProof // alias ⇒ no EncodeRLP method
|
||||
|
||||
func (p *NoProof) EncodeRLP(w io.Writer) error {
|
||||
payload := []interface{}{uint16(proofNone), NoProofAlias(*p)}
|
||||
return rlp.Encode(w, payload)
|
||||
}
|
||||
|
||||
func (*NoProof) Variant() variant { return proofNone }
|
||||
|
||||
func (*BlockProofHistoricalSummariesDeneb) Variant() variant { return proofDeneb }
|
||||
|
||||
func variantOf(p Proof) variant {
|
||||
return p.Variant()
|
||||
}
|
||||
Loading…
Reference in a new issue