diff --git a/api/gateway/availability.go b/api/gateway/availability.go deleted file mode 100644 index b399b66483..0000000000 --- a/api/gateway/availability.go +++ /dev/null @@ -1,55 +0,0 @@ -package gateway - -import ( - "encoding/json" - "errors" - "net/http" - "strconv" - - "github.com/gorilla/mux" - - "github.com/celestiaorg/celestia-node/share" -) - -const heightAvailabilityEndpoint = "/data_available" - -// AvailabilityResponse represents the response to a -// `/data_available` request. -type AvailabilityResponse struct { - Available bool `json:"available"` -} - -func (h *Handler) handleHeightAvailabilityRequest(w http.ResponseWriter, r *http.Request) { - heightStr := mux.Vars(r)[heightKey] - height, err := strconv.Atoi(heightStr) - if err != nil { - writeError(w, http.StatusBadRequest, heightAvailabilityEndpoint, err) - return - } - - err = h.share.SharesAvailable(r.Context(), uint64(height)) - switch { - case err == nil: - resp, err := json.Marshal(&AvailabilityResponse{Available: true}) - if err != nil { - writeError(w, http.StatusInternalServerError, heightAvailabilityEndpoint, err) - return - } - _, werr := w.Write(resp) - if werr != nil { - log.Errorw("serving request", "endpoint", heightAvailabilityEndpoint, "err", err) - } - case errors.Is(err, share.ErrNotAvailable): - resp, err := json.Marshal(&AvailabilityResponse{Available: false}) - if err != nil { - writeError(w, http.StatusInternalServerError, heightAvailabilityEndpoint, err) - return - } - _, werr := w.Write(resp) - if werr != nil { - log.Errorw("serving request", "endpoint", heightAvailabilityEndpoint, "err", err) - } - default: - writeError(w, http.StatusInternalServerError, heightAvailabilityEndpoint, err) - } -} diff --git a/api/gateway/bindings.go b/api/gateway/bindings.go deleted file mode 100644 index 257a20e013..0000000000 --- a/api/gateway/bindings.go +++ /dev/null @@ -1,67 +0,0 @@ -package gateway - -import ( - "fmt" - "net/http" -) - -func (h *Handler) RegisterEndpoints(rpc *Server) { - // state endpoints - rpc.RegisterHandlerFunc( - fmt.Sprintf("%s/{%s}", balanceEndpoint, addrKey), - h.handleBalanceRequest, - http.MethodGet, - ) - - rpc.RegisterHandlerFunc( - healthEndpoint, - h.handleHealthRequest, - http.MethodGet, - ) - - // share endpoints - rpc.RegisterHandlerFunc( - fmt.Sprintf( - "%s/{%s}/height/{%s}", - namespacedSharesEndpoint, - namespaceKey, - heightKey, - ), - h.handleSharesByNamespaceRequest, - http.MethodGet, - ) - - rpc.RegisterHandlerFunc( - fmt.Sprintf("%s/{%s}", namespacedSharesEndpoint, namespaceKey), - h.handleSharesByNamespaceRequest, - http.MethodGet, - ) - - rpc.RegisterHandlerFunc( - fmt.Sprintf("%s/{%s}/height/{%s}", namespacedDataEndpoint, namespaceKey, heightKey), - h.handleDataByNamespaceRequest, - http.MethodGet, - ) - - rpc.RegisterHandlerFunc( - fmt.Sprintf("%s/{%s}", namespacedDataEndpoint, namespaceKey), - h.handleDataByNamespaceRequest, - http.MethodGet, - ) - - // DAS endpoints - rpc.RegisterHandlerFunc( - fmt.Sprintf("%s/{%s}", heightAvailabilityEndpoint, heightKey), - h.handleHeightAvailabilityRequest, - http.MethodGet, - ) - - // header endpoints - rpc.RegisterHandlerFunc( - fmt.Sprintf("%s/{%s}", headerByHeightEndpoint, heightKey), - h.handleHeaderRequest, - http.MethodGet, - ) - - rpc.RegisterHandlerFunc(headEndpoint, h.handleHeadRequest, http.MethodGet) -} diff --git a/api/gateway/bindings_test.go b/api/gateway/bindings_test.go deleted file mode 100644 index 338948c584..0000000000 --- a/api/gateway/bindings_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package gateway - -import ( - "fmt" - "net/http" - "testing" - - "github.com/gorilla/mux" - "github.com/stretchr/testify/require" -) - -func TestRegisterEndpoints(t *testing.T) { - handler := &Handler{} - rpc := NewServer("localhost", "6969") - - handler.RegisterEndpoints(rpc) - - testCases := []struct { - name string - path string - method string - expected bool - }{ - { - name: "Get balance endpoint", - path: fmt.Sprintf("%s/{%s}", balanceEndpoint, addrKey), - method: http.MethodGet, - expected: true, - }, - { - name: "Get namespaced shares by height endpoint", - path: fmt.Sprintf("%s/{%s}/height/{%s}", namespacedSharesEndpoint, namespaceKey, heightKey), - method: http.MethodGet, - expected: true, - }, - { - name: "Get namespaced shares endpoint", - path: fmt.Sprintf("%s/{%s}", namespacedSharesEndpoint, namespaceKey), - method: http.MethodGet, - expected: true, - }, - { - name: "Get namespaced data by height endpoint", - path: fmt.Sprintf("%s/{%s}/height/{%s}", namespacedDataEndpoint, namespaceKey, heightKey), - method: http.MethodGet, - expected: true, - }, - { - name: "Get namespaced data endpoint", - path: fmt.Sprintf("%s/{%s}", namespacedDataEndpoint, namespaceKey), - method: http.MethodGet, - expected: true, - }, - { - name: "Get health endpoint", - path: "/status/health", - method: http.MethodGet, - expected: true, - }, - - // Going forward, we can add previously deprecated and since - // removed endpoints here to ensure we don't accidentally re-enable - // them in the future and accidentally expand surface area - { - name: "example totally bogus endpoint", - path: fmt.Sprintf("/wutang/{%s}/%s", "chambers", "36"), - method: http.MethodGet, - expected: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - require.Equal( - t, - tc.expected, - hasEndpointRegistered(rpc.Router(), tc.path, tc.method), - "Endpoint registration mismatch for: %s %s %s", tc.name, tc.method, tc.path) - }) - } -} - -func hasEndpointRegistered(router *mux.Router, path, method string) bool { - var registered bool - err := router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { - template, err := route.GetPathTemplate() - if err != nil { - return err - } - - if template == path { - methods, err := route.GetMethods() - if err != nil { - return err - } - - for _, m := range methods { - if m == method { - registered = true - return nil - } - } - } - return nil - }) - if err != nil { - fmt.Println("Error walking through routes:", err) - return false - } - - return registered -} diff --git a/api/gateway/config.go b/api/gateway/config.go deleted file mode 100644 index 0485da486e..0000000000 --- a/api/gateway/config.go +++ /dev/null @@ -1,23 +0,0 @@ -package gateway - -import ( - "fmt" - "net" - "strconv" -) - -type Config struct { - Address string - Port string -} - -func (cfg *Config) Validate() error { - if ip := net.ParseIP(cfg.Address); ip == nil { - return fmt.Errorf("service/gateway: invalid listen address format: %s", cfg.Address) - } - _, err := strconv.Atoi(cfg.Port) - if err != nil { - return fmt.Errorf("service/gateway: invalid port: %s", err.Error()) - } - return nil -} diff --git a/api/gateway/handler.go b/api/gateway/handler.go deleted file mode 100644 index 2602528170..0000000000 --- a/api/gateway/handler.go +++ /dev/null @@ -1,33 +0,0 @@ -package gateway - -import ( - logging "github.com/ipfs/go-log/v2" - - "github.com/celestiaorg/celestia-node/das" - "github.com/celestiaorg/celestia-node/nodebuilder/header" - "github.com/celestiaorg/celestia-node/nodebuilder/share" - "github.com/celestiaorg/celestia-node/nodebuilder/state" -) - -var log = logging.Logger("gateway") - -type Handler struct { - state state.Module - share share.Module - header header.Module - das *das.DASer -} - -func NewHandler( - state state.Module, - share share.Module, - header header.Module, - das *das.DASer, -) *Handler { - return &Handler{ - state: state, - share: share, - header: header, - das: das, - } -} diff --git a/api/gateway/header.go b/api/gateway/header.go deleted file mode 100644 index f76d5d48e1..0000000000 --- a/api/gateway/header.go +++ /dev/null @@ -1,78 +0,0 @@ -package gateway - -import ( - "encoding/json" - "net/http" - "strconv" - - "github.com/gorilla/mux" - - "github.com/celestiaorg/celestia-node/header" -) - -const ( - headEndpoint = "/head" - headerByHeightEndpoint = "/header" -) - -var heightKey = "height" - -func (h *Handler) handleHeadRequest(w http.ResponseWriter, r *http.Request) { - head, err := h.header.LocalHead(r.Context()) - if err != nil { - writeError(w, http.StatusInternalServerError, headEndpoint, err) - return - } - resp, err := json.Marshal(head) - if err != nil { - writeError(w, http.StatusInternalServerError, headEndpoint, err) - return - } - _, err = w.Write(resp) - if err != nil { - log.Errorw("writing response", "endpoint", headEndpoint, "err", err) - return - } -} - -func (h *Handler) handleHeaderRequest(w http.ResponseWriter, r *http.Request) { - header, err := h.performGetHeaderRequest(w, r, headerByHeightEndpoint) - if err != nil { - // return here as we've already logged and written the error - return - } - // marshal and write response - resp, err := json.Marshal(header) - if err != nil { - writeError(w, http.StatusInternalServerError, headerByHeightEndpoint, err) - return - } - _, err = w.Write(resp) - if err != nil { - log.Errorw("writing response", "endpoint", headerByHeightEndpoint, "err", err) - return - } -} - -func (h *Handler) performGetHeaderRequest( - w http.ResponseWriter, - r *http.Request, - endpoint string, -) (*header.ExtendedHeader, error) { - // read and parse request - vars := mux.Vars(r) - heightStr := vars[heightKey] - height, err := strconv.Atoi(heightStr) - if err != nil { - writeError(w, http.StatusBadRequest, endpoint, err) - return nil, err - } - - header, err := h.header.GetByHeight(r.Context(), uint64(height)) - if err != nil { - writeError(w, http.StatusInternalServerError, endpoint, err) - return nil, err - } - - return header, nil -} diff --git a/api/gateway/health.go b/api/gateway/health.go deleted file mode 100644 index 2a96e0200e..0000000000 --- a/api/gateway/health.go +++ /dev/null @@ -1,18 +0,0 @@ -package gateway - -import ( - "net/http" -) - -const ( - healthEndpoint = "/status/health" -) - -func (h *Handler) handleHealthRequest(w http.ResponseWriter, _ *http.Request) { - _, err := w.Write([]byte("ok")) - if err != nil { - log.Errorw("serving request", "endpoint", healthEndpoint, "err", err) - writeError(w, http.StatusBadGateway, healthEndpoint, err) - return - } -} diff --git a/api/gateway/middleware.go b/api/gateway/middleware.go deleted file mode 100644 index 4b669113dd..0000000000 --- a/api/gateway/middleware.go +++ /dev/null @@ -1,41 +0,0 @@ -package gateway - -import ( - "context" - "net/http" - "time" -) - -const timeout = time.Minute - -func (h *Handler) RegisterMiddleware(srv *Server) { - srv.RegisterMiddleware( - setContentType, - wrapRequestContext, - enableCors, - ) -} - -func enableCors(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Access-Control-Allow-Origin", "*") - next.ServeHTTP(w, r) - }) -} - -func setContentType(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("Content-Type", "application/json") - next.ServeHTTP(w, r) - }) -} - -// wrapRequestContext ensures we implement a deadline on serving requests -// via the gateway server-side to prevent context leaks. -func wrapRequestContext(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx, cancel := context.WithTimeout(r.Context(), timeout) - defer cancel() - next.ServeHTTP(w, r.WithContext(ctx)) - }) -} diff --git a/api/gateway/server.go b/api/gateway/server.go deleted file mode 100644 index 7eab7c7bf9..0000000000 --- a/api/gateway/server.go +++ /dev/null @@ -1,103 +0,0 @@ -package gateway - -import ( - "context" - "net" - "net/http" - "sync/atomic" - "time" - - "github.com/gorilla/mux" -) - -// Server represents a gateway server on the Node. -type Server struct { - srv *http.Server - srvMux *mux.Router // http request multiplexer - listener net.Listener - - started atomic.Bool -} - -// NewServer returns a new gateway Server. -func NewServer(address, port string) *Server { - srvMux := mux.NewRouter() - srvMux.Use(setContentType) - - server := &Server{ - srvMux: srvMux, - } - server.srv = &http.Server{ - Addr: address + ":" + port, - Handler: server, - // the amount of time allowed to read request headers. set to the default 2 seconds - ReadHeaderTimeout: 2 * time.Second, - } - return server -} - -func (s *Server) Router() *mux.Router { - return s.srvMux -} - -// Start starts the gateway Server, listening on the given address. -func (s *Server) Start(context.Context) error { - couldStart := s.started.CompareAndSwap(false, true) - if !couldStart { - log.Warn("cannot start server: already started") - return nil - } - listener, err := net.Listen("tcp", s.srv.Addr) - if err != nil { - return err - } - s.listener = listener - log.Infow("server started", "listening on", s.srv.Addr) - //nolint:errcheck - go s.srv.Serve(listener) - return nil -} - -// Stop stops the gateway Server. -func (s *Server) Stop(ctx context.Context) error { - couldStop := s.started.CompareAndSwap(true, false) - if !couldStop { - log.Warn("cannot stop server: already stopped") - return nil - } - err := s.srv.Shutdown(ctx) - if err != nil { - return err - } - s.listener = nil - log.Info("server stopped") - return nil -} - -// RegisterMiddleware allows to register a custom middleware that will be called before -// http.Request will reach handler. -func (s *Server) RegisterMiddleware(middlewareFuncs ...mux.MiddlewareFunc) { - for _, m := range middlewareFuncs { - // `router.Use` appends new middleware to existing - s.srvMux.Use(m) - } -} - -// RegisterHandlerFunc registers the given http.HandlerFunc on the Server's multiplexer -// on the given pattern. -func (s *Server) RegisterHandlerFunc(pattern string, handlerFunc http.HandlerFunc, method string) { - s.srvMux.HandleFunc(pattern, handlerFunc).Methods(method) -} - -// ServeHTTP serves inbound requests on the Server. -func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { - s.srvMux.ServeHTTP(w, r) -} - -// ListenAddr returns the listen address of the server. -func (s *Server) ListenAddr() string { - if s.listener == nil { - return "" - } - return s.listener.Addr().String() -} diff --git a/api/gateway/server_test.go b/api/gateway/server_test.go deleted file mode 100644 index cb8e3d17ae..0000000000 --- a/api/gateway/server_test.go +++ /dev/null @@ -1,129 +0,0 @@ -package gateway - -import ( - "context" - "fmt" - "io" - "net/http" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - address = "localhost" - port = "0" -) - -func TestServer(t *testing.T) { - server := NewServer(address, port) - - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) - - err := server.Start(ctx) - require.NoError(t, err) - - // register ping handler - ping := new(ping) - server.RegisterHandlerFunc("/ping", ping.ServeHTTP, http.MethodGet) - - url := fmt.Sprintf("http://%s/ping", server.ListenAddr()) - - resp, err := http.Get(url) - require.NoError(t, err) - - buf, err := io.ReadAll(resp.Body) - require.NoError(t, err) - t.Cleanup(func() { - resp.Body.Close() - }) - assert.Equal(t, "pong", string(buf)) - - err = server.Stop(ctx) - require.NoError(t, err) -} - -func TestCorsEnabled(t *testing.T) { - server := NewServer(address, port) - server.RegisterMiddleware(enableCors) - - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) - - err := server.Start(ctx) - require.NoError(t, err) - - // register ping handler - ping := new(ping) - server.RegisterHandlerFunc("/ping", ping.ServeHTTP, http.MethodGet) - - url := fmt.Sprintf("http://%s/ping", server.ListenAddr()) - - resp, err := http.Get(url) - require.NoError(t, err) - defer resp.Body.Close() - - require.NoError(t, err) - require.Equal(t, resp.Header.Get("Access-Control-Allow-Origin"), "*") -} - -// TestServer_contextLeakProtection tests to ensure a context -// deadline was added by the context wrapper middleware server-side. -func TestServer_contextLeakProtection(t *testing.T) { - server := NewServer(address, port) - server.RegisterMiddleware(wrapRequestContext) - - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) - - err := server.Start(ctx) - require.NoError(t, err) - - // register ping handler - ch := new(contextHandler) - server.RegisterHandlerFunc("/ch", ch.ServeHTTP, http.MethodGet) - - url := fmt.Sprintf("http://%s/ch", server.ListenAddr()) - req, err := http.NewRequest(http.MethodGet, url, nil) - require.NoError(t, err) - - cli := new(http.Client) - - originalCtx, originalCancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute)) - t.Cleanup(originalCancel) - resp, err := cli.Do(req.WithContext(originalCtx)) - require.NoError(t, err) - buf, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.NoError(t, resp.Body.Close()) - - dur := new(time.Time) - err = dur.UnmarshalJSON(buf) - require.NoError(t, err) - assert.True(t, dur.After(time.Now())) -} - -type ping struct{} - -func (p ping) ServeHTTP(w http.ResponseWriter, _ *http.Request) { - //nolint:errcheck - w.Write([]byte("pong")) -} - -type contextHandler struct{} - -func (ch contextHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - deadline, ok := r.Context().Deadline() - if !ok { - w.Write([]byte("no deadline")) //nolint:errcheck - return - } - bin, err := deadline.MarshalJSON() - if err != nil { - panic(err) - } - w.Write(bin) //nolint:errcheck -} diff --git a/api/gateway/share.go b/api/gateway/share.go deleted file mode 100644 index 835916d923..0000000000 --- a/api/gateway/share.go +++ /dev/null @@ -1,139 +0,0 @@ -package gateway - -import ( - "context" - "encoding/hex" - "encoding/json" - "net/http" - "strconv" - - "github.com/gorilla/mux" - - libshare "github.com/celestiaorg/go-square/v2/share" -) - -const ( - namespacedSharesEndpoint = "/namespaced_shares" - namespacedDataEndpoint = "/namespaced_data" -) - -var namespaceKey = "nid" - -// NamespacedSharesResponse represents the response to a -// SharesByNamespace request. -type NamespacedSharesResponse struct { - Shares []libshare.Share `json:"shares"` - Height uint64 `json:"height"` -} - -// NamespacedDataResponse represents the response to a -// DataByNamespace request. -type NamespacedDataResponse struct { - Data [][]byte `json:"data"` - Height uint64 `json:"height"` -} - -func (h *Handler) handleSharesByNamespaceRequest(w http.ResponseWriter, r *http.Request) { - height, namespace, err := parseGetByNamespaceArgs(r) - if err != nil { - writeError(w, http.StatusBadRequest, namespacedSharesEndpoint, err) - return - } - shares, err := h.getShares(r.Context(), height, namespace) - if err != nil { - writeError(w, http.StatusInternalServerError, namespacedSharesEndpoint, err) - return - } - resp, err := json.Marshal(&NamespacedSharesResponse{ - Shares: shares, - Height: height, - }) - if err != nil { - writeError(w, http.StatusInternalServerError, namespacedSharesEndpoint, err) - return - } - _, err = w.Write(resp) - if err != nil { - log.Errorw("serving request", "endpoint", namespacedSharesEndpoint, "err", err) - } -} - -func (h *Handler) handleDataByNamespaceRequest(w http.ResponseWriter, r *http.Request) { - height, namespace, err := parseGetByNamespaceArgs(r) - if err != nil { - writeError(w, http.StatusBadRequest, namespacedDataEndpoint, err) - return - } - shares, err := h.getShares(r.Context(), height, namespace) - if err != nil { - writeError(w, http.StatusInternalServerError, namespacedDataEndpoint, err) - return - } - data, err := dataFromShares(shares) - if err != nil { - writeError(w, http.StatusInternalServerError, namespacedDataEndpoint, err) - return - } - resp, err := json.Marshal(&NamespacedDataResponse{ - Data: data, - Height: height, - }) - if err != nil { - writeError(w, http.StatusInternalServerError, namespacedDataEndpoint, err) - return - } - _, err = w.Write(resp) - if err != nil { - log.Errorw("serving request", "endpoint", namespacedDataEndpoint, "err", err) - } -} - -func (h *Handler) getShares( - ctx context.Context, - height uint64, - namespace libshare.Namespace, -) ([]libshare.Share, error) { - shares, err := h.share.GetNamespaceData(ctx, height, namespace) - if err != nil { - return nil, err - } - - return shares.Flatten(), nil -} - -func dataFromShares(input []libshare.Share) (data [][]byte, err error) { - sequences, err := libshare.ParseShares(input, false) - if err != nil { - return nil, err - } - for _, sequence := range sequences { - raw, err := sequence.RawData() - if err != nil { - return nil, err - } - data = append(data, raw) - } - return data, nil -} - -func parseGetByNamespaceArgs(r *http.Request) (height uint64, namespace libshare.Namespace, err error) { - vars := mux.Vars(r) - // if a height was given, parse it, otherwise get namespaced shares/data from the latest header - if strHeight, ok := vars[heightKey]; ok { - height, err = strconv.ParseUint(strHeight, 10, 64) - if err != nil { - return 0, libshare.Namespace{}, err - } - } - hexNamespace := vars[namespaceKey] - nsString, err := hex.DecodeString(hexNamespace) - if err != nil { - return 0, libshare.Namespace{}, err - } - ns, err := libshare.NewNamespaceFromBytes(nsString) - if err != nil { - return 0, libshare.Namespace{}, err - } - namespace = ns - return height, namespace, namespace.ValidateForData() -} diff --git a/api/gateway/share_test.go b/api/gateway/share_test.go deleted file mode 100644 index 1096287ffc..0000000000 --- a/api/gateway/share_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package gateway - -import ( - _ "embed" - "testing" - - "github.com/stretchr/testify/require" - - libshare "github.com/celestiaorg/go-square/v2/share" -) - -func Test_dataFromShares(t *testing.T) { - testData := [][]byte{ - []byte("beep"), - []byte("beeap"), - []byte("BEEEEAHP"), - } - - ns := libshare.RandomNamespace() - sss := libshare.NewSparseShareSplitter() - for _, data := range testData { - b, err := libshare.NewBlob(ns, data, libshare.ShareVersionZero, nil) - require.NoError(t, err) - require.NoError(t, sss.Write(b)) - } - - sssShares := sss.Export() - - rawSSSShares := make([][]byte, len(sssShares)) - for i := 0; i < len(sssShares); i++ { - d := sssShares[i].ToBytes() - rawSSSShares[i] = d - } - - shrs, err := libshare.FromBytes(rawSSSShares) - require.NoError(t, err) - parsedSSSShares, err := dataFromShares(shrs) - require.NoError(t, err) - - require.Equal(t, testData, parsedSSSShares) -} diff --git a/api/gateway/state.go b/api/gateway/state.go deleted file mode 100644 index 92171a9e7e..0000000000 --- a/api/gateway/state.go +++ /dev/null @@ -1,62 +0,0 @@ -package gateway - -import ( - "encoding/json" - "errors" - "net/http" - - "github.com/cosmos/cosmos-sdk/types" - "github.com/gorilla/mux" - - "github.com/celestiaorg/celestia-node/state" -) - -const ( - balanceEndpoint = "/balance" -) - -const addrKey = "address" - -var ErrInvalidAddressFormat = errors.New("address must be a valid account or validator address") - -func (h *Handler) handleBalanceRequest(w http.ResponseWriter, r *http.Request) { - var ( - bal *state.Balance - err error - ) - // read and parse request - vars := mux.Vars(r) - addrStr, exists := vars[addrKey] - if !exists { - writeError(w, http.StatusBadRequest, balanceEndpoint, errors.New("balance endpoint requires address")) - return - } - - // convert address to Address type - var addr state.AccAddress - addr, err = types.AccAddressFromBech32(addrStr) - if err != nil { - // first check if it is a validator address and can be converted - valAddr, err := types.ValAddressFromBech32(addrStr) - if err != nil { - writeError(w, http.StatusBadRequest, balanceEndpoint, ErrInvalidAddressFormat) - return - } - addr = valAddr.Bytes() - } - - bal, err = h.state.BalanceForAddress(r.Context(), state.Address{Address: addr}) - if err != nil { - writeError(w, http.StatusInternalServerError, balanceEndpoint, err) - return - } - resp, err := json.Marshal(bal) - if err != nil { - writeError(w, http.StatusInternalServerError, balanceEndpoint, err) - return - } - _, err = w.Write(resp) - if err != nil { - log.Errorw("writing response", "endpoint", balanceEndpoint, "err", err) - } -} diff --git a/api/gateway/util.go b/api/gateway/util.go deleted file mode 100644 index d3739f9e9c..0000000000 --- a/api/gateway/util.go +++ /dev/null @@ -1,19 +0,0 @@ -package gateway - -import ( - "net/http" -) - -func writeError(w http.ResponseWriter, statusCode int, endpoint string, err error) { - log.Debugw("serving request", "endpoint", endpoint, "err", err) - - w.WriteHeader(statusCode) - - errorMessage := err.Error() // Get the error message as a string - errorBytes := []byte(errorMessage) - - _, err = w.Write(errorBytes) - if err != nil { - log.Errorw("writing error response", "endpoint", endpoint, "err", err) - } -} diff --git a/api/gateway/util_test.go b/api/gateway/util_test.go deleted file mode 100644 index d41b0918d2..0000000000 --- a/api/gateway/util_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package gateway - -import ( - "errors" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestWriteError(t *testing.T) { - t.Run("writeError", func(t *testing.T) { - // Create a mock HTTP response writer - w := httptest.NewRecorder() - - testErr := errors.New("test error") - - writeError(w, http.StatusInternalServerError, "/api/endpoint", testErr) - assert.Equal(t, http.StatusInternalServerError, w.Code) - responseBody := w.Body.Bytes() - assert.Equal(t, testErr.Error(), string(responseBody)) - }) -} diff --git a/cmd/node.go b/cmd/node.go index 9152eb53e3..36d9e3fcde 100644 --- a/cmd/node.go +++ b/cmd/node.go @@ -5,7 +5,6 @@ import ( "github.com/spf13/pflag" "github.com/celestiaorg/celestia-node/nodebuilder/core" - "github.com/celestiaorg/celestia-node/nodebuilder/gateway" "github.com/celestiaorg/celestia-node/nodebuilder/header" "github.com/celestiaorg/celestia-node/nodebuilder/node" "github.com/celestiaorg/celestia-node/nodebuilder/p2p" @@ -21,7 +20,6 @@ func NewBridge(options ...func(*cobra.Command, []*pflag.FlagSet)) *cobra.Command MiscFlags(), core.Flags(), rpc.Flags(), - gateway.Flags(), state.Flags(), pruner.Flags(), } @@ -47,7 +45,6 @@ func NewLight(options ...func(*cobra.Command, []*pflag.FlagSet)) *cobra.Command MiscFlags(), core.Flags(), rpc.Flags(), - gateway.Flags(), state.Flags(), pruner.Flags(), } @@ -73,7 +70,6 @@ func NewFull(options ...func(*cobra.Command, []*pflag.FlagSet)) *cobra.Command { MiscFlags(), core.Flags(), rpc.Flags(), - gateway.Flags(), state.Flags(), pruner.Flags(), } diff --git a/cmd/util.go b/cmd/util.go index 026002c1d6..c970c4db68 100644 --- a/cmd/util.go +++ b/cmd/util.go @@ -14,7 +14,6 @@ import ( libshare "github.com/celestiaorg/go-square/v2/share" "github.com/celestiaorg/celestia-node/nodebuilder/core" - "github.com/celestiaorg/celestia-node/nodebuilder/gateway" "github.com/celestiaorg/celestia-node/nodebuilder/header" "github.com/celestiaorg/celestia-node/nodebuilder/node" "github.com/celestiaorg/celestia-node/nodebuilder/p2p" @@ -114,7 +113,6 @@ func PersistentPreRunEnv(cmd *cobra.Command, nodeType node.Type, _ []string) err state.ParseFlags(cmd, &cfg.State) rpc_cfg.ParseFlags(cmd, &cfg.RPC) - gateway.ParseFlags(cmd, &cfg.Gateway) pruner.ParseFlags(cmd, &cfg.Pruner, nodeType) switch nodeType { diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 95784ebf9c..f4cbf9a677 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -4,7 +4,7 @@ set -e if [ "$1" = 'celestia' ]; then echo "Initializing Celestia Node with command:" - COMMAND="celestia "${NODE_TYPE}" init --p2p.network "${P2P_NETWORK}" --rpc.addr="0.0.0.0" --gateway.addr="0.0.0.0"" + COMMAND="celestia "${NODE_TYPE}" init --p2p.network "${P2P_NETWORK}" --rpc.addr="0.0.0.0"" if [[ -n "$NODE_STORE" ]]; then COMMAND=${COMMAND}" --node.store "${NODE_STORE}"" echo $COMMAND diff --git a/go.mod b/go.mod index 892231341d..f2848536ec 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,6 @@ require ( github.com/gofrs/flock v0.12.1 github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 - github.com/gorilla/mux v1.8.1 github.com/grafana/otel-profiling-go v0.5.1 github.com/grafana/pyroscope-go v1.1.2 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 @@ -185,6 +184,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect diff --git a/nodebuilder/config.go b/nodebuilder/config.go index f73466e825..d11672dfcd 100644 --- a/nodebuilder/config.go +++ b/nodebuilder/config.go @@ -11,7 +11,6 @@ import ( "github.com/celestiaorg/celestia-node/nodebuilder/core" "github.com/celestiaorg/celestia-node/nodebuilder/das" - "github.com/celestiaorg/celestia-node/nodebuilder/gateway" "github.com/celestiaorg/celestia-node/nodebuilder/header" "github.com/celestiaorg/celestia-node/nodebuilder/node" "github.com/celestiaorg/celestia-node/nodebuilder/p2p" @@ -27,31 +26,29 @@ type ConfigLoader func() (*Config, error) // Config is main configuration structure for a Node. // It combines configuration units for all Node subsystems. type Config struct { - Node node.Config - Core core.Config - State state.Config - P2P p2p.Config - RPC rpc.Config - Gateway gateway.Config - Share share.Config - Header header.Config - DASer das.Config `toml:",omitempty"` - Pruner pruner.Config + Node node.Config + Core core.Config + State state.Config + P2P p2p.Config + RPC rpc.Config + Share share.Config + Header header.Config + DASer das.Config `toml:",omitempty"` + Pruner pruner.Config } // DefaultConfig provides a default Config for a given Node Type 'tp'. // NOTE: Currently, configs are identical, but this will change. func DefaultConfig(tp node.Type) *Config { commonConfig := &Config{ - Node: node.DefaultConfig(tp), - Core: core.DefaultConfig(), - State: state.DefaultConfig(), - P2P: p2p.DefaultConfig(tp), - RPC: rpc.DefaultConfig(), - Gateway: gateway.DefaultConfig(), - Share: share.DefaultConfig(tp), - Header: header.DefaultConfig(tp), - Pruner: pruner.DefaultConfig(), + Node: node.DefaultConfig(tp), + Core: core.DefaultConfig(), + State: state.DefaultConfig(), + P2P: p2p.DefaultConfig(tp), + RPC: rpc.DefaultConfig(), + Share: share.DefaultConfig(tp), + Header: header.DefaultConfig(tp), + Pruner: pruner.DefaultConfig(), } switch tp { diff --git a/nodebuilder/config_test.go b/nodebuilder/config_test.go index 227fefd3c7..38d8cb7f36 100644 --- a/nodebuilder/config_test.go +++ b/nodebuilder/config_test.go @@ -54,7 +54,6 @@ func TestUpdateConfig(t *testing.T) { // ensure old custom values were not changed require.Equal(t, "thisshouldnthavechanged", cfg.State.DefaultKeyName) require.Equal(t, "7979", cfg.RPC.Port) - require.True(t, cfg.Gateway.Enabled) } // outdatedConfig is an outdated config from a light node @@ -87,11 +86,6 @@ var outdatedConfig = ` Address = "0.0.0.0" Port = "7979" -[Gateway] - Address = "0.0.0.0" - Port = "26659" - Enabled = true - [Share] PeersLimit = 5 DiscoveryInterval = "30s" diff --git a/nodebuilder/gateway/config.go b/nodebuilder/gateway/config.go deleted file mode 100644 index c49a4749a3..0000000000 --- a/nodebuilder/gateway/config.go +++ /dev/null @@ -1,37 +0,0 @@ -package gateway - -import ( - "fmt" - "strconv" - - "github.com/celestiaorg/celestia-node/libs/utils" -) - -type Config struct { - Address string - Port string - Enabled bool -} - -func DefaultConfig() Config { - return Config{ - Address: defaultBindAddress, - // do NOT expose the same port as celestia-core by default so that both can run on the same machine - Port: defaultPort, - Enabled: false, - } -} - -func (cfg *Config) Validate() error { - sanitizedAddress, err := utils.ValidateAddr(cfg.Address) - if err != nil { - return fmt.Errorf("gateway: invalid address: %w", err) - } - cfg.Address = sanitizedAddress - - _, err = strconv.Atoi(cfg.Port) - if err != nil { - return fmt.Errorf("gateway: invalid port: %s", err.Error()) - } - return nil -} diff --git a/nodebuilder/gateway/config_test.go b/nodebuilder/gateway/config_test.go deleted file mode 100644 index 9ef3f1e310..0000000000 --- a/nodebuilder/gateway/config_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package gateway - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -// TestDefaultConfig tests that the default gateway config is correct. -func TestDefaultConfig(t *testing.T) { - expected := Config{ - Address: defaultBindAddress, - Port: defaultPort, - Enabled: false, - } - - assert.Equal(t, expected, DefaultConfig()) -} diff --git a/nodebuilder/gateway/constructors.go b/nodebuilder/gateway/constructors.go deleted file mode 100644 index c28153b0a5..0000000000 --- a/nodebuilder/gateway/constructors.go +++ /dev/null @@ -1,26 +0,0 @@ -package gateway - -import ( - "github.com/celestiaorg/celestia-node/api/gateway" - "github.com/celestiaorg/celestia-node/das" - "github.com/celestiaorg/celestia-node/nodebuilder/header" - "github.com/celestiaorg/celestia-node/nodebuilder/share" - "github.com/celestiaorg/celestia-node/nodebuilder/state" -) - -// Handler constructs a new RPC Handler from the given services. -func Handler( - state state.Module, - share share.Module, - header header.Module, - daser *das.DASer, - serv *gateway.Server, -) { - handler := gateway.NewHandler(state, share, header, daser) - handler.RegisterEndpoints(serv) - handler.RegisterMiddleware(serv) -} - -func server(cfg *Config) *gateway.Server { - return gateway.NewServer(cfg.Address, cfg.Port) -} diff --git a/nodebuilder/gateway/defaults.go b/nodebuilder/gateway/defaults.go deleted file mode 100644 index e6c48d5d4e..0000000000 --- a/nodebuilder/gateway/defaults.go +++ /dev/null @@ -1,6 +0,0 @@ -package gateway - -const ( - defaultBindAddress = "localhost" - defaultPort = "26659" -) diff --git a/nodebuilder/gateway/defaults_test.go b/nodebuilder/gateway/defaults_test.go deleted file mode 100644 index c504f8cca4..0000000000 --- a/nodebuilder/gateway/defaults_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package gateway - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestServerDefaultConstants(t *testing.T) { - assert.Equal(t, "localhost", defaultBindAddress) - assert.Equal(t, "26659", defaultPort) -} diff --git a/nodebuilder/gateway/flags.go b/nodebuilder/gateway/flags.go deleted file mode 100644 index 62c6f2a6d2..0000000000 --- a/nodebuilder/gateway/flags.go +++ /dev/null @@ -1,57 +0,0 @@ -package gateway - -import ( - "fmt" - - "github.com/spf13/cobra" - flag "github.com/spf13/pflag" -) - -var ( - enabledFlag = "gateway" - addrFlag = "gateway.addr" - portFlag = "gateway.port" -) - -// Flags gives a set of hardcoded node/gateway package flags. -func Flags() *flag.FlagSet { - flags := &flag.FlagSet{} - - flags.Bool( - enabledFlag, - false, - "Enables the REST gateway. WARNING: gateway will be deprecated in upcoming release!", - ) - flags.String( - addrFlag, - "", - fmt.Sprintf("Set a custom gateway listen address (default: %s)", defaultBindAddress), - ) - flags.String( - portFlag, - "", - fmt.Sprintf("Set a custom gateway port (default: %s)", defaultPort), - ) - - return flags -} - -// ParseFlags parses gateway flags from the given cmd and saves them to the passed config. -func ParseFlags(cmd *cobra.Command, cfg *Config) { - enabled, err := cmd.Flags().GetBool(enabledFlag) - if cmd.Flags().Changed(enabledFlag) && err == nil { - cfg.Enabled = enabled - } - addr, port := cmd.Flag(addrFlag), cmd.Flag(portFlag) - if !cfg.Enabled && (addr.Changed || port.Changed) { - log.Warn("custom address or port provided without enabling gateway, setting config values") - } - addrVal := addr.Value.String() - if addrVal != "" { - cfg.Address = addrVal - } - portVal := port.Value.String() - if portVal != "" { - cfg.Port = portVal - } -} diff --git a/nodebuilder/gateway/flags_test.go b/nodebuilder/gateway/flags_test.go deleted file mode 100644 index 893d793fcc..0000000000 --- a/nodebuilder/gateway/flags_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package gateway - -import ( - "fmt" - "strconv" - "testing" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestFlags(t *testing.T) { - flags := Flags() - - enabled := flags.Lookup(enabledFlag) - require.NotNil(t, enabled) - assert.Equal(t, "false", enabled.Value.String()) - assert.Equal(t, "Enables the REST gateway. WARNING: gateway will be deprecated in upcoming release!", enabled.Usage) - - addr := flags.Lookup(addrFlag) - require.NotNil(t, addr) - assert.Equal(t, "", addr.Value.String()) - assert.Equal(t, fmt.Sprintf("Set a custom gateway listen address (default: %s)", defaultBindAddress), addr.Usage) - - port := flags.Lookup(portFlag) - require.NotNil(t, port) - assert.Equal(t, "", port.Value.String()) - assert.Equal(t, fmt.Sprintf("Set a custom gateway port (default: %s)", defaultPort), port.Usage) -} - -func TestParseFlags(t *testing.T) { - tests := []struct { - name string - enabledFlag bool - addrFlag string - portFlag string - expectedCfg *Config - }{ - { - name: "Enabled flag is true", - enabledFlag: true, - addrFlag: "127.0.0.1", - portFlag: "8080", - expectedCfg: &Config{ - Enabled: true, - Address: "127.0.0.1", - Port: "8080", - }, - }, - { - name: "Enabled flag is false", - enabledFlag: false, - addrFlag: "127.0.0.1", - portFlag: "8080", - expectedCfg: &Config{ - Enabled: false, - Address: "127.0.0.1", - Port: "8080", - }, - }, - { - name: "Enabled flag is false and address/port flags are not changed", - enabledFlag: false, - addrFlag: "", - portFlag: "", - expectedCfg: &Config{ - Enabled: false, - Address: "", - Port: "", - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - cmd := &cobra.Command{} - cfg := &Config{} - - cmd.Flags().AddFlagSet(Flags()) - - err := cmd.Flags().Set(enabledFlag, strconv.FormatBool(test.enabledFlag)) - assert.NoError(t, err) - err = cmd.Flags().Set(addrFlag, test.addrFlag) - assert.NoError(t, err) - err = cmd.Flags().Set(portFlag, test.portFlag) - assert.NoError(t, err) - - ParseFlags(cmd, cfg) - assert.Equal(t, test.expectedCfg.Enabled, cfg.Enabled) - assert.Equal(t, test.expectedCfg.Address, cfg.Address) - assert.Equal(t, test.expectedCfg.Port, cfg.Port) - }) - } -} diff --git a/nodebuilder/gateway/module.go b/nodebuilder/gateway/module.go deleted file mode 100644 index 20306aa7de..0000000000 --- a/nodebuilder/gateway/module.go +++ /dev/null @@ -1,63 +0,0 @@ -package gateway - -import ( - "context" - - logging "github.com/ipfs/go-log/v2" - "go.uber.org/fx" - - "github.com/celestiaorg/celestia-node/api/gateway" - headerServ "github.com/celestiaorg/celestia-node/nodebuilder/header" - "github.com/celestiaorg/celestia-node/nodebuilder/node" - shareServ "github.com/celestiaorg/celestia-node/nodebuilder/share" - stateServ "github.com/celestiaorg/celestia-node/nodebuilder/state" -) - -var log = logging.Logger("module/gateway") - -func ConstructModule(tp node.Type, cfg *Config) fx.Option { - // sanitize config values before constructing module - cfgErr := cfg.Validate() - if !cfg.Enabled { - return fx.Options() - } - - log.Warn("WARNING: gateway module is deprecated and will be removed in an upcoming release.") - baseComponents := fx.Options( - fx.Supply(cfg), - fx.Error(cfgErr), - fx.Provide(fx.Annotate( - server, - fx.OnStart(func(ctx context.Context, server *gateway.Server) error { - return server.Start(ctx) - }), - fx.OnStop(func(ctx context.Context, server *gateway.Server) error { - return server.Stop(ctx) - }), - )), - ) - - switch tp { - case node.Light, node.Full: - return fx.Module( - "gateway", - baseComponents, - fx.Invoke(Handler), - ) - case node.Bridge: - return fx.Module( - "gateway", - baseComponents, - fx.Invoke(func( - state stateServ.Module, - share shareServ.Module, - header headerServ.Module, - serv *gateway.Server, - ) { - Handler(state, share, header, nil, serv) - }), - ) - default: - panic("invalid node type") - } -} diff --git a/nodebuilder/module.go b/nodebuilder/module.go index 43de56eedd..7a9cfed93b 100644 --- a/nodebuilder/module.go +++ b/nodebuilder/module.go @@ -13,7 +13,6 @@ import ( "github.com/celestiaorg/celestia-node/nodebuilder/da" "github.com/celestiaorg/celestia-node/nodebuilder/das" "github.com/celestiaorg/celestia-node/nodebuilder/fraud" - "github.com/celestiaorg/celestia-node/nodebuilder/gateway" modhead "github.com/celestiaorg/celestia-node/nodebuilder/header" "github.com/celestiaorg/celestia-node/nodebuilder/node" "github.com/celestiaorg/celestia-node/nodebuilder/p2p" @@ -48,7 +47,6 @@ func ConstructModule(tp node.Type, network p2p.Network, cfg *Config, store Store p2p.ConstructModule(tp, &cfg.P2P), modhead.ConstructModule[*header.ExtendedHeader](tp, &cfg.Header), share.ConstructModule(tp, &cfg.Share), - gateway.ConstructModule(tp, &cfg.Gateway), state.ConstructModule(tp, &cfg.State, &cfg.Core), das.ConstructModule(tp, &cfg.DASer), fraud.ConstructModule(tp), diff --git a/nodebuilder/node.go b/nodebuilder/node.go index b328d8c590..b5ac9e6204 100644 --- a/nodebuilder/node.go +++ b/nodebuilder/node.go @@ -19,7 +19,6 @@ import ( "go.uber.org/fx/fxevent" "go.uber.org/zap/zapcore" - "github.com/celestiaorg/celestia-node/api/gateway" "github.com/celestiaorg/celestia-node/api/rpc" "github.com/celestiaorg/celestia-node/nodebuilder/blob" "github.com/celestiaorg/celestia-node/nodebuilder/blobstream" @@ -55,8 +54,7 @@ type Node struct { AdminSigner jwt.Signer // rpc components - RPCServer *rpc.Server // not optional - GatewayServer *gateway.Server `optional:"true"` + RPCServer *rpc.Server // not optional // block store EDSStore *store.Store `optional:"true"` diff --git a/nodebuilder/rpc/config_test.go b/nodebuilder/rpc/config_test.go index 1c78a1a19f..0b18159c3a 100644 --- a/nodebuilder/rpc/config_test.go +++ b/nodebuilder/rpc/config_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) -// TestDefaultConfig tests that the default gateway config is correct. +// TestDefaultConfig tests that the default rpc config is correct. func TestDefaultConfig(t *testing.T) { expected := Config{ Address: defaultBindAddress, diff --git a/nodebuilder/tests/blob_test.go b/nodebuilder/tests/blob_test.go index 4b5ad52b24..8596d49527 100644 --- a/nodebuilder/tests/blob_test.go +++ b/nodebuilder/tests/blob_test.go @@ -111,7 +111,6 @@ func TestBlobModule(t *testing.T) { assert.Equal(t, v1[0].Commitment, blobV1.Commitment) assert.NotNil(t, blobV1.Signer()) assert.Equal(t, blobV1.Signer(), v1[0].Signer()) - }, }, {