github.com/status-im/status-go@v1.1.0/eth-node/types/topic.go (about)

     1  package types
     2  
     3  import (
     4  	"github.com/ethereum/go-ethereum/common/hexutil"
     5  )
     6  
     7  const (
     8  	// TopicLength is the expected length of the topic, in bytes
     9  	TopicLength = 4
    10  	// BloomFilterSize is the expected length of a bloom filter byte array, in bytes
    11  	BloomFilterSize = 64
    12  )
    13  
    14  // TopicType represents a cryptographically secure, probabilistic partial
    15  // classifications of a message, determined as the first (left) 4 bytes of the
    16  // SHA3 hash of some arbitrary data given by the original author of the message.
    17  type TopicType [TopicLength]byte
    18  
    19  // BytesToTopic converts from the byte array representation of a topic
    20  // into the TopicType type.
    21  func BytesToTopic(b []byte) (t TopicType) {
    22  	sz := TopicLength
    23  	if x := len(b); x < TopicLength {
    24  		sz = x
    25  	}
    26  	for i := 0; i < sz; i++ {
    27  		t[i] = b[i]
    28  	}
    29  	return t
    30  }
    31  
    32  // String converts a topic byte array to a string representation.
    33  func (t TopicType) String() string {
    34  	return EncodeHex(t[:])
    35  }
    36  
    37  // MarshalText returns the hex representation of t.
    38  func (t TopicType) MarshalText() ([]byte, error) {
    39  	return HexBytes(t[:]).MarshalText()
    40  }
    41  
    42  // UnmarshalText parses a hex representation to a topic.
    43  func (t *TopicType) UnmarshalText(input []byte) error {
    44  	return UnmarshalFixedText("Topic", input, t[:])
    45  }
    46  
    47  // TopicToBloom converts the topic (4 bytes) to the bloom filter (64 bytes)
    48  func TopicToBloom(topic TopicType) []byte {
    49  	b := make([]byte, BloomFilterSize)
    50  	var index [3]int
    51  	for j := 0; j < 3; j++ {
    52  		index[j] = int(topic[j])
    53  		if (topic[3] & (1 << uint(j))) != 0 {
    54  			index[j] += 256
    55  		}
    56  	}
    57  
    58  	for j := 0; j < 3; j++ {
    59  		byteIndex := index[j] / 8
    60  		bitIndex := index[j] % 8
    61  		b[byteIndex] = (1 << uint(bitIndex))
    62  	}
    63  	return b
    64  }
    65  
    66  // BloomFilterMatch returns true if a sample matches a bloom filter
    67  func BloomFilterMatch(filter, sample []byte) bool {
    68  	if filter == nil {
    69  		return true
    70  	}
    71  
    72  	for i := 0; i < BloomFilterSize; i++ {
    73  		f := filter[i]
    74  		s := sample[i]
    75  		if (f | s) != f {
    76  			return false
    77  		}
    78  	}
    79  
    80  	return true
    81  }
    82  
    83  // MakeFullNodeBloom returns a bloom filter which matches all topics
    84  func MakeFullNodeBloom() []byte {
    85  	bloom := make([]byte, BloomFilterSize)
    86  	for i := 0; i < BloomFilterSize; i++ {
    87  		bloom[i] = 0xFF
    88  	}
    89  	return bloom
    90  }
    91  
    92  func StringToTopic(s string) (t TopicType) {
    93  	str, _ := hexutil.Decode(s)
    94  	return BytesToTopic(str)
    95  }
    96  
    97  func TopicTypeToByteArray(t TopicType) []byte {
    98  	return t[:4]
    99  }