github.com/luckypickle/go-ethereum-vet@v1.14.2/light/odr_util.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser 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 // The go-ethereum library 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 Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package light 18 19 import ( 20 "bytes" 21 "context" 22 23 "github.com/luckypickle/go-ethereum-vet/common" 24 "github.com/luckypickle/go-ethereum-vet/core" 25 "github.com/luckypickle/go-ethereum-vet/core/rawdb" 26 "github.com/luckypickle/go-ethereum-vet/core/types" 27 "github.com/luckypickle/go-ethereum-vet/crypto" 28 "github.com/luckypickle/go-ethereum-vet/rlp" 29 ) 30 31 var sha3_nil = crypto.Keccak256Hash(nil) 32 33 func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*types.Header, error) { 34 db := odr.Database() 35 hash := rawdb.ReadCanonicalHash(db, number) 36 if (hash != common.Hash{}) { 37 // if there is a canonical hash, there is a header too 38 header := rawdb.ReadHeader(db, hash, number) 39 if header == nil { 40 panic("Canonical hash present but header not found") 41 } 42 return header, nil 43 } 44 45 var ( 46 chtCount, sectionHeadNum uint64 47 sectionHead common.Hash 48 ) 49 if odr.ChtIndexer() != nil { 50 chtCount, sectionHeadNum, sectionHead = odr.ChtIndexer().Sections() 51 canonicalHash := rawdb.ReadCanonicalHash(db, sectionHeadNum) 52 // if the CHT was injected as a trusted checkpoint, we have no canonical hash yet so we accept zero hash too 53 for chtCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) { 54 chtCount-- 55 if chtCount > 0 { 56 sectionHeadNum = chtCount*CHTFrequencyClient - 1 57 sectionHead = odr.ChtIndexer().SectionHead(chtCount - 1) 58 canonicalHash = rawdb.ReadCanonicalHash(db, sectionHeadNum) 59 } 60 } 61 } 62 if number >= chtCount*CHTFrequencyClient { 63 return nil, ErrNoTrustedCht 64 } 65 r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: number} 66 if err := odr.Retrieve(ctx, r); err != nil { 67 return nil, err 68 } 69 return r.Header, nil 70 } 71 72 func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) { 73 hash := rawdb.ReadCanonicalHash(odr.Database(), number) 74 if (hash != common.Hash{}) { 75 return hash, nil 76 } 77 header, err := GetHeaderByNumber(ctx, odr, number) 78 if header != nil { 79 return header.Hash(), nil 80 } 81 return common.Hash{}, err 82 } 83 84 // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 85 func GetBodyRLP(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (rlp.RawValue, error) { 86 if data := rawdb.ReadBodyRLP(odr.Database(), hash, number); data != nil { 87 return data, nil 88 } 89 r := &BlockRequest{Hash: hash, Number: number} 90 if err := odr.Retrieve(ctx, r); err != nil { 91 return nil, err 92 } else { 93 return r.Rlp, nil 94 } 95 } 96 97 // GetBody retrieves the block body (transactons, uncles) corresponding to the 98 // hash. 99 func GetBody(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Body, error) { 100 data, err := GetBodyRLP(ctx, odr, hash, number) 101 if err != nil { 102 return nil, err 103 } 104 body := new(types.Body) 105 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 106 return nil, err 107 } 108 return body, nil 109 } 110 111 // GetBlock retrieves an entire block corresponding to the hash, assembling it 112 // back from the stored header and body. 113 func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Block, error) { 114 // Retrieve the block header and body contents 115 header := rawdb.ReadHeader(odr.Database(), hash, number) 116 if header == nil { 117 return nil, ErrNoHeader 118 } 119 body, err := GetBody(ctx, odr, hash, number) 120 if err != nil { 121 return nil, err 122 } 123 // Reassemble the block and return 124 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles), nil 125 } 126 127 // GetBlockReceipts retrieves the receipts generated by the transactions included 128 // in a block given by its hash. 129 func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (types.Receipts, error) { 130 // Retrieve the potentially incomplete receipts from disk or network 131 receipts := rawdb.ReadReceipts(odr.Database(), hash, number) 132 if receipts == nil { 133 r := &ReceiptsRequest{Hash: hash, Number: number} 134 if err := odr.Retrieve(ctx, r); err != nil { 135 return nil, err 136 } 137 receipts = r.Receipts 138 } 139 // If the receipts are incomplete, fill the derived fields 140 if len(receipts) > 0 && receipts[0].TxHash == (common.Hash{}) { 141 block, err := GetBlock(ctx, odr, hash, number) 142 if err != nil { 143 return nil, err 144 } 145 genesis := rawdb.ReadCanonicalHash(odr.Database(), 0) 146 config := rawdb.ReadChainConfig(odr.Database(), genesis) 147 148 if err := core.SetReceiptsData(config, block, receipts); err != nil { 149 return nil, err 150 } 151 rawdb.WriteReceipts(odr.Database(), hash, number, receipts) 152 } 153 return receipts, nil 154 } 155 156 // GetBlockLogs retrieves the logs generated by the transactions included in a 157 // block given by its hash. 158 func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) ([][]*types.Log, error) { 159 // Retrieve the potentially incomplete receipts from disk or network 160 receipts := rawdb.ReadReceipts(odr.Database(), hash, number) 161 if receipts == nil { 162 r := &ReceiptsRequest{Hash: hash, Number: number} 163 if err := odr.Retrieve(ctx, r); err != nil { 164 return nil, err 165 } 166 receipts = r.Receipts 167 } 168 // Return the logs without deriving any computed fields on the receipts 169 logs := make([][]*types.Log, len(receipts)) 170 for i, receipt := range receipts { 171 logs[i] = receipt.Logs 172 } 173 return logs, nil 174 } 175 176 // GetBloomBits retrieves a batch of compressed bloomBits vectors belonging to the given bit index and section indexes 177 func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxList []uint64) ([][]byte, error) { 178 db := odr.Database() 179 result := make([][]byte, len(sectionIdxList)) 180 var ( 181 reqList []uint64 182 reqIdx []int 183 ) 184 185 var ( 186 bloomTrieCount, sectionHeadNum uint64 187 sectionHead common.Hash 188 ) 189 if odr.BloomTrieIndexer() != nil { 190 bloomTrieCount, sectionHeadNum, sectionHead = odr.BloomTrieIndexer().Sections() 191 canonicalHash := rawdb.ReadCanonicalHash(db, sectionHeadNum) 192 // if the BloomTrie was injected as a trusted checkpoint, we have no canonical hash yet so we accept zero hash too 193 for bloomTrieCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) { 194 bloomTrieCount-- 195 if bloomTrieCount > 0 { 196 sectionHeadNum = bloomTrieCount*BloomTrieFrequency - 1 197 sectionHead = odr.BloomTrieIndexer().SectionHead(bloomTrieCount - 1) 198 canonicalHash = rawdb.ReadCanonicalHash(db, sectionHeadNum) 199 } 200 } 201 } 202 203 for i, sectionIdx := range sectionIdxList { 204 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*BloomTrieFrequency-1) 205 // if we don't have the canonical hash stored for this section head number, we'll still look for 206 // an entry with a zero sectionHead (we store it with zero section head too if we don't know it 207 // at the time of the retrieval) 208 bloomBits, err := rawdb.ReadBloomBits(db, bitIdx, sectionIdx, sectionHead) 209 if err == nil { 210 result[i] = bloomBits 211 } else { 212 if sectionIdx >= bloomTrieCount { 213 return nil, ErrNoTrustedBloomTrie 214 } 215 reqList = append(reqList, sectionIdx) 216 reqIdx = append(reqIdx, i) 217 } 218 } 219 if reqList == nil { 220 return result, nil 221 } 222 223 r := &BloomRequest{BloomTrieRoot: GetBloomTrieRoot(db, bloomTrieCount-1, sectionHead), BloomTrieNum: bloomTrieCount - 1, BitIdx: bitIdx, SectionIdxList: reqList} 224 if err := odr.Retrieve(ctx, r); err != nil { 225 return nil, err 226 } else { 227 for i, idx := range reqIdx { 228 result[idx] = r.BloomBits[i] 229 } 230 return result, nil 231 } 232 }