-
Notifications
You must be signed in to change notification settings - Fork 75
/
addr.go
125 lines (103 loc) · 3.18 KB
/
addr.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
package auth
import (
"fmt"
"strings"
"github.com/ethereum/go-ethereum/common"
)
const separator = "@"
// Addr represents a parsed unified address. It just encapsulates an ability
// to contain either ETH common address, network address or both of them
// separated by "@".
//
// No assumption is given for the real meaning of the addresses it contains.
// It's the user responsibility to verify that the given network address is
// owned by the specified ETH address if both of them provided.
//
// We use the following common address scheme:
// - When only ETH address specified - "0x8125721C2413d99a33E351e1F6Bb4e56b6b633FD".
// Usually this is intended to be used for real address resolution using
// Rendezvous server.
// - When only network address specified - "localhost:8080", "127.0.0.1:10000", etc.
// This can be used if you really know that the target is located in a
// well-known place in the network.
// - When both ETH and network addresses specified - "0x8125721C2413d99a33E351e1F6Bb4e56b6b633FD@localhost:8080".
// This can be represented as a combination of first two cases. The difference
// is in how you treat its real meaning. For example, the network address may
// be used as a hint for NPP dialer.
// It's the user's responsibility to verify that the given network address
// is really matches the ETH address provided, usually, using TLS certificates.
type Addr struct {
eth *common.Address
netAddr string
}
// ParseAddr parses the specified string into an unified address.
func ParseAddr(addr string) (*Addr, error) {
parts := strings.SplitN(addr, separator, -1)
switch len(parts) {
case 1:
addr := parts[0]
if common.IsHexAddress(addr) {
return NewETHAddr(common.HexToAddress(addr)), nil
} else {
return &Addr{netAddr: addr}, nil
}
case 2:
ethAddr := parts[0]
netAddr := parts[1]
if !common.IsHexAddress(ethAddr) {
return nil, errInvalidETHAddressFormat()
}
eth := common.HexToAddress(ethAddr)
return &Addr{
eth: ð,
netAddr: netAddr,
}, nil
default:
return nil, errInvalidETHAddressFormat()
}
}
// NewETHAddr constructs a new unified address from the given ETH address.
func NewETHAddr(addr common.Address) *Addr {
return &Addr{
eth: &addr,
}
}
func (m *Addr) ETH() (common.Address, error) {
if m.eth == nil {
return common.Address{}, fmt.Errorf("no Ethereum address specified")
}
return *m.eth, nil
}
func (m *Addr) Addr() (string, error) {
if len(m.netAddr) == 0 {
return "", fmt.Errorf("no network address specified")
}
return m.netAddr, nil
}
func (m Addr) String() string {
if m.eth != nil {
if len(m.netAddr) > 0 {
return fmt.Sprintf("%s@%s", m.eth.Hex(), m.netAddr)
}
return m.eth.Hex()
}
return m.netAddr
}
func (m Addr) MarshalText() ([]byte, error) {
return []byte(m.String()), nil
}
func (m *Addr) UnmarshalYAML(unmarshal func(interface{}) error) error {
var addr string
if err := unmarshal(&addr); err != nil {
return err
}
value, err := ParseAddr(addr)
if err != nil {
return fmt.Errorf("cannot convert `%s` into an `auth.Addr` address: %s", addr, err)
}
*m = *value
return nil
}
func errInvalidETHAddressFormat() error {
return fmt.Errorf("invalid Ethereum address format")
}