github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/light/odr_util.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:39</date> 10 //</624450096611725312> 11 12 13 package light 14 15 import ( 16 "bytes" 17 "context" 18 19 "github.com/ethereum/go-ethereum/common" 20 "github.com/ethereum/go-ethereum/core" 21 "github.com/ethereum/go-ethereum/core/rawdb" 22 "github.com/ethereum/go-ethereum/core/types" 23 "github.com/ethereum/go-ethereum/crypto" 24 "github.com/ethereum/go-ethereum/rlp" 25 ) 26 27 var sha3_nil = crypto.Keccak256Hash(nil) 28 29 func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*types.Header, error) { 30 db := odr.Database() 31 hash := rawdb.ReadCanonicalHash(db, number) 32 if (hash != common.Hash{}) { 33 //如果有一个规范散列,也有一个头 34 header := rawdb.ReadHeader(db, hash, number) 35 if header == nil { 36 panic("Canonical hash present but header not found") 37 } 38 return header, nil 39 } 40 41 var ( 42 chtCount, sectionHeadNum uint64 43 sectionHead common.Hash 44 ) 45 if odr.ChtIndexer() != nil { 46 chtCount, sectionHeadNum, sectionHead = odr.ChtIndexer().Sections() 47 canonicalHash := rawdb.ReadCanonicalHash(db, sectionHeadNum) 48 //如果将cht作为可信检查点注入,那么我们还没有规范散列,因此我们也接受零散列。 49 for chtCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) { 50 chtCount-- 51 if chtCount > 0 { 52 sectionHeadNum = chtCount*odr.IndexerConfig().ChtSize - 1 53 sectionHead = odr.ChtIndexer().SectionHead(chtCount - 1) 54 canonicalHash = rawdb.ReadCanonicalHash(db, sectionHeadNum) 55 } 56 } 57 } 58 if number >= chtCount*odr.IndexerConfig().ChtSize { 59 return nil, ErrNoTrustedCht 60 } 61 r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: number, Config: odr.IndexerConfig()} 62 if err := odr.Retrieve(ctx, r); err != nil { 63 return nil, err 64 } 65 return r.Header, nil 66 } 67 68 func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) { 69 hash := rawdb.ReadCanonicalHash(odr.Database(), number) 70 if (hash != common.Hash{}) { 71 return hash, nil 72 } 73 header, err := GetHeaderByNumber(ctx, odr, number) 74 if header != nil { 75 return header.Hash(), nil 76 } 77 return common.Hash{}, err 78 } 79 80 //getBodyrlp在rlp编码中检索块体(事务和uncles)。 81 func GetBodyRLP(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (rlp.RawValue, error) { 82 if data := rawdb.ReadBodyRLP(odr.Database(), hash, number); data != nil { 83 return data, nil 84 } 85 r := &BlockRequest{Hash: hash, Number: number} 86 if err := odr.Retrieve(ctx, r); err != nil { 87 return nil, err 88 } else { 89 return r.Rlp, nil 90 } 91 } 92 93 //getBody检索与 94 //搞砸。 95 func GetBody(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Body, error) { 96 data, err := GetBodyRLP(ctx, odr, hash, number) 97 if err != nil { 98 return nil, err 99 } 100 body := new(types.Body) 101 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 102 return nil, err 103 } 104 return body, nil 105 } 106 107 //GetBlock检索与哈希对应的整个块,并对其进行组装 108 //从存储的标题和正文返回。 109 func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Block, error) { 110 //检索块标题和正文内容 111 header := rawdb.ReadHeader(odr.Database(), hash, number) 112 if header == nil { 113 return nil, ErrNoHeader 114 } 115 body, err := GetBody(ctx, odr, hash, number) 116 if err != nil { 117 return nil, err 118 } 119 //重新组装阀块并返回 120 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles), nil 121 } 122 123 //GetBlockReceipts检索由包含的事务生成的收据 124 //在由散列给出的块中。 125 func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (types.Receipts, error) { 126 //从磁盘或网络检索可能不完整的收据 127 receipts := rawdb.ReadReceipts(odr.Database(), hash, number) 128 if receipts == nil { 129 r := &ReceiptsRequest{Hash: hash, Number: number} 130 if err := odr.Retrieve(ctx, r); err != nil { 131 return nil, err 132 } 133 receipts = r.Receipts 134 } 135 //如果收据不完整,请填写派生字段 136 if len(receipts) > 0 && receipts[0].TxHash == (common.Hash{}) { 137 block, err := GetBlock(ctx, odr, hash, number) 138 if err != nil { 139 return nil, err 140 } 141 genesis := rawdb.ReadCanonicalHash(odr.Database(), 0) 142 config := rawdb.ReadChainConfig(odr.Database(), genesis) 143 144 if err := core.SetReceiptsData(config, block, receipts); err != nil { 145 return nil, err 146 } 147 rawdb.WriteReceipts(odr.Database(), hash, number, receipts) 148 } 149 return receipts, nil 150 } 151 152 //GetBlockLogs检索包含在 153 //由散列给出的块。 154 func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) ([][]*types.Log, error) { 155 //从磁盘或网络检索可能不完整的收据 156 receipts := rawdb.ReadReceipts(odr.Database(), hash, number) 157 if receipts == nil { 158 r := &ReceiptsRequest{Hash: hash, Number: number} 159 if err := odr.Retrieve(ctx, r); err != nil { 160 return nil, err 161 } 162 receipts = r.Receipts 163 } 164 //返回日志,而不导出收据上的任何计算字段 165 logs := make([][]*types.Log, len(receipts)) 166 for i, receipt := range receipts { 167 logs[i] = receipt.Logs 168 } 169 return logs, nil 170 } 171 172 //GetBloomBits检索属于给定位索引和节索引的一批压缩BloomBits向量 173 func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxList []uint64) ([][]byte, error) { 174 var ( 175 db = odr.Database() 176 result = make([][]byte, len(sectionIdxList)) 177 reqList []uint64 178 reqIdx []int 179 ) 180 181 var ( 182 bloomTrieCount, sectionHeadNum uint64 183 sectionHead common.Hash 184 ) 185 if odr.BloomTrieIndexer() != nil { 186 bloomTrieCount, sectionHeadNum, sectionHead = odr.BloomTrieIndexer().Sections() 187 canonicalHash := rawdb.ReadCanonicalHash(db, sectionHeadNum) 188 //如果将Bloomtrie作为受信任的检查点注入,那么我们还没有规范的哈希,因此我们也接受零哈希。 189 for bloomTrieCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) { 190 bloomTrieCount-- 191 if bloomTrieCount > 0 { 192 sectionHeadNum = bloomTrieCount*odr.IndexerConfig().BloomTrieSize - 1 193 sectionHead = odr.BloomTrieIndexer().SectionHead(bloomTrieCount - 1) 194 canonicalHash = rawdb.ReadCanonicalHash(db, sectionHeadNum) 195 } 196 } 197 } 198 199 for i, sectionIdx := range sectionIdxList { 200 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*odr.IndexerConfig().BloomSize-1) 201 //如果没有为该节头编号存储规范散列,我们仍将查找 202 //一个零分区头的条目(如果我们不知道,我们也用零分区头存储它 203 //在检索时) 204 bloomBits, err := rawdb.ReadBloomBits(db, bitIdx, sectionIdx, sectionHead) 205 if err == nil { 206 result[i] = bloomBits 207 } else { 208 //todo(rjl493456442)将sectionindex转换为bloomtrie相对索引 209 if sectionIdx >= bloomTrieCount { 210 return nil, ErrNoTrustedBloomTrie 211 } 212 reqList = append(reqList, sectionIdx) 213 reqIdx = append(reqIdx, i) 214 } 215 } 216 if reqList == nil { 217 return result, nil 218 } 219 220 r := &BloomRequest{BloomTrieRoot: GetBloomTrieRoot(db, bloomTrieCount-1, sectionHead), BloomTrieNum: bloomTrieCount - 1, 221 BitIdx: bitIdx, SectionIndexList: reqList, Config: odr.IndexerConfig()} 222 if err := odr.Retrieve(ctx, r); err != nil { 223 return nil, err 224 } else { 225 for i, idx := range reqIdx { 226 result[idx] = r.BloomBits[i] 227 } 228 return result, nil 229 } 230 } 231