Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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 cmd/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ func runNode(ctx context.Context, nc *config) (_ io.Closer, retErr error) {
return nil, errors.Wrap(err, "failed to create services")
}

app, err := api.NewApp(nc.apiKey, minerScheduler, svs)
app, err := api.NewApp(nc.apiKey, minerScheduler, svs, cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize application")
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/wallet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,11 +449,11 @@ func createWallet(
return errors.Wrap(err, "failed to write the wallet's data to the wallet")

}
fmt.Printf("New account has been added to wallet successfully %s\n", walletPath) //nolint:forbidigo // As intended
fmt.Printf("Account Seed: %s\n", walletCredentials.accountSeed.String())
fmt.Printf("Public Key: %s\n", walletCredentials.pk.String())
fmt.Printf("Secret Key: %s\n", walletCredentials.sk.String())
fmt.Printf("Address: %s\n", walletCredentials.address.String())
fmt.Fprintf(os.Stdout, "New account has been added to wallet successfully %s\n", walletPath)
fmt.Fprintf(os.Stdout, "Account Seed: %s\n", walletCredentials.accountSeed.String())
fmt.Fprintf(os.Stdout, "Public Key: %s\n", walletCredentials.pk.String())
fmt.Fprintf(os.Stdout, "Secret Key: %s\n", walletCredentials.sk.String())
fmt.Fprintf(os.Stdout, "Address: %s\n", walletCredentials.address.String())
return nil
}

Expand Down
45 changes: 45 additions & 0 deletions itests/clients/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,48 @@ func (c *HTTPClient) RollbackToHeight(t testing.TB, height uint64, returnTxToUtx
require.NoErrorf(t, err, "failed to rollback to height on %s node", c.impl.String())
return blockID
}

func (c *HTTPClient) HeightFinalized(t testing.TB) proto.Height {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

h, _, err := c.cli.Blocks.HeightFinalized(ctx)
require.NoErrorf(t, err, "failed to get finalized height from %s node", c.impl.String())

return h
}

func (c *HTTPClient) BlockFinalized(t testing.TB) *proto.BlockHeader {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

header, _, err := c.cli.Blocks.BlockFinalized(ctx)
require.NoErrorf(t, err, "failed to get finalized header from %s node", c.impl.String())
require.NotNil(t, header, "finalized header is nil from %s node", c.impl.String())

return header
}

func (c *HTTPClient) CommitmentGeneratorsAt(t testing.TB, height proto.Height) []client.GeneratorInfoResponse {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

gens, _, err := c.cli.Generators.CommitmentGeneratorsAt(ctx, height)
require.NoErrorf(t, err, "failed to get generators at height %d from %s node", height, c.impl.String())

return gens
}

