Skip to content

Commit 8047dba

Browse files
committed
add node identity
1 parent c6c1e4a commit 8047dba

9 files changed

Lines changed: 223 additions & 1 deletion

File tree

api/nodeidentityopts.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package api
2+
3+
// NodeIdentityOpts are the options for obtaining the node identity.
4+
type NodeIdentityOpts struct {
5+
Common CommonOpts
6+
}

api/v1/identity.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package v1
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
7+
"github.com/pkg/errors"
8+
)
9+
10+
// NodeIdentity contains the node identity information.
11+
type NodeIdentity struct {
12+
PeerID string `json:"peer_id"`
13+
Enr string `json:"enr"`
14+
P2PAddresses []string `json:"p2p_addresses"`
15+
DiscoveryAddresses []string `json:"discovery_addresses"`
16+
Metadata map[string]string `json:"metadata"`
17+
}
18+
19+
type nodeIdentityJSON struct {
20+
PeerID string `json:"peer_id"`
21+
Enr string `json:"enr"`
22+
P2PAddresses []string `json:"p2p_addresses"`
23+
DiscoveryAddresses []string `json:"discovery_addresses"`
24+
Metadata map[string]string `json:"metadata"`
25+
}
26+
27+
// MarshalJSON implements json.Marshaler.
28+
func (n *NodeIdentity) MarshalJSON() ([]byte, error) {
29+
return json.Marshal(&nodeIdentityJSON{
30+
PeerID: n.PeerID,
31+
Enr: n.Enr,
32+
P2PAddresses: n.P2PAddresses,
33+
DiscoveryAddresses: n.DiscoveryAddresses,
34+
Metadata: n.Metadata,
35+
})
36+
}
37+
38+
// UnmarshalJSON implements json.Unmarshaler.
39+
func (n *NodeIdentity) UnmarshalJSON(input []byte) error {
40+
var nodeIdentityJSON nodeIdentityJSON
41+
42+
if err := json.Unmarshal(input, &nodeIdentityJSON); err != nil {
43+
return errors.Wrap(err, "invalid JSON")
44+
}
45+
46+
n.PeerID = nodeIdentityJSON.PeerID
47+
n.Enr = nodeIdentityJSON.Enr
48+
n.P2PAddresses = nodeIdentityJSON.P2PAddresses
49+
n.DiscoveryAddresses = nodeIdentityJSON.DiscoveryAddresses
50+
n.Metadata = nodeIdentityJSON.Metadata
51+
52+
return nil
53+
}
54+
55+
func (n *NodeIdentity) String() string {
56+
data, err := json.Marshal(n)
57+
if err != nil {
58+
return fmt.Sprintf("ERR: %v", err)
59+
}
60+
61+
return string(data)
62+
}

http/nodeidentity.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package http
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"fmt"
7+
8+
client "github.com/attestantio/go-eth2-client"
9+
"github.com/attestantio/go-eth2-client/api"
10+
apiv1 "github.com/attestantio/go-eth2-client/api/v1"
11+
)
12+
13+
// NodeIdentity provides the identity information of the node.
14+
func (s *Service) NodeIdentity(ctx context.Context,
15+
opts *api.NodeIdentityOpts,
16+
) (
17+
*api.Response[*apiv1.NodeIdentity],
18+
error,
19+
) {
20+
if err := s.assertIsActive(ctx); err != nil {
21+
return nil, err
22+
}
23+
if opts == nil {
24+
return nil, client.ErrNoOptions
25+
}
26+
27+
endpoint := "/eth/v1/node/identity"
28+
httpResponse, err := s.get(ctx, endpoint, "", &opts.Common, false)
29+
if err != nil {
30+
return nil, err
31+
}
32+
33+
if httpResponse.contentType != ContentTypeJSON {
34+
return nil, fmt.Errorf("unexpected content type %v (expected JSON)", httpResponse.contentType)
35+
}
36+
37+
data, metadata, err := decodeJSONResponse(bytes.NewReader(httpResponse.body), &apiv1.NodeIdentity{})
38+
if err != nil {
39+
return nil, err
40+
}
41+
42+
return &api.Response[*apiv1.NodeIdentity]{
43+
Data: data,
44+
Metadata: metadata,
45+
}, nil
46+
}

mock/nodeidentity.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package mock
2+
3+
import (
4+
"context"
5+
6+
"github.com/attestantio/go-eth2-client/api"
7+
apiv1 "github.com/attestantio/go-eth2-client/api/v1"
8+
)
9+
10+
// NodeIdentity provides the identity information of the node.
11+
func (s *Service) NodeIdentity(ctx context.Context,
12+
opts *api.NodeIdentityOpts,
13+
) (
14+
*api.Response[*apiv1.NodeIdentity],
15+
error,
16+
) {
17+
if s.NodeIdentityFunc != nil {
18+
return s.NodeIdentityFunc(ctx, opts)
19+
}
20+
21+
return &api.Response[*apiv1.NodeIdentity]{
22+
Data: &apiv1.NodeIdentity{
23+
PeerID: "16Uiu2HAmMockPeerID",
24+
Enr: "enr:-mock-enr-value",
25+
P2PAddresses: []string{"/ip4/127.0.0.1/tcp/9000"},
26+
DiscoveryAddresses: []string{"/ip4/127.0.0.1/udp/9000"},
27+
Metadata: map[string]string{
28+
"seq_number": "1",
29+
"attnets": "0xffffffffffffffff",
30+
},
31+
},
32+
}, nil
33+
}

