Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Note that as network usage increases, hardware requirements may change.
- CPU: Equivalent of 8 AWS vCPU
- RAM: 16 GB
- Storage: 200 GB
- OS: Ubuntu 18.04/20.04 or MacOS >= Catalina
- OS: Ubuntu 18.04/20.04 or macOS >= 10.15 (Catalina)
- Network: Reliable IPv4 or IPv6 network connection, with an open public port.
- Software Dependencies:
- [Go](https://golang.org/doc/install) version >= 1.16.8 and set up [`$GOPATH`](https://github.com/golang/go/wiki/SettingGOPATH).
Expand Down
32 changes: 32 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# Release Notes

## [v1.7.2](https://github.com/ava-labs/avalanchego/releases/tag/v1.7.2)

This version is backwards compatible to [v1.7.0](https://github.com/ava-labs/avalanchego/releases/tag/v1.7.0). It is optional, but encouraged.

### Coreth

- Fixed memory leak in the estimate gas API.
- Reduced the default RPC gas limit to 50,000,000 gas.
- Improved RPC logging.
- Removed pre-AP5 legacy code.

### PlatformVM

- Optimized validator set change calculations.
- Removed storage of non-decided blocks.
- Simplified error handling.
- Removed pre-AP5 legacy code.

### Networking

- Explicitly fail requests with responses that failed to be parsed.
- Removed pre-AP5 legacy code.

### Configs

- Introduced the ability for a delayed graceful node shutdown.
- Added the ability to take all configs as environment variables for containerized deployments.

### Utils

- Fixed panic bug in logging library when importing from external projects.

## [v1.7.1](https://github.com/ava-labs/avalanchego/releases/tag/v1.7.1)

This update is backwards compatible with [v1.7.0](https://github.com/ava-labs/avalanchego/releases/tag/v1.7.0). Please see the expected update times in the v1.7.0 release.
Expand Down
2 changes: 1 addition & 1 deletion api/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ func (a *auth) CreateHandler() (http.Handler, error) {
server.RegisterCodec(codec, "application/json")
server.RegisterCodec(codec, "application/json;charset=UTF-8")
return server, server.RegisterService(
&service{auth: a},
&Service{auth: a},
"auth",
)
}
Expand Down
10 changes: 5 additions & 5 deletions api/auth/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"github.com/ava-labs/avalanchego/api"
)

// service that serves the Auth API functionality.
type service struct {
// Service that serves the Auth API functionality.
type Service struct {
auth *auth
}

Expand All @@ -32,7 +32,7 @@ type Token struct {
Token string `json:"token"` // The new token. Expires in [TokenLifespan].
}

func (s *service) NewToken(_ *http.Request, args *NewTokenArgs, reply *Token) error {
func (s *Service) NewToken(_ *http.Request, args *NewTokenArgs, reply *Token) error {
s.auth.log.Debug("Auth: NewToken called")

var err error
Expand All @@ -45,7 +45,7 @@ type RevokeTokenArgs struct {
Token
}

func (s *service) RevokeToken(_ *http.Request, args *RevokeTokenArgs, reply *api.SuccessResponse) error {
func (s *Service) RevokeToken(_ *http.Request, args *RevokeTokenArgs, reply *api.SuccessResponse) error {
s.auth.log.Debug("Auth: RevokeToken called")

reply.Success = true
Expand All @@ -57,7 +57,7 @@ type ChangePasswordArgs struct {
NewPassword string `json:"newPassword"` // New authorization password
}

func (s *service) ChangePassword(_ *http.Request, args *ChangePasswordArgs, reply *api.SuccessResponse) error {
func (s *Service) ChangePassword(_ *http.Request, args *ChangePasswordArgs, reply *api.SuccessResponse) error {
s.auth.log.Debug("Auth: ChangePassword called")

reply.Success = true
Expand Down
92 changes: 92 additions & 0 deletions api/health/health.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package health

import (
"net/http"
"time"

stdjson "encoding/json"

"github.com/gorilla/rpc/v2"

"github.com/prometheus/client_golang/prometheus"

"github.com/ava-labs/avalanchego/snow/engine/common"
"github.com/ava-labs/avalanchego/utils/json"
"github.com/ava-labs/avalanchego/utils/logging"

healthlib "github.com/ava-labs/avalanchego/health"
)

var _ Health = &health{}

// Health wraps a [healthlib.Service]. Handler() returns a handler that handles
// incoming HTTP API requests. We have this in a separate package from
// [healthlib] to avoid a circular import where this service imports
// snow/engine/common but that package imports [healthlib].Checkable
type Health interface {
healthlib.Service

Handler() (*common.HTTPHandler, error)
}

func New(checkFreq time.Duration, log logging.Logger, namespace string, registry prometheus.Registerer) (Health, error) {
service, err := healthlib.NewService(checkFreq, log, namespace, registry)
return &health{
Service: service,
log: log,
}, err
}

type health struct {
healthlib.Service
log logging.Logger
}

func (h *health) Handler() (*common.HTTPHandler, error) {
newServer := rpc.NewServer()
codec := json.NewCodec()
newServer.RegisterCodec(codec, "application/json")
newServer.RegisterCodec(codec, "application/json;charset=UTF-8")

// If a GET request is sent, we respond with a 200 if the node is healthy or
// a 503 if the node isn't healthy.
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
newServer.ServeHTTP(w, r)
return
}

// Make sure the content type is set before writing the header.
w.Header().Set("Content-Type", "application/json")

checks, healthy := h.Results()
if !healthy {
// If a health check has failed, we should return a 503.
w.WriteHeader(http.StatusServiceUnavailable)
}
// The encoder will call write on the writer, which will write the
// header with a 200.
err := stdjson.NewEncoder(w).Encode(APIHealthServerReply{
Checks: checks,
Healthy: healthy,
})
if err != nil {
h.log.Debug("failed to encode the health check response due to %s", err)
}
})

err := newServer.RegisterService(
&Service{
log: h.log,
health: h.Service,
},
"health",
)
return &common.HTTPHandler{
LockOptions: common.NoLock,
Handler: handler,
}, err
}
30 changes: 30 additions & 0 deletions api/health/no_op.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package health

import (
healthback "github.com/AppsFlyer/go-sundheit"

"github.com/ava-labs/avalanchego/snow/engine/common"

healthlib "github.com/ava-labs/avalanchego/health"
)

var _ Health = &noOp{}

type noOp struct{}

// NewNoOp returns a noop version of the health interface that does nothing for
// when the Health API is disabled
func NewNoOp() Health { return &noOp{} }

func (n *noOp) Results() (map[string]healthback.Result, bool) {
return map[string]healthback.Result{}, true
}

func (n *noOp) RegisterCheck(string, healthlib.Check) error { return nil }

func (n *noOp) RegisterMonotonicCheck(string, healthlib.Check) error { return nil }

func (n *noOp) Handler() (*common.HTTPHandler, error) { return nil, nil }
116 changes: 10 additions & 106 deletions api/health/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,134 +5,38 @@ package health

import (
"net/http"
"time"

stdjson "encoding/json"

health "github.com/AppsFlyer/go-sundheit"
healthback "github.com/AppsFlyer/go-sundheit"

"github.com/gorilla/rpc/v2"

"github.com/prometheus/client_golang/prometheus"

"github.com/ava-labs/avalanchego/snow/engine/common"
"github.com/ava-labs/avalanchego/utils/json"
"github.com/ava-labs/avalanchego/utils/logging"

healthlib "github.com/ava-labs/avalanchego/health"
)

var _ Service = &apiServer{}

// Service wraps a [healthlib.Service]. Handler() returns a handler
// that handles incoming HTTP API requests. We have this in a separate
// package from [healthlib] to avoid a circular import where this service
// imports snow/engine/common but that package imports [healthlib].Checkable
type Service interface {
healthlib.Service
Handler() (*common.HTTPHandler, error)
}

func NewService(checkFreq time.Duration, log logging.Logger, namespace string, registry prometheus.Registerer) (Service, error) {
service, err := healthlib.NewService(checkFreq, log, namespace, registry)
if err != nil {
return nil, err
}
return &apiServer{
Service: service,
log: log,
}, nil
}

// APIServer serves HTTP for a health service
type apiServer struct {
healthlib.Service
log logging.Logger
}

func (as *apiServer) Handler() (*common.HTTPHandler, error) {
newServer := rpc.NewServer()
codec := json.NewCodec()
newServer.RegisterCodec(codec, "application/json")
newServer.RegisterCodec(codec, "application/json;charset=UTF-8")
if err := newServer.RegisterService(as, "health"); err != nil {
return nil, err
}

// If a GET request is sent, we respond with a 200 if the node is healthy or
// a 503 if the node isn't healthy.
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
newServer.ServeHTTP(w, r)
return
}

// Make sure the content type is set before writing the header.
w.Header().Set("Content-Type", "application/json")

checks, healthy := as.Results()
if !healthy {
// If a health check has failed, we should return a 503.
w.WriteHeader(http.StatusServiceUnavailable)
}
// The encoder will call write on the writer, which will write the
// header with a 200.
err := stdjson.NewEncoder(w).Encode(APIHealthServerReply{
Checks: checks,
Healthy: healthy,
})
if err != nil {
as.log.Debug("failed to encode the health check response due to %s", err)
}
})
return &common.HTTPHandler{LockOptions: common.NoLock, Handler: handler}, nil
type Service struct {
log logging.Logger
health healthlib.Service
}

// APIHealthArgs are the arguments for Health
type APIHealthArgs struct{}

// APIHealthReply is the response for Health
type APIHealthServerReply struct {
Checks map[string]health.Result `json:"checks"`
Healthy bool `json:"healthy"`
Checks map[string]healthback.Result `json:"checks"`
Healthy bool `json:"healthy"`
}

// Health returns a summation of the health of the node
func (as *apiServer) Health(_ *http.Request, _ *APIHealthArgs, reply *APIHealthServerReply) error {
as.log.Debug("Health.health called")
reply.Checks, reply.Healthy = as.Results()
func (s *Service) Health(_ *http.Request, _ *APIHealthArgs, reply *APIHealthServerReply) error {
s.log.Debug("Health.health called")
reply.Checks, reply.Healthy = s.health.Results()
if reply.Healthy {
return nil
}
replyStr, err := stdjson.Marshal(reply.Checks)
as.log.Warn("Health.health is returning an error: %s", string(replyStr))
s.log.Warn("Health.health is returning an error: %s", string(replyStr))
return err
}

type noOp struct{}

// NewNoOpService returns a NoOp version of health check
// for when the Health API is disabled
func NewNoOpService() Service {
return &noOp{}
}

// RegisterCheck implements the Service interface
func (n *noOp) Results() (map[string]health.Result, bool) {
return map[string]health.Result{}, true
}

// RegisterCheck implements the Service interface
func (n *noOp) Handler() (_ *common.HTTPHandler, _ error) {
return nil, nil
}

// RegisterCheckFn implements the Service interface
func (n *noOp) RegisterCheck(_ string, _ healthlib.Check) error {
return nil
}

// RegisterMonotonicCheckFn implements the Service interface
func (n *noOp) RegisterMonotonicCheck(_ string, _ healthlib.Check) error {
return nil
}
Loading