github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/internal/era/iterator.go (about)

     1  // Copyright 2023 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package era
    18  
    19  import (
    20  	"errors"
    21  	"io"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/rlp"
    26  )
    27  
    28  // Iterator wraps RawIterator and returns decoded Era1 entries.
    29  type Iterator struct {
    30  	inner *RawIterator
    31  }
    32  
    33  // NewIterator returns a new Iterator instance. Next must be immediately
    34  // called on new iterators to load the first item.
    35  func NewIterator(e *Era) (*Iterator, error) {
    36  	inner, err := NewRawIterator(e)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	return &Iterator{inner}, nil
    41  }
    42  
    43  // Next moves the iterator to the next block entry. It returns false when all
    44  // items have been read or an error has halted its progress. Block, Receipts,
    45  // and BlockAndReceipts should no longer be called after false is returned.
    46  func (it *Iterator) Next() bool {
    47  	return it.inner.Next()
    48  }
    49  
    50  // Number returns the current number block the iterator will return.
    51  func (it *Iterator) Number() uint64 {
    52  	return it.inner.next - 1
    53  }
    54  
    55  // Error returns the error status of the iterator. It should be called before
    56  // reading from any of the iterator's values.
    57  func (it *Iterator) Error() error {
    58  	return it.inner.Error()
    59  }
    60  
    61  // Block returns the block for the iterator's current position.
    62  func (it *Iterator) Block() (*types.Block, error) {
    63  	if it.inner.Header == nil || it.inner.Body == nil {
    64  		return nil, errors.New("header and body must be non-nil")
    65  	}
    66  	var (
    67  		header types.Header
    68  		body   types.Body
    69  	)
    70  	if err := rlp.Decode(it.inner.Header, &header); err != nil {
    71  		return nil, err
    72  	}
    73  	if err := rlp.Decode(it.inner.Body, &body); err != nil {
    74  		return nil, err
    75  	}
    76  	return types.NewBlockWithHeader(&header).WithBody(body), nil
    77  }
    78  
    79  // Receipts returns the receipts for the iterator's current position.
    80  func (it *Iterator) Receipts() (types.Receipts, error) {
    81  	if it.inner.Receipts == nil {
    82  		return nil, errors.New("receipts must be non-nil")
    83  	}
    84  	var receipts types.Receipts
    85  	err := rlp.Decode(it.inner.Receipts, &receipts)
    86  	return receipts, err
    87  }
    88  
    89  // BlockAndReceipts returns the block and receipts for the iterator's current
    90  // position.
    91  func (it *Iterator) BlockAndReceipts() (*types.Block, types.Receipts, error) {
    92  	b, err := it.Block()
    93  	if err != nil {
    94  		return nil, nil, err
    95  	}
    96  	r, err := it.Receipts()
    97  	if err != nil {
    98  		return nil, nil, err
    99  	}
   100  	return b, r, nil
   101  }
   102  
   103  // TotalDifficulty returns the total difficulty for the iterator's current
   104  // position.
   105  func (it *Iterator) TotalDifficulty() (*big.Int, error) {
   106  	td, err := io.ReadAll(it.inner.TotalDifficulty)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return new(big.Int).SetBytes(reverseOrder(td)), nil
   111  }
   112  
   113  // RawIterator reads an RLP-encode Era1 entries.
   114  type RawIterator struct {
   115  	e    *Era   // backing Era1
   116  	next uint64 // next block to read
   117  	err  error  // last error
   118  
   119  	Header          io.Reader
   120  	Body            io.Reader
   121  	Receipts        io.Reader
   122  	TotalDifficulty io.Reader
   123  }
   124  
   125  // NewRawIterator returns a new RawIterator instance. Next must be immediately
   126  // called on new iterators to load the first item.
   127  func NewRawIterator(e *Era) (*RawIterator, error) {
   128  	return &RawIterator{
   129  		e:    e,
   130  		next: e.m.start,
   131  	}, nil
   132  }
   133  
   134  // Next moves the iterator to the next block entry. It returns false when all
   135  // items have been read or an error has halted its progress. Header, Body,
   136  // Receipts, TotalDifficulty will be set to nil in the case returning false or
   137  // finding an error and should therefore no longer be read from.
   138  func (it *RawIterator) Next() bool {
   139  	// Clear old errors.
   140  	it.err = nil
   141  	if it.e.m.start+it.e.m.count <= it.next {
   142  		it.clear()
   143  		return false
   144  	}
   145  	off, err := it.e.readOffset(it.next)
   146  	if err != nil {
   147  		// Error here means block index is corrupted, so don't
   148  		// continue.
   149  		it.clear()
   150  		it.err = err
   151  		return false
   152  	}
   153  	var n int64
   154  	if it.Header, n, it.err = newSnappyReader(it.e.s, TypeCompressedHeader, off); it.err != nil {
   155  		it.clear()
   156  		return true
   157  	}
   158  	off += n
   159  	if it.Body, n, it.err = newSnappyReader(it.e.s, TypeCompressedBody, off); it.err != nil {
   160  		it.clear()
   161  		return true
   162  	}
   163  	off += n
   164  	if it.Receipts, n, it.err = newSnappyReader(it.e.s, TypeCompressedReceipts, off); it.err != nil {
   165  		it.clear()
   166  		return true
   167  	}
   168  	off += n
   169  	if it.TotalDifficulty, _, it.err = it.e.s.ReaderAt(TypeTotalDifficulty, off); it.err != nil {
   170  		it.clear()
   171  		return true
   172  	}
   173  	it.next += 1
   174  	return true
   175  }
   176  
   177  // Number returns the current number block the iterator will return.
   178  func (it *RawIterator) Number() uint64 {
   179  	return it.next - 1
   180  }
   181  
   182  // Error returns the error status of the iterator. It should be called before
   183  // reading from any of the iterator's values.
   184  func (it *RawIterator) Error() error {
   185  	if it.err == io.EOF {
   186  		return nil
   187  	}
   188  	return it.err
   189  }
   190  
   191  // clear sets all the outputs to nil.
   192  func (it *RawIterator) clear() {
   193  	it.Header = nil
   194  	it.Body = nil
   195  	it.Receipts = nil
   196  	it.TotalDifficulty = nil
   197  }