mock/service.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type Service struct {
6868
ForkFunc func(context.Context, *api.ForkOpts) (*api.Response[*phase0.Fork], error)
6969
ForkScheduleFunc func(context.Context, *api.ForkScheduleOpts) (*api.Response[[]*phase0.Fork], error)
7070
GenesisFunc func(context.Context, *api.GenesisOpts) (*api.Response[*apiv1.Genesis], error)
71+
NodeIdentityFunc func(context.Context, *api.NodeIdentityOpts) (*api.Response[*apiv1.NodeIdentity], error)
7172
NodePeersFunc func(context.Context, *api.NodePeersOpts) (*api.Response[[]*apiv1.Peer], error)
7273
NodePeerCountFunc func(context.Context, *api.NodePeerCountOpts) (*api.Response[*apiv1.PeerCount], error)
7374
NodeSyncingFunc func(context.Context, *api.NodeSyncingOpts) (*api.Response[*apiv1.SyncState], error)

multi/nodeidentity.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package multi
2+
3+
import (
4+
"context"
5+
6+
consensusclient "github.com/attestantio/go-eth2-client"
7+
"github.com/attestantio/go-eth2-client/api"
8+
apiv1 "github.com/attestantio/go-eth2-client/api/v1"
9+
)
10+
11+
// NodeIdentity provides the identity information of the node.
12+
func (s *Service) NodeIdentity(ctx context.Context, opts *api.NodeIdentityOpts) (*api.Response[*apiv1.NodeIdentity], error) {
13+
res, err := s.doCall(ctx, func(ctx context.Context, client consensusclient.Service) (any, error) {
14+
nodeIdentity, err := client.(consensusclient.NodeIdentityProvider).NodeIdentity(ctx, opts)
15+
if err != nil {
16+
return nil, err
17+
}
18+
19+
return nodeIdentity, nil
20+
}, nil)
21+
if err != nil {
22+
return nil, err
23+
}
24+
25+
response, isResponse := res.(*api.Response[*apiv1.NodeIdentity])
26+
if !isResponse {
27+
return nil, ErrIncorrectType
28+
}
29+
30+
return response, nil
31+
}

service.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,16 @@ type GenesisProvider interface {
526526
error,
527527
)
528528
}
529-
529+
// NodeIdentityProvider is the interface for providing node identity information.
530+
type NodeIdentityProvider interface {
531+
// NodeIdentity provides the identity information of the node.
532+
NodeIdentity(ctx context.Context,
533+
opts *api.NodeIdentityOpts,
534+
) (
535+
*api.Response[*apiv1.NodeIdentity],
536+
error,
537+
)
538+
}
530539
// NodePeersProvider is the interface for providing peer information.
531540
type NodePeersProvider interface {
532541
// NodePeers provides the peers of the node.

testclients/erroring.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,24 @@ func (s *Erroring) SlotFromStateID(ctx context.Context, stateID string) (phase0.
126126
return next.SlotFromStateID(ctx, stateID)
127127
}
128128

129+
// NodeIdentity provides the identity information of the node.
130+
func (s *Erroring) NodeIdentity(ctx context.Context,
131+
opts *api.NodeIdentityOpts,
132+
) (
133+
*api.Response[*apiv1.NodeIdentity],
134+
error,
135+
) {
136+
if err := s.maybeError(ctx); err != nil {
137+
return nil, err
138+
}
139+
next, isNext := s.next.(consensusclient.NodeIdentityProvider)
140+
if !isNext {
141+
return nil, fmt.Errorf("%s@%s does not support this call", s.next.Name(), s.next.Address())
142+
}
143+
144+
return next.NodeIdentity(ctx, opts)
145+
}
146+
129147
// NodeVersion returns a free-text string with the node version.
130148
func (s *Erroring) NodeVersion(ctx context.Context,
131149
opts *api.NodeVersionOpts,

testclients/sleepy.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,22 @@ func (s *Sleepy) SlotFromStateID(ctx context.Context, stateID string) (phase0.Sl
119119
return next.SlotFromStateID(ctx, stateID)
120120
}
121121

122+
// NodeIdentity provides the identity information of the node.
123+
func (s *Sleepy) NodeIdentity(ctx context.Context,
124+
opts *api.NodeIdentityOpts,
125+
) (
126+
*api.Response[*apiv1.NodeIdentity],
127+
error,
128+
) {
129+
s.sleep(ctx)
130+
next, isNext := s.next.(consensusclient.NodeIdentityProvider)
131+
if !isNext {
132+
return nil, errors.New("next does not support this call")
133+
}
134+
135+
return next.NodeIdentity(ctx, opts)
136+
}
137+
122138
// NodeVersion returns a free-text string with the node version.
123139
func (s *Sleepy) NodeVersion(ctx context.Context,
124140
opts *api.NodeVersionOpts,

0 commit comments

Comments
 (0)