github.com/klaytn/klaytn@v1.12.1/blockchain/bloombits/generator.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2017 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/bloombits/generator.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package bloombits 22 23 import ( 24 "errors" 25 26 "github.com/klaytn/klaytn/blockchain/types" 27 ) 28 29 var ( 30 // errSectionOutOfBounds is returned if the user tried to add more bloom filters 31 // to the batch than available space, or if tries to retrieve above the capacity. 32 errSectionOutOfBounds = errors.New("section out of bounds") 33 34 // errBloomBitOutOfBounds is returned if the user tried to retrieve specified 35 // bit bloom above the capacity. 36 errBloomBitOutOfBounds = errors.New("bloom bit out of bounds") 37 ) 38 39 // Generator takes a number of bloom filters and generates the rotated bloom bits 40 // to be used for batched filtering. 41 type Generator struct { 42 blooms [types.BloomBitLength][]byte // Rotated blooms for per-bit matching 43 sections uint // Number of sections to batch together 44 nextSec uint // Next section to set when adding a bloom 45 } 46 47 // NewGenerator creates a rotated bloom generator that can iteratively fill a 48 // batched bloom filter's bits. 49 func NewGenerator(sections uint) (*Generator, error) { 50 if sections%8 != 0 { 51 return nil, errors.New("section count not multiple of 8") 52 } 53 b := &Generator{sections: sections} 54 for i := 0; i < types.BloomBitLength; i++ { 55 b.blooms[i] = make([]byte, sections/8) 56 } 57 return b, nil 58 } 59 60 // AddBloom takes a single bloom filter and sets the corresponding bit column 61 // in memory accordingly. 62 func (b *Generator) AddBloom(index uint, bloom types.Bloom) error { 63 // Make sure we're not adding more bloom filters than our capacity 64 if b.nextSec >= b.sections { 65 return errSectionOutOfBounds 66 } 67 if b.nextSec != index { 68 return errors.New("bloom filter with unexpected index") 69 } 70 // Rotate the bloom and insert into our collection 71 byteIndex := b.nextSec / 8 72 bitMask := byte(1) << byte(7-b.nextSec%8) 73 74 for i := 0; i < types.BloomBitLength; i++ { 75 bloomByteIndex := types.BloomByteLength - 1 - i/8 76 bloomBitMask := byte(1) << byte(i%8) 77 78 if (bloom[bloomByteIndex] & bloomBitMask) != 0 { 79 b.blooms[i][byteIndex] |= bitMask 80 } 81 } 82 b.nextSec++ 83 84 return nil 85 } 86 87 // Bitset returns the bit vector belonging to the given bit index after all 88 // blooms have been added. 89 func (b *Generator) Bitset(idx uint) ([]byte, error) { 90 if b.nextSec != b.sections { 91 return nil, errors.New("bloom not fully generated yet") 92 } 93 if idx >= types.BloomBitLength { 94 return nil, errBloomBitOutOfBounds 95 } 96 return b.blooms[idx], nil 97 }