github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/bloombits/generator.go (about) 1 package bloombits 2 3 import ( 4 "errors" 5 6 "github.com/quickchainproject/quickchain/core/types" 7 ) 8 9 // errSectionOutOfBounds is returned if the user tried to add more bloom filters 10 // to the batch than available space, or if tries to retrieve above the capacity, 11 var errSectionOutOfBounds = errors.New("section out of bounds") 12 13 // Generator takes a number of bloom filters and generates the rotated bloom bits 14 // to be used for batched filtering. 15 type Generator struct { 16 blooms [types.BloomBitLength][]byte // Rotated blooms for per-bit matching 17 sections uint // Number of sections to batch together 18 nextBit uint // Next bit to set when adding a bloom 19 } 20 21 // NewGenerator creates a rotated bloom generator that can iteratively fill a 22 // batched bloom filter's bits. 23 func NewGenerator(sections uint) (*Generator, error) { 24 if sections%8 != 0 { 25 return nil, errors.New("section count not multiple of 8") 26 } 27 b := &Generator{sections: sections} 28 for i := 0; i < types.BloomBitLength; i++ { 29 b.blooms[i] = make([]byte, sections/8) 30 } 31 return b, nil 32 } 33 34 // AddBloom takes a single bloom filter and sets the corresponding bit column 35 // in memory accordingly. 36 func (b *Generator) AddBloom(index uint, bloom types.Bloom) error { 37 // Make sure we're not adding more bloom filters than our capacity 38 if b.nextBit >= b.sections { 39 return errSectionOutOfBounds 40 } 41 if b.nextBit != index { 42 return errors.New("bloom filter with unexpected index") 43 } 44 // Rotate the bloom and insert into our collection 45 byteIndex := b.nextBit / 8 46 bitMask := byte(1) << byte(7-b.nextBit%8) 47 48 for i := 0; i < types.BloomBitLength; i++ { 49 bloomByteIndex := types.BloomByteLength - 1 - i/8 50 bloomBitMask := byte(1) << byte(i%8) 51 52 if (bloom[bloomByteIndex] & bloomBitMask) != 0 { 53 b.blooms[i][byteIndex] |= bitMask 54 } 55 } 56 b.nextBit++ 57 58 return nil 59 } 60 61 // Bitset returns the bit vector belonging to the given bit index after all 62 // blooms have been added. 63 func (b *Generator) Bitset(idx uint) ([]byte, error) { 64 if b.nextBit != b.sections { 65 return nil, errors.New("bloom not fully generated yet") 66 } 67 if idx >= b.sections { 68 return nil, errSectionOutOfBounds 69 } 70 return b.blooms[idx], nil 71 }