github.hscsec.cn/juliankolbe/go-ethereum@v1.9.7/core/bloombits/generator.go (about) 1 // Copyright 2017 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 bloombits 18 19 import ( 20 "errors" 21 22 "github.com/ethereum/go-ethereum/core/types" 23 ) 24 25 var ( 26 // errSectionOutOfBounds is returned if the user tried to add more bloom filters 27 // to the batch than available space, or if tries to retrieve above the capacity. 28 errSectionOutOfBounds = errors.New("section out of bounds") 29 30 // errBloomBitOutOfBounds is returned if the user tried to retrieve specified 31 // bit bloom above the capacity. 32 errBloomBitOutOfBounds = errors.New("bloom bit out of bounds") 33 ) 34 35 // Generator takes a number of bloom filters and generates the rotated bloom bits 36 // to be used for batched filtering. 37 type Generator struct { 38 blooms [types.BloomBitLength][]byte // Rotated blooms for per-bit matching 39 sections uint // Number of sections to batch together 40 nextSec uint // Next section to set when adding a bloom 41 } 42 43 // NewGenerator creates a rotated bloom generator that can iteratively fill a 44 // batched bloom filter's bits. 45 func NewGenerator(sections uint) (*Generator, error) { 46 if sections%8 != 0 { 47 return nil, errors.New("section count not multiple of 8") 48 } 49 b := &Generator{sections: sections} 50 for i := 0; i < types.BloomBitLength; i++ { 51 b.blooms[i] = make([]byte, sections/8) 52 } 53 return b, nil 54 } 55 56 // AddBloom takes a single bloom filter and sets the corresponding bit column 57 // in memory accordingly. 58 func (b *Generator) AddBloom(index uint, bloom types.Bloom) error { 59 // Make sure we're not adding more bloom filters than our capacity 60 if b.nextSec >= b.sections { 61 return errSectionOutOfBounds 62 } 63 if b.nextSec != index { 64 return errors.New("bloom filter with unexpected index") 65 } 66 // Rotate the bloom and insert into our collection 67 byteIndex := b.nextSec / 8 68 bitMask := byte(1) << byte(7-b.nextSec%8) 69 70 for i := 0; i < types.BloomBitLength; i++ { 71 bloomByteIndex := types.BloomByteLength - 1 - i/8 72 bloomBitMask := byte(1) << byte(i%8) 73 74 if (bloom[bloomByteIndex] & bloomBitMask) != 0 { 75 b.blooms[i][byteIndex] |= bitMask 76 } 77 } 78 b.nextSec++ 79 80 return nil 81 } 82 83 // Bitset returns the bit vector belonging to the given bit index after all 84 // blooms have been added. 85 func (b *Generator) Bitset(idx uint) ([]byte, error) { 86 if b.nextSec != b.sections { 87 return nil, errors.New("bloom not fully generated yet") 88 } 89 if idx >= types.BloomBitLength { 90 return nil, errBloomBitOutOfBounds 91 } 92 return b.blooms[idx], nil 93 }