Skip to content

Commit cf7ad84

Browse files
authored
feat(nodebuilder/node): Implement Module (#1313)
Resolves #977
1 parent 52048ce commit cf7ad84

File tree

11 files changed

+279
-26
lines changed

11 files changed

+279
-26
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,6 @@ pb-gen:
151151
## openrpc-gen: Generate OpenRPC spec for Celestia-Node's RPC api
152152
openrpc-gen:
153153
@echo "--> Generating OpenRPC spec"
154-
@go run ./cmd/docgen fraud header state share das p2p
154+
@go run ./cmd/docgen fraud header state share das p2p node
155155
.PHONY: openrpc-gen
156156

api/rpc/client/client.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,20 @@ import (
88
"github.com/celestiaorg/celestia-node/nodebuilder/das"
99
"github.com/celestiaorg/celestia-node/nodebuilder/fraud"
1010
"github.com/celestiaorg/celestia-node/nodebuilder/header"
11+
"github.com/celestiaorg/celestia-node/nodebuilder/node"
1112
"github.com/celestiaorg/celestia-node/nodebuilder/p2p"
1213
"github.com/celestiaorg/celestia-node/nodebuilder/share"
1314
"github.com/celestiaorg/celestia-node/nodebuilder/state"
1415
)
1516

16-
type API interface {
17-
fraud.Module
18-
header.Module
19-
state.Module
20-
share.Module
21-
das.Module
22-
p2p.Module
23-
}
24-
2517
type Client struct {
2618
Fraud fraud.API
2719
Header header.API
2820
State state.API
2921
Share share.API
3022
DAS das.API
3123
P2P p2p.API
24+
Node node.API
3225

3326
closer multiClientCloser
3427
}
@@ -68,6 +61,7 @@ func NewClient(ctx context.Context, addr string) (*Client, error) {
6861
"fraud": &client.Fraud.Internal,
6962
"das": &client.DAS.Internal,
7063
"p2p": &client.P2P.Internal,
64+
"node": &client.Node.Internal,
7165
}
7266
for name, module := range modules {
7367
closer, err := jsonrpc.NewClient(ctx, addr, name, module, nil)

api/rpc_test.go

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,19 @@ import (
1515
"github.com/celestiaorg/celestia-node/api/rpc"
1616
"github.com/celestiaorg/celestia-node/api/rpc/client"
1717
"github.com/celestiaorg/celestia-node/nodebuilder"
18+
"github.com/celestiaorg/celestia-node/nodebuilder/das"
1819
dasMock "github.com/celestiaorg/celestia-node/nodebuilder/das/mocks"
20+
"github.com/celestiaorg/celestia-node/nodebuilder/fraud"
1921
fraudMock "github.com/celestiaorg/celestia-node/nodebuilder/fraud/mocks"
22+
"github.com/celestiaorg/celestia-node/nodebuilder/header"
2023
headerMock "github.com/celestiaorg/celestia-node/nodebuilder/header/mocks"
2124
"github.com/celestiaorg/celestia-node/nodebuilder/node"
25+
nodeMock "github.com/celestiaorg/celestia-node/nodebuilder/node/mocks"
26+
"github.com/celestiaorg/celestia-node/nodebuilder/p2p"
2227
p2pMock "github.com/celestiaorg/celestia-node/nodebuilder/p2p/mocks"
28+
"github.com/celestiaorg/celestia-node/nodebuilder/share"
2329
shareMock "github.com/celestiaorg/celestia-node/nodebuilder/share/mocks"
30+
statemod "github.com/celestiaorg/celestia-node/nodebuilder/state"
2431
stateMock "github.com/celestiaorg/celestia-node/nodebuilder/state/mocks"
2532
"github.com/celestiaorg/celestia-node/state"
2633
)
@@ -58,33 +65,67 @@ func TestRPCCallsUnderlyingNode(t *testing.T) {
5865
require.Equal(t, expectedBalance, balance)
5966
}
6067

68+
// api contains all modules that are made available as the node's
69+
// public API surface (except for the `node` module as the node
70+
// module contains a method `Info` that is also contained in the
71+
// p2p module).
72+
type api interface {
73+
fraud.Module
74+
header.Module
75+
statemod.Module
76+
share.Module
77+
das.Module
78+
p2p.Module
79+
}
80+
6181
func TestModulesImplementFullAPI(t *testing.T) {
62-
api := reflect.TypeOf(new(client.API)).Elem()
82+
api := reflect.TypeOf(new(api)).Elem()
83+
nodeapi := reflect.TypeOf(new(node.Module)).Elem() // TODO @renaynay: explain
6384
client := reflect.TypeOf(new(client.Client)).Elem()
6485
for i := 0; i < client.NumField(); i++ {
6586
module := client.Field(i)
66-
// the "closers" field is not an actual module
67-
if module.Name == "closer" {
87+
switch module.Name {
88+
case "closer":
89+
// the "closers" field is not an actual module
6890
continue
69-
}
70-
internal, ok := module.Type.FieldByName("Internal")
71-
require.True(t, ok, "module %s's API does not have an Internal field", module.Name)
72-
for j := 0; j < internal.Type.NumField(); j++ {
73-
impl := internal.Type.Field(j)
74-
method, _ := api.MethodByName(impl.Name)
75-
require.Equal(t, method.Type, impl.Type, "method %s does not match", impl.Name)
91+
case "Node":
92+
// node module contains a duplicate method to the p2p module
93+
// and must be tested separately.
94+
internal, ok := module.Type.FieldByName("Internal")
95+
require.True(t, ok, "module %s's API does not have an Internal field", module.Name)
96+
for j := 0; j < internal.Type.NumField(); j++ {
97+
impl := internal.Type.Field(j)
98+
method, _ := nodeapi.MethodByName(impl.Name)
99+
require.Equal(t, method.Type, impl.Type, "method %s does not match", impl.Name)
100+
}
101+
default:
102+
internal, ok := module.Type.FieldByName("Internal")
103+
require.True(t, ok, "module %s's API does not have an Internal field", module.Name)
104+
for j := 0; j < internal.Type.NumField(); j++ {
105+
impl := internal.Type.Field(j)
106+
method, _ := api.MethodByName(impl.Name)
107+
require.Equal(t, method.Type, impl.Type, "method %s does not match", impl.Name)
108+
}
76109
}
77110
}
78111
}
79112

80113
func TestAllReturnValuesAreMarshalable(t *testing.T) {
81-
ra := reflect.TypeOf(new(client.API)).Elem()
114+
ra := reflect.TypeOf(new(api)).Elem()
82115
for i := 0; i < ra.NumMethod(); i++ {
83116
m := ra.Method(i)
84117
for j := 0; j < m.Type.NumOut(); j++ {
85118
implementsMarshaler(t, m.Type.Out(j))
86119
}
87120
}
121+
// NOTE: see comment above api interface definition.
122+
na := reflect.TypeOf(new(node.Module)).Elem()
123+
for i := 0; i < na.NumMethod(); i++ {
124+
m := na.Method(i)
125+
for j := 0; j < m.Type.NumOut(); j++ {
126+
implementsMarshaler(t, m.Type.Out(j))
127+
}
128+
}
88129
}
89130

90131
func implementsMarshaler(t *testing.T, typ reflect.Type) {
@@ -145,6 +186,7 @@ func setupNodeWithModifiedRPC(t *testing.T) (*nodebuilder.Node, *mockAPI) {
145186
headerMock.NewMockModule(ctrl),
146187
dasMock.NewMockModule(ctrl),
147188
p2pMock.NewMockModule(ctrl),
189+
nodeMock.NewMockModule(ctrl),
148190
}
149191

150192
// given the behavior of fx.Invoke, this invoke will be called last as it is added at the root
@@ -156,6 +198,7 @@ func setupNodeWithModifiedRPC(t *testing.T) (*nodebuilder.Node, *mockAPI) {
156198
srv.RegisterService("header", mockAPI.Header)
157199
srv.RegisterService("das", mockAPI.Das)
158200
srv.RegisterService("p2p", mockAPI.P2P)
201+
srv.RegisterService("node", mockAPI.Node)
159202
})
160203
nd := nodebuilder.TestNode(t, node.Full, invokeRPC)
161204
// start node
@@ -175,4 +218,5 @@ type mockAPI struct {
175218
Header *headerMock.MockModule
176219
Das *dasMock.MockModule
177220
P2P *p2pMock.MockModule
221+
Node *nodeMock.MockModule
178222
}

docs/adr/adr-009-public-api.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,16 @@ SyncHead(ctx context.Context) (*header.ExtendedHeader, error)
203203
```go
204204

205205
type NodeModule interface {
206-
// Type returns the node type.
207-
Type() node.Type
208-
// Version returns information about the current binary build.
209-
Version() string
210-
206+
// Info returns administrative information about the node.
207+
Info(context.Context) (Info, error)
208+
211209
// LogLevelSet sets the given component log level to the given level.
212210
LogLevelSet(ctx context.Context, name, level string) error
211+
212+
// AuthVerify returns the permissions assigned to the given token.
213+
AuthVerify(ctx context.Context, token string) ([]auth.Permission, error)
214+
// AuthNew signs and returns a new token with the given permissions.
215+
AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error)
213216
}
214217

215218
```

nodebuilder/default_services.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/celestiaorg/celestia-node/nodebuilder/das"
55
"github.com/celestiaorg/celestia-node/nodebuilder/fraud"
66
"github.com/celestiaorg/celestia-node/nodebuilder/header"
7+
"github.com/celestiaorg/celestia-node/nodebuilder/node"
78
"github.com/celestiaorg/celestia-node/nodebuilder/p2p"
89
"github.com/celestiaorg/celestia-node/nodebuilder/share"
910
"github.com/celestiaorg/celestia-node/nodebuilder/state"
@@ -18,4 +19,5 @@ var PackageToAPI = map[string]interface{}{
1819
"header": &header.API{},
1920
"daser": &das.API{},
2021
"p2p": &p2p.API{},
22+
"node": &node.API{},
2123
}

nodebuilder/module.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func ConstructModule(tp node.Type, network p2p.Network, cfg *Config, store Store
4141
core.ConstructModule(tp, &cfg.Core),
4242
das.ConstructModule(tp, &cfg.DASer),
4343
fraud.ConstructModule(tp),
44+
node.ConstructModule(tp),
4445
)
4546

4647
return fx.Module(

nodebuilder/node/admin.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package node
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/filecoin-project/go-jsonrpc/auth"
8+
logging "github.com/ipfs/go-log/v2"
9+
)
10+
11+
type module struct {
12+
tp Type
13+
}
14+
15+
func newModule(tp Type) Module {
16+
return &module{
17+
tp: tp,
18+
}
19+
}
20+
21+
// Info contains information related to the administrative
22+
// node.
23+
type Info struct {
24+
Type Type `json:"type"`
25+
APIVersion string `json:"api_version"`
26+
}
27+
28+
func (m *module) Info(context.Context) (Info, error) {
29+
return Info{
30+
Type: m.tp,
31+
// TODO @renaynay @distractedm1nd: Implement versioning in API and way to extract that into this struct
32+
}, nil
33+
}
34+
35+
func (m *module) LogLevelSet(_ context.Context, name, level string) error {
36+
return logging.SetLogLevel(name, level)
37+
}
38+
39+
func (m *module) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) {
40+
return []auth.Permission{}, fmt.Errorf("not implemented")
41+
}
42+
43+
func (m *module) AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) {
44+
return nil, fmt.Errorf("not implemented")
45+
}

nodebuilder/node/mocks/api.go

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nodebuilder/node/module.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package node
2+
3+
import (
4+
"go.uber.org/fx"
5+
)
6+
7+
func ConstructModule(tp Type) fx.Option {
8+
return fx.Module(
9+
"node",
10+
fx.Provide(func() Module {
11+
return newModule(tp)
12+
}),
13+
)
14+
}

0 commit comments

Comments
 (0)