github.com/codingfuture/orig-energi3@v0.8.4/core/types/bloom9.go (about)

     1  // Copyright 2018 The Energi Core Authors
     2  // Copyright 2014 The go-ethereum Authors
     3  // This file is part of the Energi Core library.
     4  //
     5  // The Energi Core 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 Energi Core 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 Energi Core library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package types
    19  
    20  import (
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/common/hexutil"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  )
    27  
    28  type bytesBacked interface {
    29  	Bytes() []byte
    30  }
    31  
    32  const (
    33  	// BloomByteLength represents the number of bytes used in a header log bloom.
    34  	BloomByteLength = 256
    35  
    36  	// BloomBitLength represents the number of bits used in a header log bloom.
    37  	BloomBitLength = 8 * BloomByteLength
    38  )
    39  
    40  // Bloom represents a 2048 bit bloom filter.
    41  type Bloom [BloomByteLength]byte
    42  
    43  // BytesToBloom converts a byte slice to a bloom filter.
    44  // It panics if b is not of suitable size.
    45  func BytesToBloom(b []byte) Bloom {
    46  	var bloom Bloom
    47  	bloom.SetBytes(b)
    48  	return bloom
    49  }
    50  
    51  // SetBytes sets the content of b to the given bytes.
    52  // It panics if d is not of suitable size.
    53  func (b *Bloom) SetBytes(d []byte) {
    54  	if len(b) < len(d) {
    55  		panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d)))
    56  	}
    57  	copy(b[BloomByteLength-len(d):], d)
    58  }
    59  
    60  // Add adds d to the filter. Future calls of Test(d) will return true.
    61  func (b *Bloom) Add(d *big.Int) {
    62  	bin := new(big.Int).SetBytes(b[:])
    63  	bin.Or(bin, bloom9(d.Bytes()))
    64  	b.SetBytes(bin.Bytes())
    65  }
    66  
    67  // Big converts b to a big integer.
    68  func (b Bloom) Big() *big.Int {
    69  	return new(big.Int).SetBytes(b[:])
    70  }
    71  
    72  func (b Bloom) Bytes() []byte {
    73  	return b[:]
    74  }
    75  
    76  func (b Bloom) Test(test *big.Int) bool {
    77  	return BloomLookup(b, test)
    78  }
    79  
    80  func (b Bloom) TestBytes(test []byte) bool {
    81  	return b.Test(new(big.Int).SetBytes(test))
    82  
    83  }
    84  
    85  func (b *Bloom) AddBloom(o *Bloom) {
    86  	b.SetBytes(new(big.Int).Or(b.Big(), o.Big()).Bytes())
    87  }
    88  
    89  // MarshalText encodes b as a hex string with 0x prefix.
    90  func (b Bloom) MarshalText() ([]byte, error) {
    91  	return hexutil.Bytes(b[:]).MarshalText()
    92  }
    93  
    94  // UnmarshalText b as a hex string with 0x prefix.
    95  func (b *Bloom) UnmarshalText(input []byte) error {
    96  	return hexutil.UnmarshalFixedText("Bloom", input, b[:])
    97  }
    98  
    99  func CreateBloom(receipts Receipts) Bloom {
   100  	bin := new(big.Int)
   101  	for _, receipt := range receipts {
   102  		bin.Or(bin, LogsBloom(receipt.Logs))
   103  	}
   104  
   105  	return BytesToBloom(bin.Bytes())
   106  }
   107  
   108  func LogsBloom(logs []*Log) *big.Int {
   109  	bin := new(big.Int)
   110  	for _, log := range logs {
   111  		bin.Or(bin, bloom9(log.Address.Bytes()))
   112  		for _, b := range log.Topics {
   113  			bin.Or(bin, bloom9(b[:]))
   114  		}
   115  	}
   116  
   117  	return bin
   118  }
   119  
   120  func bloom9(b []byte) *big.Int {
   121  	b = crypto.Keccak256(b)
   122  
   123  	r := new(big.Int)
   124  
   125  	for i := 0; i < 6; i += 2 {
   126  		t := big.NewInt(1)
   127  		b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 2047
   128  		r.Or(r, t.Lsh(t, b))
   129  	}
   130  
   131  	return r
   132  }
   133  
   134  var Bloom9 = bloom9
   135  
   136  func BloomLookup(bin Bloom, topic bytesBacked) bool {
   137  	bloom := bin.Big()
   138  	cmp := bloom9(topic.Bytes())
   139  
   140  	return bloom.And(bloom, cmp).Cmp(cmp) == 0
   141  }