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  }