github.com/klaytn/klaytn@v1.12.1/blockchain/types/bloom.go (about)

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