mirror of https://github.com/ethereum/go-ethereum
parent
7b501906db
commit
9a53390f49
@ -0,0 +1,35 @@ |
||||
// Contains the Whisper protocol Topic element. For formal details please see
|
||||
// the specs at https://github.com/ethereum/wiki/wiki/Whisper-PoC-1-Protocol-Spec#topics.
|
||||
|
||||
package whisper |
||||
|
||||
import "github.com/ethereum/go-ethereum/crypto" |
||||
|
||||
// Topic represents a cryptographically secure, probabilistic partial
|
||||
// classifications of a message, determined as the first (left) 4 bytes of the
|
||||
// SHA3 hash of some arbitrary data given by the original author of the message.
|
||||
type Topic [4]byte |
||||
|
||||
// NewTopic creates a topic from the 4 byte prefix of the SHA3 hash of the data.
|
||||
func NewTopic(data []byte) Topic { |
||||
prefix := [4]byte{} |
||||
copy(prefix[:], crypto.Sha3(data)[:4]) |
||||
return Topic(prefix) |
||||
} |
||||
|
||||
// String converts a topic byte array to a string representation.
|
||||
func (self *Topic) String() string { |
||||
return string(self[:]) |
||||
} |
||||
|
||||
// TopicSet represents a hash set to check if a topic exists or not.
|
||||
type TopicSet map[string]struct{} |
||||
|
||||
// NewTopicSet creates a topic hash set from a slice of topics.
|
||||
func NewTopicSet(topics []Topic) TopicSet { |
||||
set := make(map[string]struct{}) |
||||
for _, topic := range topics { |
||||
set[topic.String()] = struct{}{} |
||||
} |
||||
return TopicSet(set) |
||||
} |
@ -0,0 +1,38 @@ |
||||
package whisper |
||||
|
||||
import ( |
||||
"bytes" |
||||
"testing" |
||||
) |
||||
|
||||
var topicCreationTests = []struct { |
||||
data []byte |
||||
hash [4]byte |
||||
}{ |
||||
{hash: [4]byte{0xc5, 0xd2, 0x46, 0x01}, data: nil}, |
||||
{hash: [4]byte{0xc5, 0xd2, 0x46, 0x01}, data: []byte{}}, |
||||
{hash: [4]byte{0x8f, 0x9a, 0x2b, 0x7d}, data: []byte("test name")}, |
||||
} |
||||
|
||||
func TestTopicCreation(t *testing.T) { |
||||
for i, tt := range topicCreationTests { |
||||
topic := NewTopic(tt.data) |
||||
if bytes.Compare(topic[:], tt.hash[:]) != 0 { |
||||
t.Errorf("test %d: hash mismatch: have %v, want %v.", i, topic, tt.hash) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestTopicSetCreation(t *testing.T) { |
||||
topics := make([]Topic, len(topicCreationTests)) |
||||
for i, tt := range topicCreationTests { |
||||
topics[i] = NewTopic(tt.data) |
||||
} |
||||
set := NewTopicSet(topics) |
||||
for i, tt := range topicCreationTests { |
||||
topic := NewTopic(tt.data) |
||||
if _, ok := set[topic.String()]; !ok { |
||||
t.Errorf("topic %d: not found in set", i) |
||||
} |
||||
} |
||||
} |
@ -1,36 +0,0 @@ |
||||
package whisper |
||||
|
||||
import "github.com/ethereum/go-ethereum/crypto" |
||||
|
||||
func hashTopic(topic []byte) []byte { |
||||
return crypto.Sha3(topic)[:4] |
||||
} |
||||
|
||||
// NOTE this isn't DRY, but I don't want to iterate twice.
|
||||
|
||||
// Returns a formatted topics byte slice.
|
||||
// data: unformatted data (e.g., no hashes needed)
|
||||
func Topics(data [][]byte) [][]byte { |
||||
d := make([][]byte, len(data)) |
||||
for i, byts := range data { |
||||
d[i] = hashTopic(byts) |
||||
} |
||||
return d |
||||
} |
||||
|
||||
func TopicsFromString(data ...string) [][]byte { |
||||
d := make([][]byte, len(data)) |
||||
for i, str := range data { |
||||
d[i] = hashTopic([]byte(str)) |
||||
} |
||||
return d |
||||
} |
||||
|
||||
func bytesToMap(s [][]byte) map[string]struct{} { |
||||
m := make(map[string]struct{}) |
||||
for _, topic := range s { |
||||
m[string(topic)] = struct{}{} |
||||
} |
||||
|
||||
return m |
||||
} |
Loading…
Reference in new issue