github.com/jiajun1992/watercarver@v0.0.0-20191031150618-dfc2b17c0c4a/go-ethereum/core/types/bloom9.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package types
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/ethereum/go-ethereum/common/hexutil"
    24  	"github.com/ethereum/go-ethereum/crypto"
    25  )
    26  
    27  type bytesBacked interface {
    28  	Bytes() []byte
    29  }
    30  
    31  const (
    32  	// BloomByteLength represents the number of bytes used in a header log bloom.
    33  	BloomByteLength = 256
    34  
    35  	// BloomBitLength represents the number of bits used in a header log bloom.
    36  	BloomBitLength = 8 * BloomByteLength
    37  )
    38  
    39  // Bloom represents a 2048 bit bloom filter.
    40  type Bloom [BloomByteLength]byte
    41  
    42  // BytesToBloom converts a byte slice to a bloom filter.
    43  // It panics if b is not of suitable size.
    44  func BytesToBloom(b []byte) Bloom {
    45  	var bloom Bloom
    46  	bloom.SetBytes(b)
    47  	return bloom
    48  }
    49  
    50  // SetBytes sets the content of b to the given bytes.
    51  // It panics if d is not of suitable size.
    52  func (b *Bloom) SetBytes(d []byte) {
    53  	if len(b) < len(d) {
    54  		panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d)))
    55  	}
    56  	copy(b[BloomByteLength-len(d):], d)
    57  }
    58  
    59  // Add adds d to the filter. Future calls of Test(d) will return true.
    60  func (b *Bloom) Add(d *big.Int) {
    61  	bin := new(big.Int).SetBytes(b[:])
    62  	bin.Or(bin, bloom9(d.Bytes()))
    63  	b.SetBytes(bin.Bytes())
    64  }
    65  
    66  // Big converts b to a big integer.
    67  func (b Bloom) Big() *big.Int {
    68  	return new(big.Int).SetBytes(b[:])
    69  }
    70  
    71  func (b Bloom) Bytes() []byte {
    72  	return b[:]
    73  }
    74  
    75  func (b Bloom) Test(test *big.Int) bool {
    76  	return BloomLookup(b, test)
    77  }
    78  
    79  func (b Bloom) TestBytes(test []byte) bool {
    80  	return b.Test(new(big.Int).SetBytes(test))
    81  
    82  }
    83  
    84  // MarshalText encodes b as a hex string with 0x prefix.
    85  func (b Bloom) MarshalText() ([]byte, error) {
    86  	return hexutil.Bytes(b[:]).MarshalText()
    87  }
    88  
    89  // UnmarshalText b as a hex string with 0x prefix.
    90  func (b *Bloom) UnmarshalText(input []byte) error {
    91  	return hexutil.UnmarshalFixedText("Bloom", input, b[:])
    92  }
    93  
    94  func CreateBloom(receipts Receipts) Bloom {
    95  	bin := new(big.Int)
    96  	for _, receipt := range receipts {
    97  		bin.Or(bin, LogsBloom(receipt.Logs))
    98  	}
    99  
   100  	return BytesToBloom(bin.Bytes())
   101  }
   102  
   103  func LogsBloom(logs []*Log) *big.Int {
   104  	bin := new(big.Int)
   105  	for _, log := range logs {
   106  		bin.Or(bin, bloom9(log.Address.Bytes()))
   107  		for _, b := range log.Topics {
   108  			bin.Or(bin, bloom9(b[:]))
   109  		}
   110  	}
   111  
   112  	return bin
   113  }
   114  
   115  func bloom9(b []byte) *big.Int {
   116  	b = crypto.Keccak256(b)
   117  
   118  	r := new(big.Int)
   119  
   120  	for i := 0; i < 6; i += 2 {
   121  		t := big.NewInt(1)
   122  		b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 2047
   123  		r.Or(r, t.Lsh(t, b))
   124  	}
   125  
   126  	return r
   127  }
   128  
   129  var Bloom9 = bloom9
   130  
   131  func BloomLookup(bin Bloom, topic bytesBacked) bool {
   132  	bloom := bin.Big()
   133  	cmp := bloom9(topic.Bytes())
   134  
   135  	return bloom.And(bloom, cmp).Cmp(cmp) == 0
   136  }