github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/core/bloombits/generator.go (about)

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