-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathlocalnode.go
131 lines (110 loc) · 3.34 KB
/
localnode.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
package enr
import (
"crypto/ecdsa"
"encoding/binary"
"errors"
"math"
"math/rand"
"net"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/multiformats/go-multiaddr"
)
func NewLocalnode(priv *ecdsa.PrivateKey) (*enode.LocalNode, error) {
db, err := enode.OpenDB("")
if err != nil {
return nil, err
}
return enode.NewLocalNode(db, priv), nil
}
type ENROption func(*enode.LocalNode) error
func WithMultiaddress(multiaddrs ...multiaddr.Multiaddr) ENROption {
return func(localnode *enode.LocalNode) (err error) {
// Randomly shuffle multiaddresses
rand.Shuffle(len(multiaddrs), func(i, j int) { multiaddrs[i], multiaddrs[j] = multiaddrs[j], multiaddrs[i] })
// Adding extra multiaddresses. Should probably not exceed the enr max size of 300bytes
failedOnceWritingENR := false
couldWriteENRatLeastOnce := false
successIdx := -1
for i := len(multiaddrs); i > 0; i-- {
err = writeMultiaddressField(localnode, multiaddrs[0:i])
if err == nil {
couldWriteENRatLeastOnce = true
successIdx = i
break
}
failedOnceWritingENR = true
}
if failedOnceWritingENR && couldWriteENRatLeastOnce {
// Could write a subset of multiaddresses but not all
err = writeMultiaddressField(localnode, multiaddrs[0:successIdx])
if err != nil {
return errors.New("could not write new ENR")
}
}
return nil
}
}
func WithCapabilities(lightpush, filter, store, relay bool) ENROption {
return func(localnode *enode.LocalNode) (err error) {
wakuflags := NewWakuEnrBitfield(lightpush, filter, store, relay)
return WithWakuBitfield(wakuflags)(localnode)
}
}
func WithWakuBitfield(flags WakuEnrBitfield) ENROption {
return func(localnode *enode.LocalNode) (err error) {
localnode.Set(enr.WithEntry(WakuENRField, flags))
return nil
}
}
func WithIP(ipAddr *net.TCPAddr) ENROption {
return func(localnode *enode.LocalNode) (err error) {
localnode.SetStaticIP(ipAddr.IP)
localnode.Set(enr.TCP(uint16(ipAddr.Port))) // TODO: ipv6?
return nil
}
}
func WithUDPPort(udpPort uint) ENROption {
return func(localnode *enode.LocalNode) (err error) {
if udpPort == 0 {
return nil
}
if udpPort > math.MaxUint16 {
return errors.New("invalid udp port number")
}
localnode.SetFallbackUDP(int(udpPort))
return nil
}
}
func Update(localnode *enode.LocalNode, enrOptions ...ENROption) error {
for _, opt := range enrOptions {
err := opt(localnode)
if err != nil {
return err
}
}
return nil
}
func writeMultiaddressField(localnode *enode.LocalNode, addrAggr []multiaddr.Multiaddr) (err error) {
defer func() {
if e := recover(); e != nil {
// Deleting the multiaddr entry, as we could not write it succesfully
localnode.Delete(enr.WithEntry(MultiaddrENRField, struct{}{}))
err = errors.New("could not write enr record")
}
}()
var fieldRaw []byte
for _, addr := range addrAggr {
maRaw := addr.Bytes()
maSize := make([]byte, 2)
binary.BigEndian.PutUint16(maSize, uint16(len(maRaw)))
fieldRaw = append(fieldRaw, maSize...)
fieldRaw = append(fieldRaw, maRaw...)
}
if len(fieldRaw) != 0 && len(fieldRaw) <= 100 { // Max length for multiaddr field before triggering the 300 bytes limit
localnode.Set(enr.WithEntry(MultiaddrENRField, fieldRaw))
}
// This is to trigger the signing record err due to exceeding 300bytes limit
_ = localnode.Node()
return nil
}