func (c *HTTPClient) SignCommit(
t testing.TB,
req *client.SignCommitRequest,
) *proto.CommitToGenerationWithProofs {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

out, _, err := c.cli.Transactions.SignCommit(ctx, req)
require.NoErrorf(t, err, "failed to sign commit transaction on %s node", c.impl.String())

require.NotNil(t, out, "empty response from /transactions/sign on %s node", c.impl.String())
return out
}
27 changes: 17 additions & 10 deletions pkg/api/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import (

"github.com/pkg/errors"

apiErr "github.com/wavesplatform/gowaves/pkg/api/errors"
"github.com/wavesplatform/gowaves/pkg/crypto"
"github.com/wavesplatform/gowaves/pkg/miner/scheduler"
"github.com/wavesplatform/gowaves/pkg/node/messages"
"github.com/wavesplatform/gowaves/pkg/node/peers"
"github.com/wavesplatform/gowaves/pkg/proto"
"github.com/wavesplatform/gowaves/pkg/services"
"github.com/wavesplatform/gowaves/pkg/settings"
"github.com/wavesplatform/gowaves/pkg/state"
"github.com/wavesplatform/gowaves/pkg/types"
)
Expand All @@ -35,6 +37,7 @@ const (
type appSettings struct {
BlockRequestLimit uint64
AssetDetailsLimit int
GenerationPeriod uint64
}

func defaultAppSettings() *appSettings {
Expand All @@ -56,19 +59,23 @@ type App struct {
settings *appSettings
}

func NewApp(apiKey string, scheduler SchedulerEmits, services services.Services) (*App, error) {
return newApp(apiKey, scheduler, services, nil)
func NewApp(apiKey string, scheduler SchedulerEmits, services services.Services,
cfg *settings.BlockchainSettings) (*App, error) {
return newApp(apiKey, scheduler, services, nil, cfg)
}

func newApp(apiKey string, scheduler SchedulerEmits, services services.Services, settings *appSettings) (*App, error) {
if settings == nil {
settings = defaultAppSettings()
func newApp(apiKey string, scheduler SchedulerEmits, services services.Services, appSettings *appSettings,
cfg *settings.BlockchainSettings) (*App, error) {
if appSettings == nil {
appSettings = defaultAppSettings()
}
digest, err := crypto.SecureHash([]byte(apiKey))
if err != nil {
return nil, err
}

if cfg != nil {
appSettings.GenerationPeriod = cfg.GenerationPeriod
}
return &App{
hashedApiKey: digest,
apiKeyEnabled: len(apiKey) > 0,
Expand All @@ -77,25 +84,25 @@ func newApp(apiKey string, scheduler SchedulerEmits, services services.Services,
utx: services.UtxPool,
peers: services.Peers,
services: services,
settings: settings,
settings: appSettings,
}, nil
}

func (a *App) TransactionsBroadcast(ctx context.Context, b []byte) (proto.Transaction, error) {
tt := proto.TransactionTypeVersion{}
err := json.Unmarshal(b, &tt)
if err != nil {
return nil, wrapToBadRequestError(err)
return nil, apiErr.NewBadRequestError(err)
}

realType, err := proto.GuessTransactionType(&tt)
if err != nil {
return nil, wrapToBadRequestError(err)
return nil, apiErr.NewBadRequestError(err)
}

err = proto.UnmarshalTransactionFromJSON(b, a.services.Scheme, realType)
if err != nil {
return nil, wrapToBadRequestError(err)
return nil, apiErr.NewBadRequestError(err)
}

respCh := make(chan error, 1)
Expand Down
8 changes: 7 additions & 1 deletion pkg/api/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ import (

"github.com/stretchr/testify/require"
"github.com/wavesplatform/gowaves/pkg/services"
"github.com/wavesplatform/gowaves/pkg/settings"
)

func TestAppAuth(t *testing.T) {
app, _ := NewApp("apiKey", nil, services.Services{})
cfg := &settings.BlockchainSettings{
FunctionalitySettings: settings.FunctionalitySettings{
GenerationPeriod: 0,
},
}
app, _ := NewApp("apiKey", nil, services.Services{}, cfg)
require.Error(t, app.checkAuth("bla"))
require.NoError(t, app.checkAuth("apiKey"))
}
15 changes: 13 additions & 2 deletions pkg/api/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/wavesplatform/gowaves/pkg/mock"
"github.com/wavesplatform/gowaves/pkg/proto"
"github.com/wavesplatform/gowaves/pkg/services"
"github.com/wavesplatform/gowaves/pkg/settings"
)

func TestApp_BlocksFirst(t *testing.T) {
Expand All @@ -26,7 +27,12 @@ func TestApp_BlocksFirst(t *testing.T) {
s := mock.NewMockState(ctrl)
s.EXPECT().BlockByHeight(proto.Height(1)).Return(g, nil)

app, err := NewApp("api-key", nil, services.Services{State: s})
cfg := &settings.BlockchainSettings{
FunctionalitySettings: settings.FunctionalitySettings{
GenerationPeriod: 0,
},
}
app, err := NewApp("api-key", nil, services.Services{State: s}, cfg)
require.NoError(t, err)
first, err := app.BlocksFirst()
require.NoError(t, err)
Expand All @@ -42,7 +48,12 @@ func TestApp_BlocksLast(t *testing.T) {
s.EXPECT().Height().Return(proto.Height(1), nil)
s.EXPECT().BlockByHeight(proto.Height(1)).Return(g, nil)

app, err := NewApp("api-key", nil, services.Services{State: s})
cfg := &settings.BlockchainSettings{
FunctionalitySettings: settings.FunctionalitySettings{
GenerationPeriod: 0,
},
}
app, err := NewApp("api-key", nil, services.Services{State: s}, cfg)
require.NoError(t, err)
first, err := app.BlocksLast()
require.NoError(t, err)
Expand Down
31 changes: 10 additions & 21 deletions pkg/api/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,6 @@ var (
notFound = errors.New("not found")
)

// BadRequestError represents a bad request error.
// Deprecated: don't use this error type in new code. Create a new error type or value in 'pkg/api/errors' package.
type BadRequestError struct {
inner error
}

func wrapToBadRequestError(err error) *BadRequestError {
return &BadRequestError{inner: err}
}

func (e *BadRequestError) Error() string {
return e.inner.Error()
}

// AuthError represents an authentication error or problem.
// Deprecated: don't use this error type in new code. Create a new error type or value in 'pkg/api/errors' package.
type AuthError struct {
Expand Down Expand Up @@ -62,17 +48,18 @@ func (eh *ErrorHandler) Handle(w http.ResponseWriter, r *http.Request, err error
}
// target errors
var (
badRequestError *BadRequestError
authError *AuthError
unknownError *apiErrs.UnknownError
apiError apiErrs.ApiError
badRequestError *apiErrs.BadRequestError
authError *AuthError
unknownError *apiErrs.UnknownError
apiError apiErrs.ApiError
unavailableError *apiErrs.UnavailableError
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New error should implement ApiError interface.

Copy link
Contributor Author

@esuwu esuwu Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They already do

// check that all targets implement the error interface
_, _, _, _ = error(badRequestError), error(authError), error(unknownError), error(apiError)
_, _, _, _, _ = error(badRequestError), error(authError), error(unknownError),
error(apiError), error(unavailableError)
)
switch {
case errors.As(err, &badRequestError):
// nickeskov: this error type will be removed in future
http.Error(w, fmt.Sprintf("Failed to complete request: %s", badRequestError.Error()), http.StatusBadRequest)
eh.sendApiErrJSON(w, r, badRequestError)
case errors.As(err, &authError):
// nickeskov: this error type will be removed in future
http.Error(w, fmt.Sprintf("Failed to complete request: %s", authError.Error()), http.StatusForbidden)
Expand All @@ -86,6 +73,8 @@ func (eh *ErrorHandler) Handle(w http.ResponseWriter, r *http.Request, err error
eh.sendApiErrJSON(w, r, unknownError)
case errors.As(err, &apiError):
eh.sendApiErrJSON(w, r, apiError)
case errors.As(err, &unavailableError):
eh.sendApiErrJSON(w, r, unavailableError)
default:
eh.logger.Error("InternalServerError",
slog.String("proto", r.Proto),
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/errors/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type (
var (
ApiKeyNotValid = &ApiKeyNotValidError{
genericError: genericError{
ID: ApiKeyNotValidErrorID,
ID: APIKeyNotValidErrorID,
HttpCode: http.StatusBadRequest,
Message: "Provided API key is not correct",
},
Expand Down
110 changes: 109 additions & 1 deletion pkg/api/errors/basics.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,119 @@ type WrongJsonError struct {
func NewWrongJsonError(cause string, validationErrors []error) *WrongJsonError {
return &WrongJsonError{
genericError: genericError{
ID: WrongJsonErrorID,
ID: WrongJSONErrorID,
HttpCode: http.StatusBadRequest,
Message: "failed to parse json message",
},
Cause: cause,
ValidationErrors: validationErrors,
}
}

// UnavailableError UnknownError is a wrapper for any error related to service unavailability.
type UnavailableError struct {
genericError
inner error
}

func (u *UnavailableError) Unwrap() error {
return u.inner
}

func (u *UnavailableError) Error() string {
if u.Unwrap() != nil {
return fmt.Sprintf(
"%s; inner error (%T): %s",
u.genericError.Error(),
u.Unwrap(), u.Unwrap().Error(),
)
}
return u.genericError.Error()
}

func NewUnavailableError(inner error) *UnavailableError {
return NewUnavailableErrorWithMsg("Service is unavailable", inner)
}

func NewUnavailableErrorWithMsg(message string, inner error) *UnavailableError {
return &UnavailableError{
genericError: genericError{
ID: ServiceUnavailableErrorID,
HttpCode: http.StatusServiceUnavailable,
Message: message,
},
inner: inner,
}
}

// BadRequestError is a wrapper for any bad request error.
type BadRequestError struct {
genericError
inner error
}

func (u *BadRequestError) Unwrap() error {
return u.inner
}

func (u *BadRequestError) Error() string {
if u.Unwrap() != nil {
return fmt.Sprintf(
"%s; inner error (%T): %s",
u.genericError.Error(),
u.Unwrap(), u.Unwrap().Error(),
)
}
return u.genericError.Error()
}

func NewBadRequestError(inner error) *BadRequestError {
return NewBadRequestErrorWithMsg("Bad request", inner)
}

func NewBadRequestErrorWithMsg(message string, inner error) *BadRequestError {
return &BadRequestError{
genericError: genericError{
ID: BadRequestErrorID,
HttpCode: http.StatusBadRequest,
Message: message,
},
inner: inner,
}
}

// NotImplementedError is a wrapper for any not implemented error.
type NotImplementedError struct {
genericError
inner error
}

func (u *NotImplementedError) Unwrap() error {
return u.inner
}

func (u *NotImplementedError) Error() string {
if u.Unwrap() != nil {
return fmt.Sprintf(
"%s; inner error (%T): %s",
u.genericError.Error(),
u.Unwrap(), u.Unwrap().Error(),
)
}
return u.genericError.Error()
}

func NewNotImplementedError(inner error) *NotImplementedError {
return NewNotImplementedErrorWithMsg("Not implemented", inner)
}

func NewNotImplementedErrorWithMsg(message string, inner error) *NotImplementedError {
return &NotImplementedError{
genericError: genericError{
ID: NotImplementedErrorID,
HttpCode: http.StatusNotImplemented,
Message: message,
},
inner: inner,
}
}
Loading
Loading