-
Notifications
You must be signed in to change notification settings - Fork 5
/
identity.go
134 lines (115 loc) · 3.21 KB
/
identity.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package handel
import (
"encoding/binary"
"fmt"
"io"
mathRand "math/rand"
)
// Identity holds the public information of a Handel node
type Identity interface {
// Address must be understandable by the Network implementation
Address() string
// PublicKey returns the public key associated with that given node
PublicKey() PublicKey
// ID returns the ID used by handel to denote and classify nodes. It is best
// if the IDs are continuous over a given finite range.
ID() int32
}
// Registry abstracts the bookeeping of the list of Handel nodes
type Registry interface {
// Size returns the total number of Handel nodes
Size() int
// Identity returns the identity at this index in the registry, or
// (nil,false) if the index is out of bound.
Identity(int) (Identity, bool)
// Identities is similar to Identity but returns an array instead that
// includes nodes whose IDs are between from inclusive and to exclusive.
Identities(from, to int) ([]Identity, bool)
}
// fixedIdentity is an Identity using fixed in-memory data.
type fixedIdentity struct {
id int32
addr string
p PublicKey
}
// NewStaticIdentity returns an Identity fixed by these parameters
func NewStaticIdentity(id int32, addr string, p PublicKey) Identity {
return &fixedIdentity{
id: id,
addr: addr,
p: p,
}
}
func (s *fixedIdentity) Address() string {
return s.addr
}
func (s *fixedIdentity) ID() int32 {
return s.id
}
func (s *fixedIdentity) PublicKey() PublicKey {
return s.p
}
func (s *fixedIdentity) String() string {
if s.addr == "" {
return fmt.Sprintf("{id:%d}", s.id)
}
return fmt.Sprintf("{id: %d - %s}", s.id, s.addr)
}
// arrayRegistry is a Registry that uses a fixed size array as backend
type arrayRegistry struct {
ids []Identity
}
// NewArrayRegistry returns a Registry that uses a fixed size array as backend
func NewArrayRegistry(ids []Identity) Registry {
return &arrayRegistry{
ids: ids,
}
}
func (a *arrayRegistry) Size() int {
return len(a.ids)
}
func (a *arrayRegistry) Identity(idx int) (Identity, bool) {
if idx < 0 || idx >= len(a.ids) {
return nil, false
}
return a.ids[idx], true
}
func (a *arrayRegistry) Identities(from, to int) ([]Identity, bool) {
if !a.inBound(from) || !a.inBound(to) {
return nil, false
}
if to < from {
return nil, false
}
return a.ids[from:to], true
}
func (a *arrayRegistry) inBound(idx int) bool {
return !(idx < 0 || idx > len(a.ids))
}
func (a *arrayRegistry) String() string {
var s = fmt.Sprintf("arrayregistry size %d:\n", a.Size())
for _, i := range a.ids {
s += fmt.Sprintf("\t-%d: %s\n", i.ID(), i.PublicKey().String())
}
return s
}
// shuffles the given array using the given source of randomness. The shuffle is
// NOT a cryptographic shuffle, it uses the math package (i.e. most probably
// fisher-yates method).
func shuffle(arr []Identity, r io.Reader) {
var isource int64
if err := binary.Read(r, binary.BigEndian, &isource); err != nil {
panic(err)
}
rnd := mathRand.New(mathRand.NewSource(isource))
//rnd := mathRand.New(&readerSource{r})
rnd.Shuffle(len(arr), func(i, j int) { arr[i], arr[j] = arr[j], arr[i] })
}
func equals(arr1, arr2 []Identity) bool {
for i := 0; i < len(arr1); i++ {
if arr1[i] != arr2[i] {
return false
}
}
return true
}