github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/bloombits.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 12:09:38</date> 10 //</624342633254227968> 11 12 13 package eth 14 15 import ( 16 "context" 17 "time" 18 19 "github.com/ethereum/go-ethereum/common" 20 "github.com/ethereum/go-ethereum/common/bitutil" 21 "github.com/ethereum/go-ethereum/core" 22 "github.com/ethereum/go-ethereum/core/bloombits" 23 "github.com/ethereum/go-ethereum/core/rawdb" 24 "github.com/ethereum/go-ethereum/core/types" 25 "github.com/ethereum/go-ethereum/ethdb" 26 "github.com/ethereum/go-ethereum/params" 27 ) 28 29 const ( 30 //BloomServiceThreads是以太坊全局使用的Goroutine数。 31 //实例到服务BloomBits查找所有正在运行的筛选器。 32 bloomServiceThreads = 16 33 34 //BloomFilterThreads是每个筛选器本地使用的goroutine数,用于 35 //将请求多路传输到全局服务goroutine。 36 bloomFilterThreads = 3 37 38 //BloomRetrievalBatch是要服务的最大Bloom位检索数。 39 //一批。 40 bloomRetrievalBatch = 16 41 42 //BloomRetrievalWait是等待足够的Bloom位请求的最长时间。 43 //累积请求整个批(避免滞后)。 44 bloomRetrievalWait = time.Duration(0) 45 ) 46 47 //StartBloomHandlers启动一批Goroutine以接受BloomBit数据库 48 //从可能的一系列过滤器中检索并为数据提供满足条件的服务。 49 func (eth *Ethereum) startBloomHandlers() { 50 for i := 0; i < bloomServiceThreads; i++ { 51 go func() { 52 for { 53 select { 54 case <-eth.shutdownChan: 55 return 56 57 case request := <-eth.bloomRequests: 58 task := <-request 59 task.Bitsets = make([][]byte, len(task.Sections)) 60 for i, section := range task.Sections { 61 head := rawdb.ReadCanonicalHash(eth.chainDb, (section+1)*params.BloomBitsBlocks-1) 62 if compVector, err := rawdb.ReadBloomBits(eth.chainDb, task.Bit, section, head); err == nil { 63 if blob, err := bitutil.DecompressBytes(compVector, int(params.BloomBitsBlocks)/8); err == nil { 64 task.Bitsets[i] = blob 65 } else { 66 task.Error = err 67 } 68 } else { 69 task.Error = err 70 } 71 } 72 request <- task 73 } 74 } 75 }() 76 } 77 } 78 79 const ( 80 //BloomConfirms是在Bloom部分 81 //considered probably final and its rotated bits are calculated. 82 bloomConfirms = 256 83 84 //BloomThrottling是处理两个连续索引之间的等待时间。 85 //部分。它在链升级期间很有用,可以防止磁盘过载。 86 bloomThrottling = 100 * time.Millisecond 87 ) 88 89 //BloomIndexer实现core.chainIndexer,建立旋转的BloomBits索引 90 //对于以太坊头段Bloom过滤器,允许快速过滤。 91 type BloomIndexer struct { 92 size uint64 //要为其生成bloombits的节大小 93 db ethdb.Database //要将索引数据和元数据写入的数据库实例 94 gen *bloombits.Generator //发电机旋转盛开钻头,装入盛开指数 95 section uint64 //节是当前正在处理的节号 96 head common.Hash //head是最后处理的头的哈希值 97 } 98 99 //newbloomindexer返回一个链索引器,它为 100 //用于快速日志筛选的规范链。 101 func NewBloomIndexer(db ethdb.Database, size, confReq uint64) *core.ChainIndexer { 102 backend := &BloomIndexer{ 103 db: db, 104 size: size, 105 } 106 table := ethdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix)) 107 108 return core.NewChainIndexer(db, table, backend, size, confReq, bloomThrottling, "bloombits") 109 } 110 111 //reset实现core.chainindexerbackend,启动新的bloombits索引 112 //部分。 113 func (b *BloomIndexer) Reset(ctx context.Context, section uint64, lastSectionHead common.Hash) error { 114 gen, err := bloombits.NewGenerator(uint(b.size)) 115 b.gen, b.section, b.head = gen, section, common.Hash{} 116 return err 117 } 118 119 //进程实现了core.chainindexerbackend,将新头的bloom添加到 120 //索引。 121 func (b *BloomIndexer) Process(ctx context.Context, header *types.Header) error { 122 b.gen.AddBloom(uint(header.Number.Uint64()-b.section*b.size), header.Bloom) 123 b.head = header.Hash() 124 return nil 125 } 126 127 //commit实现core.chainindexerbackend,完成bloom部分和 128 //把它写进数据库。 129 func (b *BloomIndexer) Commit() error { 130 batch := b.db.NewBatch() 131 for i := 0; i < types.BloomBitLength; i++ { 132 bits, err := b.gen.Bitset(uint(i)) 133 if err != nil { 134 return err 135 } 136 rawdb.WriteBloomBits(batch, uint(i), b.section, b.head, bitutil.CompressBytes(bits)) 137 } 138 return batch.Write() 139 } 140