Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions cmd/rollkit/commands/run_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package commands

import (
"context"
"errors"
"fmt"
"math/rand"
"net"
"net/url"
"os"
"syscall"
"time"

cmtcmd "github.com/cometbft/cometbft/cmd/cometbft/commands"
Expand All @@ -24,6 +26,7 @@ import (
"github.com/mitchellh/mapstructure"
"google.golang.org/grpc"

"github.com/rollkit/go-da"
proxy "github.com/rollkit/go-da/proxy/jsonrpc"
goDATest "github.com/rollkit/go-da/test"
seqGRPC "github.com/rollkit/go-sequencing/proxy/grpc"
Expand All @@ -47,6 +50,8 @@ var (

// initialize the logger with the cometBFT defaults
logger = cometlog.NewTMLogger(cometlog.NewSyncWriter(os.Stdout))

errMockDAServerAlreadyRunning = errors.New("mock DA server already running")
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
)

// MockSequencerAddress is a sample address used by the mock sequencer
Expand Down Expand Up @@ -127,12 +132,16 @@ func NewRunNodeCmd() *cobra.Command {

// use mock jsonrpc da server by default
if !cmd.Flags().Lookup("rollkit.da_address").Changed {
srv, err := startMockDAServJSONRPC(cmd.Context())
if err != nil {
srv, err := startMockDAServJSONRPC(cmd.Context(), nodeConfig.DAAddress, proxy.NewServer)
if err != nil && !errors.Is(err, errMockDAServerAlreadyRunning) {
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
return fmt.Errorf("failed to launch mock da server: %w", err)
}
// nolint:errcheck,gosec
defer func() { srv.Stop(cmd.Context()) }()
defer func() {
if srv != nil {
srv.Stop(cmd.Context())
}
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
}()
}

// use mock grpc sequencer server by default
Expand Down Expand Up @@ -236,13 +245,27 @@ func addNodeFlags(cmd *cobra.Command) {
}

// startMockDAServJSONRPC starts a mock JSONRPC server
func startMockDAServJSONRPC(ctx context.Context) (*proxy.Server, error) {
addr, _ := url.Parse(nodeConfig.DAAddress)
srv := proxy.NewServer(addr.Hostname(), addr.Port(), goDATest.NewDummyDA())
err := srv.Start(ctx)
func startMockDAServJSONRPC(
ctx context.Context,
daAddress string,
newServer func(string, string, da.DA) *proxy.Server,
) (*proxy.Server, error) {
addr, err := url.Parse(daAddress)
if err != nil {
return nil, err
}

srv := newServer(addr.Hostname(), addr.Port(), goDATest.NewDummyDA())
if err := srv.Start(ctx); err != nil {
if errors.Is(err, syscall.EADDRINUSE) {
logger.Info("Mock DA server is already running", "address", nodeConfig.DAAddress)
return nil, errMockDAServerAlreadyRunning
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
}
return nil, err
}

logger.Info("Starting mock DA server", "address", nodeConfig.DAAddress)

Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
return srv, nil
}

Expand Down
88 changes: 88 additions & 0 deletions cmd/rollkit/commands/run_node_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package commands

import (
"context"
"errors"
"net/url"
"reflect"
"syscall"
"testing"
"time"

"github.com/rollkit/go-da"
proxy "github.com/rollkit/go-da/proxy/jsonrpc"
"github.com/stretchr/testify/assert"
)

func TestParseFlags(t *testing.T) {
Expand Down Expand Up @@ -133,3 +141,83 @@ func TestAggregatorFlagInvariants(t *testing.T) {
}
}
}

// MockServer wraps proxy.Server to allow us to control its behavior in tests
type MockServer struct {
*proxy.Server
StartFunc func(context.Context) error
StopFunc func(context.Context) error
}

func (m *MockServer) Start(ctx context.Context) error {
if m.StartFunc != nil {
return m.StartFunc(ctx)
}
return m.Server.Start(ctx)
}

func (m *MockServer) Stop(ctx context.Context) error {
if m.StopFunc != nil {
return m.StopFunc(ctx)
}
return m.Server.Stop(ctx)
}

func TestStartMockDAServJSONRPC(t *testing.T) {
tests := []struct {
name string
daAddress string
mockServerErr error
expectedErr error
}{
{
name: "Success",
daAddress: "http://localhost:26657",
mockServerErr: nil,
expectedErr: nil,
},
{
name: "Invalid URL",
daAddress: "://invalid",
mockServerErr: nil,
expectedErr: &url.Error{},
},
{
name: "Server Already Running",
daAddress: "http://localhost:26657",
mockServerErr: syscall.EADDRINUSE,
expectedErr: errMockDAServerAlreadyRunning,
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
},
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
{
name: "Other Server Error",
daAddress: "http://localhost:26657",
mockServerErr: errors.New("other error"),
expectedErr: errors.New("other error"),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
newServerFunc := func(hostname, port string, da da.DA) *proxy.Server {
mockServer := &MockServer{
Server: proxy.NewServer(hostname, port, da),
StartFunc: func(ctx context.Context) error {
return tt.mockServerErr
},
}
return mockServer.Server
}

srv, err := startMockDAServJSONRPC(context.Background(), tt.daAddress, newServerFunc)

if tt.expectedErr != nil {
assert.Error(t, err)
assert.IsType(t, tt.expectedErr, err)
assert.Nil(t, srv)
Comment thread
yarikbratashchuk marked this conversation as resolved.
Resolved
} else {
assert.NoError(t, err)
assert.NotNil(t, srv)
}
})
}
}