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 }