github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/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/tirogen/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 bitIndex := byte(7 - b.nextSec%8) 69 for byt := 0; byt < types.BloomByteLength; byt++ { 70 bloomByte := bloom[types.BloomByteLength-1-byt] 71 if bloomByte == 0 { 72 continue 73 } 74 base := 8 * byt 75 b.blooms[base+7][byteIndex] |= ((bloomByte >> 7) & 1) << bitIndex 76 b.blooms[base+6][byteIndex] |= ((bloomByte >> 6) & 1) << bitIndex 77 b.blooms[base+5][byteIndex] |= ((bloomByte >> 5) & 1) << bitIndex 78 b.blooms[base+4][byteIndex] |= ((bloomByte >> 4) & 1) << bitIndex 79 b.blooms[base+3][byteIndex] |= ((bloomByte >> 3) & 1) << bitIndex 80 b.blooms[base+2][byteIndex] |= ((bloomByte >> 2) & 1) << bitIndex 81 b.blooms[base+1][byteIndex] |= ((bloomByte >> 1) & 1) << bitIndex 82 b.blooms[base][byteIndex] |= (bloomByte & 1) << bitIndex 83 } 84 b.nextSec++ 85 return nil 86 } 87 88 // Bitset returns the bit vector belonging to the given bit index after all 89 // blooms have been added. 90 func (b *Generator) Bitset(idx uint) ([]byte, error) { 91 if b.nextSec != b.sections { 92 return nil, errors.New("bloom not fully generated yet") 93 } 94 if idx >= types.BloomBitLength { 95 return nil, errBloomBitOutOfBounds 96 } 97 return b.blooms[idx], nil 98 }