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