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