From d03b96df2664e38c14358fb09067df05132bb14f Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 13 Apr 2023 21:32:00 -0400 Subject: [PATCH 01/77] Ban usage of require.Error --- .golangci.yml | 27 ++-- api/admin/client.go | 5 +- api/admin/client_test.go | 128 +++++++++--------- snow/uptime/manager_test.go | 13 +- utils/logging/level.go | 5 +- .../txs/executor/advance_time_test.go | 6 +- .../txs/executor/create_chain_test.go | 6 +- vms/platformvm/txs/executor/export_test.go | 16 +-- vms/platformvm/txs/executor/import_test.go | 47 +++---- vms/platformvm/utxo/handler.go | 6 +- 10 files changed, 122 insertions(+), 137 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 78f38391262a..c89d83c41b62 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -20,6 +20,7 @@ linters: - depguard - errcheck - exportloopref + - forbidigo - goconst - gocritic - gofmt @@ -49,11 +50,27 @@ linters: # - lll linters-settings: + depguard: + list-type: blacklist + packages-with-error-message: + - io/ioutil: 'io/ioutil is deprecated. Use package io or os instead.' + - github.com/stretchr/testify/assert: 'github.com/stretchr/testify/require should be used instead.' + include-go-root: true errorlint: # Check for plain type assertions and type switches. asserts: false # Check for plain error comparisons. comparison: false + # https://golangci-lint.run/usage/linters/#forbidigo + forbidigo: + # Forbid the following identifiers (list of regexp). + forbid: + - 'require\.Error$(# ErrorIs should be used instead)?' + exclude_godoc_examples: false + # https://golangci-lint.run/usage/linters#gosec + gosec: + excludes: + - G107 # https://securego.io/docs/rules/g107.html revive: rules: # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr @@ -103,13 +120,3 @@ linters-settings: - "all" - "-SA6002" # argument should be pointer-like to avoid allocation, for sync.Pool - "-SA1019" # deprecated packages e.g., golang.org/x/crypto/ripemd160 - # https://golangci-lint.run/usage/linters#gosec - gosec: - excludes: - - G107 # https://securego.io/docs/rules/g107.html - depguard: - list-type: blacklist - packages-with-error-message: - - io/ioutil: 'io/ioutil is deprecated. Use package io or os instead.' - - github.com/stretchr/testify/assert: 'github.com/stretchr/testify/require should be used instead.' - include-go-root: true diff --git a/api/admin/client.go b/api/admin/client.go index 51cb0754fd40..0dcb3e720546 100644 --- a/api/admin/client.go +++ b/api/admin/client.go @@ -5,7 +5,6 @@ package admin import ( "context" - "fmt" "github.com/ava-labs/avalanchego/api" "github.com/ava-labs/avalanchego/ids" @@ -106,13 +105,13 @@ func (c *client) SetLoggerLevel( if len(logLevel) > 0 { logLevelArg, err = logging.ToLevel(logLevel) if err != nil { - return fmt.Errorf("couldn't parse %q to log level", logLevel) + return err } } if len(displayLevel) > 0 { displayLevelArg, err = logging.ToLevel(displayLevel) if err != nil { - return fmt.Errorf("couldn't parse %q to log level", displayLevel) + return err } } return c.requester.SendRequest(ctx, "admin.setLoggerLevel", &SetLoggerLevelArgs{ diff --git a/api/admin/client_test.go b/api/admin/client_test.go index e034e398e5cd..b357965b262b 100644 --- a/api/admin/client_test.go +++ b/api/admin/client_test.go @@ -240,61 +240,56 @@ func TestReloadInstalledVMs(t *testing.T) { func TestSetLoggerLevel(t *testing.T) { type test struct { - name string - logLevel string - displayLevel string - serviceErr bool - clientShouldErr bool + name string + logLevel string + displayLevel string + serviceErr error + clientErr error } tests := []test{ { - name: "Happy path", - logLevel: "INFO", - displayLevel: "INFO", - serviceErr: false, - clientShouldErr: false, + name: "Happy path", + logLevel: "INFO", + displayLevel: "INFO", + serviceErr: nil, + clientErr: nil, }, { - name: "Service errors", - logLevel: "INFO", - displayLevel: "INFO", - serviceErr: true, - clientShouldErr: true, + name: "Service errors", + logLevel: "INFO", + displayLevel: "INFO", + serviceErr: errTest, + clientErr: errTest, }, { - name: "Invalid log level", - logLevel: "invalid", - displayLevel: "INFO", - serviceErr: false, - clientShouldErr: true, + name: "Invalid log level", + logLevel: "invalid", + displayLevel: "INFO", + serviceErr: nil, + clientErr: logging.ErrUnknownLevel, }, { - name: "Invalid display level", - logLevel: "INFO", - displayLevel: "invalid", - serviceErr: false, - clientShouldErr: true, + name: "Invalid display level", + logLevel: "INFO", + displayLevel: "invalid", + serviceErr: nil, + clientErr: logging.ErrUnknownLevel, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - var err error - if tt.serviceErr { - err = errTest + + c := client{ + requester: NewMockClient(&api.EmptyReply{}, tt.serviceErr), } - mockClient := client{requester: NewMockClient(&api.EmptyReply{}, err)} - err = mockClient.SetLoggerLevel( + err := c.SetLoggerLevel( context.Background(), "", tt.logLevel, tt.displayLevel, ) - if tt.clientShouldErr { - require.Error(err) - } else { - require.NoError(err) - } + require.ErrorIs(err, tt.clientErr) }) } } @@ -304,8 +299,8 @@ func TestGetLoggerLevel(t *testing.T) { name string loggerName string serviceResponse map[string]LogAndDisplayLevels - serviceErr bool - clientShouldErr bool + serviceErr error + clientErr error } tests := []test{ { @@ -314,35 +309,37 @@ func TestGetLoggerLevel(t *testing.T) { serviceResponse: map[string]LogAndDisplayLevels{ "foo": {LogLevel: logging.Info, DisplayLevel: logging.Info}, }, - serviceErr: false, - clientShouldErr: false, + serviceErr: nil, + clientErr: nil, }, { name: "service errors", loggerName: "foo", serviceResponse: nil, - serviceErr: true, - clientShouldErr: true, + serviceErr: errTest, + clientErr: errTest, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - var err error - if tt.serviceErr { - err = errTest + + c := client{ + requester: NewMockClient( + &GetLoggerLevelReply{ + LoggerLevels: tt.serviceResponse, + }, + tt.serviceErr, + ), } - mockClient := client{requester: NewMockClient(&GetLoggerLevelReply{LoggerLevels: tt.serviceResponse}, err)} - res, err := mockClient.GetLoggerLevel( + res, err := c.GetLoggerLevel( context.Background(), tt.loggerName, ) - if tt.clientShouldErr { - require.Error(err) - return + require.ErrorIs(err, tt.clientErr) + if tt.clientErr == nil { + require.EqualValues(tt.serviceResponse, res) } - require.NoError(err) - require.EqualValues(tt.serviceResponse, res) }) } } @@ -350,40 +347,37 @@ func TestGetLoggerLevel(t *testing.T) { func TestGetConfig(t *testing.T) { type test struct { name string - serviceErr bool - clientShouldErr bool + serviceErr error + clientErr error expectedResponse interface{} } var resp interface{} = "response" tests := []test{ { name: "Happy path", - serviceErr: false, - clientShouldErr: false, + serviceErr: nil, + clientErr: nil, expectedResponse: &resp, }, { name: "service errors", - serviceErr: true, - clientShouldErr: true, + serviceErr: errTest, + clientErr: errTest, expectedResponse: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - var err error - if tt.serviceErr { - err = errTest + + c := client{ + requester: NewMockClient(tt.expectedResponse, tt.serviceErr), } - mockClient := client{requester: NewMockClient(tt.expectedResponse, err)} - res, err := mockClient.GetConfig(context.Background()) - if tt.clientShouldErr { - require.Error(err) - return + res, err := c.GetConfig(context.Background()) + require.ErrorIs(err, tt.clientErr) + if tt.clientErr == nil { + require.Equal(resp, res) } - require.NoError(err) - require.EqualValues("response", res) }) } } diff --git a/snow/uptime/manager_test.go b/snow/uptime/manager_test.go index bea1533e71b0..1f5a854e819a 100644 --- a/snow/uptime/manager_test.go +++ b/snow/uptime/manager_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" ) @@ -56,7 +57,7 @@ func TestStartTrackingDBError(t *testing.T) { up.clock.Set(currentTime) err := up.StartTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, errTest) } func TestStartTrackingNonValidator(t *testing.T) { @@ -69,7 +70,7 @@ func TestStartTrackingNonValidator(t *testing.T) { subnetID := ids.GenerateTestID() err := up.StartTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } func TestStartTrackingInThePast(t *testing.T) { @@ -182,7 +183,7 @@ func TestStopTrackingDisconnectedNonValidator(t *testing.T) { require.NoError(err) err = up.StopTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } func TestStopTrackingConnectedDBError(t *testing.T) { @@ -204,7 +205,7 @@ func TestStopTrackingConnectedDBError(t *testing.T) { s.dbReadError = errTest err = up.StopTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, errTest) } func TestStopTrackingNonConnectedPast(t *testing.T) { @@ -256,7 +257,7 @@ func TestStopTrackingNonConnectedDBError(t *testing.T) { s.dbWriteError = errTest err = up.StopTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, errTest) } func TestConnectAndDisconnect(t *testing.T) { @@ -552,7 +553,7 @@ func TestCalculateUptimeNonValidator(t *testing.T) { up := NewManager(s).(*manager) _, err := up.CalculateUptimePercentFrom(nodeID0, subnetID, startTime) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } func TestCalculateUptimePercentageDivBy0(t *testing.T) { diff --git a/utils/logging/level.go b/utils/logging/level.go index a7951c03e360..173c606c44e2 100644 --- a/utils/logging/level.go +++ b/utils/logging/level.go @@ -5,6 +5,7 @@ package logging import ( "encoding/json" + "errors" "fmt" "strings" @@ -44,6 +45,8 @@ const ( unknownLowStr = "unkno" ) +var ErrUnknownLevel = errors.New("unknown log level") + // Inverse of Level.String() func ToLevel(l string) (Level, error) { switch strings.ToUpper(l) { @@ -64,7 +67,7 @@ func ToLevel(l string) (Level, error) { case verboStr: return Verbo, nil default: - return Off, fmt.Errorf("unknown log level: %q", l) + return Off, fmt.Errorf("%w: %q", ErrUnknownLevel, l) } } diff --git a/vms/platformvm/txs/executor/advance_time_test.go b/vms/platformvm/txs/executor/advance_time_test.go index 0b8ccbefb6af..3fdf80fcb0c8 100644 --- a/vms/platformvm/txs/executor/advance_time_test.go +++ b/vms/platformvm/txs/executor/advance_time_test.go @@ -104,7 +104,7 @@ func TestAdvanceTimeTxTimestampTooEarly(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've failed verification because proposed timestamp same as current timestamp") + require.ErrorIs(err, errChildBlockNotAfterParent) } // Ensure semantic verification fails when proposed timestamp is after next validator set change time @@ -138,7 +138,7 @@ func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've failed verification because proposed timestamp is after pending validator start time") + require.ErrorIs(err, errChildBlockAfterStakerChangeTime) } err = shutdownEnvironment(env) @@ -172,7 +172,7 @@ func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've failed verification because proposed timestamp is after pending validator start time") + require.ErrorIs(err, errChildBlockAfterStakerChangeTime) } } diff --git a/vms/platformvm/txs/executor/create_chain_test.go b/vms/platformvm/txs/executor/create_chain_test.go index f451c540c621..6d504d564186 100644 --- a/vms/platformvm/txs/executor/create_chain_test.go +++ b/vms/platformvm/txs/executor/create_chain_test.go @@ -52,7 +52,7 @@ func TestCreateChainTxInsufficientControlSigs(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have erred because a sig is missing") + require.ErrorIs(err, errUnauthorizedSubnetModification) } // Ensure Execute fails when an incorrect control signature is given @@ -94,7 +94,7 @@ func TestCreateChainTxWrongControlSig(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because a sig is invalid") + require.ErrorIs(err, errUnauthorizedSubnetModification) } // Ensure Execute fails when the Subnet the blockchain specifies as @@ -129,7 +129,7 @@ func TestCreateChainTxNoSuchSubnet(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because subnet doesn't exist") + require.ErrorIs(err, errCantFindSubnet) } // Ensure valid tx passes semanticVerify diff --git a/vms/platformvm/txs/executor/export_test.go b/vms/platformvm/txs/executor/export_test.go index ca10b3c140e9..547f933c3079 100644 --- a/vms/platformvm/txs/executor/export_test.go +++ b/vms/platformvm/txs/executor/export_test.go @@ -28,8 +28,6 @@ func TestNewExportTx(t *testing.T) { destinationChainID ids.ID sourceKeys []*secp256k1.PrivateKey timestamp time.Time - shouldErr bool - shouldVerify bool } sourceKey := preFundedKeys[0] @@ -40,16 +38,12 @@ func TestNewExportTx(t *testing.T) { destinationChainID: xChainID, sourceKeys: []*secp256k1.PrivateKey{sourceKey}, timestamp: defaultValidateStartTime, - shouldErr: false, - shouldVerify: true, }, { description: "P->C export", destinationChainID: cChainID, sourceKeys: []*secp256k1.PrivateKey{sourceKey}, timestamp: env.config.ApricotPhase5Time, - shouldErr: false, - shouldVerify: true, }, } @@ -67,10 +61,6 @@ func TestNewExportTx(t *testing.T) { tt.sourceKeys, ids.ShortEmpty, // Change address ) - if tt.shouldErr { - require.Error(err) - return - } require.NoError(err) fakedState, err := state.NewDiff(lastAcceptedID, env) @@ -88,11 +78,7 @@ func TestNewExportTx(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&verifier) - if tt.shouldVerify { - require.NoError(err) - } else { - require.Error(err) - } + require.NoError(err) }) } } diff --git a/vms/platformvm/txs/executor/import_test.go b/vms/platformvm/txs/executor/import_test.go index bb2bdd155fde..479fad577c86 100644 --- a/vms/platformvm/txs/executor/import_test.go +++ b/vms/platformvm/txs/executor/import_test.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/utxo" "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) @@ -27,13 +28,12 @@ func TestNewImportTx(t *testing.T) { }() type test struct { - description string - sourceChainID ids.ID - sharedMemory atomic.SharedMemory - sourceKeys []*secp256k1.PrivateKey - timestamp time.Time - shouldErr bool - shouldVerify bool + description string + sourceChainID ids.ID + sharedMemory atomic.SharedMemory + sourceKeys []*secp256k1.PrivateKey + timestamp time.Time + expectedBuildError error } factory := secp256k1.Factory{} @@ -104,8 +104,8 @@ func TestNewImportTx(t *testing.T) { env.ctx.AVAXAssetID: env.config.TxFee - 1, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - shouldErr: true, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + expectedBuildError: utxo.ErrInsufficientFunds, }, { description: "can barely pay fee", @@ -116,9 +116,8 @@ func TestNewImportTx(t *testing.T) { env.ctx.AVAXAssetID: env.config.TxFee, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - shouldErr: false, - shouldVerify: true, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + expectedBuildError: nil, }, { description: "attempting to import from C-chain", @@ -129,10 +128,9 @@ func TestNewImportTx(t *testing.T) { env.ctx.AVAXAssetID: env.config.TxFee, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - timestamp: env.config.ApricotPhase5Time, - shouldErr: false, - shouldVerify: true, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + timestamp: env.config.ApricotPhase5Time, + expectedBuildError: nil, }, { description: "attempting to import non-avax from X-chain", @@ -144,10 +142,9 @@ func TestNewImportTx(t *testing.T) { customAssetID: 1, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - timestamp: env.config.BanffTime, - shouldErr: false, - shouldVerify: true, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + timestamp: env.config.BanffTime, + expectedBuildError: nil, }, } @@ -163,8 +160,8 @@ func TestNewImportTx(t *testing.T) { tt.sourceKeys, ids.ShortEmpty, ) - if tt.shouldErr { - require.Error(err) + require.ErrorIs(err, tt.expectedBuildError) + if tt.expectedBuildError != nil { return } require.NoError(err) @@ -202,11 +199,7 @@ func TestNewImportTx(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&verifier) - if tt.shouldVerify { - require.NoError(err) - } else { - require.Error(err) - } + require.NoError(err) }) } } diff --git a/vms/platformvm/utxo/handler.go b/vms/platformvm/utxo/handler.go index 90206baed06e..7c97938fa404 100644 --- a/vms/platformvm/utxo/handler.go +++ b/vms/platformvm/utxo/handler.go @@ -28,6 +28,7 @@ import ( var ( _ Handler = (*handler)(nil) + ErrInsufficientFunds = errors.New("insufficient funds") errCantSign = errors.New("can't sign") errLockedFundsNotMarkedAsLocked = errors.New("locked funds not marked as locked") ) @@ -371,8 +372,9 @@ func (h *handler) Spend( if amountBurned < fee || amountStaked < amount { return nil, nil, nil, nil, fmt.Errorf( - "provided keys have balance (unlocked, locked) (%d, %d) but need (%d, %d)", - amountBurned, amountStaked, fee, amount) + "%w (unlocked, locked) (%d, %d) but need (%d, %d)", + ErrInsufficientFunds, amountBurned, amountStaked, fee, amount, + ) } avax.SortTransferableInputsWithSigners(ins, signers) // sort inputs and keys From bfe48dd3217a5707a912cbc36c38051061576f08 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 13 Apr 2023 21:48:41 -0400 Subject: [PATCH 02/77] lint apis + chains --- api/auth/auth.go | 5 ++--- api/auth/auth_test.go | 30 +++++++++++++++++------------ api/health/client_test.go | 4 ++-- chains/atomic/test_shared_memory.go | 10 +++++++--- utils/password/password.go | 4 ++-- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/api/auth/auth.go b/api/auth/auth.go index 733f276e86bb..0f78192cb111 100644 --- a/api/auth/auth.go +++ b/api/auth/auth.go @@ -50,7 +50,6 @@ var ( errTokenInsufficientPermission = errors.New("the provided auth token does not allow access to this endpoint") errWrongPassword = errors.New("incorrect password") errSamePassword = errors.New("new password can't be same as old password") - errNoPassword = errors.New("no password") errNoEndpoints = errors.New("must name at least one endpoint") errTooManyEndpoints = fmt.Errorf("can only name at most %d endpoints", maxEndpoints) @@ -121,7 +120,7 @@ func NewFromHash(log logging.Logger, endpoint string, pw password.Hash) Auth { func (a *auth) NewToken(pw string, duration time.Duration, endpoints []string) (string, error) { if pw == "" { - return "", errNoPassword + return "", password.ErrEmptyPassword } if l := len(endpoints); l == 0 { return "", errNoEndpoints @@ -170,7 +169,7 @@ func (a *auth) RevokeToken(tokenStr, pw string) error { return errNoToken } if pw == "" { - return errNoPassword + return password.ErrEmptyPassword } a.lock.Lock() diff --git a/api/auth/auth_test.go b/api/auth/auth_test.go index c86bcc22a669..c6a92585e15c 100644 --- a/api/auth/auth_test.go +++ b/api/auth/auth_test.go @@ -39,13 +39,15 @@ func init() { var dummyHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) func TestNewTokenWrongPassword(t *testing.T) { + require := require.New(t) + auth := NewFromHash(logging.NoLog{}, "auth", hashedPassword) _, err := auth.NewToken("", defaultTokenLifespan, []string{"endpoint1, endpoint2"}) - require.Error(t, err, "should have failed because password is wrong") + require.ErrorIs(err, password.ErrEmptyPassword) _, err = auth.NewToken("notThePassword", defaultTokenLifespan, []string{"endpoint1, endpoint2"}) - require.Error(t, err, "should have failed because password is wrong") + require.ErrorIs(err, errWrongPassword) } func TestNewTokenHappyPath(t *testing.T) { @@ -76,12 +78,14 @@ func TestNewTokenHappyPath(t *testing.T) { } func TestTokenHasWrongSig(t *testing.T) { + require := require.New(t) + auth := NewFromHash(logging.NoLog{}, "auth", hashedPassword).(*auth) // Make a token endpoints := []string{"endpoint1", "endpoint2", "endpoint3"} tokenStr, err := auth.NewToken(testPassword, defaultTokenLifespan, endpoints) - require.NoError(t, err) + require.NoError(err) // Try to parse the token using the wrong password _, err = jwt.ParseWithClaims(tokenStr, &endpointClaims{}, func(*jwt.Token) (interface{}, error) { @@ -89,7 +93,7 @@ func TestTokenHasWrongSig(t *testing.T) { defer auth.lock.RUnlock() return []byte(""), nil }) - require.Error(t, err, "should have failed because password is wrong") + require.ErrorIs(err, jwt.ErrSignatureInvalid) // Try to parse the token using the wrong password _, err = jwt.ParseWithClaims(tokenStr, &endpointClaims{}, func(*jwt.Token) (interface{}, error) { @@ -97,35 +101,37 @@ func TestTokenHasWrongSig(t *testing.T) { defer auth.lock.RUnlock() return []byte("notThePassword"), nil }) - require.Error(t, err, "should have failed because password is wrong") + require.ErrorIs(err, jwt.ErrSignatureInvalid) } func TestChangePassword(t *testing.T) { + require := require.New(t) + auth := NewFromHash(logging.NoLog{}, "auth", hashedPassword).(*auth) password2 := "fejhkefjhefjhefhje" // #nosec G101 var err error err = auth.ChangePassword("", password2) - require.Error(t, err, "should have failed because old password is wrong") + require.ErrorIs(err, errWrongPassword) err = auth.ChangePassword("notThePassword", password2) - require.Error(t, err, "should have failed because old password is wrong") + require.ErrorIs(err, errWrongPassword) err = auth.ChangePassword(testPassword, "") - require.Error(t, err, "should have failed because new password is empty") + require.ErrorIs(err, password.ErrEmptyPassword) err = auth.ChangePassword(testPassword, password2) - require.NoError(t, err, "should have succeeded") - require.True(t, auth.password.Check(password2), "password should have been changed") + require.NoError(err) + require.True(auth.password.Check(password2), "password should have been changed") password3 := "ufwhwohwfohawfhwdwd" // #nosec G101 err = auth.ChangePassword(testPassword, password3) - require.Error(t, err, "should have failed because old password is wrong") + require.ErrorIs(err, errWrongPassword) err = auth.ChangePassword(password2, password3) - require.NoError(t, err, "should have succeeded") + require.NoError(err) } func TestRevokeToken(t *testing.T) { diff --git a/api/health/client_test.go b/api/health/client_test.go index 88d0696e414b..e42be5dbe852 100644 --- a/api/health/client_test.go +++ b/api/health/client_test.go @@ -87,7 +87,7 @@ func TestClient(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 20*time.Microsecond) healthy, err := AwaitHealthy(ctx, c, time.Microsecond, nil) cancel() - require.Error(err) + require.ErrorIs(err, context.DeadlineExceeded) require.False(healthy) } @@ -95,7 +95,7 @@ func TestClient(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 20*time.Microsecond) healthy, err := AwaitReady(ctx, c, time.Microsecond, nil) cancel() - require.Error(err) + require.ErrorIs(err, context.DeadlineExceeded) require.False(healthy) } diff --git a/chains/atomic/test_shared_memory.go b/chains/atomic/test_shared_memory.go index 0e7d918aa04e..e793da06365c 100644 --- a/chains/atomic/test_shared_memory.go +++ b/chains/atomic/test_shared_memory.go @@ -193,6 +193,7 @@ func TestSharedMemoryLargeIndexed(t *testing.T, chainID0, chainID1 ids.ID, sm0, func TestSharedMemoryCantDuplicatePut(t *testing.T, _, chainID1 ids.ID, sm0, _ SharedMemory, _ database.Database) { require := require.New(t) + err := sm0.Apply(map[ids.ID]*Requests{chainID1: {PutRequests: []*Element{ { Key: []byte{0}, @@ -203,26 +204,29 @@ func TestSharedMemoryCantDuplicatePut(t *testing.T, _, chainID1 ids.ID, sm0, _ S Value: []byte{2}, }, }}}) - require.Error(err, "shouldn't be able to write duplicated keys") + require.ErrorIs(err, errDuplicatedOperation) + err = sm0.Apply(map[ids.ID]*Requests{chainID1: {PutRequests: []*Element{{ Key: []byte{0}, Value: []byte{1}, }}}}) require.NoError(err) + err = sm0.Apply(map[ids.ID]*Requests{chainID1: {PutRequests: []*Element{{ Key: []byte{0}, Value: []byte{1}, }}}}) - require.Error(err, "shouldn't be able to write duplicated keys") + require.ErrorIs(err, errDuplicatedOperation) } func TestSharedMemoryCantDuplicateRemove(t *testing.T, _, chainID1 ids.ID, sm0, _ SharedMemory, _ database.Database) { require := require.New(t) + err := sm0.Apply(map[ids.ID]*Requests{chainID1: {RemoveRequests: [][]byte{{0}}}}) require.NoError(err) err = sm0.Apply(map[ids.ID]*Requests{chainID1: {RemoveRequests: [][]byte{{0}}}}) - require.Error(err, "shouldn't be able to remove duplicated keys") + require.ErrorIs(err, errDuplicatedOperation) } func TestSharedMemoryCommitOnPut(t *testing.T, _, chainID1 ids.ID, sm0, _ SharedMemory, db database.Database) { diff --git a/utils/password/password.go b/utils/password/password.go index af66b0c7a99a..417649b276d2 100644 --- a/utils/password/password.go +++ b/utils/password/password.go @@ -51,7 +51,7 @@ const ( ) var ( - errEmptyPassword = errors.New("empty password") + ErrEmptyPassword = errors.New("empty password") errPassMaxLength = fmt.Errorf("password exceeds maximum length of %d chars", maxPassLen) errWeakPassword = errors.New("password is too weak") ) @@ -70,7 +70,7 @@ func SufficientlyStrong(password string, minimumStrength Strength) bool { func IsValid(password string, minimumStrength Strength) error { switch { case len(password) == 0: - return errEmptyPassword + return ErrEmptyPassword case len(password) > maxPassLen: return errPassMaxLength case !SufficientlyStrong(password, minimumStrength): From 50b03d1eeaa6504ed5114be6a68a0086c0990b89 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 13 Apr 2023 21:51:34 -0400 Subject: [PATCH 03/77] lint history_test.go --- x/merkledb/history_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x/merkledb/history_test.go b/x/merkledb/history_test.go index 29da9974fc62..0151cde1774e 100644 --- a/x/merkledb/history_test.go +++ b/x/merkledb/history_test.go @@ -223,10 +223,10 @@ func Test_History_Bad_GetValueChanges_Input(t *testing.T) { require.NoError(err) _, err = db.history.getValueChanges(startRoot, endRoot, nil, nil, -1) - require.Error(err, ErrInvalidMaxLength) + require.ErrorIs(err, ErrInvalidMaxLength) _, err = db.history.getValueChanges(endRoot, startRoot, nil, nil, 1) - require.Error(err, ErrStartRootNotFound) + require.ErrorIs(err, ErrStartRootNotFound) // trigger the first root to be deleted by exiting the lookback window batch = db.NewBatch() @@ -235,9 +235,9 @@ func Test_History_Bad_GetValueChanges_Input(t *testing.T) { err = batch.Write() require.NoError(err) - // now this root should no lnger be present + // now this root should no longer be present _, err = db.history.getValueChanges(toBeDeletedRoot, endRoot, nil, nil, 1) - require.Error(err, ErrRootIDNotPresent) + require.ErrorIs(err, ErrStartRootNotFound) // same start/end roots should yield an empty changelist changes, err := db.history.getValueChanges(endRoot, endRoot, nil, nil, 10) @@ -304,7 +304,7 @@ func Test_History_Trigger_History_Queue_Looping(t *testing.T) { // proof from first root shouldn't be generatable since it should have been removed from the history _, err = db.GetRangeProofAtRoot(context.Background(), origRootID, []byte("k"), []byte("key3"), 10) - require.Error(err, ErrRootIDNotPresent) + require.ErrorIs(err, ErrRootIDNotPresent) } func Test_History_Values_Lookup_Over_Queue_Break(t *testing.T) { From 4b00093c082382ef570bc9748980e74b116ed1dd Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 13 Apr 2023 22:48:17 -0400 Subject: [PATCH 04/77] continuing cleanup --- api/admin/service_test.go | 8 +- api/info/service_test.go | 8 +- api/metrics/multi_gatherer_test.go | 2 +- api/metrics/optional_gatherer_test.go | 2 +- utils/crypto/keychain/keychain_test.go | 12 +-- utils/hashing/consistent/ring_test.go | 7 +- vms/platformvm/blocks/builder/builder_test.go | 3 +- .../txs/executor/create_chain_test.go | 35 ++++---- vms/platformvm/utxo/handler.go | 7 +- x/merkledb/db_test.go | 15 ++-- x/merkledb/trie_test.go | 80 ++++++++++--------- 11 files changed, 89 insertions(+), 90 deletions(-) diff --git a/api/admin/service_test.go b/api/admin/service_test.go index 0cebe8d61a70..fec4ba1771fe 100644 --- a/api/admin/service_test.go +++ b/api/admin/service_test.go @@ -76,7 +76,7 @@ func TestLoadVMsSuccess(t *testing.T) { err := resources.admin.LoadVMs(&http.Request{}, nil, &reply) require.Equal(t, expectedVMRegistry, reply.NewVMs) - require.Equal(t, err, nil) + require.NoError(t, err) } // Tests behavior for LoadVMs if we fail to reload vms. @@ -90,8 +90,7 @@ func TestLoadVMsReloadFails(t *testing.T) { reply := LoadVMsReply{} err := resources.admin.LoadVMs(&http.Request{}, nil, &reply) - - require.Equal(t, err, errTest) + require.ErrorIs(t, err, errTest) } // Tests behavior for LoadVMs if we fail to fetch our aliases @@ -115,6 +114,5 @@ func TestLoadVMsGetAliasesFails(t *testing.T) { reply := LoadVMsReply{} err := resources.admin.LoadVMs(&http.Request{}, nil, &reply) - - require.Equal(t, err, errTest) + require.ErrorIs(t, err, errTest) } diff --git a/api/info/service_test.go b/api/info/service_test.go index 3492b6411367..4e9e1160fecb 100644 --- a/api/info/service_test.go +++ b/api/info/service_test.go @@ -70,7 +70,7 @@ func TestGetVMsSuccess(t *testing.T) { err := resources.info.GetVMs(nil, nil, &reply) require.Equal(t, expectedVMRegistry, reply.VMs) - require.Equal(t, err, nil) + require.NoError(t, err) } // Tests GetVMs if we fail to list our vms. @@ -83,8 +83,7 @@ func TestGetVMsVMsListFactoriesFails(t *testing.T) { reply := GetVMsReply{} err := resources.info.GetVMs(nil, nil, &reply) - - require.Equal(t, errTest, err) + require.ErrorIs(t, err, errTest) } // Tests GetVMs if we can't get our vm aliases. @@ -104,6 +103,5 @@ func TestGetVMsGetAliasesFails(t *testing.T) { reply := GetVMsReply{} err := resources.info.GetVMs(nil, nil, &reply) - - require.Equal(t, err, errTest) + require.ErrorIs(t, err, errTest) } diff --git a/api/metrics/multi_gatherer_test.go b/api/metrics/multi_gatherer_test.go index aead517d6555..e5288244982c 100644 --- a/api/metrics/multi_gatherer_test.go +++ b/api/metrics/multi_gatherer_test.go @@ -31,7 +31,7 @@ func TestMultiGathererDuplicatedPrefix(t *testing.T) { require.NoError(err) err = g.Register("", og) - require.Equal(errDuplicatedPrefix, err) + require.ErrorIs(err, errDuplicatedPrefix) err = g.Register("lol", og) require.NoError(err) diff --git a/api/metrics/optional_gatherer_test.go b/api/metrics/optional_gatherer_test.go index 6b528886d80c..31bab3f80d0d 100644 --- a/api/metrics/optional_gatherer_test.go +++ b/api/metrics/optional_gatherer_test.go @@ -34,7 +34,7 @@ func TestOptionalGathererDuplicated(t *testing.T) { require.NoError(err) err = g.Register(og) - require.Equal(errDuplicatedRegister, err) + require.ErrorIs(err, errDuplicatedRegister) } func TestOptionalGathererAddedError(t *testing.T) { diff --git a/utils/crypto/keychain/keychain_test.go b/utils/crypto/keychain/keychain_test.go index e260e87c6698..5d8b82fcd400 100644 --- a/utils/crypto/keychain/keychain_test.go +++ b/utils/crypto/keychain/keychain_test.go @@ -26,7 +26,7 @@ func TestNewLedgerKeychain(t *testing.T) { // user request invalid number of addresses to derive ledger := NewMockLedger(ctrl) _, err := NewLedgerKeychain(ledger, 0) - require.Equal(err, ErrInvalidNumAddrsToDerive) + require.ErrorIs(err, ErrInvalidNumAddrsToDerive) // ledger does not return expected number of derived addresses ledger = NewMockLedger(ctrl) @@ -38,7 +38,7 @@ func TestNewLedgerKeychain(t *testing.T) { ledger = NewMockLedger(ctrl) ledger.EXPECT().Addresses([]uint32{0}).Return([]ids.ShortID{addr}, errTest).Times(1) _, err = NewLedgerKeychain(ledger, 1) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path ledger = NewMockLedger(ctrl) @@ -160,7 +160,7 @@ func TestLedgerSigner_SignHash(t *testing.T) { require.True(b) _, err = s.SignHash(toSign) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path 1 addr ledger = NewMockLedger(ctrl) @@ -218,7 +218,7 @@ func TestNewLedgerKeychainFromIndices(t *testing.T) { // user request invalid number of indices ledger := NewMockLedger(ctrl) _, err := NewLedgerKeychainFromIndices(ledger, []uint32{}) - require.Equal(err, ErrInvalidIndicesLength) + require.ErrorIs(err, ErrInvalidIndicesLength) // ledger does not return expected number of derived addresses ledger = NewMockLedger(ctrl) @@ -230,7 +230,7 @@ func TestNewLedgerKeychainFromIndices(t *testing.T) { ledger = NewMockLedger(ctrl) ledger.EXPECT().Addresses([]uint32{0}).Return([]ids.ShortID{addr}, errTest).Times(1) _, err = NewLedgerKeychainFromIndices(ledger, []uint32{0}) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path ledger = NewMockLedger(ctrl) @@ -382,7 +382,7 @@ func TestLedgerSignerFromIndices_SignHash(t *testing.T) { require.True(b) _, err = s.SignHash(toSign) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path 1 addr ledger = NewMockLedger(ctrl) diff --git a/utils/hashing/consistent/ring_test.go b/utils/hashing/consistent/ring_test.go index d5b59c58936c..a72cbadea478 100644 --- a/utils/hashing/consistent/ring_test.go +++ b/utils/hashing/consistent/ring_test.go @@ -211,11 +211,8 @@ func TestGetOnEmptyRingReturnsError(t *testing.T) { key: "foo", hash: 0, } - - node, err := ring.Get(foo) - - require.Equal(t, nil, node) - require.Equal(t, errEmptyRing, err) + _, err := ring.Get(foo) + require.ErrorIs(t, err, errEmptyRing) } // Tests that trying to call Remove on a node that doesn't exist should return false. diff --git a/vms/platformvm/blocks/builder/builder_test.go b/vms/platformvm/blocks/builder/builder_test.go index 8f8954a9ba3b..f8193377362c 100644 --- a/vms/platformvm/blocks/builder/builder_test.go +++ b/vms/platformvm/blocks/builder/builder_test.go @@ -289,11 +289,10 @@ func TestGetNextStakerToReward(t *testing.T) { state := tt.stateF(ctrl) txID, shouldReward, err := getNextStakerToReward(tt.timestamp, state) + require.ErrorIs(err, tt.expectedErr) if tt.expectedErr != nil { - require.Equal(tt.expectedErr, err) return } - require.NoError(err) require.Equal(tt.expectedTxID, txID) require.Equal(tt.expectedShouldReward, shouldReward) }) diff --git a/vms/platformvm/txs/executor/create_chain_test.go b/vms/platformvm/txs/executor/create_chain_test.go index 6d504d564186..db6bbd658c20 100644 --- a/vms/platformvm/txs/executor/create_chain_test.go +++ b/vms/platformvm/txs/executor/create_chain_test.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/utxo" "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) @@ -167,28 +168,28 @@ func TestCreateChainTxValid(t *testing.T) { func TestCreateChainTxAP3FeeChange(t *testing.T) { ap3Time := defaultGenesisTime.Add(time.Hour) tests := []struct { - name string - time time.Time - fee uint64 - expectsError bool + name string + time time.Time + fee uint64 + expectedError error }{ { - name: "pre-fork - correctly priced", - time: defaultGenesisTime, - fee: 0, - expectsError: false, + name: "pre-fork - correctly priced", + time: defaultGenesisTime, + fee: 0, + expectedError: nil, }, { - name: "post-fork - incorrectly priced", - time: ap3Time, - fee: 100*defaultTxFee - 1*units.NanoAvax, - expectsError: true, + name: "post-fork - incorrectly priced", + time: ap3Time, + fee: 100*defaultTxFee - 1*units.NanoAvax, + expectedError: utxo.ErrMustBurnMore, }, { - name: "post-fork - correctly priced", - time: ap3Time, - fee: 100 * defaultTxFee, - expectsError: false, + name: "post-fork - correctly priced", + time: ap3Time, + fee: 100 * defaultTxFee, + expectedError: nil, }, } for _, test := range tests { @@ -237,7 +238,7 @@ func TestCreateChainTxAP3FeeChange(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Equal(test.expectsError, err != nil) + require.ErrorIs(err, test.expectedError) }) } } diff --git a/vms/platformvm/utxo/handler.go b/vms/platformvm/utxo/handler.go index 7c97938fa404..fa9a661983c5 100644 --- a/vms/platformvm/utxo/handler.go +++ b/vms/platformvm/utxo/handler.go @@ -29,6 +29,7 @@ var ( _ Handler = (*handler)(nil) ErrInsufficientFunds = errors.New("insufficient funds") + ErrMustBurnMore = errors.New("tx must burn more unlocked tokens") errCantSign = errors.New("can't sign") errLockedFundsNotMarkedAsLocked = errors.New("locked funds not marked as locked") ) @@ -650,10 +651,10 @@ func (h *handler) VerifySpendUTXOs( // More unlocked tokens produced than consumed. Invalid. if unlockedProducedAsset > unlockedConsumedAsset { return fmt.Errorf( - "tx produces more unlocked %q (%d) than it consumes (%d)", + "%w: %d %s", + ErrMustBurnMore, + unlockedProducedAsset-unlockedConsumedAsset, assetID, - unlockedProducedAsset, - unlockedConsumedAsset, ) } } diff --git a/x/merkledb/db_test.go b/x/merkledb/db_test.go index 8a0f98d3b4fb..cca72733d490 100644 --- a/x/merkledb/db_test.go +++ b/x/merkledb/db_test.go @@ -374,21 +374,22 @@ func Test_MerkleDB_InsertNil(t *testing.T) { } func Test_MerkleDB_InsertAndRetrieve(t *testing.T) { + require := require.New(t) + db, err := getBasicDB() - require.NoError(t, err) + require.NoError(err) // value hasn't been inserted so shouldn't exist value, err := db.Get([]byte("key")) - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) - require.Nil(t, value) + require.ErrorIs(err, database.ErrNotFound) + require.Nil(value) err = db.Put([]byte("key"), []byte("value")) - require.NoError(t, err) + require.NoError(err) value, err = db.Get([]byte("key")) - require.NoError(t, err) - require.Equal(t, []byte("value"), value) + require.NoError(err) + require.Equal([]byte("value"), value) } func Test_MerkleDB_HealthCheck(t *testing.T) { diff --git a/x/merkledb/trie_test.go b/x/merkledb/trie_test.go index 530a2db633fc..e7c75e52bf4e 100644 --- a/x/merkledb/trie_test.go +++ b/x/merkledb/trie_test.go @@ -251,53 +251,59 @@ func Test_Trie_Partial_Commit_Leaves_Valid_Tries(t *testing.T) { } func Test_Trie_WriteToDB(t *testing.T) { + require := require.New(t) + dbTrie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, dbTrie) + require.NoError(err) + require.NotNil(dbTrie) + trie, err := dbTrie.NewView() - require.NoError(t, err) + require.NoError(err) // value hasn't been inserted so shouldn't exist value, err := trie.GetValue(context.Background(), []byte("key")) - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) - require.Nil(t, value) + require.ErrorIs(err, database.ErrNotFound) + require.Nil(value) err = trie.Insert(context.Background(), []byte("key"), []byte("value")) - require.NoError(t, err) + require.NoError(err) value, err = getNodeValue(trie, "key") - require.NoError(t, err) - require.Equal(t, []byte("value"), value) + require.NoError(err) + require.Equal([]byte("value"), value) err = trie.CommitToDB(context.Background()) - require.NoError(t, err) + require.NoError(err) + p := newPath([]byte("key")) rawBytes, err := dbTrie.nodeDB.Get(p.Bytes()) - require.NoError(t, err) + require.NoError(err) + node, err := parseNode(p, rawBytes) - require.NoError(t, err) - require.Equal(t, []byte("value"), node.value.value) + require.NoError(err) + require.Equal([]byte("value"), node.value.value) } func Test_Trie_InsertAndRetrieve(t *testing.T) { + require := require.New(t) + dbTrie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, dbTrie) + require.NoError(err) + require.NotNil(dbTrie) + trie := Trie(dbTrie) // value hasn't been inserted so shouldn't exist value, err := dbTrie.Get([]byte("key")) - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) - require.Nil(t, value) + require.ErrorIs(err, database.ErrNotFound) + require.Nil(value) err = trie.Insert(context.Background(), []byte("key"), []byte("value")) - require.NoError(t, err) + require.NoError(err) value, err = getNodeValue(trie, "key") - require.NoError(t, err) - require.Equal(t, []byte("value"), value) + require.NoError(err) + require.Equal([]byte("value"), value) } func Test_Trie_Overwrite(t *testing.T) { @@ -637,32 +643,30 @@ func Test_Trie_CommitChanges(t *testing.T) { } func Test_Trie_BatchApply(t *testing.T) { + require := require.New(t) + dbTrie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, dbTrie) + require.NoError(err) + require.NotNil(dbTrie) + trie, err := dbTrie.NewView() - require.NoError(t, err) + require.NoError(err) - err = trie.Insert(context.Background(), []byte("key1"), []byte("value1")) - require.NoError(t, err) - err = trie.Insert(context.Background(), []byte("key12"), []byte("value12")) - require.NoError(t, err) - err = trie.Insert(context.Background(), []byte("key134"), []byte("value134")) - require.NoError(t, err) - err = trie.Remove(context.Background(), []byte("key1")) - require.NoError(t, err) + require.NoError(trie.Insert(context.Background(), []byte("key1"), []byte("value1"))) + require.NoError(trie.Insert(context.Background(), []byte("key12"), []byte("value12"))) + require.NoError(trie.Insert(context.Background(), []byte("key134"), []byte("value134"))) + require.NoError(trie.Remove(context.Background(), []byte("key1"))) value, err := getNodeValue(trie, "key12") - require.NoError(t, err) - require.Equal(t, []byte("value12"), value) + require.NoError(err) + require.Equal([]byte("value12"), value) value, err = getNodeValue(trie, "key134") - require.NoError(t, err) - require.Equal(t, []byte("value134"), value) + require.NoError(err) + require.Equal([]byte("value134"), value) _, err = getNodeValue(trie, "key1") - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) + require.ErrorIs(err, database.ErrNotFound) } func Test_Trie_ChainDeletion(t *testing.T) { From 4b7e77cf546135a8d7249e746fb2bdf73045bf21 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 13 Apr 2023 22:56:48 -0400 Subject: [PATCH 05/77] more cleanup --- utils/crypto/secp256k1/secp256k1.go | 3 ++- vms/secp256k1fx/fx_test.go | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/utils/crypto/secp256k1/secp256k1.go b/utils/crypto/secp256k1/secp256k1.go index 80de06c09b36..857921bf2ea5 100644 --- a/utils/crypto/secp256k1/secp256k1.go +++ b/utils/crypto/secp256k1/secp256k1.go @@ -44,6 +44,7 @@ const ( ) var ( + ErrInvalidSig = errors.New("invalid signature") errCompressed = errors.New("wasn't expecting a compressed key") errMissingQuotes = errors.New("first and last characters should be quotes") errMissingKeyPrefix = fmt.Errorf("private key missing %s prefix", PrivateKeyPrefix) @@ -108,7 +109,7 @@ func (f *Factory) RecoverHashPublicKey(hash, sig []byte) (*PublicKey, error) { rawPubkey, compressed, err := ecdsa.RecoverCompact(sig, hash) if err != nil { - return nil, err + return nil, ErrInvalidSig } if compressed { diff --git a/vms/secp256k1fx/fx_test.go b/vms/secp256k1fx/fx_test.go index cc48fb640796..733f49c59b2f 100644 --- a/vms/secp256k1fx/fx_test.go +++ b/vms/secp256k1fx/fx_test.go @@ -296,7 +296,7 @@ func TestFxVerifyTransferWrongAmounts(t *testing.T) { }, } - require.Error(fx.VerifyTransfer(tx, in, cred, out)) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), ErrMismatchedAmounts) } func TestFxVerifyTransferTimelocked(t *testing.T) { @@ -479,7 +479,7 @@ func TestFxVerifyTransferInvalidSignature(t *testing.T) { require.NoError(fx.VerifyTransfer(tx, in, cred, out)) require.NoError(fx.Bootstrapped()) - require.Error(fx.VerifyTransfer(tx, in, cred, out), errAddrsNotSortedUnique) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), secp256k1.ErrInvalidSig) } func TestFxVerifyTransferWrongSigner(t *testing.T) { @@ -518,7 +518,7 @@ func TestFxVerifyTransferWrongSigner(t *testing.T) { require.NoError(fx.VerifyTransfer(tx, in, cred, out)) require.NoError(fx.Bootstrapped()) - require.Error(fx.VerifyTransfer(tx, in, cred, out)) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), ErrWrongSig) } func TestFxVerifyTransferSigIndexOOB(t *testing.T) { From 2b086348715af795ef34ae48db36e9d741f1afdd Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 13 Apr 2023 23:17:53 -0400 Subject: [PATCH 06/77] revert grpc test failure --- chains/atomic/test_shared_memory.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/chains/atomic/test_shared_memory.go b/chains/atomic/test_shared_memory.go index e793da06365c..5befe97c084d 100644 --- a/chains/atomic/test_shared_memory.go +++ b/chains/atomic/test_shared_memory.go @@ -204,7 +204,8 @@ func TestSharedMemoryCantDuplicatePut(t *testing.T, _, chainID1 ids.ID, sm0, _ S Value: []byte{2}, }, }}}) - require.ErrorIs(err, errDuplicatedOperation) + // TODO: require error to be errDuplicatedOperation + require.Error(err) err = sm0.Apply(map[ids.ID]*Requests{chainID1: {PutRequests: []*Element{{ Key: []byte{0}, @@ -216,7 +217,8 @@ func TestSharedMemoryCantDuplicatePut(t *testing.T, _, chainID1 ids.ID, sm0, _ S Key: []byte{0}, Value: []byte{1}, }}}}) - require.ErrorIs(err, errDuplicatedOperation) + // TODO: require error to be errDuplicatedOperation + require.Error(err) } func TestSharedMemoryCantDuplicateRemove(t *testing.T, _, chainID1 ids.ID, sm0, _ SharedMemory, _ database.Database) { @@ -226,7 +228,8 @@ func TestSharedMemoryCantDuplicateRemove(t *testing.T, _, chainID1 ids.ID, sm0, require.NoError(err) err = sm0.Apply(map[ids.ID]*Requests{chainID1: {RemoveRequests: [][]byte{{0}}}}) - require.ErrorIs(err, errDuplicatedOperation) + // TODO: require error to be errDuplicatedOperation + require.Error(err) } func TestSharedMemoryCommitOnPut(t *testing.T, _, chainID1 ids.ID, sm0, _ SharedMemory, db database.Database) { From 29a2d0ad6b6cfcae051fb0707ee73be5b9eb1d3a Mon Sep 17 00:00:00 2001 From: Stephen Date: Sat, 15 Apr 2023 13:38:28 -0400 Subject: [PATCH 07/77] Add some nolints + improve error interface --- chains/atomic/test_shared_memory.go | 6 +++--- codec/codec.go | 14 +++++++++++- codec/hierarchycodec/codec.go | 8 +++++-- codec/linearcodec/codec.go | 8 +++++-- codec/manager.go | 5 +++-- codec/reflectcodec/struct_fielder.go | 7 +++++- codec/reflectcodec/type_codec.go | 32 +++++++++++++++++----------- codec/registry.go | 4 ++++ codec/test_codec.go | 24 ++++++++++----------- 9 files changed, 73 insertions(+), 35 deletions(-) diff --git a/chains/atomic/test_shared_memory.go b/chains/atomic/test_shared_memory.go index 5befe97c084d..7d3c9ded1a73 100644 --- a/chains/atomic/test_shared_memory.go +++ b/chains/atomic/test_shared_memory.go @@ -205,7 +205,7 @@ func TestSharedMemoryCantDuplicatePut(t *testing.T, _, chainID1 ids.ID, sm0, _ S }, }}}) // TODO: require error to be errDuplicatedOperation - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors too err = sm0.Apply(map[ids.ID]*Requests{chainID1: {PutRequests: []*Element{{ Key: []byte{0}, @@ -218,7 +218,7 @@ func TestSharedMemoryCantDuplicatePut(t *testing.T, _, chainID1 ids.ID, sm0, _ S Value: []byte{1}, }}}}) // TODO: require error to be errDuplicatedOperation - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors too } func TestSharedMemoryCantDuplicateRemove(t *testing.T, _, chainID1 ids.ID, sm0, _ SharedMemory, _ database.Database) { @@ -229,7 +229,7 @@ func TestSharedMemoryCantDuplicateRemove(t *testing.T, _, chainID1 ids.ID, sm0, err = sm0.Apply(map[ids.ID]*Requests{chainID1: {RemoveRequests: [][]byte{{0}}}}) // TODO: require error to be errDuplicatedOperation - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors too } func TestSharedMemoryCommitOnPut(t *testing.T, _, chainID1 ids.ID, sm0, _ SharedMemory, db database.Database) { diff --git a/codec/codec.go b/codec/codec.go index 004b2553437c..413b6d174be2 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -3,7 +3,19 @@ package codec -import "github.com/ava-labs/avalanchego/utils/wrappers" +import ( + "errors" + + "github.com/ava-labs/avalanchego/utils/wrappers" +) + +var ( + ErrUnsupportedType = errors.New("unsupported type") + ErrMaxSliceLenExceeded = errors.New("max slice length exceeded") + ErrDoesNotImplementInterface = errors.New("does not implement interface") + ErrUnexportedField = errors.New("unexported field") + ErrExtraSpace = errors.New("trailing buffer space") +) // Codec marshals and unmarshals type Codec interface { diff --git a/codec/hierarchycodec/codec.go b/codec/hierarchycodec/codec.go index af66bf244690..d1d03d879275 100644 --- a/codec/hierarchycodec/codec.go +++ b/codec/hierarchycodec/codec.go @@ -89,7 +89,7 @@ func (c *hierarchyCodec) RegisterType(val interface{}) error { valType := reflect.TypeOf(val) if _, exists := c.typeToTypeID[valType]; exists { - return fmt.Errorf("type %v has already been registered", valType) + return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType) } valTypeID := typeID{ @@ -142,7 +142,11 @@ func (c *hierarchyCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type } // Ensure type actually does implement the interface if !implementingType.Implements(valueType) { - return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s does not implement interface %s", implementingType, valueType) + return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s %w %s", + implementingType, + codec.ErrDoesNotImplementInterface, + valueType, + ) } return reflect.New(implementingType).Elem(), nil // instance of the proper type } diff --git a/codec/linearcodec/codec.go b/codec/linearcodec/codec.go index 30b317c8a650..d488b3a1d4c0 100644 --- a/codec/linearcodec/codec.go +++ b/codec/linearcodec/codec.go @@ -79,7 +79,7 @@ func (c *linearCodec) RegisterType(val interface{}) error { valType := reflect.TypeOf(val) if _, exists := c.typeToTypeID[valType]; exists { - return fmt.Errorf("type %v has already been registered", valType) + return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType) } c.typeIDToType[c.nextTypeID] = valType @@ -120,7 +120,11 @@ func (c *linearCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type) ( } // Ensure type actually does implement the interface if !implementingType.Implements(valueType) { - return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s does not implement interface %s", implementingType, valueType) + return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s %w %s", + implementingType, + codec.ErrDoesNotImplementInterface, + valueType, + ) } return reflect.New(implementingType).Elem(), nil // instance of the proper type } diff --git a/codec/manager.go b/codec/manager.go index 8cfefc6b99a2..9bb8cffefeb8 100644 --- a/codec/manager.go +++ b/codec/manager.go @@ -25,6 +25,7 @@ const ( var ( errMarshalNil = errors.New("can't marshal nil pointer or interface") errUnmarshalNil = errors.New("can't unmarshal nil") + errUnmarshalTooBig = errors.New("byte array exceeds maximum length") errCantPackVersion = errors.New("couldn't pack codec version") errCantUnpackVersion = errors.New("couldn't unpack codec version") errUnknownVersion = errors.New("unknown codec version") @@ -149,9 +150,9 @@ func (m *manager) Unmarshal(bytes []byte, dest interface{}) (uint16, error) { } m.lock.RLock() - if len(bytes) > m.maxSize { + if byteLen := len(bytes); byteLen > m.maxSize { m.lock.RUnlock() - return 0, fmt.Errorf("byte array exceeds maximum length, %d", m.maxSize) + return 0, fmt.Errorf("%w: %d > %d", errUnmarshalTooBig, byteLen, m.maxSize) } p := wrappers.Packer{ diff --git a/codec/reflectcodec/struct_fielder.go b/codec/reflectcodec/struct_fielder.go index 7a54182ccb66..27edb58a1793 100644 --- a/codec/reflectcodec/struct_fielder.go +++ b/codec/reflectcodec/struct_fielder.go @@ -8,6 +8,8 @@ import ( "reflect" "strconv" "sync" + + "github.com/ava-labs/avalanchego/codec" ) const ( @@ -91,7 +93,10 @@ func (s *structFielder) GetSerializedFields(t reflect.Type) ([]FieldDesc, error) continue } if !field.IsExported() { // Can only marshal exported fields - return nil, fmt.Errorf("can't marshal un-exported field %s", field.Name) + return nil, fmt.Errorf("can not marshal %w: %s", + codec.ErrUnexportedField, + field.Name, + ) } sliceLenField := field.Tag.Get(SliceLenTagName) maxSliceLen := s.maxSliceLen diff --git a/codec/reflectcodec/type_codec.go b/codec/reflectcodec/type_codec.go index a92ade189bf5..c4a0afbf32ef 100644 --- a/codec/reflectcodec/type_codec.go +++ b/codec/reflectcodec/type_codec.go @@ -19,12 +19,9 @@ const ( ) var ( - ErrMaxMarshalSliceLimitExceeded = errors.New("maximum marshal slice limit exceeded") - errMarshalNil = errors.New("can't marshal nil pointer or interface") errUnmarshalNil = errors.New("can't unmarshal nil") errNeedPointer = errors.New("argument to unmarshal must be a pointer") - errExtraSpace = errors.New("trailing buffer space") ) var _ codec.Codec = (*genericCodec)(nil) @@ -278,9 +275,10 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice numElts := value.Len() // # elements in the slice/array. 0 if this slice is nil. if uint32(numElts) > maxSliceLen { return fmt.Errorf("%w; slice length, %d, exceeds maximum length, %d", - ErrMaxMarshalSliceLimitExceeded, + codec.ErrMaxSliceLenExceeded, numElts, - maxSliceLen) + maxSliceLen, + ) } p.PackInt(uint32(numElts)) // pack # elements if p.Err != nil { @@ -312,7 +310,11 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice return p.Err } if uint32(numElts) > c.maxSliceLen { - return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", ErrMaxMarshalSliceLimitExceeded, numElts, c.maxSliceLen) + return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", + codec.ErrMaxSliceLenExceeded, + numElts, + c.maxSliceLen, + ) } for i := 0; i < numElts; i++ { // Process each element in the array if err := c.marshal(value.Index(i), p, c.maxSliceLen); err != nil { @@ -332,7 +334,7 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice } return nil default: - return fmt.Errorf("can't marshal unknown kind %s", valueKind) + return fmt.Errorf("%w: %s", codec.ErrUnsupportedType, valueKind) } } @@ -354,7 +356,11 @@ func (c *genericCodec) Unmarshal(bytes []byte, dest interface{}) error { return err } if p.Offset != len(bytes) { - return errExtraSpace + return fmt.Errorf("%w: read %d provided %d", + codec.ErrExtraSpace, + p.Offset, + len(bytes), + ) } return nil } @@ -424,15 +430,17 @@ func (c *genericCodec) unmarshal(p *wrappers.Packer, value reflect.Value, maxSli } if numElts32 > maxSliceLen { return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", - ErrMaxMarshalSliceLimitExceeded, + codec.ErrMaxSliceLenExceeded, numElts32, - maxSliceLen) + maxSliceLen, + ) } if numElts32 > math.MaxInt32 { return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", - ErrMaxMarshalSliceLimitExceeded, + codec.ErrMaxSliceLenExceeded, numElts32, - math.MaxInt32) + math.MaxInt32, + ) } numElts := int(numElts32) diff --git a/codec/registry.go b/codec/registry.go index 9031c94f2421..f0f1c2ff8157 100644 --- a/codec/registry.go +++ b/codec/registry.go @@ -3,6 +3,10 @@ package codec +import "errors" + +var ErrDuplicateType = errors.New("duplicate type registration") + // Registry registers new types that can be marshaled into type Registry interface { RegisterType(interface{}) error diff --git a/codec/test_codec.go b/codec/test_codec.go index 8da7a1be1dc8..b5a5f10f88a3 100644 --- a/codec/test_codec.go +++ b/codec/test_codec.go @@ -157,7 +157,7 @@ func TestRegisterStructTwice(codec GeneralCodec, t testing.TB) { require := require.New(t) require.NoError(codec.RegisterType(&MyInnerStruct{})) - require.Error(codec.RegisterType(&MyInnerStruct{})) + require.ErrorIs(codec.RegisterType(&MyInnerStruct{}), ErrDuplicateType) } func TestUInt32(codec GeneralCodec, t testing.TB) { @@ -193,7 +193,7 @@ func TestUIntPtr(codec GeneralCodec, t testing.TB) { number := uintptr(500) _, err = manager.Marshal(0, number) - require.Error(err) + require.ErrorIs(err, ErrUnsupportedType) } func TestSlice(codec GeneralCodec, t testing.TB) { @@ -562,10 +562,10 @@ func TestSerializeUnexportedField(codec GeneralCodec, t testing.TB) { require.NoError(err) _, err = manager.Marshal(0, myS) - require.Error(err) + require.ErrorIs(err, ErrUnexportedField) _, err = manager.Size(0, myS) - require.Error(err) + require.ErrorIs(err, ErrUnexportedField) } func TestSerializeOfNoSerializeField(codec GeneralCodec, t testing.TB) { @@ -709,7 +709,7 @@ func TestSliceWithEmptySerializationOutOfMemory(codec GeneralCodec, t testing.TB Arr: make([]emptyStruct, math.MaxInt32), } _, err = manager.Marshal(0, val) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) bytesLen, err := manager.Size(0, val) require.NoError(err) @@ -726,7 +726,7 @@ func TestSliceTooLarge(codec GeneralCodec, t testing.TB) { val := []struct{}{} b := []byte{0x00, 0x00, 0xff, 0xff, 0xff, 0xff} _, err = manager.Unmarshal(b, &val) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) } // Ensure serializing structs with negative number members works @@ -774,7 +774,7 @@ func TestTooLargeUnmarshal(codec GeneralCodec, t testing.TB) { s := inner{} _, err = manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, errUnmarshalTooBig) } type outerInterface interface { @@ -813,7 +813,7 @@ func TestUnmarshalInvalidInterface(codec GeneralCodec, t testing.TB) { bytes := []byte{0, 0, 0, 0, 0, 1} s := outer{} _, err := manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, ErrDoesNotImplementInterface) } } @@ -832,11 +832,11 @@ func TestRestrictedSlice(codec GeneralCodec, t testing.TB) { s := inner{} _, err = manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) s.Bytes = []byte{0, 1, 2} _, err = manager.Marshal(0, s) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) } // Test unmarshaling something with extra data @@ -851,7 +851,7 @@ func TestExtraSpace(codec GeneralCodec, t testing.TB) { byteSlice := []byte{0x00, 0x00, 0x01, 0x02} var b byte _, err = manager.Unmarshal(byteSlice, &b) - require.Error(err) + require.ErrorIs(err, ErrExtraSpace) } // Ensure deserializing slices that have been length restricted errors correctly @@ -874,7 +874,7 @@ func TestSliceLengthOverflow(codec GeneralCodec, t testing.TB) { s := inner{} _, err = manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) } type MultipleVersionsStruct struct { From fcffb84ef9d1f1984547a378aafb89e2d3e43dc3 Mon Sep 17 00:00:00 2001 From: Stephen Date: Sat, 15 Apr 2023 13:51:15 -0400 Subject: [PATCH 08/77] use errorIs where previously intended --- utils/wrappers/packing_test.go | 2 +- vms/platformvm/vm_test.go | 4 ++-- vms/proposervm/indexer/height_indexer_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/wrappers/packing_test.go b/utils/wrappers/packing_test.go index 1d6740205130..af21be914961 100644 --- a/utils/wrappers/packing_test.go +++ b/utils/wrappers/packing_test.go @@ -189,7 +189,7 @@ func TestPackerUnpackFixedBytes(t *testing.T) { require.Nil(p.UnpackFixedBytes(4)) require.True(p.Errored()) - require.Error(p.Err, errBadLength) + require.ErrorIs(p.Err, errBadLength) } func TestPackerPackBytes(t *testing.T) { diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 539fd3862f84..3ec161044c32 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -701,7 +701,7 @@ func TestAddValidatorReject(t *testing.T) { require.NoError(blk.Reject(context.Background())) _, _, err = vm.state.GetTx(tx.ID()) - require.Error(err, database.ErrNotFound) + require.ErrorIs(err, database.ErrNotFound) _, err = vm.state.GetPendingValidator(constants.PrimaryNetworkID, nodeID) require.ErrorIs(err, database.ErrNotFound) @@ -826,7 +826,7 @@ func TestAddSubnetValidatorReject(t *testing.T) { require.NoError(blk.Reject(context.Background())) _, _, err = vm.state.GetTx(tx.ID()) - require.Error(err, database.ErrNotFound) + require.ErrorIs(err, database.ErrNotFound) // Verify that new validator NOT in pending validator set _, err = vm.state.GetPendingValidator(testSubnet1.ID(), nodeID) diff --git a/vms/proposervm/indexer/height_indexer_test.go b/vms/proposervm/indexer/height_indexer_test.go index 3c1e671f1b71..bffdc7a81a6c 100644 --- a/vms/proposervm/indexer/height_indexer_test.go +++ b/vms/proposervm/indexer/height_indexer_test.go @@ -177,7 +177,7 @@ func TestHeightBlockIndexAcrossFork(t *testing.T) { require.True(loadedForkHeight == forkHeight) for height := uint64(0); height < forkHeight; height++ { _, err := storedState.GetBlockIDAtHeight(height) - require.Error(err, database.ErrNotFound) + require.ErrorIs(err, database.ErrNotFound) } for height := forkHeight; height <= blkNumber; height++ { _, err := storedState.GetBlockIDAtHeight(height) From 3e1174f4bbcebc0d930eeb4304e32b6bac77882c Mon Sep 17 00:00:00 2001 From: Stephen Date: Sat, 15 Apr 2023 16:34:35 -0400 Subject: [PATCH 09/77] wip --- codec/manager.go | 9 +++++---- vms/proposervm/block/block.go | 4 +++- vms/proposervm/block/block_test.go | 4 ++-- vms/proposervm/block/build_test.go | 4 ++-- vms/proposervm/block/parse_test.go | 5 +++-- vms/proposervm/summary/parse_test.go | 4 +++- vms/registry/vm_registerer.go | 9 +++++++-- vms/registry/vm_registerer_test.go | 4 ++-- vms/rpcchainvm/state_syncable_vm_test.go | 14 +++++++------- 9 files changed, 34 insertions(+), 23 deletions(-) diff --git a/codec/manager.go b/codec/manager.go index 9bb8cffefeb8..83f2c0b0e183 100644 --- a/codec/manager.go +++ b/codec/manager.go @@ -23,12 +23,13 @@ const ( ) var ( + ErrUnknownVersion = errors.New("unknown codec version") + errMarshalNil = errors.New("can't marshal nil pointer or interface") errUnmarshalNil = errors.New("can't unmarshal nil") errUnmarshalTooBig = errors.New("byte array exceeds maximum length") errCantPackVersion = errors.New("couldn't pack codec version") errCantUnpackVersion = errors.New("couldn't unpack codec version") - errUnknownVersion = errors.New("unknown codec version") errDuplicatedVersion = errors.New("duplicated codec version") ) @@ -108,7 +109,7 @@ func (m *manager) Size(version uint16, value interface{}) (int, error) { m.lock.RUnlock() if !exists { - return 0, errUnknownVersion + return 0, ErrUnknownVersion } res, err := c.Size(value) @@ -128,7 +129,7 @@ func (m *manager) Marshal(version uint16, value interface{}) ([]byte, error) { m.lock.RUnlock() if !exists { - return nil, errUnknownVersion + return nil, ErrUnknownVersion } p := wrappers.Packer{ @@ -168,7 +169,7 @@ func (m *manager) Unmarshal(bytes []byte, dest interface{}) (uint16, error) { c, exists := m.codecs[version] m.lock.RUnlock() if !exists { - return version, errUnknownVersion + return version, ErrUnknownVersion } return version, c.Unmarshal(p.Bytes[p.Offset:], dest) } diff --git a/vms/proposervm/block/block.go b/vms/proposervm/block/block.go index efdba8015b53..5b55f7d34448 100644 --- a/vms/proposervm/block/block.go +++ b/vms/proposervm/block/block.go @@ -6,6 +6,7 @@ package block import ( "crypto/x509" "errors" + "fmt" "time" "github.com/ava-labs/avalanchego/ids" @@ -19,6 +20,7 @@ var ( errUnexpectedProposer = errors.New("expected no proposer but one was provided") errMissingProposer = errors.New("expected proposer but none was provided") + errInvalidCertificate = errors.New("invalid certificate") ) type Block interface { @@ -92,7 +94,7 @@ func (b *statelessBlock) initialize(bytes []byte) error { cert, err := x509.ParseCertificate(b.StatelessBlock.Certificate) if err != nil { - return err + return fmt.Errorf("%w: %s", errInvalidCertificate, err) } if err := staking.VerifyCertificate(cert); err != nil { diff --git a/vms/proposervm/block/block_test.go b/vms/proposervm/block/block_test.go index 7b6b6de5c041..d0b1a817b941 100644 --- a/vms/proposervm/block/block_test.go +++ b/vms/proposervm/block/block_test.go @@ -41,10 +41,10 @@ func TestVerifyNoCertWithSignature(t *testing.T) { builtBlock.Signature = []byte{0} err = builtBlock.Verify(false, ids.Empty) - require.Error(err) + require.ErrorIs(err, errUnexpectedProposer) err = builtBlock.Verify(true, ids.Empty) - require.Error(err) + require.ErrorIs(err, errMissingProposer) } func TestBlockSizeLimit(t *testing.T) { diff --git a/vms/proposervm/block/build_test.go b/vms/proposervm/block/build_test.go index c2d89cffa556..a4136c7089ca 100644 --- a/vms/proposervm/block/build_test.go +++ b/vms/proposervm/block/build_test.go @@ -49,7 +49,7 @@ func TestBuild(t *testing.T) { require.NoError(err) err = builtBlock.Verify(false, chainID) - require.Error(err) + require.ErrorIs(err, errUnexpectedProposer) } func TestBuildUnsigned(t *testing.T) { @@ -73,7 +73,7 @@ func TestBuildUnsigned(t *testing.T) { require.NoError(err) err = builtBlock.Verify(true, ids.Empty) - require.Error(err) + require.ErrorIs(err, errMissingProposer) } func TestBuildHeader(t *testing.T) { diff --git a/vms/proposervm/block/parse_test.go b/vms/proposervm/block/parse_test.go index f74996011630..777b4d16d70a 100644 --- a/vms/proposervm/block/parse_test.go +++ b/vms/proposervm/block/parse_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/staking" ) @@ -60,7 +61,7 @@ func TestParseDuplicateExtension(t *testing.T) { require.NoError(err) _, err = Parse(blockBytes) - require.Error(err) // Do not check for errDuplicateExtension to support g1.19 + require.ErrorIs(err, errInvalidCertificate) } func TestParseHeader(t *testing.T) { @@ -130,5 +131,5 @@ func TestParseGibberish(t *testing.T) { bytes := []byte{0, 1, 2, 3, 4, 5} _, err := Parse(bytes) - require.Error(err) + require.ErrorIs(err, codec.ErrUnknownVersion) } diff --git a/vms/proposervm/summary/parse_test.go b/vms/proposervm/summary/parse_test.go index 3d527e27754d..b22be83582e2 100644 --- a/vms/proposervm/summary/parse_test.go +++ b/vms/proposervm/summary/parse_test.go @@ -7,6 +7,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/codec" ) func TestParse(t *testing.T) { @@ -35,5 +37,5 @@ func TestParseGibberish(t *testing.T) { bytes := []byte{0, 1, 2, 3, 4, 5} _, err := Parse(bytes) - require.Error(err) + require.ErrorIs(err, codec.ErrUnknownVersion) } diff --git a/vms/registry/vm_registerer.go b/vms/registry/vm_registerer.go index 6a6fdd85f421..09221457009d 100644 --- a/vms/registry/vm_registerer.go +++ b/vms/registry/vm_registerer.go @@ -5,6 +5,7 @@ package registry import ( "context" + "errors" "fmt" "path" "sync" @@ -19,7 +20,11 @@ import ( "github.com/ava-labs/avalanchego/vms" ) -var _ VMRegisterer = (*vmRegisterer)(nil) +var ( + _ VMRegisterer = (*vmRegisterer)(nil) + + errNotVM = errors.New("not a VM") +) // VMRegisterer defines functionality to install a virtual machine. type VMRegisterer interface { @@ -97,7 +102,7 @@ func (r *vmRegisterer) createStaticHandlers( commonVM, ok := vm.(common.VM) if !ok { - return nil, fmt.Errorf("%s doesn't implement VM", vmID) + return nil, fmt.Errorf("%s is %w", vmID, errNotVM) } handlers, err := commonVM.CreateStaticHandlers(ctx) diff --git a/vms/registry/vm_registerer_test.go b/vms/registry/vm_registerer_test.go index e469277b21c5..58df3f9f7dec 100644 --- a/vms/registry/vm_registerer_test.go +++ b/vms/registry/vm_registerer_test.go @@ -48,7 +48,7 @@ func TestRegisterBadVM(t *testing.T) { // Since this factory produces a bad vm, we should get an error. vmFactory.EXPECT().New(logging.NoLog{}).Times(1).Return(vm, nil) - require.Error(t, resources.registerer.Register(context.Background(), id, vmFactory)) + require.ErrorIs(t, resources.registerer.Register(context.Background(), id, vmFactory), errNotVM) } // Tests Register if creating endpoints for a VM fails + shutdown fails @@ -245,7 +245,7 @@ func TestRegisterWithReadLockBadVM(t *testing.T) { // Since this factory produces a bad vm, we should get an error. vmFactory.EXPECT().New(logging.NoLog{}).Times(1).Return(vm, nil) - require.Error(t, resources.registerer.RegisterWithReadLock(context.Background(), id, vmFactory)) + require.ErrorIs(t, resources.registerer.RegisterWithReadLock(context.Background(), id, vmFactory), errNotVM) } // Tests RegisterWithReadLock if creating endpoints for a VM fails + shutdown fails diff --git a/vms/rpcchainvm/state_syncable_vm_test.go b/vms/rpcchainvm/state_syncable_vm_test.go index d2c47856757c..4be3941815ee 100644 --- a/vms/rpcchainvm/state_syncable_vm_test.go +++ b/vms/rpcchainvm/state_syncable_vm_test.go @@ -326,7 +326,7 @@ func TestStateSyncEnabled(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.StateSyncEnabled(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestGetOngoingSyncStateSummary(t *testing.T) { @@ -351,7 +351,7 @@ func TestGetOngoingSyncStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.GetOngoingSyncStateSummary(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestGetLastStateSummary(t *testing.T) { @@ -376,7 +376,7 @@ func TestGetLastStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.GetLastStateSummary(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestParseStateSummary(t *testing.T) { @@ -400,12 +400,12 @@ func TestParseStateSummary(t *testing.T) { // test parsing nil summary _, err = vm.ParseStateSummary(context.Background(), nil) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors // test a non-special error. // TODO: retrieve exact error _, err = vm.ParseStateSummary(context.Background(), mockedSummary.Bytes()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestGetStateSummary(t *testing.T) { @@ -430,7 +430,7 @@ func TestGetStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.GetStateSummary(context.Background(), mockedSummary.Height()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestAcceptStateSummary(t *testing.T) { @@ -458,7 +458,7 @@ func TestAcceptStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = summary.Accept(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } // Show that LastAccepted call returns the right answer after a StateSummary From a54394272397f8b6bb6028f9c8e59d3fbef212ce Mon Sep 17 00:00:00 2001 From: Stephen Date: Sat, 15 Apr 2023 18:17:05 -0400 Subject: [PATCH 10/77] wip --- .../txs/executor/create_chain_test.go | 2 +- vms/platformvm/utxo/handler.go | 35 +++++--- vms/platformvm/utxo/handler_test.go | 87 +++++++++---------- vms/platformvm/warp/message_test.go | 9 +- vms/platformvm/warp/test_signer.go | 3 +- vms/platformvm/warp/unsigned_message_test.go | 9 +- vms/proposervm/batched_vm_test.go | 8 +- 7 files changed, 85 insertions(+), 68 deletions(-) diff --git a/vms/platformvm/txs/executor/create_chain_test.go b/vms/platformvm/txs/executor/create_chain_test.go index db6bbd658c20..4ca3ae84270d 100644 --- a/vms/platformvm/txs/executor/create_chain_test.go +++ b/vms/platformvm/txs/executor/create_chain_test.go @@ -183,7 +183,7 @@ func TestCreateChainTxAP3FeeChange(t *testing.T) { name: "post-fork - incorrectly priced", time: ap3Time, fee: 100*defaultTxFee - 1*units.NanoAvax, - expectedError: utxo.ErrMustBurnMore, + expectedError: utxo.ErrInsufficientUnlockedFunds, }, { name: "post-fork - correctly priced", diff --git a/vms/platformvm/utxo/handler.go b/vms/platformvm/utxo/handler.go index fa9a661983c5..71cd3616e08a 100644 --- a/vms/platformvm/utxo/handler.go +++ b/vms/platformvm/utxo/handler.go @@ -29,7 +29,12 @@ var ( _ Handler = (*handler)(nil) ErrInsufficientFunds = errors.New("insufficient funds") - ErrMustBurnMore = errors.New("tx must burn more unlocked tokens") + ErrInsufficientUnlockedFunds = errors.New("insufficient unlocked funds") + ErrInsufficientLockedFunds = errors.New("insufficient locked funds") + errWrongNumberCredentials = errors.New("wrong number of credentials") + errWrongNumberUTXOs = errors.New("wrong number of UTXOs") + errAssetIDMismatch = errors.New("input asset ID does not match UTXO asset ID") + errLocktimeMismatch = errors.New("input locktime does not match UTXO locktime") errCantSign = errors.New("can't sign") errLockedFundsNotMarkedAsLocked = errors.New("locked funds not marked as locked") ) @@ -462,14 +467,16 @@ func (h *handler) VerifySpendUTXOs( ) error { if len(ins) != len(creds) { return fmt.Errorf( - "there are %d inputs but %d credentials. Should be same number", + "%w: %d inputs != %d credentials", + errWrongNumberCredentials, len(ins), len(creds), ) } if len(ins) != len(utxos) { return fmt.Errorf( - "there are %d inputs but %d utxos. Should be same number", + "%w: %d inputs != %d utxos", + errWrongNumberUTXOs, len(ins), len(utxos), ) @@ -499,8 +506,8 @@ func (h *handler) VerifySpendUTXOs( claimedAssetID := input.AssetID() if realAssetID != claimedAssetID { return fmt.Errorf( - "input %d has asset ID %s but UTXO has asset ID %s", - index, + "%w: %s != %s", + errAssetIDMismatch, claimedAssetID, realAssetID, ) @@ -523,7 +530,12 @@ func (h *handler) VerifySpendUTXOs( } else if ok { if inner.Locktime != locktime { // This input is locked, but its locktime is wrong - return fmt.Errorf("expected input %d locktime to be %d but got %d", index, locktime, inner.Locktime) + return fmt.Errorf( + "%w: %d != %d", + errLocktimeMismatch, + inner.Locktime, + locktime, + ) } in = inner.TransferableIn } @@ -633,10 +645,11 @@ func (h *handler) VerifySpendUTXOs( unlockedConsumedAsset := unlockedConsumed[assetID] if increase > unlockedConsumedAsset { return fmt.Errorf( - "address %s produces %d unlocked and consumes %d unlocked for locktime %d", + "%w: %s needs %d more %s for locktime %d", + ErrInsufficientLockedFunds, ownerID, - increase, - unlockedConsumedAsset, + increase-unlockedConsumedAsset, + assetID, locktime, ) } @@ -651,8 +664,8 @@ func (h *handler) VerifySpendUTXOs( // More unlocked tokens produced than consumed. Invalid. if unlockedProducedAsset > unlockedConsumedAsset { return fmt.Errorf( - "%w: %d %s", - ErrMustBurnMore, + "%w: needs %d more %s", + ErrInsufficientUnlockedFunds, unlockedProducedAsset-unlockedConsumedAsset, assetID, ) diff --git a/vms/platformvm/utxo/handler_test.go b/vms/platformvm/utxo/handler_test.go index d5a2759eb63f..d11ec51b6514 100644 --- a/vms/platformvm/utxo/handler_test.go +++ b/vms/platformvm/utxo/handler_test.go @@ -4,15 +4,17 @@ package utxo import ( - "math" "testing" "time" + stdmath "math" + "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -62,7 +64,7 @@ func TestVerifySpendUTXOs(t *testing.T) { outs []*avax.TransferableOutput creds []verify.Verifiable producedAmounts map[ids.ID]uint64 - shouldErr bool + expectedErr error }{ { description: "no inputs, no outputs, no fee", @@ -71,7 +73,7 @@ func TestVerifySpendUTXOs(t *testing.T) { outs: []*avax.TransferableOutput{}, creds: []verify.Verifiable{}, producedAmounts: map[ids.ID]uint64{}, - shouldErr: false, + expectedErr: nil, }, { description: "no inputs, no outputs, positive fee", @@ -82,7 +84,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: ErrInsufficientUnlockedFunds, }, { description: "wrong utxo assetID, one input, no outputs, no fee", @@ -103,7 +105,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: errAssetIDMismatch, }, { description: "one wrong assetID input, no outputs, no fee", @@ -124,7 +126,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: errAssetIDMismatch, }, { description: "one input, one wrong assetID output, no fee", @@ -152,7 +154,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: ErrInsufficientUnlockedFunds, }, { description: "attempt to consume locked output as unlocked", @@ -176,7 +178,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: errLockedFundsNotMarkedAsLocked, }, { description: "attempt to modify locktime", @@ -203,7 +205,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: errLocktimeMismatch, }, { description: "one input, no outputs, positive fee", @@ -226,7 +228,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: false, + expectedErr: nil, }, { description: "wrong number of credentials", @@ -247,7 +249,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: errWrongNumberCredentials, }, { description: "wrong number of UTXOs", @@ -265,7 +267,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: errWrongNumberUTXOs, }, { description: "invalid credential", @@ -288,7 +290,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: secp256k1fx.ErrNilCredential, }, { description: "invalid signature", @@ -324,7 +326,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: secp256k1.ErrInvalidSig, }, { description: "one input, no outputs, positive fee", @@ -347,7 +349,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: false, + expectedErr: nil, }, { description: "locked one input, no outputs, no fee", @@ -374,7 +376,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: false, + expectedErr: nil, }, { description: "locked one input, no outputs, positive fee", @@ -403,7 +405,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: ErrInsufficientUnlockedFunds, }, { description: "one locked and one unlocked input, one locked output, positive fee", @@ -459,7 +461,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: false, + expectedErr: nil, }, { description: "one locked and one unlocked input, one locked output, positive fee, partially locked", @@ -515,7 +517,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: false, + expectedErr: nil, }, { description: "one unlocked input, one locked output, zero fee", @@ -550,7 +552,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: false, + expectedErr: nil, }, { description: "attempted overflow", @@ -580,7 +582,7 @@ func TestVerifySpendUTXOs(t *testing.T) { { Asset: avax.Asset{ID: h.ctx.AVAXAssetID}, Out: &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, + Amt: stdmath.MaxUint64, }, }, }, @@ -588,7 +590,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: math.ErrOverflow, }, { description: "attempted mint", @@ -623,7 +625,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: ErrInsufficientLockedFunds, }, { description: "attempted mint through locking", @@ -658,7 +660,7 @@ func TestVerifySpendUTXOs(t *testing.T) { Out: &stakeable.LockOut{ Locktime: 1, TransferableOut: &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, + Amt: stdmath.MaxUint64, }, }, }, @@ -667,7 +669,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: math.ErrOverflow, }, { description: "attempted mint through mixed locking (low then high)", @@ -699,7 +701,7 @@ func TestVerifySpendUTXOs(t *testing.T) { Out: &stakeable.LockOut{ Locktime: 1, TransferableOut: &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, + Amt: stdmath.MaxUint64, }, }, }, @@ -708,7 +710,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: ErrInsufficientLockedFunds, }, { description: "attempted mint through mixed locking (high then low)", @@ -732,7 +734,7 @@ func TestVerifySpendUTXOs(t *testing.T) { { Asset: avax.Asset{ID: h.ctx.AVAXAssetID}, Out: &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, + Amt: stdmath.MaxUint64, }, }, { @@ -749,7 +751,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: ErrInsufficientLockedFunds, }, { description: "transfer non-avax asset", @@ -781,7 +783,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: false, + expectedErr: nil, }, { description: "lock non-avax asset", @@ -816,7 +818,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: false, + expectedErr: nil, }, { description: "attempted asset conversion", @@ -848,7 +850,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: map[ids.ID]uint64{}, - shouldErr: true, + expectedErr: ErrInsufficientUnlockedFunds, }, { description: "attempted asset conversion with burn", @@ -875,7 +877,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: ErrInsufficientUnlockedFunds, }, { description: "two inputs, one output with custom asset, with fee", @@ -922,7 +924,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: false, + expectedErr: nil, }, { description: "one input, fee, custom asset", @@ -949,7 +951,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ h.ctx.AVAXAssetID: 1, }, - shouldErr: true, + expectedErr: ErrInsufficientUnlockedFunds, }, { description: "one input, custom fee", @@ -976,7 +978,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ customAssetID: 1, }, - shouldErr: false, + expectedErr: nil, }, { description: "one input, custom fee, wrong burn", @@ -1003,7 +1005,7 @@ func TestVerifySpendUTXOs(t *testing.T) { producedAmounts: map[ids.ID]uint64{ customAssetID: 1, }, - shouldErr: true, + expectedErr: ErrInsufficientUnlockedFunds, }, { description: "two inputs, multiple fee", @@ -1044,7 +1046,7 @@ func TestVerifySpendUTXOs(t *testing.T) { h.ctx.AVAXAssetID: 1, customAssetID: 1, }, - shouldErr: false, + expectedErr: nil, }, { description: "one unlock input, one locked output, zero fee, unlocked, custom asset", @@ -1079,7 +1081,7 @@ func TestVerifySpendUTXOs(t *testing.T) { &secp256k1fx.Credential{}, }, producedAmounts: make(map[ids.ID]uint64), - shouldErr: false, + expectedErr: nil, }, } @@ -1096,12 +1098,7 @@ func TestVerifySpendUTXOs(t *testing.T) { test.creds, test.producedAmounts, ) - - if test.shouldErr { - require.Error(err) - } else { - require.NoError(err) - } + require.ErrorIs(err, test.expectedErr) }) } } diff --git a/vms/platformvm/warp/message_test.go b/vms/platformvm/warp/message_test.go index 943755304ac1..f9df318314ec 100644 --- a/vms/platformvm/warp/message_test.go +++ b/vms/platformvm/warp/message_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/crypto/bls" ) @@ -39,6 +39,9 @@ func TestMessage(t *testing.T) { } func TestParseMessageJunk(t *testing.T) { - _, err := ParseMessage(utils.RandomBytes(1024)) - require.Error(t, err) + require := require.New(t) + + bytes := []byte{0, 1, 2, 3, 4, 5, 6, 7} + _, err := ParseMessage(bytes) + require.ErrorIs(err, codec.ErrUnknownVersion) } diff --git a/vms/platformvm/warp/test_signer.go b/vms/platformvm/warp/test_signer.go index f030447f38eb..fb9331f41cec 100644 --- a/vms/platformvm/warp/test_signer.go +++ b/vms/platformvm/warp/test_signer.go @@ -30,7 +30,8 @@ func TestSignerWrongChainID(t *testing.T, s Signer, _ *bls.SecretKey, _ ids.ID) require.NoError(err) _, err = s.Sign(msg) - require.Error(err) + // TODO: require error to be errWrongSourceChainID + require.Error(err) //nolint:forbidigo // currently returns grpc errors too } // Test that a signature generated with the signer verifies correctly diff --git a/vms/platformvm/warp/unsigned_message_test.go b/vms/platformvm/warp/unsigned_message_test.go index cf8073d802b4..e9029aec7dfc 100644 --- a/vms/platformvm/warp/unsigned_message_test.go +++ b/vms/platformvm/warp/unsigned_message_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" ) func TestUnsignedMessage(t *testing.T) { @@ -29,6 +29,9 @@ func TestUnsignedMessage(t *testing.T) { } func TestParseUnsignedMessageJunk(t *testing.T) { - _, err := ParseUnsignedMessage(utils.RandomBytes(1024)) - require.Error(t, err) + require := require.New(t) + + bytes := []byte{0, 1, 2, 3, 4, 5, 6, 7} + _, err := ParseUnsignedMessage(bytes) + require.ErrorIs(err, codec.ErrUnknownVersion) } diff --git a/vms/proposervm/batched_vm_test.go b/vms/proposervm/batched_vm_test.go index b61b9062538c..c5202a634ce9 100644 --- a/vms/proposervm/batched_vm_test.go +++ b/vms/proposervm/batched_vm_test.go @@ -34,18 +34,18 @@ func TestCoreVMNotRemote(t *testing.T) { maxBlocksNum := 1000 // an high value to get all built blocks maxBlocksSize := 1000000 // an high value to get all built blocks maxBlocksRetrivalTime := time.Duration(1000000) // an high value to get all built blocks - _, errAncestors := proVM.GetAncestors( + _, err := proVM.GetAncestors( context.Background(), blkID, maxBlocksNum, maxBlocksSize, maxBlocksRetrivalTime, ) - require.Error(errAncestors) + require.ErrorIs(err, block.ErrRemoteVMNotImplemented) var blks [][]byte - _, errBatchedParse := proVM.BatchedParseBlock(context.Background(), blks) - require.Error(errBatchedParse) + _, err = proVM.BatchedParseBlock(context.Background(), blks) + require.ErrorIs(err, block.ErrRemoteVMNotImplemented) } func TestGetAncestorsPreForkOnly(t *testing.T) { From 3c0217c763dea9e40e59960c1da615a2d9954731 Mon Sep 17 00:00:00 2001 From: Stephen Date: Sat, 15 Apr 2023 18:21:35 -0400 Subject: [PATCH 11/77] wip --- .../txs/executor/standard_tx_executor_test.go | 20 +++---------------- .../txs/remove_subnet_validator_tx.go | 4 ++-- .../txs/remove_subnet_validator_tx_test.go | 2 +- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 5a2581e478e2..e0f92d1c14b5 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -1072,7 +1072,6 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { type test struct { name string newExecutor func(*gomock.Controller) (*txs.RemoveSubnetValidatorTx, *StandardTxExecutor) - shouldErr bool expectedErr error } @@ -1114,7 +1113,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: false, + expectedErr: nil, }, { name: "tx fails syntactic verification", @@ -1139,7 +1138,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: true, + expectedErr: txs.ErrRemovePrimaryNetworkValidator, }, { name: "node isn't a validator of the subnet", @@ -1164,7 +1163,6 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: true, expectedErr: errNotValidator, }, { @@ -1193,7 +1191,6 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: true, expectedErr: errRemovePermissionlessValidator, }, { @@ -1220,7 +1217,6 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: true, expectedErr: errWrongNumberOfCredentials, }, { @@ -1246,7 +1242,6 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: true, expectedErr: errCantFindSubnet, }, { @@ -1279,7 +1274,6 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: true, expectedErr: errUnauthorizedSubnetModification, }, { @@ -1315,7 +1309,6 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - shouldErr: true, expectedErr: errFlowCheckFailed, }, } @@ -1328,14 +1321,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { unsignedTx, executor := tt.newExecutor(ctrl) err := executor.RemoveSubnetValidatorTx(unsignedTx) - if tt.shouldErr { - require.Error(err) - if tt.expectedErr != nil { - require.ErrorIs(err, tt.expectedErr) - } - return - } - require.NoError(err) + require.ErrorIs(err, tt.expectedErr) }) } } diff --git a/vms/platformvm/txs/remove_subnet_validator_tx.go b/vms/platformvm/txs/remove_subnet_validator_tx.go index fc6126aa581d..2221c2f345ca 100644 --- a/vms/platformvm/txs/remove_subnet_validator_tx.go +++ b/vms/platformvm/txs/remove_subnet_validator_tx.go @@ -15,7 +15,7 @@ import ( var ( _ UnsignedTx = (*RemoveSubnetValidatorTx)(nil) - errRemovePrimaryNetworkValidator = errors.New("can't remove primary network validator with RemoveSubnetValidatorTx") + ErrRemovePrimaryNetworkValidator = errors.New("can't remove primary network validator with RemoveSubnetValidatorTx") ) // Removes a validator from a subnet. @@ -37,7 +37,7 @@ func (tx *RemoveSubnetValidatorTx) SyntacticVerify(ctx *snow.Context) error { // already passed syntactic verification return nil case tx.Subnet == constants.PrimaryNetworkID: - return errRemovePrimaryNetworkValidator + return ErrRemovePrimaryNetworkValidator } if err := tx.BaseTx.SyntacticVerify(ctx); err != nil { diff --git a/vms/platformvm/txs/remove_subnet_validator_tx_test.go b/vms/platformvm/txs/remove_subnet_validator_tx_test.go index 6ad782af5bc9..5e60fcc3d537 100644 --- a/vms/platformvm/txs/remove_subnet_validator_tx_test.go +++ b/vms/platformvm/txs/remove_subnet_validator_tx_test.go @@ -103,7 +103,7 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { } }, shouldErr: true, - requireSpecificErr: errRemovePrimaryNetworkValidator, + requireSpecificErr: ErrRemovePrimaryNetworkValidator, }, { name: "invalid subnetAuth", From c47dad4192f77d88f9f949f29dff09ae1de5e064 Mon Sep 17 00:00:00 2001 From: Stephen Date: Sat, 15 Apr 2023 19:37:32 -0400 Subject: [PATCH 12/77] Fix bad addValidatorTx tests --- .../txs/executor/staker_tx_verification.go | 4 +- .../txs/executor/standard_tx_executor_test.go | 59 +++++++++++-------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 54edaca9c3b5..67f0092397f3 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -34,6 +34,7 @@ var ( errOverDelegated = errors.New("validator would be over delegated") errIsNotTransformSubnetTx = errors.New("is not a transform subnet tx") errTimestampNotBeforeStartTime = errors.New("chain timestamp not before start time") + errAlreadyValidator = errors.New("already a validator") errDuplicateValidator = errors.New("duplicate validator") errDelegateToPermissionedValidator = errors.New("delegation to permissioned validator") errWrongStakedAssetID = errors.New("incorrect staked assetID") @@ -103,8 +104,9 @@ func verifyAddValidatorTx( _, err := GetValidator(chainState, constants.PrimaryNetworkID, tx.Validator.NodeID) if err == nil { return nil, fmt.Errorf( - "attempted to issue duplicate validation for %s", + "%s is %w of the primary network", tx.Validator.NodeID, + errAlreadyValidator, ) } if err != database.ErrNotFound { diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index e0f92d1c14b5..93680acfddd2 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -840,7 +840,7 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've errored because start time too early") + require.ErrorIs(err, errTimestampNotBeforeStartTime) } { @@ -866,33 +866,44 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've errored because start time too far in the future") + require.ErrorIs(err, errFutureStakeTime) } { - // Case: Validator already validating primary network + // Case: Validator in current validator set of primary network + startTime := defaultGenesisTime.Add(1 * time.Second) tx, err := env.txBuilder.NewAddValidatorTx( - env.config.MinValidatorStake, - uint64(defaultValidateStartTime.Unix()), - uint64(defaultValidateEndTime.Unix()), + env.config.MinValidatorStake, // stake amount + uint64(startTime.Unix()), // start time + uint64(startTime.Add(defaultMinStakingDuration).Unix()), // end time nodeID, ids.ShortEmpty, - reward.PercentDenominator, + reward.PercentDenominator, // shares []*secp256k1.PrivateKey{preFundedKeys[0]}, - ids.ShortEmpty, // change addr + ids.ShortEmpty, // change addr // key + ) + require.NoError(err) + + staker, err := state.NewCurrentStaker( + tx.ID(), + tx.Unsigned.(*txs.AddValidatorTx), + 0, ) require.NoError(err) onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + onAcceptState.PutCurrentValidator(staker) + onAcceptState.AddTx(tx, status.Committed) + executor := StandardTxExecutor{ Backend: &env.backend, State: onAcceptState, Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've errored because validator already validating") + require.ErrorIs(err, errAlreadyValidator) } { @@ -910,38 +921,34 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { ) require.NoError(err) - staker, err := state.NewCurrentStaker( + staker, err := state.NewPendingStaker( tx.ID(), tx.Unsigned.(*txs.AddValidatorTx), - 0, ) require.NoError(err) - env.state.PutCurrentValidator(staker) - env.state.AddTx(tx, status.Committed) - dummyHeight := uint64(1) - env.state.SetHeight(dummyHeight) - err = env.state.Commit() - require.NoError(err) - onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + onAcceptState.PutPendingValidator(staker) + onAcceptState.AddTx(tx, status.Committed) + executor := StandardTxExecutor{ Backend: &env.backend, State: onAcceptState, Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator in pending validator set") + require.ErrorIs(err, errAlreadyValidator) } { // Case: Validator doesn't have enough tokens to cover stake amount + startTime := defaultGenesisTime.Add(1 * time.Second) tx, err := env.txBuilder.NewAddValidatorTx( // create the tx env.config.MinValidatorStake, - uint64(defaultValidateStartTime.Unix()), - uint64(defaultValidateEndTime.Unix()), + uint64(startTime.Unix()), + uint64(startTime.Add(defaultMinStakingDuration).Unix()), nodeID, ids.ShortEmpty, reward.PercentDenominator, @@ -954,20 +961,20 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { utxoIDs, err := env.state.UTXOIDs(preFundedKeys[0].PublicKey().Address().Bytes(), ids.Empty, math.MaxInt32) require.NoError(err) - for _, utxoID := range utxoIDs { - env.state.DeleteUTXO(utxoID) - } - onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + for _, utxoID := range utxoIDs { + onAcceptState.DeleteUTXO(utxoID) + } + executor := StandardTxExecutor{ Backend: &env.backend, State: onAcceptState, Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because tx fee paying key has no funds") + require.ErrorIs(err, errFlowCheckFailed) } } From 3a21dd8747bbca7a8cf76603dc36fc804bd170d1 Mon Sep 17 00:00:00 2001 From: Stephen Date: Mon, 17 Apr 2023 14:24:52 -0400 Subject: [PATCH 13/77] wip --- .../txs/executor/staker_tx_verification.go | 11 ++- .../txs/executor/standard_tx_executor_test.go | 73 +++++++++++-------- vms/secp256k1fx/fx_test.go | 4 +- vms/secp256k1fx/input.go | 8 +- vms/secp256k1fx/input_test.go | 6 +- vms/secp256k1fx/mint_operation_test.go | 2 +- vms/secp256k1fx/transfer_input.go | 2 +- vms/secp256k1fx/transfer_input_test.go | 6 +- 8 files changed, 67 insertions(+), 45 deletions(-) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 67f0092397f3..0e758b379c7d 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -184,8 +184,10 @@ func verifyAddSubnetValidatorTx( _, err := GetValidator(chainState, tx.SubnetValidator.Subnet, tx.Validator.NodeID) if err == nil { return fmt.Errorf( - "attempted to issue duplicate subnet validation for %s", + "attempted to issue %w for %s on subnet %s", + errDuplicateValidator, tx.Validator.NodeID, + tx.SubnetValidator.Subnet, ) } if err != database.ErrNotFound { @@ -197,6 +199,13 @@ func verifyAddSubnetValidatorTx( } primaryNetworkValidator, err := GetValidator(chainState, constants.PrimaryNetworkID, tx.Validator.NodeID) + if err == database.ErrNotFound { + return fmt.Errorf( + "%s %w of the primary network", + tx.Validator.NodeID, + errNotValidator, + ) + } if err != nil { return fmt.Errorf( "failed to fetch the primary network validator for %s: %w", diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 93680acfddd2..ef646cd1544f 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -399,9 +399,10 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { // Case: Proposed validator currently validating primary network // but stops validating subnet after stops validating primary network // (note that keys[0] is a genesis validator) + startTime := defaultValidateStartTime.Add(time.Second) tx, err := env.txBuilder.NewAddSubnetValidatorTx( defaultWeight, - uint64(defaultValidateStartTime.Unix()), + uint64(startTime.Unix()), uint64(defaultValidateEndTime.Unix())+1, ids.NodeID(nodeID), testSubnet1.ID(), @@ -419,7 +420,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator stops validating primary network earlier than subnet") + require.ErrorIs(err, errValidatorSubset) } { @@ -494,7 +495,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator not in the current or pending validator sets of the primary network") + require.ErrorIs(err, errNotValidator) } staker, err := state.NewCurrentStaker( @@ -536,7 +537,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator starts validating primary network before starting to validate primary network") + require.ErrorIs(err, errValidatorSubset) } { @@ -562,7 +563,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator stops validating primary network after stops validating primary network") + require.ErrorIs(err, errValidatorSubset) } { @@ -616,7 +617,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because starts validating at current timestamp") + require.ErrorIs(err, errTimestampNotBeforeStartTime) } // reset the timestamp @@ -650,12 +651,13 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { { // Node with ID nodeIDKey.PublicKey().Address() now validating subnet with ID testSubnet1.ID + startTime := defaultValidateStartTime.Add(time.Second) duplicateSubnetTx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultValidateStartTime.Unix()), // start time - uint64(defaultValidateEndTime.Unix()), // end time - ids.NodeID(nodeID), // node ID - testSubnet1.ID(), // subnet ID + defaultWeight, // weight + uint64(startTime.Unix()), // start time + uint64(defaultValidateEndTime.Unix()), // end time + ids.NodeID(nodeID), // node ID + testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]}, ids.ShortEmpty, // change addr ) @@ -670,7 +672,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: duplicateSubnetTx, } err = duplicateSubnetTx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because validator already validating the specified subnet") + require.ErrorIs(err, errDuplicateValidator) } env.state.DeleteCurrentValidator(staker) @@ -679,11 +681,12 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { require.NoError(err) { - // Case: Too many signatures + // Case: Duplicate signatures + startTime := defaultValidateStartTime.Add(time.Second) tx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultGenesisTime.Unix()), // start time - uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix())+1, // end time + defaultWeight, // weight + uint64(startTime.Unix()), // start time + uint64(startTime.Add(defaultMinStakingDuration).Unix())+1, // end time ids.NodeID(nodeID), // node ID testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1], testSubnet1ControlKeys[2]}, @@ -691,6 +694,13 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { ) require.NoError(err) + // Duplicate a signature + addSubnetValidatorTx := tx.Unsigned.(*txs.AddSubnetValidatorTx) + input := addSubnetValidatorTx.SubnetAuth.(*secp256k1fx.Input) + input.SigIndices = append(input.SigIndices, input.SigIndices[0]) + // This tx was syntactically verified when it was created...pretend it wasn't so we don't use cache + addSubnetValidatorTx.SyntacticallyVerified = false + onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) @@ -700,15 +710,16 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because tx has 3 signatures but only 2 needed") + require.ErrorIs(err, secp256k1fx.ErrNotSortedUnique) } { // Case: Too few signatures + startTime := defaultValidateStartTime.Add(time.Second) tx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultGenesisTime.Unix()), // start time - uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix()), // end time + defaultWeight, // weight + uint64(startTime.Unix()), // start time + uint64(startTime.Add(defaultMinStakingDuration).Unix()), // end time ids.NodeID(nodeID), // node ID testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[2]}, @@ -732,15 +743,16 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because not enough control sigs") + require.ErrorIs(err, errUnauthorizedSubnetModification) } { // Case: Control Signature from invalid key (keys[3] is not a control key) + startTime := defaultValidateStartTime.Add(time.Second) tx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultGenesisTime.Unix()), // start time - uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix()), // end time + defaultWeight, // weight + uint64(startTime.Unix()), // start time + uint64(startTime.Add(defaultMinStakingDuration).Unix()), // end time ids.NodeID(nodeID), // node ID testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], preFundedKeys[1]}, @@ -751,7 +763,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { // Replace a valid signature with one from keys[3] sig, err := preFundedKeys[3].SignHash(hashing.ComputeHash256(tx.Unsigned.Bytes())) require.NoError(err) - copy(tx.Creds[0].(*secp256k1fx.Credential).Sigs[0][:], sig) + copy(tx.Creds[1].(*secp256k1fx.Credential).Sigs[0][:], sig) onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) @@ -762,16 +774,17 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because a control sig is invalid") + require.ErrorIs(err, errUnauthorizedSubnetModification) } { // Case: Proposed validator in pending validator set for subnet // First, add validator to pending validator set of subnet + startTime := defaultValidateStartTime.Add(time.Second) tx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultGenesisTime.Unix())+1, // start time - uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix())+1, // end time + defaultWeight, // weight + uint64(startTime.Unix())+1, // start time + uint64(startTime.Add(defaultMinStakingDuration).Unix())+1, // end time ids.NodeID(nodeID), // node ID testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]}, @@ -801,7 +814,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because validator already in pending validator set of the specified subnet") + require.ErrorIs(err, errDuplicateValidator) } } diff --git a/vms/secp256k1fx/fx_test.go b/vms/secp256k1fx/fx_test.go index 733f49c59b2f..e163dd7e9cab 100644 --- a/vms/secp256k1fx/fx_test.go +++ b/vms/secp256k1fx/fx_test.go @@ -1028,7 +1028,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr2}, }, - errNotSortedUnique, + ErrNotSortedUnique, }, { "threshold 2, repeated address and repeated sig", @@ -1061,7 +1061,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr2}, }, - errNotSortedUnique, + ErrNotSortedUnique, }, { "threshold 1, 1 sig, index out of bounds", diff --git a/vms/secp256k1fx/input.go b/vms/secp256k1fx/input.go index 5659727c672c..df5511e2900c 100644 --- a/vms/secp256k1fx/input.go +++ b/vms/secp256k1fx/input.go @@ -15,8 +15,8 @@ const ( ) var ( - errNilInput = errors.New("nil input") - errNotSortedUnique = errors.New("signatures not sorted and unique") + ErrNilInput = errors.New("nil input") + ErrNotSortedUnique = errors.New("signatures not sorted and unique") ) type Input struct { @@ -35,9 +35,9 @@ func (in *Input) Cost() (uint64, error) { func (in *Input) Verify() error { switch { case in == nil: - return errNilInput + return ErrNilInput case !utils.IsSortedAndUniqueOrdered(in.SigIndices): - return errNotSortedUnique + return ErrNotSortedUnique default: return nil } diff --git a/vms/secp256k1fx/input_test.go b/vms/secp256k1fx/input_test.go index 72088530027b..40728330727f 100644 --- a/vms/secp256k1fx/input_test.go +++ b/vms/secp256k1fx/input_test.go @@ -18,17 +18,17 @@ func TestInputVerifyNil(t *testing.T) { { name: "nil input", in: nil, - expectedErr: errNilInput, + expectedErr: ErrNilInput, }, { name: "not sorted", in: &Input{SigIndices: []uint32{2, 1}}, - expectedErr: errNotSortedUnique, + expectedErr: ErrNotSortedUnique, }, { name: "not unique", in: &Input{SigIndices: []uint32{2, 2}}, - expectedErr: errNotSortedUnique, + expectedErr: ErrNotSortedUnique, }, { name: "passes verification", diff --git a/vms/secp256k1fx/mint_operation_test.go b/vms/secp256k1fx/mint_operation_test.go index 9b68b1c8725a..30288b5cf4fb 100644 --- a/vms/secp256k1fx/mint_operation_test.go +++ b/vms/secp256k1fx/mint_operation_test.go @@ -49,7 +49,7 @@ func TestMintOperationVerify(t *testing.T) { MintOutput: validMintOutput, TransferOutput: validTransferOutput, }, - expectedErr: errNotSortedUnique, + expectedErr: ErrNotSortedUnique, }, { name: "invalid mint output", diff --git a/vms/secp256k1fx/transfer_input.go b/vms/secp256k1fx/transfer_input.go index 2fb69c64345f..6dadd558fc49 100644 --- a/vms/secp256k1fx/transfer_input.go +++ b/vms/secp256k1fx/transfer_input.go @@ -27,7 +27,7 @@ func (in *TransferInput) Amount() uint64 { func (in *TransferInput) Verify() error { switch { case in == nil: - return errNilInput + return ErrNilInput case in.Amt == 0: return ErrNoValueInput default: diff --git a/vms/secp256k1fx/transfer_input_test.go b/vms/secp256k1fx/transfer_input_test.go index 96d2c40e2dbf..e7fff8782f36 100644 --- a/vms/secp256k1fx/transfer_input_test.go +++ b/vms/secp256k1fx/transfer_input_test.go @@ -38,7 +38,7 @@ func TestTransferInputVerify(t *testing.T) { func TestTransferInputVerifyNil(t *testing.T) { require := require.New(t) in := (*TransferInput)(nil) - require.ErrorIs(in.Verify(), errNilInput) + require.ErrorIs(in.Verify(), ErrNilInput) } func TestTransferInputVerifyNoValue(t *testing.T) { @@ -60,7 +60,7 @@ func TestTransferInputVerifyDuplicated(t *testing.T) { SigIndices: []uint32{0, 0}, }, } - require.ErrorIs(in.Verify(), errNotSortedUnique) + require.ErrorIs(in.Verify(), ErrNotSortedUnique) } func TestTransferInputVerifyUnsorted(t *testing.T) { @@ -71,7 +71,7 @@ func TestTransferInputVerifyUnsorted(t *testing.T) { SigIndices: []uint32{1, 0}, }, } - require.ErrorIs(in.Verify(), errNotSortedUnique) + require.ErrorIs(in.Verify(), ErrNotSortedUnique) } func TestTransferInputSerialize(t *testing.T) { From 1be6077075a1b16051181d56072cb737bc6cf97e Mon Sep 17 00:00:00 2001 From: Stephen Date: Mon, 17 Apr 2023 15:59:59 -0400 Subject: [PATCH 14/77] fix proposal tests --- vms/platformvm/txs/executor/proposal_tx_executor.go | 11 ++++++++--- vms/platformvm/txs/executor/reward_validator_test.go | 8 ++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index a8b96b00c63a..cd523be70313 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -32,6 +32,8 @@ const ( var ( _ txs.Visitor = (*ProposalTxExecutor)(nil) + errRemoveStakerTooEarly = errors.New("attempting to remove staker before their end time") + errRemoveWrongStaker = errors.New("attempting to remove wrong staker") errChildBlockNotAfterParent = errors.New("proposed timestamp not after current chain time") errInvalidState = errors.New("generated output isn't valid state") errShouldBePermissionlessStaker = errors.New("expected permissionless staker") @@ -323,9 +325,10 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error if stakerToRemove.TxID != tx.TxID { return fmt.Errorf( - "attempting to remove TxID: %s. Should be removing %s", - tx.TxID, + "%w: %s != %s", + errRemoveWrongStaker, stakerToRemove.TxID, + tx.TxID, ) } @@ -333,8 +336,10 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error currentChainTime := e.OnCommitState.GetTimestamp() if !stakerToRemove.EndTime.Equal(currentChainTime) { return fmt.Errorf( - "attempting to remove TxID: %s before their end time %s", + "%w: TxID = %s with %s < %s", + errRemoveStakerTooEarly, tx.TxID, + currentChainTime, stakerToRemove.EndTime, ) } diff --git a/vms/platformvm/txs/executor/reward_validator_test.go b/vms/platformvm/txs/executor/reward_validator_test.go index bc49bdd145ea..470683b3d44c 100644 --- a/vms/platformvm/txs/executor/reward_validator_test.go +++ b/vms/platformvm/txs/executor/reward_validator_test.go @@ -58,7 +58,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.Error(tx.Unsigned.Visit(&txExecutor)) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveStakerTooEarly) // Advance chain timestamp to time that next validator leaves env.state.SetTimestamp(stakerToRemove.EndTime) @@ -79,7 +79,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.Error(tx.Unsigned.Visit(&txExecutor)) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveWrongStaker) // Case 3: Happy path tx, err = env.txBuilder.NewRewardValidatorTx(stakerToRemove.TxID) @@ -159,7 +159,7 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.Error(tx.Unsigned.Visit(&txExecutor)) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveStakerTooEarly) // Advance chain timestamp to time that next validator leaves env.state.SetTimestamp(stakerToRemove.EndTime) @@ -174,7 +174,7 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.Error(tx.Unsigned.Visit(&txExecutor)) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveWrongStaker) // Case 3: Happy path tx, err = env.txBuilder.NewRewardValidatorTx(stakerToRemove.TxID) From 5e419d2d0dae11f0a23f5c399786d60a0ac02268 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 22:27:24 -0400 Subject: [PATCH 15/77] nit --- .../txs/executor/standard_tx_executor_test.go | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index ef646cd1544f..7873a7047a12 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -167,6 +167,7 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { currentTimestamp := dummyH.state.GetTimestamp() type test struct { + description string stakeAmount uint64 startTime uint64 endTime uint64 @@ -176,11 +177,11 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup func(*environment) AP3Time time.Time shouldErr bool - description string } tests := []test{ { + description: "validator stops validating primary network earlier than subnet", stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(defaultValidateStartTime.Unix()), endTime: uint64(defaultValidateEndTime.Unix()) + 1, @@ -190,9 +191,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator stops validating primary network earlier than subnet", }, { + description: fmt.Sprintf("validator should not be added more than (%s) in the future", MaxFutureStartTime), stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(currentTimestamp.Add(MaxFutureStartTime + time.Second).Unix()), endTime: uint64(currentTimestamp.Add(MaxFutureStartTime * 2).Unix()), @@ -202,9 +203,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: fmt.Sprintf("validator should not be added more than (%s) in the future", MaxFutureStartTime), }, { + description: "end time is after the primary network end time", stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(defaultValidateStartTime.Unix()), endTime: uint64(defaultValidateEndTime.Unix()) + 1, @@ -214,9 +215,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "end time is after the primary network end time", }, { + description: "validator not in the current or pending validator sets of the subnet", stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(defaultValidateStartTime.Add(5 * time.Second).Unix()), endTime: uint64(defaultValidateEndTime.Add(-5 * time.Second).Unix()), @@ -226,9 +227,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator not in the current or pending validator sets of the subnet", }, { + description: "validator starts validating subnet before primary network", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime - 1, // start validating subnet before primary network endTime: newValidatorEndTime, @@ -238,9 +239,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: addMinStakeValidator, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator starts validating subnet before primary network", }, { + description: "validator stops validating primary network before subnet", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, endTime: newValidatorEndTime + 1, // stop validating subnet after stopping validating primary network @@ -250,9 +251,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: addMinStakeValidator, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator stops validating primary network before subnet", }, { + description: "valid", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, // same start time as for primary network endTime: newValidatorEndTime, // same end time as for primary network @@ -262,9 +263,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: addMinStakeValidator, AP3Time: defaultGenesisTime, shouldErr: false, - description: "valid", }, { + description: "starts validating at current timestamp", stakeAmount: dummyH.config.MinDelegatorStake, // weight startTime: uint64(currentTimestamp.Unix()), // start time endTime: uint64(defaultValidateEndTime.Unix()), // end time @@ -274,9 +275,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "starts validating at current timestamp", }, { + description: "tx fee paying key has no funds", stakeAmount: dummyH.config.MinDelegatorStake, // weight startTime: uint64(defaultValidateStartTime.Unix()), // start time endTime: uint64(defaultValidateEndTime.Unix()), // end time @@ -297,11 +298,11 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { err = target.state.Commit() require.NoError(t, err) }, - AP3Time: defaultGenesisTime, - shouldErr: true, - description: "tx fee paying key has no funds", + AP3Time: defaultGenesisTime, + shouldErr: true, }, { + description: "over delegation before AP3", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, // same start time as for primary network endTime: newValidatorEndTime, // same end time as for primary network @@ -311,9 +312,9 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: addMaxStakeValidator, AP3Time: defaultValidateEndTime, shouldErr: false, - description: "over delegation before AP3", }, { + description: "over delegation after AP3", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, // same start time as for primary network endTime: newValidatorEndTime, // same end time as for primary network @@ -323,7 +324,6 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { setup: addMaxStakeValidator, AP3Time: defaultGenesisTime, shouldErr: true, - description: "over delegation after AP3", }, } From 530d076d94caa743dedcc43b9ab04ae53f0a1848 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 22:28:56 -0400 Subject: [PATCH 16/77] fix keystore user --- vms/components/keystore/user_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vms/components/keystore/user_test.go b/vms/components/keystore/user_test.go index 38c40b78ab2e..379897e9d2a8 100644 --- a/vms/components/keystore/user_test.go +++ b/vms/components/keystore/user_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/encdb" "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/ids" @@ -29,20 +30,20 @@ func TestUserClosedDB(t *testing.T) { u := NewUserFromDB(db) _, err = u.GetAddresses() - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) _, err = u.GetKey(ids.ShortEmpty) - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) _, err = GetKeychain(u, nil) - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) factory := secp256k1.Factory{} sk, err := factory.NewPrivateKey() require.NoError(err) err = u.PutKeys(sk) - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) } func TestUser(t *testing.T) { From 90ba1ab72b41a8279aec890f9255e6c30d990d55 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 22:33:06 -0400 Subject: [PATCH 17/77] nit --- vms/components/message/message_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vms/components/message/message_test.go b/vms/components/message/message_test.go index dbaf15432f21..163a8f8b04a2 100644 --- a/vms/components/message/message_test.go +++ b/vms/components/message/message_test.go @@ -8,12 +8,11 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/codec" ) func TestParseGibberish(t *testing.T) { - randomBytes := utils.RandomBytes(256 * units.KiB) + randomBytes := []byte{0, 1, 2, 3, 4, 5} _, err := Parse(randomBytes) - require.Error(t, err) + require.ErrorIs(t, err, codec.ErrUnknownVersion) } From 7d0d353ae4e965871318a34830655c80ae051ef8 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 22:36:39 -0400 Subject: [PATCH 18/77] cleanup test --- .../txs/transform_subnet_tx_test.go | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/vms/platformvm/txs/transform_subnet_tx_test.go b/vms/platformvm/txs/transform_subnet_tx_test.go index 82128bfc4aef..84cad0765e5e 100644 --- a/vms/platformvm/txs/transform_subnet_tx_test.go +++ b/vms/platformvm/txs/transform_subnet_tx_test.go @@ -372,6 +372,29 @@ func TestTransformSubnetTxSyntacticVerify(t *testing.T) { }, err: errInvalidSubnetAuth, }, + { + name: "invalid BaseTx", + txFunc: func(*gomock.Controller) *TransformSubnetTx { + return &TransformSubnetTx{ + BaseTx: invalidBaseTx, + Subnet: ids.GenerateTestID(), + AssetID: ids.GenerateTestID(), + InitialSupply: 10, + MaximumSupply: 10, + MinConsumptionRate: 0, + MaxConsumptionRate: reward.PercentDenominator, + MinValidatorStake: 2, + MaxValidatorStake: 10, + MinStakeDuration: 1, + MaxStakeDuration: 2, + MinDelegationFee: reward.PercentDenominator, + MinDelegatorStake: 1, + MaxValidatorWeightFactor: 1, + UptimeRequirement: reward.PercentDenominator, + } + }, + err: avax.ErrWrongNetworkID, + }, { name: "passes verification", txFunc: func(ctrl *gomock.Controller) *TransformSubnetTx { @@ -411,26 +434,4 @@ func TestTransformSubnetTxSyntacticVerify(t *testing.T) { require.ErrorIs(t, err, tt.err) }) } - - t.Run("invalid BaseTx", func(t *testing.T) { - tx := &TransformSubnetTx{ - BaseTx: invalidBaseTx, - Subnet: ids.GenerateTestID(), - AssetID: ids.GenerateTestID(), - InitialSupply: 10, - MaximumSupply: 10, - MinConsumptionRate: 0, - MaxConsumptionRate: reward.PercentDenominator, - MinValidatorStake: 2, - MaxValidatorStake: 10, - MinStakeDuration: 1, - MaxStakeDuration: 2, - MinDelegationFee: reward.PercentDenominator, - MinDelegatorStake: 1, - MaxValidatorWeightFactor: 1, - UptimeRequirement: reward.PercentDenominator, - } - err := tx.SyntacticVerify(ctx) - require.Error(t, err) - }) } From 53bca50d9e6a93332ada93e99639dc1282e7f5cb Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 22:43:17 -0400 Subject: [PATCH 19/77] cleanup --- .../txs/remove_subnet_validator_tx_test.go | 36 +++++++------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/vms/platformvm/txs/remove_subnet_validator_tx_test.go b/vms/platformvm/txs/remove_subnet_validator_tx_test.go index 5e60fcc3d537..1b31e5f363e2 100644 --- a/vms/platformvm/txs/remove_subnet_validator_tx_test.go +++ b/vms/platformvm/txs/remove_subnet_validator_tx_test.go @@ -22,12 +22,9 @@ var errInvalidSubnetAuth = errors.New("invalid subnet auth") func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { type test struct { - name string - txFunc func(*gomock.Controller) *RemoveSubnetValidatorTx - shouldErr bool - // If [shouldErr] and [requireSpecificErr] != nil, - // require that the error we get is [requireSpecificErr]. - requireSpecificErr error + name string + txFunc func(*gomock.Controller) *RemoveSubnetValidatorTx + expectedErr error } var ( @@ -61,8 +58,6 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { // A BaseTx that fails syntactic verification. invalidBaseTx := BaseTx{} - // Sanity check. - require.Error(t, invalidBaseTx.SyntacticVerify(ctx)) tests := []test{ { @@ -70,14 +65,14 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { txFunc: func(*gomock.Controller) *RemoveSubnetValidatorTx { return nil }, - shouldErr: true, + expectedErr: ErrNilTx, }, { name: "already verified", txFunc: func(*gomock.Controller) *RemoveSubnetValidatorTx { return &RemoveSubnetValidatorTx{BaseTx: verifiedBaseTx} }, - shouldErr: false, + expectedErr: nil, }, { name: "invalid BaseTx", @@ -90,7 +85,7 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { BaseTx: invalidBaseTx, } }, - shouldErr: true, + expectedErr: avax.ErrWrongNetworkID, }, { name: "invalid subnetID", @@ -102,8 +97,7 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { Subnet: constants.PrimaryNetworkID, } }, - shouldErr: true, - requireSpecificErr: ErrRemovePrimaryNetworkValidator, + expectedErr: ErrRemovePrimaryNetworkValidator, }, { name: "invalid subnetAuth", @@ -120,8 +114,7 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { SubnetAuth: invalidSubnetAuth, } }, - shouldErr: true, - requireSpecificErr: errInvalidSubnetAuth, + expectedErr: errInvalidSubnetAuth, }, { name: "passes verification", @@ -138,7 +131,7 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { SubnetAuth: validSubnetAuth, } }, - shouldErr: false, + expectedErr: nil, }, } @@ -150,15 +143,10 @@ func TestRemoveSubnetValidatorTxSyntacticVerify(t *testing.T) { tx := tt.txFunc(ctrl) err := tx.SyntacticVerify(ctx) - if tt.shouldErr { - require.Error(err) - if tt.requireSpecificErr != nil { - require.ErrorIs(err, tt.requireSpecificErr) - } - return + require.ErrorIs(err, tt.expectedErr) + if tt.expectedErr == nil { + require.True(tx.SyntacticallyVerified) } - require.NoError(err) - require.True(tx.SyntacticallyVerified) }) } } From b445380cce194aeb6d4c725986705d9bb5c10591 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 22:49:34 -0400 Subject: [PATCH 20/77] cleanup --- vms/platformvm/txs/create_chain_test.go | 124 +++++++++++------------- 1 file changed, 55 insertions(+), 69 deletions(-) diff --git a/vms/platformvm/txs/create_chain_test.go b/vms/platformvm/txs/create_chain_test.go index 60a01269ccbe..7154072bd8a9 100644 --- a/vms/platformvm/txs/create_chain_test.go +++ b/vms/platformvm/txs/create_chain_test.go @@ -26,7 +26,6 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { type test struct { description string - shouldErr bool subnetID ids.ID genesisData []byte vmID ids.ID @@ -34,12 +33,12 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { chainName string keys []*secp256k1.PrivateKey setup func(*CreateChainTx) *CreateChainTx + expectedErr error } tests := []test{ { description: "tx is nil", - shouldErr: true, subnetID: testSubnet1ID, genesisData: nil, vmID: constants.AVMID, @@ -49,10 +48,10 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { setup: func(*CreateChainTx) *CreateChainTx { return nil }, + expectedErr: ErrNilTx, }, { description: "vm ID is empty", - shouldErr: true, subnetID: testSubnet1ID, genesisData: nil, vmID: constants.AVMID, @@ -63,24 +62,10 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { tx.VMID = ids.ID{} return tx }, - }, - { - description: "subnet ID is empty", - shouldErr: true, - subnetID: testSubnet1ID, - genesisData: nil, - vmID: constants.AVMID, - fxIDs: nil, - chainName: "yeet", - keys: []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]}, - setup: func(tx *CreateChainTx) *CreateChainTx { - tx.SubnetID = ids.ID{} - return tx - }, + expectedErr: errInvalidVMID, }, { description: "subnet ID is platform chain's ID", - shouldErr: true, subnetID: testSubnet1ID, genesisData: nil, vmID: constants.AVMID, @@ -91,10 +76,10 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { tx.SubnetID = ctx.ChainID return tx }, + expectedErr: ErrCantValidatePrimaryNetwork, }, { description: "chain name is too long", - shouldErr: true, subnetID: testSubnet1ID, genesisData: nil, vmID: constants.AVMID, @@ -105,10 +90,10 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { tx.ChainName = string(make([]byte, MaxNameLen+1)) return tx }, + expectedErr: errNameTooLong, }, { description: "chain name has invalid character", - shouldErr: true, subnetID: testSubnet1ID, genesisData: nil, vmID: constants.AVMID, @@ -119,10 +104,10 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { tx.ChainName = "⌘" return tx }, + expectedErr: errIllegalNameCharacter, }, { description: "genesis data is too long", - shouldErr: true, subnetID: testSubnet1ID, genesisData: nil, vmID: constants.AVMID, @@ -133,62 +118,63 @@ func TestUnsignedCreateChainTxVerify(t *testing.T) { tx.GenesisData = make([]byte, MaxGenesisLen+1) return tx }, + expectedErr: errGenesisTooLong, }, } for _, test := range tests { - inputs := []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: ids.ID{'t', 'x', 'I', 'D'}, - OutputIndex: 2, - }, - Asset: avax.Asset{ID: ids.ID{'a', 's', 's', 'e', 't'}}, - In: &secp256k1fx.TransferInput{ - Amt: uint64(5678), - Input: secp256k1fx.Input{SigIndices: []uint32{0}}, - }, - }} - outputs := []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: ids.ID{'a', 's', 's', 'e', 't'}}, - Out: &secp256k1fx.TransferOutput{ - Amt: uint64(1234), - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{preFundedKeys[0].PublicKey().Address()}, + t.Run(test.description, func(t *testing.T) { + require := require.New(t) + + inputs := []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: ids.ID{'t', 'x', 'I', 'D'}, + OutputIndex: 2, }, - }, - }} - subnetAuth := &secp256k1fx.Input{ - SigIndices: []uint32{0, 1}, - } + Asset: avax.Asset{ID: ids.ID{'a', 's', 's', 'e', 't'}}, + In: &secp256k1fx.TransferInput{ + Amt: uint64(5678), + Input: secp256k1fx.Input{SigIndices: []uint32{0}}, + }, + }} + outputs := []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: ids.ID{'a', 's', 's', 'e', 't'}}, + Out: &secp256k1fx.TransferOutput{ + Amt: uint64(1234), + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{preFundedKeys[0].PublicKey().Address()}, + }, + }, + }} + subnetAuth := &secp256k1fx.Input{ + SigIndices: []uint32{0, 1}, + } - createChainTx := &CreateChainTx{ - BaseTx: BaseTx{BaseTx: avax.BaseTx{ - NetworkID: ctx.NetworkID, - BlockchainID: ctx.ChainID, - Ins: inputs, - Outs: outputs, - }}, - SubnetID: test.subnetID, - ChainName: test.chainName, - VMID: test.vmID, - FxIDs: test.fxIDs, - GenesisData: test.genesisData, - SubnetAuth: subnetAuth, - } + createChainTx := &CreateChainTx{ + BaseTx: BaseTx{BaseTx: avax.BaseTx{ + NetworkID: ctx.NetworkID, + BlockchainID: ctx.ChainID, + Ins: inputs, + Outs: outputs, + }}, + SubnetID: test.subnetID, + ChainName: test.chainName, + VMID: test.vmID, + FxIDs: test.fxIDs, + GenesisData: test.genesisData, + SubnetAuth: subnetAuth, + } - signers := [][]*secp256k1.PrivateKey{preFundedKeys} - stx, err := NewSigned(createChainTx, Codec, signers) - require.NoError(t, err) + signers := [][]*secp256k1.PrivateKey{preFundedKeys} + stx, err := NewSigned(createChainTx, Codec, signers) + require.NoError(err) - createChainTx.SyntacticallyVerified = false - stx.Unsigned = test.setup(createChainTx) + createChainTx.SyntacticallyVerified = false + stx.Unsigned = test.setup(createChainTx) - err = stx.SyntacticVerify(ctx) - if !test.shouldErr { - require.NoError(t, err) - } else { - require.Error(t, err) - } + err = stx.SyntacticVerify(ctx) + require.ErrorIs(err, test.expectedErr) + }) } } From 6309a370f35b868cb5006eea2eff752aab9de459 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:09:55 -0400 Subject: [PATCH 21/77] cleanup aliases --- ids/aliases.go | 34 +++++++++++++++++++++++----------- ids/test_aliases.go | 12 ++++++++---- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/ids/aliases.go b/ids/aliases.go index f0f101393124..f765a0c42865 100644 --- a/ids/aliases.go +++ b/ids/aliases.go @@ -4,21 +4,36 @@ package ids import ( + "errors" "fmt" "sync" ) +var ( + errNoIDWithAlias = errors.New("there is no ID with alias") + errNoAliasForID = errors.New("there is no alias for ID") + errAliasAlreadyMapped = errors.New("alias already mapped to an ID") +) + // AliaserReader allows one to lookup the aliases given to an ID. type AliaserReader interface { + // Lookup returns the ID associated with alias Lookup(alias string) (ID, error) + + // PrimaryAlias returns the first alias of [id] PrimaryAlias(id ID) (string, error) + + // Aliases returns the aliases of an ID Aliases(id ID) ([]string, error) } -// Aliaser allows one to give an ID aliases. An ID can have arbitrarily many -// aliases; two IDs may not have the same alias. +// AliaserWriter allows one to give an ID aliases. An ID can have arbitrarily +// many aliases; two IDs may not have the same alias. type AliaserWriter interface { + // Alias gives [id] the alias [alias] Alias(id ID, alias string) error + + // RemoveAliases of the provided ID RemoveAliases(id ID) } @@ -27,6 +42,9 @@ type AliaserWriter interface { type Aliaser interface { AliaserReader AliaserWriter + + // PrimaryAliasOrDefault returns the first alias of [id], or ID string as a + // default if no alias exists PrimaryAliasOrDefault(id ID) string } @@ -43,7 +61,6 @@ func NewAliaser() Aliaser { } } -// Lookup returns the ID associated with alias func (a *aliaser) Lookup(alias string) (ID, error) { a.lock.RLock() defer a.lock.RUnlock() @@ -51,22 +68,20 @@ func (a *aliaser) Lookup(alias string) (ID, error) { if id, ok := a.dealias[alias]; ok { return id, nil } - return ID{}, fmt.Errorf("there is no ID with alias %s", alias) + return ID{}, fmt.Errorf("%w: %s", errNoIDWithAlias, alias) } -// PrimaryAlias returns the first alias of [id] func (a *aliaser) PrimaryAlias(id ID) (string, error) { a.lock.RLock() defer a.lock.RUnlock() aliases := a.aliases[id] if len(aliases) == 0 { - return "", fmt.Errorf("there is no alias for ID %s", id) + return "", fmt.Errorf("%w: %s", errNoAliasForID, id) } return aliases[0], nil } -// PrimaryAliasOrDefault returns the first alias of [id], or ID string as default func (a *aliaser) PrimaryAliasOrDefault(id ID) string { alias, err := a.PrimaryAlias(id) if err != nil { @@ -75,7 +90,6 @@ func (a *aliaser) PrimaryAliasOrDefault(id ID) string { return alias } -// Aliases returns the aliases of an ID func (a *aliaser) Aliases(id ID) ([]string, error) { a.lock.RLock() defer a.lock.RUnlock() @@ -83,13 +97,12 @@ func (a *aliaser) Aliases(id ID) ([]string, error) { return a.aliases[id], nil } -// Alias gives [id] the alias [alias] func (a *aliaser) Alias(id ID, alias string) error { a.lock.Lock() defer a.lock.Unlock() if _, exists := a.dealias[alias]; exists { - return fmt.Errorf("%s is already used as an alias for an ID", alias) + return fmt.Errorf("%w: %s", errAliasAlreadyMapped, alias) } a.dealias[alias] = id @@ -97,7 +110,6 @@ func (a *aliaser) Alias(id ID, alias string) error { return nil } -// RemoveAliases of the provided ID func (a *aliaser) RemoveAliases(id ID) { a.lock.Lock() defer a.lock.Unlock() diff --git a/ids/test_aliases.go b/ids/test_aliases.go index 06a7fe3afba9..04d5e5d139c5 100644 --- a/ids/test_aliases.go +++ b/ids/test_aliases.go @@ -17,7 +17,8 @@ var AliasTests = []func(require *require.Assertions, r AliaserReader, w AliaserW func AliaserLookupErrorTest(require *require.Assertions, r AliaserReader, _ AliaserWriter) { _, err := r.Lookup("Batman") - require.Error(err, "expected an error due to missing alias") + // TODO: require error to be errNoIDWithAlias + require.Error(err) //nolint:forbidigo // currently returns grpc errors too } func AliaserLookupTest(require *require.Assertions, r AliaserReader, w AliaserWriter) { @@ -63,7 +64,8 @@ func AliaserPrimaryAliasTest(require *require.Assertions, r AliaserReader, w Ali require.NoError(err) _, err = r.PrimaryAlias(id1) - require.Error(err) + // TODO: require error to be errNoAliasForID + require.Error(err) //nolint:forbidigo // currently returns grpc errors too expected := "Batman" res, err := r.PrimaryAlias(id2) @@ -78,7 +80,8 @@ func AliaserAliasClashTest(require *require.Assertions, _ AliaserReader, w Alias require.NoError(err) err = w.Alias(id2, "Batman") - require.Error(err) + // TODO: require error to be errAliasAlreadyMapped + require.Error(err) //nolint:forbidigo // currently returns grpc errors too } func AliaserRemoveAliasTest(require *require.Assertions, r AliaserReader, w AliaserWriter) { @@ -93,7 +96,8 @@ func AliaserRemoveAliasTest(require *require.Assertions, r AliaserReader, w Alia w.RemoveAliases(id1) _, err = r.PrimaryAlias(id1) - require.Error(err) + // TODO: require error to be errNoAliasForID + require.Error(err) //nolint:forbidigo // currently returns grpc errors too err = w.Alias(id2, "Batman") require.NoError(err) From dcb3c9132b381d00b2fa2f43d29ae8881598675a Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:11:01 -0400 Subject: [PATCH 22/77] cleanup --- snow/choices/status_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/snow/choices/status_test.go b/snow/choices/status_test.go index 960af7b46744..de7d60fe6ade 100644 --- a/snow/choices/status_test.go +++ b/snow/choices/status_test.go @@ -17,8 +17,7 @@ func TestStatusValid(t *testing.T) { require.NoError(Rejected.Valid()) require.NoError(Processing.Valid()) require.NoError(Unknown.Valid()) - - require.Error(Status(math.MaxInt32).Valid()) + require.ErrorIs(Status(math.MaxInt32).Valid(), errUnknownStatus) } func TestStatusDecided(t *testing.T) { @@ -28,7 +27,6 @@ func TestStatusDecided(t *testing.T) { require.True(Rejected.Decided()) require.False(Processing.Decided()) require.False(Unknown.Decided()) - require.False(Status(math.MaxInt32).Decided()) } @@ -39,7 +37,6 @@ func TestStatusFetched(t *testing.T) { require.True(Rejected.Fetched()) require.True(Processing.Fetched()) require.False(Unknown.Fetched()) - require.False(Status(math.MaxInt32).Fetched()) } @@ -50,6 +47,5 @@ func TestStatusString(t *testing.T) { require.Equal("Rejected", Rejected.String()) require.Equal("Processing", Processing.String()) require.Equal("Unknown", Unknown.String()) - require.Equal("Invalid status", Status(math.MaxInt32).String()) } From 7ae3c490ba31187b20342cb9a18c82d868eb9726 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:14:33 -0400 Subject: [PATCH 23/77] cleanup vertex builder tests --- snow/engine/avalanche/vertex/builder_test.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/snow/engine/avalanche/vertex/builder_test.go b/snow/engine/avalanche/vertex/builder_test.go index 7ed6a9a59365..132ccbc33f73 100644 --- a/snow/engine/avalanche/vertex/builder_test.go +++ b/snow/engine/avalanche/vertex/builder_test.go @@ -11,7 +11,9 @@ import ( "github.com/ava-labs/avalanchego/ids" ) -func TestBuildInvalid(t *testing.T) { +func TestBuildDuplicateTxs(t *testing.T) { + require := require.New(t) + chainID := ids.ID{1} height := uint64(2) parentIDs := []ids.ID{{4}, {5}} @@ -22,10 +24,12 @@ func TestBuildInvalid(t *testing.T) { parentIDs, txs, ) - require.Error(t, err, "build should have errored because restrictions were provided in epoch 0") + require.ErrorIs(err, errInvalidTxs) } func TestBuildValid(t *testing.T) { + require := require.New(t) + chainID := ids.ID{1} height := uint64(2) parentIDs := []ids.ID{{4}, {5}} @@ -36,9 +40,9 @@ func TestBuildValid(t *testing.T) { parentIDs, txs, ) - require.NoError(t, err) - require.Equal(t, chainID, vtx.ChainID()) - require.Equal(t, height, vtx.Height()) - require.Equal(t, parentIDs, vtx.ParentIDs()) - require.Equal(t, txs, vtx.Txs()) + require.NoError(err) + require.Equal(chainID, vtx.ChainID()) + require.Equal(height, vtx.Height()) + require.Equal(parentIDs, vtx.ParentIDs()) + require.Equal(txs, vtx.Txs()) } From a0c68209fef9c3f5b5ce24e62b9c94d650ef0062 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:16:10 -0400 Subject: [PATCH 24/77] nit --- snow/engine/avalanche/vertex/parser_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/snow/engine/avalanche/vertex/parser_test.go b/snow/engine/avalanche/vertex/parser_test.go index 8f1f2e9e3ef6..acffb5c8d66f 100644 --- a/snow/engine/avalanche/vertex/parser_test.go +++ b/snow/engine/avalanche/vertex/parser_test.go @@ -8,13 +8,14 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" ) func TestParseInvalid(t *testing.T) { - vtxBytes := []byte{} + vtxBytes := []byte{1, 2, 3, 4, 5} _, err := Parse(vtxBytes) - require.Error(t, err, "parse on an invalid vertex should have errored") + require.ErrorIs(t, err, codec.ErrUnknownVersion) } func TestParseValid(t *testing.T) { From 9687dde752737b367bd48a3ec8c8f3bd73a2c67a Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:25:21 -0400 Subject: [PATCH 25/77] more cleanup --- utils/buffer/bounded_nonblocking_queue_test.go | 2 +- utils/compression/compressor_test.go | 14 ++++++++------ utils/compression/type_test.go | 8 +++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/utils/buffer/bounded_nonblocking_queue_test.go b/utils/buffer/bounded_nonblocking_queue_test.go index 402a089b8397..ab2f7e209a5b 100644 --- a/utils/buffer/bounded_nonblocking_queue_test.go +++ b/utils/buffer/bounded_nonblocking_queue_test.go @@ -14,7 +14,7 @@ func TestNewBoundedQueue(t *testing.T) { // Case: maxSize < 1 _, err := NewBoundedQueue[bool](0, nil) - require.Error(err) + require.ErrorIs(err, errInvalidMaxSize) // Case: maxSize == 1 and nil onEvict b, err := NewBoundedQueue[bool](1, nil) diff --git a/utils/compression/compressor_test.go b/utils/compression/compressor_test.go index 341fb4a29bf9..cbd2eb114a4e 100644 --- a/utils/compression/compressor_test.go +++ b/utils/compression/compressor_test.go @@ -114,21 +114,23 @@ func TestSizeLimiting(t *testing.T) { continue } t.Run(compressionType.String(), func(t *testing.T) { + require := require.New(t) + compressor, err := compressorFunc(maxMessageSize) - require.NoError(t, err) + require.NoError(err) data := make([]byte, maxMessageSize+1) _, err = compressor.Compress(data) // should be too large - require.Error(t, err) + require.ErrorIs(err, ErrMsgTooLarge) compressor2, err := compressorFunc(2 * maxMessageSize) - require.NoError(t, err) + require.NoError(err) dataCompressed, err := compressor2.Compress(data) - require.NoError(t, err) + require.NoError(err) _, err = compressor.Decompress(dataCompressed) // should be too large - require.Error(t, err) + require.ErrorIs(err, ErrDecompressedMsgTooLarge) }) } } @@ -178,7 +180,7 @@ func fuzzHelper(f *testing.F, compressionType Type) { if len(data) > maxMessageSize { _, err := compressor.Compress(data) - require.Error(err) + require.ErrorIs(err, ErrMsgTooLarge) } compressed, err := compressor.Compress(data) diff --git a/utils/compression/type_test.go b/utils/compression/type_test.go index aa9a47f3ad96..20313d053824 100644 --- a/utils/compression/type_test.go +++ b/utils/compression/type_test.go @@ -10,15 +10,17 @@ import ( ) func TestTypeString(t *testing.T) { + require := require.New(t) + for _, compressionType := range []Type{TypeNone, TypeGzip, TypeZstd} { s := compressionType.String() parsedType, err := TypeFromString(s) - require.NoError(t, err) - require.Equal(t, compressionType, parsedType) + require.NoError(err) + require.Equal(compressionType, parsedType) } _, err := TypeFromString("unknown") - require.Error(t, err) + require.ErrorIs(err, errUnknownCompressionType) } func TestTypeMarshalJSON(t *testing.T) { From aaf70b18a7534d2c5310242c2be5646abae43dc0 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:32:46 -0400 Subject: [PATCH 26/77] cleanup index tests --- indexer/index.go | 19 ++++++++----------- indexer/index_test.go | 4 ++-- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/indexer/index.go b/indexer/index.go index 07de46ee737c..fae7ebcb12e1 100644 --- a/indexer/index.go +++ b/indexer/index.go @@ -23,11 +23,9 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" ) -const ( - // Maximum number of containers IDs that can be fetched at a time - // in a call to GetContainerRange - MaxFetchedByRange = 1024 -) +// Maximum number of containers IDs that can be fetched at a time in a call to +// GetContainerRange +const MaxFetchedByRange = 1024 var ( // Maps to the byte representation of the next accepted index @@ -35,7 +33,8 @@ var ( indexToContainerPrefix = []byte{0x01} containerToIDPrefix = []byte{0x02} errNoneAccepted = errors.New("no containers have been accepted") - errNumToFetchZero = fmt.Errorf("numToFetch must be in [1,%d]", MaxFetchedByRange) + errNumToFetchInvalid = fmt.Errorf("numToFetch must be in [1,%d]", MaxFetchedByRange) + errNoContainerAtIndex = errors.New("no container at index") _ Index = (*index)(nil) ) @@ -195,7 +194,7 @@ func (i *index) GetContainerByIndex(index uint64) (Container, error) { func (i *index) getContainerByIndex(index uint64) (Container, error) { lastAcceptedIndex, ok := i.lastAcceptedIndex() if !ok || index > lastAcceptedIndex { - return Container{}, fmt.Errorf("no container at index %d", index) + return Container{}, fmt.Errorf("%w %d", errNoContainerAtIndex, index) } indexBytes := database.PackUInt64(index) return i.getContainerByIndexBytes(indexBytes) @@ -224,10 +223,8 @@ func (i *index) getContainerByIndexBytes(indexBytes []byte) (Container, error) { // [numToFetch] should be in [0, MaxFetchedByRange] func (i *index) GetContainerRange(startIndex, numToFetch uint64) ([]Container, error) { // Check arguments for validity - if numToFetch == 0 { - return nil, errNumToFetchZero - } else if numToFetch > MaxFetchedByRange { - return nil, fmt.Errorf("requested %d but maximum page size is %d", numToFetch, MaxFetchedByRange) + if numToFetch == 0 || numToFetch > MaxFetchedByRange { + return nil, fmt.Errorf("%w but is %d", errNumToFetchInvalid, numToFetch) } i.lock.RLock() diff --git a/indexer/index_test.go b/indexer/index_test.go index 79ef4a5b4e0e..1572fb8837fb 100644 --- a/indexer/index_test.go +++ b/indexer/index_test.go @@ -132,7 +132,7 @@ func TestIndexGetContainerByRangeMaxPageSize(t *testing.T) { // Page size too large _, err = idx.GetContainerRange(0, MaxFetchedByRange+1) - require.Error(err) + require.ErrorIs(err, errNumToFetchInvalid) // Make sure data is right containers, err := idx.GetContainerRange(0, MaxFetchedByRange) @@ -170,7 +170,7 @@ func TestDontIndexSameContainerTwice(t *testing.T) { require.NoError(idx.Accept(ctx, containerID, []byte{1, 2, 3})) require.NoError(idx.Accept(ctx, containerID, []byte{4, 5, 6})) _, err = idx.GetContainerByIndex(1) - require.Error(err, "should not have accepted same container twice") + require.ErrorIs(err, errNoContainerAtIndex) gotContainer, err := idx.GetContainerByID(containerID) require.NoError(err) require.EqualValues(gotContainer.Bytes, []byte{1, 2, 3}, "should not have accepted same container twice") From 2aba09ab7afce3a20735834bc6f907fe6e8ce34c Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:44:11 -0400 Subject: [PATCH 27/77] check error --- network/network_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/network_test.go b/network/network_test.go index 63efee693d3c..2d6db3f9a37a 100644 --- a/network/network_test.go +++ b/network/network_test.go @@ -6,6 +6,7 @@ package network import ( "context" "crypto" + "crypto/rsa" "net" "sync" "testing" @@ -420,7 +421,7 @@ func TestTrackVerifiesSignatures(t *testing.T) { Signature: nil, }}) // The signature is wrong so this peer tracking info isn't useful. - require.Error(err) + require.ErrorIs(err, rsa.ErrVerification) network.peersLock.RLock() require.Empty(network.trackedIPs) From c466b869b3429cfce0c789d26a7894084800f3f5 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:46:12 -0400 Subject: [PATCH 28/77] mor ecleanup --- network/dialer/dialer_test.go | 2 +- network/throttling/dial_throttler_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/network/dialer/dialer_test.go b/network/dialer/dialer_test.go index 8fd516cda3d9..95011996bcdf 100644 --- a/network/dialer/dialer_test.go +++ b/network/dialer/dialer_test.go @@ -64,7 +64,7 @@ func TestDialerCancelDial(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() _, err = dialer.Dial(ctx, myIP) - require.Error(err) + require.ErrorIs(err, context.Canceled) // Make an outgoing connection with a non-cancelled context conn, err := dialer.Dial(context.Background(), myIP) diff --git a/network/throttling/dial_throttler_test.go b/network/throttling/dial_throttler_test.go index f3c3f65139a4..fdc491cf8981 100644 --- a/network/throttling/dial_throttler_test.go +++ b/network/throttling/dial_throttler_test.go @@ -86,7 +86,7 @@ func TestDialThrottlerCancel(t *testing.T) { // Should block because 5 already taken within last second err := throttler.Acquire(ctx) // Should error because we call cancel() below - require.Error(t, err) + require.ErrorIs(t, err, context.Canceled) acquiredChan <- struct{}{} }() @@ -95,7 +95,7 @@ func TestDialThrottlerCancel(t *testing.T) { select { case <-acquiredChan: case <-time.After(10 * time.Millisecond): - t.Fatal("Acquire should have returned immediately upon context cancelation") + t.Fatal("Acquire should have returned immediately upon context cancellation") } close(acquiredChan) } From 0a16f3766e8999d92c491c5ecfbbb8424def49af Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:47:13 -0400 Subject: [PATCH 29/77] cleanup --- network/throttling/inbound_conn_throttler_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/network/throttling/inbound_conn_throttler_test.go b/network/throttling/inbound_conn_throttler_test.go index 9e13e32b8db0..14f68167c3d1 100644 --- a/network/throttling/inbound_conn_throttler_test.go +++ b/network/throttling/inbound_conn_throttler_test.go @@ -4,6 +4,7 @@ package throttling import ( + "context" "net" "testing" @@ -44,6 +45,8 @@ func (ml *MockListener) Addr() net.Addr { } func TestInboundConnThrottlerClose(t *testing.T) { + require := require.New(t) + closed := false l := &MockListener{ t: t, @@ -54,8 +57,9 @@ func TestInboundConnThrottlerClose(t *testing.T) { } wrappedL := NewThrottledListener(l, 1) err := wrappedL.Close() - require.NoError(t, err) - require.True(t, closed) + require.NoError(err) + require.True(closed) + select { case <-wrappedL.(*throttledListener).ctx.Done(): default: @@ -64,7 +68,7 @@ func TestInboundConnThrottlerClose(t *testing.T) { // Accept() should return an error because the context is cancelled _, err = wrappedL.Accept() - require.Error(t, err) + require.ErrorIs(err, context.Canceled) } func TestInboundConnThrottlerAddr(t *testing.T) { From 4e18013626dfc42dbb87ea6f68922d18da8e5756 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:47:57 -0400 Subject: [PATCH 30/77] nit --- snow/engine/common/queue/jobs_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snow/engine/common/queue/jobs_test.go b/snow/engine/common/queue/jobs_test.go index 296266eed2f9..7ad245905e45 100644 --- a/snow/engine/common/queue/jobs_test.go +++ b/snow/engine/common/queue/jobs_test.go @@ -390,7 +390,7 @@ func TestHandleJobWithMissingDependencyOnRunnableStack(t *testing.T) { _, err = jobs.ExecuteAll(context.Background(), snow.DefaultConsensusContextTest(), &common.Halter{}, false) // Assert that the database closed error on job1 causes ExecuteAll // to fail in the middle of execution. - require.Error(err) + require.ErrorIs(err, database.ErrClosed) require.True(executed0) require.False(executed1) From bc5bfc3c2a2e8cb50f8b14d35e645319cbab9fce Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:53:10 -0400 Subject: [PATCH 31/77] cleanup --- snow/validators/set_test.go | 21 ++++++++++++--------- utils/sampler/uniform_replacer.go | 2 +- utils/sampler/uniform_resample.go | 2 +- utils/sampler/weighted.go | 2 +- utils/sampler/weighted_array.go | 2 +- utils/sampler/weighted_heap.go | 2 +- utils/sampler/weighted_linear.go | 2 +- utils/sampler/weighted_uniform.go | 2 +- 8 files changed, 19 insertions(+), 16 deletions(-) diff --git a/snow/validators/set_test.go b/snow/validators/set_test.go index 645a521535ce..59d6b1e57555 100644 --- a/snow/validators/set_test.go +++ b/snow/validators/set_test.go @@ -4,13 +4,16 @@ package validators import ( - "math" "testing" + stdmath "math" + "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/sampler" "github.com/ava-labs/avalanchego/utils/set" ) @@ -42,8 +45,8 @@ func TestSetAddOverflow(t *testing.T) { err := s.Add(ids.GenerateTestNodeID(), nil, ids.Empty, 1) require.NoError(err) - err = s.Add(ids.GenerateTestNodeID(), nil, ids.Empty, math.MaxUint64) - require.Error(err) + err = s.Add(ids.GenerateTestNodeID(), nil, ids.Empty, stdmath.MaxUint64) + require.ErrorIs(err, math.ErrOverflow) weight := s.Weight() require.EqualValues(1, weight) @@ -74,8 +77,8 @@ func TestSetAddWeightOverflow(t *testing.T) { err = s.Add(nodeID, nil, ids.Empty, 1) require.NoError(err) - err = s.AddWeight(nodeID, math.MaxUint64-1) - require.Error(err) + err = s.AddWeight(nodeID, stdmath.MaxUint64-1) + require.ErrorIs(err, math.ErrOverflow) weight := s.Weight() require.EqualValues(2, weight) @@ -166,7 +169,7 @@ func TestSetRemoveWeightUnderflow(t *testing.T) { require.NoError(err) err = s.RemoveWeight(nodeID, 2) - require.Error(err) + require.ErrorIs(err, math.ErrUnderflow) weight := s.Weight() require.EqualValues(2, weight) @@ -384,10 +387,10 @@ func TestSetSample(t *testing.T) { require.Equal([]ids.NodeID{nodeID0}, sampled) _, err = s.Sample(2) - require.Error(err) + require.ErrorIs(err, sampler.ErrOutOfRange) nodeID1 := ids.GenerateTestNodeID() - err = s.Add(nodeID1, nil, ids.Empty, math.MaxInt64-1) + err = s.Add(nodeID1, nil, ids.Empty, stdmath.MaxInt64-1) require.NoError(err) sampled, err = s.Sample(1) @@ -416,7 +419,7 @@ func TestSetString(t *testing.T) { err := s.Add(nodeID0, nil, ids.Empty, 1) require.NoError(err) - err = s.Add(nodeID1, nil, ids.Empty, math.MaxInt64-1) + err = s.Add(nodeID1, nil, ids.Empty, stdmath.MaxInt64-1) require.NoError(err) expected := "Validator Set: (Size = 2, Weight = 9223372036854775807)\n" + diff --git a/utils/sampler/uniform_replacer.go b/utils/sampler/uniform_replacer.go index a4a16b9dd795..dd1d25ea3809 100644 --- a/utils/sampler/uniform_replacer.go +++ b/utils/sampler/uniform_replacer.go @@ -73,7 +73,7 @@ func (s *uniformReplacer) Reset() { func (s *uniformReplacer) Next() (uint64, error) { if s.drawsCount >= s.length { - return 0, errOutOfRange + return 0, ErrOutOfRange } draw := s.rng.Uint64Inclusive(s.length-1-s.drawsCount) + s.drawsCount diff --git a/utils/sampler/uniform_resample.go b/utils/sampler/uniform_resample.go index 4afc3f7a84d8..ecb5deea0f11 100644 --- a/utils/sampler/uniform_resample.go +++ b/utils/sampler/uniform_resample.go @@ -60,7 +60,7 @@ func (s *uniformResample) Reset() { func (s *uniformResample) Next() (uint64, error) { i := uint64(len(s.drawn)) if i >= s.length { - return 0, errOutOfRange + return 0, ErrOutOfRange } for { diff --git a/utils/sampler/weighted.go b/utils/sampler/weighted.go index 58998d47969b..69212d4351c2 100644 --- a/utils/sampler/weighted.go +++ b/utils/sampler/weighted.go @@ -5,7 +5,7 @@ package sampler import "errors" -var errOutOfRange = errors.New("out of range") +var ErrOutOfRange = errors.New("out of range") // Weighted defines how to sample a specified valued based on a provided // weighted distribution diff --git a/utils/sampler/weighted_array.go b/utils/sampler/weighted_array.go index c6b411b80d9b..0db1dda17af9 100644 --- a/utils/sampler/weighted_array.go +++ b/utils/sampler/weighted_array.go @@ -81,7 +81,7 @@ func (s *weightedArray) Initialize(weights []uint64) error { func (s *weightedArray) Sample(value uint64) (int, error) { if len(s.arr) == 0 || s.arr[len(s.arr)-1].cumulativeWeight <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } minIndex := 0 maxIndex := len(s.arr) - 1 diff --git a/utils/sampler/weighted_heap.go b/utils/sampler/weighted_heap.go index 1457d66539cb..4b7fb84df482 100644 --- a/utils/sampler/weighted_heap.go +++ b/utils/sampler/weighted_heap.go @@ -81,7 +81,7 @@ func (s *weightedHeap) Initialize(weights []uint64) error { func (s *weightedHeap) Sample(value uint64) (int, error) { if len(s.heap) == 0 || s.heap[0].cumulativeWeight <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } index := 0 diff --git a/utils/sampler/weighted_linear.go b/utils/sampler/weighted_linear.go index f58fa22a3239..a5d0e3b16711 100644 --- a/utils/sampler/weighted_linear.go +++ b/utils/sampler/weighted_linear.go @@ -68,7 +68,7 @@ func (s *weightedLinear) Initialize(weights []uint64) error { func (s *weightedLinear) Sample(value uint64) (int, error) { if len(s.arr) == 0 || s.arr[len(s.arr)-1].cumulativeWeight <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } index := 0 diff --git a/utils/sampler/weighted_uniform.go b/utils/sampler/weighted_uniform.go index 14620475c2bf..bff76ead34e4 100644 --- a/utils/sampler/weighted_uniform.go +++ b/utils/sampler/weighted_uniform.go @@ -63,7 +63,7 @@ func (s *weightedUniform) Initialize(weights []uint64) error { func (s *weightedUniform) Sample(value uint64) (int, error) { if uint64(len(s.indices)) <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } return s.indices[int(value)], nil } From a6628faba780b6fdce39e643fe327c724fc01a68 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 18 Apr 2023 23:53:58 -0400 Subject: [PATCH 32/77] nit --- vms/platformvm/blocks/executor/manager_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vms/platformvm/blocks/executor/manager_test.go b/vms/platformvm/blocks/executor/manager_test.go index fb15dd3c6d05..4bd341e23653 100644 --- a/vms/platformvm/blocks/executor/manager_test.go +++ b/vms/platformvm/blocks/executor/manager_test.go @@ -36,7 +36,7 @@ func TestGetBlock(t *testing.T) { // Case: block isn't in memory or database state.EXPECT().GetStatelessBlock(statelessBlk.ID()).Return(nil, choices.Unknown, database.ErrNotFound).Times(1) _, err := manager.GetBlock(statelessBlk.ID()) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } { // Case: block isn't in memory but is in database. From 4cb24cfb7437cc5b5ec218b67977e6068cc55073 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 00:04:07 -0400 Subject: [PATCH 33/77] merged --- vms/components/chain/state.go | 14 ++++++++----- vms/components/chain/state_test.go | 33 +++++++++++++++--------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/vms/components/chain/state.go b/vms/components/chain/state.go index fe499194a495..d18fa8f954d4 100644 --- a/vms/components/chain/state.go +++ b/vms/components/chain/state.go @@ -5,6 +5,7 @@ package chain import ( "context" + "errors" "fmt" "github.com/prometheus/client_golang/prometheus" @@ -194,14 +195,17 @@ func NewMeteredState( return c, nil } -// SetLastAcceptedBlock sets the last accepted block to [lastAcceptedBlock]. This should be called -// with an internal block - not a wrapped block returned from state. +var errSetAcceptedWithProcessing = errors.New("cannot set last accepted block with blocks processing") + +// SetLastAcceptedBlock sets the last accepted block to [lastAcceptedBlock]. +// This should be called with an internal block - not a wrapped block returned +// from state. // -// This also flushes [lastAcceptedBlock] from missingBlocks and unverifiedBlocks to -// ensure that their contents stay valid. +// This also flushes [lastAcceptedBlock] from missingBlocks and unverifiedBlocks +// to ensure that their contents stay valid. func (s *State) SetLastAcceptedBlock(lastAcceptedBlock snowman.Block) error { if len(s.verifiedBlocks) != 0 { - return fmt.Errorf("cannot set chain state last accepted block with non-zero number of verified blocks in processing: %d", len(s.verifiedBlocks)) + return fmt.Errorf("%w: %d", errSetAcceptedWithProcessing, len(s.verifiedBlocks)) } // [lastAcceptedBlock] is no longer missing or unverified, so we evict it from the corresponding diff --git a/vms/components/chain/state_test.go b/vms/components/chain/state_test.go index 448fcb44d5f2..100c9d0a2ab8 100644 --- a/vms/components/chain/state_test.go +++ b/vms/components/chain/state_test.go @@ -682,6 +682,8 @@ func TestMeteredCache(t *testing.T) { // Test the bytesToIDCache func TestStateBytesToIDCache(t *testing.T) { + require := require.New(t) + testBlks := NewTestBlocks(3) genesisBlock := testBlks[0] genesisBlock.SetStatus(choices.Accepted) @@ -708,27 +710,27 @@ func TestStateBytesToIDCache(t *testing.T) { // Shouldn't have blk1 ID to start with _, err := chainState.GetBlock(context.Background(), blk1.ID()) - require.Error(t, err) + require.ErrorIs(err, database.ErrNotFound) _, ok := chainState.bytesToIDCache.Get(string(blk1.Bytes())) - require.False(t, ok) + require.False(ok) // Parse blk1 from bytes _, err = chainState.ParseBlock(context.Background(), blk1.Bytes()) - require.NoError(t, err) + require.NoError(err) // blk1 should be in cache now _, ok = chainState.bytesToIDCache.Get(string(blk1.Bytes())) - require.True(t, ok) + require.True(ok) // Parse another block _, err = chainState.ParseBlock(context.Background(), blk2.Bytes()) - require.NoError(t, err) + require.NoError(err) // Should have bumped blk1 from cache _, ok = chainState.bytesToIDCache.Get(string(blk2.Bytes())) - require.True(t, ok) + require.True(ok) _, ok = chainState.bytesToIDCache.Get(string(blk1.Bytes())) - require.False(t, ok) + require.False(ok) } // TestSetLastAcceptedBlock ensures chainState's last accepted block @@ -823,6 +825,8 @@ func TestSetLastAcceptedBlock(t *testing.T) { } func TestSetLastAcceptedBlockWithProcessingBlocksErrors(t *testing.T) { + require := require.New(t) + testBlks := NewTestBlocks(5) genesisBlock := testBlks[0] genesisBlock.SetStatus(choices.Accepted) @@ -849,19 +853,16 @@ func TestSetLastAcceptedBlockWithProcessingBlocksErrors(t *testing.T) { }) builtBlk, err := chainState.BuildBlock(context.Background()) - if err != nil { - t.Fatal(err) - } - require.Len(t, chainState.verifiedBlocks, 0) + require.NoError(err) + require.Empty(chainState.verifiedBlocks) - if err := builtBlk.Verify(context.Background()); err != nil { - t.Fatalf("Built block failed verification due to %s", err) - } - require.Len(t, chainState.verifiedBlocks, 1) + require.NoError(builtBlk.Verify(context.Background())) + require.Len(chainState.verifiedBlocks, 1) checkProcessingBlock(t, chainState, builtBlk) - require.Error(t, chainState.SetLastAcceptedBlock(resetBlk), "should have errored resetting chain state with processing block") + err = chainState.SetLastAcceptedBlock(resetBlk) + require.ErrorIs(err, errSetAcceptedWithProcessing) } func TestStateParseTransitivelyAcceptedBlock(t *testing.T) { From 948b115edfc09de18152f40bb8a5dbb9b99d0bac Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 00:07:18 -0400 Subject: [PATCH 34/77] add nolints --- snow/validators/gvalidators/validator_state_test.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/snow/validators/gvalidators/validator_state_test.go b/snow/validators/gvalidators/validator_state_test.go index 2effc82bf0f3..9671e48677e3 100644 --- a/snow/validators/gvalidators/validator_state_test.go +++ b/snow/validators/gvalidators/validator_state_test.go @@ -82,7 +82,8 @@ func TestGetMinimumHeight(t *testing.T) { state.server.EXPECT().GetMinimumHeight(gomock.Any()).Return(expectedHeight, errCustom) _, err = state.client.GetMinimumHeight(context.Background()) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } func TestGetCurrentHeight(t *testing.T) { @@ -105,7 +106,8 @@ func TestGetCurrentHeight(t *testing.T) { state.server.EXPECT().GetCurrentHeight(gomock.Any()).Return(expectedHeight, errCustom) _, err = state.client.GetCurrentHeight(context.Background()) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } func TestGetSubnetID(t *testing.T) { @@ -129,7 +131,8 @@ func TestGetSubnetID(t *testing.T) { state.server.EXPECT().GetSubnetID(gomock.Any(), chainID).Return(expectedSubnetID, errCustom) _, err = state.client.GetSubnetID(context.Background(), chainID) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } func TestGetValidatorSet(t *testing.T) { @@ -180,7 +183,8 @@ func TestGetValidatorSet(t *testing.T) { state.server.EXPECT().GetValidatorSet(gomock.Any(), height, subnetID).Return(expectedVdrs, errCustom) _, err = state.client.GetValidatorSet(context.Background(), height, subnetID) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } // BenchmarkGetValidatorSet measures the time it takes complete a gRPC client From a03c3e3dacb4f364fe3d20ed00c31539abc334d1 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 00:18:49 -0400 Subject: [PATCH 35/77] cleanup more tests --- utils/cb58/cb58.go | 12 +++---- utils/crypto/secp256k1/secp256k1_test.go | 46 ++++++++++++++++-------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/utils/cb58/cb58.go b/utils/cb58/cb58.go index 23cf9c49c17f..7fcc58cf249d 100644 --- a/utils/cb58/cb58.go +++ b/utils/cb58/cb58.go @@ -6,6 +6,7 @@ package cb58 import ( "bytes" "errors" + "fmt" "math" "github.com/mr-tron/base58/base58" @@ -13,13 +14,12 @@ import ( "github.com/ava-labs/avalanchego/utils/hashing" ) -const ( - checksumLen = 4 -) +const checksumLen = 4 var ( + ErrBase58Decoding = errors.New("base58 decoding error") + ErrMissingChecksum = errors.New("input string is smaller than the checksum size") errEncodingOverFlow = errors.New("encoding overflow") - errMissingChecksum = errors.New("input string is smaller than the checksum size") errBadChecksum = errors.New("invalid input checksum") ) @@ -41,10 +41,10 @@ func Encode(bytes []byte) (string, error) { func Decode(str string) ([]byte, error) { decodedBytes, err := base58.Decode(str) if err != nil { - return nil, err + return nil, fmt.Errorf("%w: %s", ErrBase58Decoding, err) } if len(decodedBytes) < checksumLen { - return nil, errMissingChecksum + return nil, ErrMissingChecksum } // Verify the checksum rawBytes := decodedBytes[:len(decodedBytes)-checksumLen] diff --git a/utils/crypto/secp256k1/secp256k1_test.go b/utils/crypto/secp256k1/secp256k1_test.go index e8abab31fdbf..8f5e3879d38d 100644 --- a/utils/crypto/secp256k1/secp256k1_test.go +++ b/utils/crypto/secp256k1/secp256k1_test.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/cache" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/cb58" "github.com/ava-labs/avalanchego/utils/hashing" ) @@ -100,7 +101,7 @@ func TestVerifyMutatedSignature(t *testing.T) { copy(sig[32:], newSBytes[:]) _, err = f.RecoverPublicKey(msg, sig) - require.Error(err) + require.ErrorIs(err, errMutatedSig) } func TestPrivateKeySECP256K1RUnmarshalJSON(t *testing.T) { @@ -123,30 +124,47 @@ func TestPrivateKeySECP256K1RUnmarshalJSONError(t *testing.T) { tests := []struct { label string in []byte + err error }{ { - "too short", - []byte(`"`), + label: "too short", + in: []byte(`"`), + err: errMissingQuotes, }, { - "missing start quote", - []byte(`PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + label: "missing start quote", + in: []byte(`PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + err: errMissingQuotes, }, { - "missing end quote", - []byte(`"PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN`), + label: "missing end quote", + in: []byte(`"PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN`), + err: errMissingQuotes, }, { - "incorrect prefix", - []byte(`"PrivateKfy-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + label: "incorrect prefix", + in: []byte(`"PrivateKfy-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + err: errMissingKeyPrefix, }, { - `"PrivateKey-"`, - []byte(`"PrivateKey-"`), + label: `"PrivateKey-"`, + in: []byte(`"PrivateKey-"`), + err: cb58.ErrBase58Decoding, }, { - `"PrivateKey-1"`, - []byte(`"PrivateKey-1"`), + label: `"PrivateKey-1"`, + in: []byte(`"PrivateKey-1"`), + err: cb58.ErrMissingChecksum, + }, + { + label: `"PrivateKey-1"`, + in: []byte(`"PrivateKey-1"`), + err: cb58.ErrMissingChecksum, + }, + { + label: `"PrivateKey-1"`, + in: []byte(`"PrivateKey-45PJLL"`), + err: errInvalidPrivateKeyLength, }, } for _, tt := range tests { @@ -155,7 +173,7 @@ func TestPrivateKeySECP256K1RUnmarshalJSONError(t *testing.T) { foo := PrivateKey{} err := foo.UnmarshalJSON(tt.in) - require.Error(err) + require.ErrorIs(err, tt.err) }) } } From e94ea5bfcd667ea02c17ebb0ca0e17aa3db609f9 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 00:20:53 -0400 Subject: [PATCH 36/77] cleanup --- utils/dynamicip/resolver.go | 5 ++++- utils/dynamicip/resolver_test.go | 34 ++++++++++++++------------------ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/utils/dynamicip/resolver.go b/utils/dynamicip/resolver.go index df797e206b36..b3a341cd2121 100644 --- a/utils/dynamicip/resolver.go +++ b/utils/dynamicip/resolver.go @@ -5,6 +5,7 @@ package dynamicip import ( "context" + "errors" "fmt" "net" "strings" @@ -23,6 +24,8 @@ const ( IFConfigMeName = "ifconfigme" ) +var errUnknownResolver = errors.New("unknown resolver") + // Resolver resolves our public IP type Resolver interface { // Resolve and return our public IP. @@ -43,6 +46,6 @@ func NewResolver(resolverName string) (Resolver, error) { case IFConfigMeName: return &ifConfigResolver{url: ifConfigMeURL}, nil default: - return nil, fmt.Errorf("got unknown resolver: %s", resolverName) + return nil, fmt.Errorf("%w: %s", errUnknownResolver, resolverName) } } diff --git a/utils/dynamicip/resolver_test.go b/utils/dynamicip/resolver_test.go index 7606bdd87c11..e5e53d40f9f3 100644 --- a/utils/dynamicip/resolver_test.go +++ b/utils/dynamicip/resolver_test.go @@ -12,44 +12,40 @@ import ( func TestNewResolver(t *testing.T) { type test struct { - service string - validService bool + service string + err error } tests := []test{ { - service: OpenDNSName, - validService: true, + service: OpenDNSName, + err: nil, }, { - service: IFConfigName, - validService: true, + service: IFConfigName, + err: nil, }, { - service: IFConfigCoName, - validService: true, + service: IFConfigCoName, + err: nil, }, { - service: IFConfigMeName, - validService: true, + service: IFConfigMeName, + err: nil, }, { - service: strings.ToUpper(IFConfigMeName), - validService: true, + service: strings.ToUpper(IFConfigMeName), + err: nil, }, { - service: "not a valid resolution service name", - validService: false, + service: "not a valid resolution service name", + err: errUnknownResolver, }, } for _, tt := range tests { t.Run(tt.service, func(t *testing.T) { require := require.New(t) _, err := NewResolver(tt.service) - if tt.validService { - require.NoError(err) - } else { - require.Error(err) - } + require.ErrorIs(err, tt.err) }) } } From fc885dc986c5d905a28662caa157b60d19f893a0 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 00:46:29 -0400 Subject: [PATCH 37/77] more cleanup --- utils/sampler/uniform_test.go | 8 ++++---- utils/sampler/weighted_test.go | 11 +++++++---- utils/sampler/weighted_without_replacement_test.go | 11 +++++++---- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/utils/sampler/uniform_test.go b/utils/sampler/uniform_test.go index d7f9cf7191a8..fe66bdb9d27d 100644 --- a/utils/sampler/uniform_test.go +++ b/utils/sampler/uniform_test.go @@ -93,7 +93,7 @@ func UniformOutOfRangeTest(t *testing.T, s Uniform) { s.Initialize(0) _, err := s.Sample(1) - require.Error(t, err, "should have reported an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func UniformEmptyTest(t *testing.T, s Uniform) { @@ -101,7 +101,7 @@ func UniformEmptyTest(t *testing.T, s Uniform) { val, err := s.Sample(0) require.NoError(t, err) - require.Len(t, val, 0, "shouldn't have selected any element") + require.Empty(t, val) } func UniformSingletonTest(t *testing.T, s Uniform) { @@ -131,7 +131,7 @@ func UniformOverSampleTest(t *testing.T, s Uniform) { s.Initialize(3) _, err := s.Sample(4) - require.Error(t, err, "should have returned an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func UniformLazilySample(t *testing.T, s Uniform) { @@ -148,7 +148,7 @@ func UniformLazilySample(t *testing.T, s Uniform) { } _, err := s.Next() - require.Error(t, err, "should have returned an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) s.Reset() } diff --git a/utils/sampler/weighted_test.go b/utils/sampler/weighted_test.go index cb22b431aa05..6830a07e387c 100644 --- a/utils/sampler/weighted_test.go +++ b/utils/sampler/weighted_test.go @@ -5,10 +5,13 @@ package sampler import ( "fmt" - "math" "testing" + stdmath "math" + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/utils/math" ) var ( @@ -86,8 +89,8 @@ func TestAllWeighted(t *testing.T) { } func WeightedInitializeOverflowTest(t *testing.T, s Weighted) { - err := s.Initialize([]uint64{1, math.MaxUint64}) - require.Error(t, err, "should have reported an overflow error") + err := s.Initialize([]uint64{1, stdmath.MaxUint64}) + require.ErrorIs(t, err, math.ErrOverflow) } func WeightedOutOfRangeTest(t *testing.T, s Weighted) { @@ -95,7 +98,7 @@ func WeightedOutOfRangeTest(t *testing.T, s Weighted) { require.NoError(t, err) _, err = s.Sample(1) - require.Error(t, err, "should have reported an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func WeightedSingletonTest(t *testing.T, s Weighted) { diff --git a/utils/sampler/weighted_without_replacement_test.go b/utils/sampler/weighted_without_replacement_test.go index 42b5ac2a293b..c62f56215257 100644 --- a/utils/sampler/weighted_without_replacement_test.go +++ b/utils/sampler/weighted_without_replacement_test.go @@ -5,12 +5,15 @@ package sampler import ( "fmt" - "math" "testing" + stdmath "math" + "github.com/stretchr/testify/require" "golang.org/x/exp/slices" + + "github.com/ava-labs/avalanchego/utils/math" ) var ( @@ -84,8 +87,8 @@ func WeightedWithoutReplacementInitializeOverflowTest( t *testing.T, s WeightedWithoutReplacement, ) { - err := s.Initialize([]uint64{1, math.MaxUint64}) - require.Error(t, err, "should have reported an overflow error") + err := s.Initialize([]uint64{1, stdmath.MaxUint64}) + require.ErrorIs(t, err, math.ErrOverflow) } func WeightedWithoutReplacementOutOfRangeTest( @@ -96,7 +99,7 @@ func WeightedWithoutReplacementOutOfRangeTest( require.NoError(t, err) _, err = s.Sample(2) - require.Error(t, err, "should have reported an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func WeightedWithoutReplacementEmptyWithoutWeightTest( From e35ed2f4bf520079ed0cf0f0a85e66d59e34a994 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 12:20:06 -0400 Subject: [PATCH 38/77] cleanup --- utils/profiler/profiler_test.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/utils/profiler/profiler_test.go b/utils/profiler/profiler_test.go index c2c89143c60c..8f04c940532a 100644 --- a/utils/profiler/profiler_test.go +++ b/utils/profiler/profiler_test.go @@ -12,35 +12,37 @@ import ( ) func TestProfiler(t *testing.T) { + require := require.New(t) + dir := t.TempDir() p := New(dir) // Test Start and Stop CPU Profiler err := p.StartCPUProfiler() - require.NoError(t, err) + require.NoError(err) err = p.StopCPUProfiler() - require.NoError(t, err) + require.NoError(err) _, err = os.Stat(filepath.Join(dir, cpuProfileFile)) - require.NoError(t, err) + require.NoError(err) // Test Stop CPU Profiler without it running err = p.StopCPUProfiler() - require.Error(t, err) + require.ErrorIs(err, errCPUProfilerNotRunning) // Test Memory Profiler err = p.MemoryProfile() - require.NoError(t, err) + require.NoError(err) _, err = os.Stat(filepath.Join(dir, memProfileFile)) - require.NoError(t, err) + require.NoError(err) // Test Lock Profiler err = p.LockProfile() - require.NoError(t, err) + require.NoError(err) _, err = os.Stat(filepath.Join(dir, lockProfileFile)) - require.NoError(t, err) + require.NoError(err) } From 6ef1ef0c82b8c840f0f2dfcfe1d36a35ddfd1192 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 12:21:26 -0400 Subject: [PATCH 39/77] nit --- vms/platformvm/status/status_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vms/platformvm/status/status_test.go b/vms/platformvm/status/status_test.go index a97552c19712..78670a01fe44 100644 --- a/vms/platformvm/status/status_test.go +++ b/vms/platformvm/status/status_test.go @@ -34,7 +34,7 @@ func TestStatusJSON(t *testing.T) { { status := Status(math.MaxInt32) _, err := json.Marshal(status) - require.Error(err) + require.ErrorIs(err, errUnknownStatus) } { @@ -47,7 +47,7 @@ func TestStatusJSON(t *testing.T) { { var status Status err := json.Unmarshal([]byte(`"not a status"`), &status) - require.Error(err) + require.ErrorIs(err, errUnknownStatus) } } @@ -68,7 +68,7 @@ func TestStatusVerify(t *testing.T) { badStatus := Status(math.MaxInt32) err := badStatus.Verify() - require.Error(err, "%s passed verification", badStatus) + require.ErrorIs(err, errUnknownStatus) } func TestStatusString(t *testing.T) { From 55e077370990f05a6be9393952933a22d2d3d219 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 12:23:05 -0400 Subject: [PATCH 40/77] fix error --- vms/platformvm/status/blockchain_status.go | 2 +- vms/platformvm/status/blockchain_status_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vms/platformvm/status/blockchain_status.go b/vms/platformvm/status/blockchain_status.go index 7866e0eb75a9..1ab25e588b3d 100644 --- a/vms/platformvm/status/blockchain_status.go +++ b/vms/platformvm/status/blockchain_status.go @@ -53,7 +53,7 @@ func (s *BlockchainStatus) UnmarshalJSON(b []byte) error { *s = Syncing case "null": default: - return errUnknownStatus + return errUnknownBlockchainStatus } return nil } diff --git a/vms/platformvm/status/blockchain_status_test.go b/vms/platformvm/status/blockchain_status_test.go index e4828e683370..08216ad77f6b 100644 --- a/vms/platformvm/status/blockchain_status_test.go +++ b/vms/platformvm/status/blockchain_status_test.go @@ -34,7 +34,7 @@ func TestBlockchainStatusJSON(t *testing.T) { { status := BlockchainStatus(math.MaxInt32) _, err := json.Marshal(status) - require.Error(err) + require.ErrorIs(err, errUnknownBlockchainStatus) } { @@ -47,7 +47,7 @@ func TestBlockchainStatusJSON(t *testing.T) { { var status BlockchainStatus err := json.Unmarshal([]byte(`"not a status"`), &status) - require.Error(err) + require.ErrorIs(err, errUnknownBlockchainStatus) } } @@ -68,7 +68,7 @@ func TestBlockchainStatusVerify(t *testing.T) { badStatus := BlockchainStatus(math.MaxInt32) err := badStatus.Verify() - require.Error(err, "%s passed verification", badStatus) + require.ErrorIs(err, errUnknownBlockchainStatus) } func TestBlockchainStatusString(t *testing.T) { From 72412b6828cb70630386ce0d16de00d4fb48816a Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 12:28:16 -0400 Subject: [PATCH 41/77] nit --- utils/wrappers/packing.go | 14 +++---- utils/wrappers/packing_test.go | 40 +++++++++---------- .../state/validator_metadata_test.go | 34 ++++++++-------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/utils/wrappers/packing.go b/utils/wrappers/packing.go index e6869b1b91e7..891f80e49ab2 100644 --- a/utils/wrappers/packing.go +++ b/utils/wrappers/packing.go @@ -33,11 +33,11 @@ func StringLen(str string) int { } var ( - errBadLength = errors.New("packer has insufficient length for input") - errNegativeOffset = errors.New("negative offset") - errInvalidInput = errors.New("input does not match expected format") - errBadBool = errors.New("unexpected value when unpacking bool") - errOversized = errors.New("size is larger than limit") + ErrInsufficientLength = errors.New("packer has insufficient length for input") + errNegativeOffset = errors.New("negative offset") + errInvalidInput = errors.New("input does not match expected format") + errBadBool = errors.New("unexpected value when unpacking bool") + errOversized = errors.New("size is larger than limit") ) // Packer packs and unpacks a byte array from/to standard values @@ -252,7 +252,7 @@ func (p *Packer) checkSpace(bytes int) { case bytes < 0: p.Add(errInvalidInput) case len(p.Bytes)-p.Offset < bytes: - p.Add(errBadLength) + p.Add(ErrInsufficientLength) } } @@ -266,7 +266,7 @@ func (p *Packer) expand(bytes int) { case neededSize <= len(p.Bytes): // Byte slice has sufficient length already return case neededSize > p.MaxSize: // Lengthening the byte slice would cause it to grow too large - p.Err = errBadLength + p.Err = ErrInsufficientLength return case neededSize <= cap(p.Bytes): // Byte slice has sufficient capacity to lengthen it without mem alloc p.Bytes = p.Bytes[:neededSize] diff --git a/utils/wrappers/packing_test.go b/utils/wrappers/packing_test.go index af21be914961..2372e1ed3cfb 100644 --- a/utils/wrappers/packing_test.go +++ b/utils/wrappers/packing_test.go @@ -33,12 +33,12 @@ func TestPackerCheckSpace(t *testing.T) { p = Packer{Bytes: []byte{0x01}, Offset: 1} p.checkSpace(1) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: []byte{0x01}, Offset: 2} p.checkSpace(0) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerExpand(t *testing.T) { @@ -47,7 +47,7 @@ func TestPackerExpand(t *testing.T) { p := Packer{Bytes: []byte{0x01}, Offset: 2} p.expand(1) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: []byte{0x01, 0x02, 0x03}, Offset: 0} p.expand(1) @@ -67,7 +67,7 @@ func TestPackerPackByte(t *testing.T) { p.PackByte(0x02) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackByte(t *testing.T) { @@ -81,7 +81,7 @@ func TestPackerUnpackByte(t *testing.T) { require.Equal(uint8(ByteSentinel), p.UnpackByte()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackShort(t *testing.T) { @@ -105,7 +105,7 @@ func TestPackerUnpackShort(t *testing.T) { require.Equal(uint16(ShortSentinel), p.UnpackShort()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackInt(t *testing.T) { @@ -119,7 +119,7 @@ func TestPackerPackInt(t *testing.T) { p.PackInt(0x05060708) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackInt(t *testing.T) { @@ -133,7 +133,7 @@ func TestPackerUnpackInt(t *testing.T) { require.Equal(uint32(IntSentinel), p.UnpackInt()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackLong(t *testing.T) { @@ -147,7 +147,7 @@ func TestPackerPackLong(t *testing.T) { p.PackLong(0x090a0b0c0d0e0f00) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackLong(t *testing.T) { @@ -161,7 +161,7 @@ func TestPackerUnpackLong(t *testing.T) { require.Equal(uint64(LongSentinel), p.UnpackLong()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackFixedBytes(t *testing.T) { @@ -175,7 +175,7 @@ func TestPackerPackFixedBytes(t *testing.T) { p.PackFixedBytes([]byte("Avax")) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackFixedBytes(t *testing.T) { @@ -189,7 +189,7 @@ func TestPackerUnpackFixedBytes(t *testing.T) { require.Nil(p.UnpackFixedBytes(4)) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackBytes(t *testing.T) { @@ -203,7 +203,7 @@ func TestPackerPackBytes(t *testing.T) { p.PackBytes([]byte("Avax")) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackBytes(t *testing.T) { @@ -217,7 +217,7 @@ func TestPackerUnpackBytes(t *testing.T) { require.Nil(p.UnpackBytes()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackLimitedBytes(t *testing.T) { @@ -231,7 +231,7 @@ func TestPackerUnpackLimitedBytes(t *testing.T) { require.Nil(p.UnpackLimitedBytes(10)) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) // Reset and don't allow enough bytes p = Packer{Bytes: p.Bytes} @@ -263,7 +263,7 @@ func TestPackerUnpackString(t *testing.T) { require.Equal("", p.UnpackStr()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackLimitedString(t *testing.T) { @@ -277,7 +277,7 @@ func TestPackerUnpackLimitedString(t *testing.T) { require.Equal("", p.UnpackLimitedStr(10)) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) // Reset and don't allow enough bytes p = Packer{Bytes: p.Bytes} @@ -301,7 +301,7 @@ func TestPacker(t *testing.T) { p.PackShort(1) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: p.Bytes} require.Equal(uint16(17), p.UnpackShort()) @@ -340,7 +340,7 @@ func TestPackerPackBool(t *testing.T) { p.PackBool(false) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackBool(t *testing.T) { @@ -355,7 +355,7 @@ func TestPackerUnpackBool(t *testing.T) { require.Equal(BoolSentinel, p.UnpackBool()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: []byte{0x42}, Offset: 0} require.Equal(false, p.UnpackBool()) diff --git a/vms/platformvm/state/validator_metadata_test.go b/vms/platformvm/state/validator_metadata_test.go index 15fc983af262..09d4a6818703 100644 --- a/vms/platformvm/state/validator_metadata_test.go +++ b/vms/platformvm/state/validator_metadata_test.go @@ -9,9 +9,11 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/wrappers" ) func TestValidatorUptimes(t *testing.T) { @@ -176,10 +178,10 @@ func TestValidatorDelegateeRewards(t *testing.T) { func TestParseValidatorMetadata(t *testing.T) { type test struct { - name string - bytes []byte - expected *validatorMetadata - shouldErr bool + name string + bytes []byte + expected *validatorMetadata + expectedErr error } tests := []test{ { @@ -188,7 +190,7 @@ func TestParseValidatorMetadata(t *testing.T) { expected: &validatorMetadata{ lastUpdated: time.Unix(0, 0), }, - shouldErr: false, + expectedErr: nil, }, { name: "nil", @@ -196,7 +198,7 @@ func TestParseValidatorMetadata(t *testing.T) { expected: &validatorMetadata{ lastUpdated: time.Unix(0, 0), }, - shouldErr: false, + expectedErr: nil, }, { name: "potential reward only", @@ -207,7 +209,7 @@ func TestParseValidatorMetadata(t *testing.T) { PotentialReward: 100000, lastUpdated: time.Unix(0, 0), }, - shouldErr: false, + expectedErr: nil, }, { name: "uptime + potential reward", @@ -227,7 +229,7 @@ func TestParseValidatorMetadata(t *testing.T) { PotentialReward: 100000, lastUpdated: time.Unix(900000, 0), }, - shouldErr: false, + expectedErr: nil, }, { name: "uptime + potential reward + potential delegatee reward", @@ -250,7 +252,7 @@ func TestParseValidatorMetadata(t *testing.T) { PotentialDelegateeReward: 20000, lastUpdated: time.Unix(900000, 0), }, - shouldErr: false, + expectedErr: nil, }, { name: "invalid codec version", @@ -266,8 +268,8 @@ func TestParseValidatorMetadata(t *testing.T) { // potential delegatee reward 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x20, }, - expected: nil, - shouldErr: true, + expected: nil, + expectedErr: codec.ErrUnknownVersion, }, { name: "short byte len", @@ -283,8 +285,8 @@ func TestParseValidatorMetadata(t *testing.T) { // potential delegatee reward 0x00, 0x00, 0x00, 0x00, 0x4E, 0x20, }, - expected: nil, - shouldErr: true, + expected: nil, + expectedErr: wrappers.ErrInsufficientLength, }, } for _, tt := range tests { @@ -292,10 +294,8 @@ func TestParseValidatorMetadata(t *testing.T) { require := require.New(t) var metadata validatorMetadata err := parseValidatorMetadata(tt.bytes, &metadata) - if tt.shouldErr { - require.Error(err) - } else { - require.NoError(err) + require.ErrorIs(err, tt.expectedErr) + if err == nil { require.Equal(tt.expected, &metadata) } }) From 0ac84492e9233e9ed87e9cd7035ccf7552727ef0 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 12:29:02 -0400 Subject: [PATCH 42/77] nit --- vms/platformvm/state/diff_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vms/platformvm/state/diff_test.go b/vms/platformvm/state/diff_test.go index 40bfee200af7..a91ee816d0a8 100644 --- a/vms/platformvm/state/diff_test.go +++ b/vms/platformvm/state/diff_test.go @@ -467,7 +467,7 @@ func TestDiffUTXO(t *testing.T) { // Make sure it's gone _, err = d.GetUTXO(utxo.InputID()) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } } From 5631d357bb5a8a454b48193eb699e0dbccb99e88 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 15:47:07 -0400 Subject: [PATCH 43/77] state fixes --- vms/platformvm/state/state_test.go | 52 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/vms/platformvm/state/state_test.go b/vms/platformvm/state/state_test.go index ef8cdb6353c3..b54ed41c5f30 100644 --- a/vms/platformvm/state/state_test.go +++ b/vms/platformvm/state/state_test.go @@ -4,10 +4,11 @@ package state import ( - "math" "testing" "time" + stdmath "math" + "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" @@ -20,6 +21,7 @@ import ( "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -517,18 +519,18 @@ func newStateFromDB(require *require.Assertions, db database.Database) State { func TestValidatorWeightDiff(t *testing.T) { type test struct { - name string - ops []func(*ValidatorWeightDiff) error - shouldErr bool - expected ValidatorWeightDiff + name string + ops []func(*ValidatorWeightDiff) error + expected *ValidatorWeightDiff + expectedErr error } tests := []test{ { - name: "no ops", - ops: []func(*ValidatorWeightDiff) error{}, - shouldErr: false, - expected: ValidatorWeightDiff{}, + name: "no ops", + ops: []func(*ValidatorWeightDiff) error{}, + expected: &ValidatorWeightDiff{}, + expectedErr: nil, }, { name: "simple decrease", @@ -540,24 +542,24 @@ func TestValidatorWeightDiff(t *testing.T) { return d.Add(true, 1) }, }, - shouldErr: false, - expected: ValidatorWeightDiff{ + expected: &ValidatorWeightDiff{ Decrease: true, Amount: 2, }, + expectedErr: nil, }, { name: "decrease overflow", ops: []func(*ValidatorWeightDiff) error{ func(d *ValidatorWeightDiff) error { - return d.Add(true, math.MaxUint64) + return d.Add(true, stdmath.MaxUint64) }, func(d *ValidatorWeightDiff) error { return d.Add(true, 1) }, }, - shouldErr: true, - expected: ValidatorWeightDiff{}, + expected: &ValidatorWeightDiff{}, + expectedErr: math.ErrOverflow, }, { name: "simple increase", @@ -569,24 +571,24 @@ func TestValidatorWeightDiff(t *testing.T) { return d.Add(false, 1) }, }, - shouldErr: false, - expected: ValidatorWeightDiff{ + expected: &ValidatorWeightDiff{ Decrease: false, Amount: 2, }, + expectedErr: nil, }, { name: "increase overflow", ops: []func(*ValidatorWeightDiff) error{ func(d *ValidatorWeightDiff) error { - return d.Add(false, math.MaxUint64) + return d.Add(false, stdmath.MaxUint64) }, func(d *ValidatorWeightDiff) error { return d.Add(false, 1) }, }, - shouldErr: true, - expected: ValidatorWeightDiff{}, + expected: &ValidatorWeightDiff{}, + expectedErr: math.ErrOverflow, }, { name: "varied use", @@ -630,11 +632,11 @@ func TestValidatorWeightDiff(t *testing.T) { return d.Add(true, 2) // Value -2 }, }, - shouldErr: false, - expected: ValidatorWeightDiff{ + expected: &ValidatorWeightDiff{ Decrease: true, Amount: 2, }, + expectedErr: nil, }, } @@ -646,12 +648,10 @@ func TestValidatorWeightDiff(t *testing.T) { for _, op := range tt.ops { errs.Add(op(diff)) } - if tt.shouldErr { - require.Error(errs.Err) - return + require.ErrorIs(errs.Err, tt.expectedErr) + if tt.expectedErr == nil { + require.Equal(tt.expected, diff) } - require.NoError(errs.Err) - require.Equal(tt.expected, *diff) }) } } From fb695156cbc09f0fb855a8b27ce486ab112f72d2 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 15:50:47 -0400 Subject: [PATCH 44/77] use bls errors --- utils/crypto/bls/public.go | 4 ++-- utils/crypto/bls/public_test.go | 2 +- utils/crypto/bls/signature.go | 4 ++-- vms/platformvm/signer/proof_of_possession_test.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/utils/crypto/bls/public.go b/utils/crypto/bls/public.go index f17d6127eb64..4a944f94f21a 100644 --- a/utils/crypto/bls/public.go +++ b/utils/crypto/bls/public.go @@ -13,7 +13,7 @@ const PublicKeyLen = blst.BLST_P1_COMPRESS_BYTES var ( ErrNoPublicKeys = errors.New("no public keys") - errFailedPublicKeyDecompress = errors.New("couldn't decompress public key") + ErrFailedPublicKeyDecompress = errors.New("couldn't decompress public key") errInvalidPublicKey = errors.New("invalid public key") errFailedPublicKeyAggregation = errors.New("couldn't aggregate public keys") ) @@ -33,7 +33,7 @@ func PublicKeyToBytes(pk *PublicKey) []byte { func PublicKeyFromBytes(pkBytes []byte) (*PublicKey, error) { pk := new(PublicKey).Uncompress(pkBytes) if pk == nil { - return nil, errFailedPublicKeyDecompress + return nil, ErrFailedPublicKeyDecompress } if !pk.KeyValidate() { return nil, errInvalidPublicKey diff --git a/utils/crypto/bls/public_test.go b/utils/crypto/bls/public_test.go index 02300295630a..9cd886400b2d 100644 --- a/utils/crypto/bls/public_test.go +++ b/utils/crypto/bls/public_test.go @@ -16,7 +16,7 @@ func TestPublicKeyFromBytesWrongSize(t *testing.T) { pkBytes := utils.RandomBytes(PublicKeyLen + 1) _, err := PublicKeyFromBytes(pkBytes) - require.ErrorIs(err, errFailedPublicKeyDecompress) + require.ErrorIs(err, ErrFailedPublicKeyDecompress) } func TestPublicKeyBytes(t *testing.T) { diff --git a/utils/crypto/bls/signature.go b/utils/crypto/bls/signature.go index 7ee03aeff474..cafba33c48e6 100644 --- a/utils/crypto/bls/signature.go +++ b/utils/crypto/bls/signature.go @@ -12,7 +12,7 @@ import ( const SignatureLen = blst.BLST_P2_COMPRESS_BYTES var ( - errFailedSignatureDecompress = errors.New("couldn't decompress signature") + ErrFailedSignatureDecompress = errors.New("couldn't decompress signature") errInvalidSignature = errors.New("invalid signature") errNoSignatures = errors.New("no signatures") errFailedSignatureAggregation = errors.New("couldn't aggregate signatures") @@ -33,7 +33,7 @@ func SignatureToBytes(sig *Signature) []byte { func SignatureFromBytes(sigBytes []byte) (*Signature, error) { sig := new(Signature).Uncompress(sigBytes) if sig == nil { - return nil, errFailedSignatureDecompress + return nil, ErrFailedSignatureDecompress } if !sig.SigValidate(false) { return nil, errInvalidSignature diff --git a/vms/platformvm/signer/proof_of_possession_test.go b/vms/platformvm/signer/proof_of_possession_test.go index c29ac1adea39..eb86c8e8dcbb 100644 --- a/vms/platformvm/signer/proof_of_possession_test.go +++ b/vms/platformvm/signer/proof_of_possession_test.go @@ -22,12 +22,12 @@ func TestProofOfPossession(t *testing.T) { blsPOP, err = newProofOfPossession() require.NoError(err) blsPOP.ProofOfPossession = [bls.SignatureLen]byte{} - require.Error(blsPOP.Verify()) + require.ErrorIs(blsPOP.Verify(), bls.ErrFailedSignatureDecompress) blsPOP, err = newProofOfPossession() require.NoError(err) blsPOP.PublicKey = [bls.PublicKeyLen]byte{} - require.Error(blsPOP.Verify()) + require.ErrorIs(blsPOP.Verify(), bls.ErrFailedPublicKeyDecompress) newBLSPOP, err := newProofOfPossession() require.NoError(err) From a870fc9785c6962aaca6cf7067e5e19e1542eaf5 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 15:57:00 -0400 Subject: [PATCH 45/77] cleanup --- .../add_permissionless_validator_tx_test.go | 129 +++++++++--------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/vms/platformvm/txs/add_permissionless_validator_tx_test.go b/vms/platformvm/txs/add_permissionless_validator_tx_test.go index 704a3d4f5435..82f437b12f6d 100644 --- a/vms/platformvm/txs/add_permissionless_validator_tx_test.go +++ b/vms/platformvm/txs/add_permissionless_validator_tx_test.go @@ -4,9 +4,10 @@ package txs import ( - "math" "testing" + stdmath "math" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" @@ -15,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/platformvm/reward" @@ -125,6 +127,29 @@ func TestAddPermissionlessValidatorTxSyntacticVerify(t *testing.T) { }, err: errTooManyShares, }, + { + name: "invalid BaseTx", + txFunc: func(*gomock.Controller) *AddPermissionlessValidatorTx { + return &AddPermissionlessValidatorTx{ + BaseTx: invalidBaseTx, + Validator: Validator{ + NodeID: ids.GenerateTestNodeID(), + }, + StakeOuts: []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: ids.GenerateTestID(), + }, + Out: &secp256k1fx.TransferOutput{ + Amt: 1, + }, + }, + }, + DelegationShares: reward.PercentDenominator, + } + }, + err: avax.ErrWrongNetworkID, + }, { name: "invalid rewards owner", txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { @@ -216,6 +241,45 @@ func TestAddPermissionlessValidatorTxSyntacticVerify(t *testing.T) { }, err: errCustom, }, + { + name: "stake overflow", + txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { + rewardsOwner := fx.NewMockOwner(ctrl) + rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() + assetID := ids.GenerateTestID() + return &AddPermissionlessValidatorTx{ + BaseTx: validBaseTx, + Validator: Validator{ + NodeID: ids.GenerateTestNodeID(), + Wght: 1, + }, + Subnet: ids.GenerateTestID(), + Signer: &signer.Empty{}, + StakeOuts: []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: assetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: stdmath.MaxUint64, + }, + }, + { + Asset: avax.Asset{ + ID: assetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: 2, + }, + }, + }, + ValidatorRewardsOwner: rewardsOwner, + DelegatorRewardsOwner: rewardsOwner, + DelegationShares: reward.PercentDenominator, + } + }, + err: math.ErrOverflow, + }, { name: "multiple staked assets", txFunc: func(ctrl *gomock.Controller) *AddPermissionlessValidatorTx { @@ -422,69 +486,6 @@ func TestAddPermissionlessValidatorTxSyntacticVerify(t *testing.T) { require.ErrorIs(t, err, tt.err) }) } - - t.Run("invalid BaseTx", func(t *testing.T) { - tx := &AddPermissionlessValidatorTx{ - BaseTx: invalidBaseTx, - Validator: Validator{ - NodeID: ids.GenerateTestNodeID(), - }, - StakeOuts: []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: ids.GenerateTestID(), - }, - Out: &secp256k1fx.TransferOutput{ - Amt: 1, - }, - }, - }, - DelegationShares: reward.PercentDenominator, - } - err := tx.SyntacticVerify(ctx) - require.Error(t, err) - }) - - t.Run("stake overflow", func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - rewardsOwner := fx.NewMockOwner(ctrl) - rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() - assetID := ids.GenerateTestID() - tx := &AddPermissionlessValidatorTx{ - BaseTx: validBaseTx, - Validator: Validator{ - NodeID: ids.GenerateTestNodeID(), - Wght: 1, - }, - Subnet: ids.GenerateTestID(), - Signer: &signer.Empty{}, - StakeOuts: []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: assetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, - }, - }, - { - Asset: avax.Asset{ - ID: assetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: 2, - }, - }, - }, - ValidatorRewardsOwner: rewardsOwner, - DelegatorRewardsOwner: rewardsOwner, - DelegationShares: reward.PercentDenominator, - } - err := tx.SyntacticVerify(ctx) - require.Error(t, err) - }) } func TestAddPermissionlessValidatorTxNotDelegatorTx(t *testing.T) { From ca7277dde124d334efacc4d90d95a8b761ebfec1 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 16:51:23 -0400 Subject: [PATCH 46/77] fix delegator tests --- vms/platformvm/txs/add_delegator_test.go | 6 ++++-- vms/platformvm/txs/add_delegator_tx.go | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/vms/platformvm/txs/add_delegator_test.go b/vms/platformvm/txs/add_delegator_test.go index 45e4872b8920..b5c051d2fb6e 100644 --- a/vms/platformvm/txs/add_delegator_test.go +++ b/vms/platformvm/txs/add_delegator_test.go @@ -111,7 +111,7 @@ func TestAddDelegatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addDelegatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, avax.ErrWrongNetworkID) addDelegatorTx.NetworkID-- // Case: delegator weight is not equal to total stake weight @@ -196,7 +196,9 @@ func TestAddDelegatorTxSyntacticVerifyNotAVAX(t *testing.T) { stx, err = NewSigned(addDelegatorTx, Codec, signers) require.NoError(err) - require.Error(stx.SyntacticVerify(ctx)) + + err = stx.SyntacticVerify(ctx) + require.ErrorIs(err, errStakeMustBeAVAX) } func TestAddDelegatorTxNotValidatorTx(t *testing.T) { diff --git a/vms/platformvm/txs/add_delegator_tx.go b/vms/platformvm/txs/add_delegator_tx.go index a44ddebba0dc..4f6fbe395b02 100644 --- a/vms/platformvm/txs/add_delegator_tx.go +++ b/vms/platformvm/txs/add_delegator_tx.go @@ -22,6 +22,7 @@ var ( _ DelegatorTx = (*AddDelegatorTx)(nil) errDelegatorWeightMismatch = errors.New("delegator weight is not equal to total stake weight") + errStakeMustBeAVAX = errors.New("stake must be AVAX") ) // AddDelegatorTx is an unsigned addDelegatorTx @@ -105,7 +106,7 @@ func (tx *AddDelegatorTx) SyntacticVerify(ctx *snow.Context) error { assetID := out.AssetID() if assetID != ctx.AVAXAssetID { - return fmt.Errorf("stake output must be AVAX but is %q", assetID) + return fmt.Errorf("%w but is %q", errStakeMustBeAVAX, assetID) } } From 61e8d4e2ecd2416567f3977810b277fa434b9042 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 16:54:34 -0400 Subject: [PATCH 47/77] fix verifier test --- vms/platformvm/blocks/executor/verifier_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vms/platformvm/blocks/executor/verifier_test.go b/vms/platformvm/blocks/executor/verifier_test.go index ee224f0cfe01..098fb9eee8c7 100644 --- a/vms/platformvm/blocks/executor/verifier_test.go +++ b/vms/platformvm/blocks/executor/verifier_test.go @@ -496,7 +496,7 @@ func TestVerifyUnverifiedParent(t *testing.T) { // Verify the block. err = blk.Visit(verifier) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } func TestBanffAbortBlockTimestampChecks(t *testing.T) { From 5ab4510b7732987a8e3e93370c4f5e7fb44608bc Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 17:11:12 -0400 Subject: [PATCH 48/77] cleanup --- version/parser.go | 15 +++++-- version/parser_test.go | 93 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 86 insertions(+), 22 deletions(-) diff --git a/version/parser.go b/version/parser.go index 9a640702e2f4..debb636a92cb 100644 --- a/version/parser.go +++ b/version/parser.go @@ -4,14 +4,21 @@ package version import ( + "errors" "fmt" "strconv" "strings" ) +var ( + errMissingVersionPrefix = errors.New("missing required version prefix") + errMissingApplicationPrefix = errors.New("missing required application prefix") + errMissingVersions = errors.New("missing version numbers") +) + func Parse(s string) (*Semantic, error) { if !strings.HasPrefix(s, "v") { - return nil, fmt.Errorf("version string %q missing required prefix", s) + return nil, fmt.Errorf("%w: %q", errMissingVersionPrefix, s) } s = s[1:] @@ -29,7 +36,7 @@ func Parse(s string) (*Semantic, error) { func ParseApplication(s string) (*Application, error) { if !strings.HasPrefix(s, "avalanche/") { - return nil, fmt.Errorf("application string %q missing required prefix", s) + return nil, fmt.Errorf("%w: %q", errMissingApplicationPrefix, s) } s = s[10:] @@ -47,8 +54,8 @@ func ParseApplication(s string) (*Application, error) { func parseVersions(s string) (int, int, int, error) { splitVersion := strings.SplitN(s, ".", 3) - if len(splitVersion) != 3 { - return 0, 0, 0, fmt.Errorf("failed to parse %s as a version", s) + if numSeperators := len(splitVersion); numSeperators != 3 { + return 0, 0, 0, fmt.Errorf("%w: expected 3 only got %d", errMissingVersions, numSeperators) } major, err := strconv.Atoi(splitVersion[0]) diff --git a/version/parser_test.go b/version/parser_test.go index d53a7359ad94..3bc8b5e30589 100644 --- a/version/parser_test.go +++ b/version/parser_test.go @@ -4,6 +4,7 @@ package version import ( + "strconv" "testing" "github.com/stretchr/testify/require" @@ -19,16 +20,48 @@ func TestParse(t *testing.T) { require.Equal(t, 2, v.Minor) require.Equal(t, 3, v.Patch) - badVersions := []string{ - "", - "1.2.3", - "vz.2.3", - "v1.z.3", - "v1.2.z", + tests := []struct { + version string + expectedErr error + }{ + { + version: "", + expectedErr: errMissingVersionPrefix, + }, + { + version: "1.2.3", + expectedErr: errMissingVersionPrefix, + }, + { + version: "z1.2.3", + expectedErr: errMissingVersionPrefix, + }, + { + version: "v1.2", + expectedErr: errMissingVersions, + }, + { + version: "vz.2.3", + expectedErr: strconv.ErrSyntax, + }, + { + version: "v1.z.3", + expectedErr: strconv.ErrSyntax, + }, + { + version: "v1.2.z", + expectedErr: strconv.ErrSyntax, + }, + { + version: "v1.2.3.4", + expectedErr: strconv.ErrSyntax, + }, } - for _, badVersion := range badVersions { - _, err := Parse(badVersion) - require.Error(t, err) + for _, test := range tests { + t.Run(test.version, func(t *testing.T) { + _, err := Parse(test.version) + require.ErrorIs(t, err, test.expectedErr) + }) } } @@ -44,15 +77,39 @@ func TestParseApplication(t *testing.T) { require.NoError(t, v.Compatible(v)) require.False(t, v.Before(v)) - badVersions := []string{ - "", - "avalanche/", - "avalanche/z.0.0", - "avalanche/0.z.0", - "avalanche/0.0.z", + tests := []struct { + version string + expectedErr error + }{ + { + version: "", + expectedErr: errMissingApplicationPrefix, + }, + { + version: "avalanche/", + expectedErr: errMissingVersions, + }, + { + version: "avalanche/z.0.0", + expectedErr: strconv.ErrSyntax, + }, + { + version: "avalanche/0.z.0", + expectedErr: strconv.ErrSyntax, + }, + { + version: "avalanche/0.0.z", + expectedErr: strconv.ErrSyntax, + }, + { + version: "avalanche/0.0.0.0", + expectedErr: strconv.ErrSyntax, + }, } - for _, badVersion := range badVersions { - _, err := ParseApplication(badVersion) - require.Error(t, err) + for _, test := range tests { + t.Run(test.version, func(t *testing.T) { + _, err := ParseApplication(test.version) + require.ErrorIs(t, err, test.expectedErr) + }) } } From 51e800abc79e51471c6cb48d20a15412cda61369 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 17:15:25 -0400 Subject: [PATCH 49/77] fix indexer tests --- vms/avm/index_test.go | 8 ++++---- vms/components/index/index.go | 13 +++++++------ vms/secp256k1fx/output_owners.go | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 8a2b681c8a67..f8b18900862d 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -415,7 +415,7 @@ func TestIndexingNewInitWithIndexingEnabled(t *testing.T) { // now disable indexing with allow-incomplete set to false _, err = index.NewNoIndexer(db, false) - require.Error(t, err) + require.ErrorIs(t, err, index.ErrCausesIncompleteIndex) // now disable indexing with allow-incomplete set to true _, err = index.NewNoIndexer(db, true) @@ -432,7 +432,7 @@ func TestIndexingNewInitWithIndexingDisabled(t *testing.T) { // It's not OK to have an incomplete index when allowIncompleteIndices is false _, err = index.NewIndexer(db, ctx.Log, "", prometheus.NewRegistry(), false) - require.Error(t, err) + require.ErrorIs(t, err, index.ErrIndexingRequiredFromGenesis) // It's OK to have an incomplete index when allowIncompleteIndices is true _, err = index.NewIndexer(db, ctx.Log, "", prometheus.NewRegistry(), true) @@ -457,12 +457,12 @@ func TestIndexingAllowIncomplete(t *testing.T) { _, err := index.NewNoIndexer(db, false) require.NoError(t, err) - // we initialise with indexing enabled now and allow incomplete indexing as false + // we initialize with indexing enabled now and allow incomplete indexing as false _, err = index.NewIndexer(db, ctx.Log, "", prometheus.NewRegistry(), false) // we should get error because: // - indexing was disabled previously // - node now is asked to enable indexing with allow incomplete set to false - require.Error(t, err) + require.ErrorIs(t, err, index.ErrIndexingRequiredFromGenesis) } func buildPlatformUTXO(utxoID avax.UTXOID, txAssetID avax.Asset, addr ids.ShortID) *avax.UTXO { diff --git a/vms/components/index/index.go b/vms/components/index/index.go index 0597f836cafe..25f004dd3f7b 100644 --- a/vms/components/index/index.go +++ b/vms/components/index/index.go @@ -23,10 +23,11 @@ import ( ) var ( - idxKey = []byte("idx") - idxCompleteKey = []byte("complete") - errIndexingRequiredFromGenesis = errors.New("running would create incomplete index. Allow incomplete indices or re-sync from genesis with indexing enabled") - errCausesIncompleteIndex = errors.New("running would create incomplete index. Allow incomplete indices or enable indexing") + ErrIndexingRequiredFromGenesis = errors.New("running would create incomplete index. Allow incomplete indices or re-sync from genesis with indexing enabled") + ErrCausesIncompleteIndex = errors.New("running would create incomplete index. Allow incomplete indices or enable indexing") + + idxKey = []byte("idx") + idxCompleteKey = []byte("complete") _ AddressTxsIndexer = (*indexer)(nil) _ AddressTxsIndexer = (*noIndexer)(nil) @@ -229,7 +230,7 @@ func checkIndexStatus(db database.KeyValueReaderWriter, enableIndexing, allowInc if !idxComplete && enableIndexing && !allowIncomplete { // In a previous run, we did not index so it's incomplete. // indexing was disabled before but now we want to index. - return errIndexingRequiredFromGenesis + return ErrIndexingRequiredFromGenesis } else if !idxComplete { // either indexing is disabled, or incomplete indices are ok, so we don't care that index is incomplete return nil @@ -237,7 +238,7 @@ func checkIndexStatus(db database.KeyValueReaderWriter, enableIndexing, allowInc // the index is complete if !enableIndexing && !allowIncomplete { // indexing is disabled this run - return errCausesIncompleteIndex + return ErrCausesIncompleteIndex } else if !enableIndexing { // running without indexing makes it incomplete return database.PutBool(db, idxCompleteKey, false) diff --git a/vms/secp256k1fx/output_owners.go b/vms/secp256k1fx/output_owners.go index eb601eb3773e..c4c9fb737bba 100644 --- a/vms/secp256k1fx/output_owners.go +++ b/vms/secp256k1fx/output_owners.go @@ -57,7 +57,7 @@ func (out *OutputOwners) MarshalJSON() ([]byte, error) { } // Fields returns JSON keys in a map that can be used with marshal JSON -// to serialise OutputOwners struct +// to serialize OutputOwners struct func (out *OutputOwners) Fields() (map[string]interface{}, error) { addrsLen := len(out.Addrs) From 65e3ce1bb8d4fdc9f88bef609eda183ab4b3c7af Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 17:17:22 -0400 Subject: [PATCH 50/77] fix avm service tests --- vms/avm/service_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index b148ed3479b4..d7d174a6dc37 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -1664,7 +1664,7 @@ func TestServiceGetNilTx(t *testing.T) { reply := api.GetTxReply{} err := s.GetTx(nil, &api.GetTxArgs{}, &reply) - require.Error(t, err, "Nil TxID should have returned an error") + require.ErrorIs(t, err, errNilTxID) } func TestServiceGetUnknownTx(t *testing.T) { @@ -1677,8 +1677,8 @@ func TestServiceGetUnknownTx(t *testing.T) { }() reply := api.GetTxReply{} - err := s.GetTx(nil, &api.GetTxArgs{TxID: ids.Empty}, &reply) - require.Error(t, err, "Unknown TxID should have returned an error") + err := s.GetTx(nil, &api.GetTxArgs{TxID: ids.GenerateTestID()}, &reply) + require.ErrorIs(t, err, database.ErrNotFound) } func TestServiceGetUTXOs(t *testing.T) { From b20ddc72d0a520438e430e03dec5c0e71672b095 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 17:23:46 -0400 Subject: [PATCH 51/77] fix platformvm service tests --- vms/platformvm/service_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/service_test.go b/vms/platformvm/service_test.go index 12cd7546c937..a59217f26ee6 100644 --- a/vms/platformvm/service_test.go +++ b/vms/platformvm/service_test.go @@ -19,6 +19,7 @@ import ( "github.com/ava-labs/avalanchego/api/keystore" "github.com/ava-labs/avalanchego/cache" "github.com/ava-labs/avalanchego/chains/atomic" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/manager" "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/ids" @@ -235,7 +236,7 @@ func TestGetTxStatus(t *testing.T) { // put the chain in existing chain list err = service.vm.Builder.AddUnverifiedTx(tx) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) // Missing shared memory UTXO mutableSharedMemory.SharedMemory = sm @@ -331,7 +332,7 @@ func TestGetTx(t *testing.T) { } var response api.GetTxReply err = service.GetTx(nil, arg, &response) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) // We haven't issued the tx yet err = service.vm.Builder.AddUnverifiedTx(tx) require.NoError(err) From bd00c1be16d0b6b32ba9ae6ac97562f363fe8f16 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 17:34:44 -0400 Subject: [PATCH 52/77] fix add validator tests --- vms/platformvm/txs/add_validator_test.go | 12 +++++++----- vms/platformvm/txs/add_validator_tx.go | 2 +- vms/secp256k1fx/fx_test.go | 10 +++++----- vms/secp256k1fx/mint_operation_test.go | 8 ++++---- vms/secp256k1fx/mint_output.go | 2 +- vms/secp256k1fx/mint_output_test.go | 4 ++-- vms/secp256k1fx/output_owners.go | 20 ++++++++++---------- vms/secp256k1fx/output_owners_test.go | 12 ++++++------ vms/secp256k1fx/transfer_output.go | 2 +- vms/secp256k1fx/transfer_output_test.go | 10 +++++----- 10 files changed, 42 insertions(+), 40 deletions(-) diff --git a/vms/platformvm/txs/add_validator_test.go b/vms/platformvm/txs/add_validator_test.go index 78eda5c95acd..74671904fa4b 100644 --- a/vms/platformvm/txs/add_validator_test.go +++ b/vms/platformvm/txs/add_validator_test.go @@ -107,7 +107,7 @@ func TestAddValidatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, avax.ErrWrongNetworkID) addValidatorTx.NetworkID-- // Case: Stake owner has no addresses @@ -119,7 +119,7 @@ func TestAddValidatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, secp256k1fx.ErrOutputUnspendable) addValidatorTx.StakeOuts = stakes // Case: Rewards owner has no addresses @@ -128,7 +128,7 @@ func TestAddValidatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, secp256k1fx.ErrOutputUnspendable) addValidatorTx.RewardsOwner.(*secp256k1fx.OutputOwners).Addrs = []ids.ShortID{rewardAddress} // Case: Too many shares @@ -137,7 +137,7 @@ func TestAddValidatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, errTooManyShares) addValidatorTx.DelegationShares-- } @@ -215,7 +215,9 @@ func TestAddValidatorTxSyntacticVerifyNotAVAX(t *testing.T) { stx, err = NewSigned(addValidatorTx, Codec, signers) require.NoError(err) - require.Error(stx.SyntacticVerify(ctx)) + + err = stx.SyntacticVerify(ctx) + require.ErrorIs(err, errStakeMustBeAVAX) } func TestAddValidatorTxNotDelegatorTx(t *testing.T) { diff --git a/vms/platformvm/txs/add_validator_tx.go b/vms/platformvm/txs/add_validator_tx.go index d7101c378ba5..be6a93c2e42b 100644 --- a/vms/platformvm/txs/add_validator_tx.go +++ b/vms/platformvm/txs/add_validator_tx.go @@ -119,7 +119,7 @@ func (tx *AddValidatorTx) SyntacticVerify(ctx *snow.Context) error { assetID := out.AssetID() if assetID != ctx.AVAXAssetID { - return fmt.Errorf("stake output must be AVAX but is %q", assetID) + return fmt.Errorf("%w but is %q", errStakeMustBeAVAX, assetID) } } diff --git a/vms/secp256k1fx/fx_test.go b/vms/secp256k1fx/fx_test.go index e163dd7e9cab..6c6bdcf472f4 100644 --- a/vms/secp256k1fx/fx_test.go +++ b/vms/secp256k1fx/fx_test.go @@ -260,7 +260,7 @@ func TestFxVerifyTransferInvalidOutput(t *testing.T) { }, } - require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), errOutputUnoptimized) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), ErrOutputUnoptimized) } func TestFxVerifyTransferWrongAmounts(t *testing.T) { @@ -881,7 +881,7 @@ func TestFxVerifyOperationInvalidOperationVerify(t *testing.T) { } utxos := []interface{}{utxo} - require.ErrorIs(fx.VerifyOperation(tx, op, cred, utxos), errOutputUnspendable) + require.ErrorIs(fx.VerifyOperation(tx, op, cred, utxos), ErrOutputUnspendable) } func TestFxVerifyOperationMismatchedMintOutputs(t *testing.T) { @@ -962,7 +962,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 0, Addrs: []ids.ShortID{addr}, }, - errOutputUnoptimized, + ErrOutputUnoptimized, }, { "threshold 0, no sigs, no addrs", @@ -995,7 +995,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 0, Addrs: []ids.ShortID{addr}, }, - errOutputUnoptimized, + ErrOutputUnoptimized, }, { "threshold 1, 0 sigs (too few sigs)", @@ -1039,7 +1039,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr}, }, - errAddrsNotSortedUnique, + ErrAddrsNotSortedUnique, }, { "threshold 2, 2 sigs", diff --git a/vms/secp256k1fx/mint_operation_test.go b/vms/secp256k1fx/mint_operation_test.go index 30288b5cf4fb..b3da2edfdd99 100644 --- a/vms/secp256k1fx/mint_operation_test.go +++ b/vms/secp256k1fx/mint_operation_test.go @@ -63,7 +63,7 @@ func TestMintOperationVerify(t *testing.T) { }, TransferOutput: validTransferOutput, }, - expectedErr: errOutputUnspendable, + expectedErr: ErrOutputUnspendable, }, { name: "invalid transfer output", @@ -78,7 +78,7 @@ func TestMintOperationVerify(t *testing.T) { }, }, }, - expectedErr: errOutputUnoptimized, + expectedErr: ErrOutputUnoptimized, }, { name: "addresses not unique", @@ -93,7 +93,7 @@ func TestMintOperationVerify(t *testing.T) { }, }, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "addresses not sorted", @@ -108,7 +108,7 @@ func TestMintOperationVerify(t *testing.T) { }, }, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "passes verification", diff --git a/vms/secp256k1fx/mint_output.go b/vms/secp256k1fx/mint_output.go index 7655fc5c3574..84dc6c44df4e 100644 --- a/vms/secp256k1fx/mint_output.go +++ b/vms/secp256k1fx/mint_output.go @@ -16,7 +16,7 @@ type MintOutput struct { func (out *MintOutput) Verify() error { switch { case out == nil: - return errNilOutput + return ErrNilOutput default: return out.OutputOwners.Verify() } diff --git a/vms/secp256k1fx/mint_output_test.go b/vms/secp256k1fx/mint_output_test.go index 7bd55cc0f1c0..c9547fd8a317 100644 --- a/vms/secp256k1fx/mint_output_test.go +++ b/vms/secp256k1fx/mint_output_test.go @@ -20,7 +20,7 @@ func TestMintOutputVerify(t *testing.T) { { name: "nil", out: nil, - expectedErr: errNilOutput, + expectedErr: ErrNilOutput, }, { name: "invalid output owners", @@ -30,7 +30,7 @@ func TestMintOutputVerify(t *testing.T) { Addrs: []ids.ShortID{ids.GenerateTestShortID()}, }, }, - expectedErr: errOutputUnspendable, + expectedErr: ErrOutputUnspendable, }, { name: "passes verification", diff --git a/vms/secp256k1fx/output_owners.go b/vms/secp256k1fx/output_owners.go index c4c9fb737bba..39c076d65635 100644 --- a/vms/secp256k1fx/output_owners.go +++ b/vms/secp256k1fx/output_owners.go @@ -17,11 +17,11 @@ import ( ) var ( - errNilOutput = errors.New("nil output") - errOutputUnspendable = errors.New("output is unspendable") - errOutputUnoptimized = errors.New("output representation should be optimized") - errAddrsNotSortedUnique = errors.New("addresses not sorted and unique") - errMarshal = errors.New("cannot marshal without ctx") + ErrNilOutput = errors.New("nil output") + ErrOutputUnspendable = errors.New("output is unspendable") + ErrOutputUnoptimized = errors.New("output representation should be optimized") + ErrAddrsNotSortedUnique = errors.New("addresses not sorted and unique") + ErrMarshal = errors.New("cannot marshal without ctx") _ verify.State = (*OutputOwners)(nil) ) @@ -63,7 +63,7 @@ func (out *OutputOwners) Fields() (map[string]interface{}, error) { // we need out.ctx to do this, if its absent, throw error if addrsLen > 0 && out.ctx == nil { - return nil, errMarshal + return nil, ErrMarshal } addresses := make([]string, addrsLen) @@ -123,13 +123,13 @@ func (out *OutputOwners) Equals(other *OutputOwners) bool { func (out *OutputOwners) Verify() error { switch { case out == nil: - return errNilOutput + return ErrNilOutput case out.Threshold > uint32(len(out.Addrs)): - return errOutputUnspendable + return ErrOutputUnspendable case out.Threshold == 0 && len(out.Addrs) > 0: - return errOutputUnoptimized + return ErrOutputUnoptimized case !utils.IsSortedAndUniqueSortable(out.Addrs): - return errAddrsNotSortedUnique + return ErrAddrsNotSortedUnique default: return nil } diff --git a/vms/secp256k1fx/output_owners_test.go b/vms/secp256k1fx/output_owners_test.go index db8e8436b5d7..cf67d2688f65 100644 --- a/vms/secp256k1fx/output_owners_test.go +++ b/vms/secp256k1fx/output_owners_test.go @@ -20,7 +20,7 @@ func TestOutputOwnersVerify(t *testing.T) { { name: "nil", out: nil, - expectedErr: errNilOutput, + expectedErr: ErrNilOutput, }, { name: "threshold > num addrs", @@ -28,7 +28,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 1, Addrs: []ids.ShortID{}, }, - expectedErr: errOutputUnspendable, + expectedErr: ErrOutputUnspendable, }, { name: "unoptimized", @@ -36,7 +36,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 0, Addrs: []ids.ShortID{ids.GenerateTestShortID()}, }, - expectedErr: errOutputUnoptimized, + expectedErr: ErrOutputUnoptimized, }, { name: "not sorted", @@ -44,7 +44,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 1, Addrs: []ids.ShortID{{2}, {1}}, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "not unique", @@ -52,7 +52,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 1, Addrs: []ids.ShortID{{2}, {2}}, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "passes verification", @@ -160,7 +160,7 @@ func TestMarshalJSONRequiresCtxWhenAddrsArePresent(t *testing.T) { } _, err := out.MarshalJSON() - require.ErrorIs(err, errMarshal) + require.ErrorIs(err, ErrMarshal) } func TestMarshalJSONDoesNotRequireCtxWhenAddrsAreAbsent(t *testing.T) { diff --git a/vms/secp256k1fx/transfer_output.go b/vms/secp256k1fx/transfer_output.go index 285ffef5a9fe..dc57d2305b6c 100644 --- a/vms/secp256k1fx/transfer_output.go +++ b/vms/secp256k1fx/transfer_output.go @@ -43,7 +43,7 @@ func (out *TransferOutput) Amount() uint64 { func (out *TransferOutput) Verify() error { switch { case out == nil: - return errNilOutput + return ErrNilOutput case out.Amt == 0: return ErrNoValueOutput default: diff --git a/vms/secp256k1fx/transfer_output_test.go b/vms/secp256k1fx/transfer_output_test.go index 08bfd173bfa6..650c1da833fc 100644 --- a/vms/secp256k1fx/transfer_output_test.go +++ b/vms/secp256k1fx/transfer_output_test.go @@ -47,7 +47,7 @@ func TestOutputVerify(t *testing.T) { func TestOutputVerifyNil(t *testing.T) { require := require.New(t) out := (*TransferOutput)(nil) - require.ErrorIs(out.Verify(), errNilOutput) + require.ErrorIs(out.Verify(), ErrNilOutput) } func TestOutputVerifyNoValue(t *testing.T) { @@ -77,7 +77,7 @@ func TestOutputVerifyUnspendable(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errOutputUnspendable) + require.ErrorIs(out.Verify(), ErrOutputUnspendable) } func TestOutputVerifyUnoptimized(t *testing.T) { @@ -92,7 +92,7 @@ func TestOutputVerifyUnoptimized(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errOutputUnoptimized) + require.ErrorIs(out.Verify(), ErrOutputUnoptimized) } func TestOutputVerifyUnsorted(t *testing.T) { @@ -108,7 +108,7 @@ func TestOutputVerifyUnsorted(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errAddrsNotSortedUnique) + require.ErrorIs(out.Verify(), ErrAddrsNotSortedUnique) } func TestOutputVerifyDuplicated(t *testing.T) { @@ -124,7 +124,7 @@ func TestOutputVerifyDuplicated(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errAddrsNotSortedUnique) + require.ErrorIs(out.Verify(), ErrAddrsNotSortedUnique) } func TestOutputSerialize(t *testing.T) { From 1c0e276f33c5a9e608fc50d4f50d376d96e217eb Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 17:41:06 -0400 Subject: [PATCH 53/77] fix add subnet validator tests --- vms/platformvm/txs/add_subnet_validator_test.go | 10 +++++----- .../txs/executor/standard_tx_executor_test.go | 2 +- vms/secp256k1fx/fx_test.go | 4 ++-- vms/secp256k1fx/input.go | 6 +++--- vms/secp256k1fx/input_test.go | 4 ++-- vms/secp256k1fx/mint_operation_test.go | 2 +- vms/secp256k1fx/transfer_input_test.go | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/vms/platformvm/txs/add_subnet_validator_test.go b/vms/platformvm/txs/add_subnet_validator_test.go index c25fd8df6b41..12c0514176c4 100644 --- a/vms/platformvm/txs/add_subnet_validator_test.go +++ b/vms/platformvm/txs/add_subnet_validator_test.go @@ -94,16 +94,16 @@ func TestAddSubnetValidatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addSubnetValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, avax.ErrWrongNetworkID) addSubnetValidatorTx.NetworkID-- - // Case: Missing Subnet ID + // Case: Specifies primary network SubnetID addSubnetValidatorTx.SyntacticallyVerified = false addSubnetValidatorTx.Subnet = ids.Empty stx, err = NewSigned(addSubnetValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, errAddPrimaryNetworkValidator) addSubnetValidatorTx.Subnet = subnetID // Case: No weight @@ -112,7 +112,7 @@ func TestAddSubnetValidatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addSubnetValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, ErrWeightTooSmall) addSubnetValidatorTx.Wght = validatorWeight // Case: Subnet auth indices not unique @@ -123,7 +123,7 @@ func TestAddSubnetValidatorTxSyntacticVerify(t *testing.T) { stx, err = NewSigned(addSubnetValidatorTx, Codec, signers) require.NoError(err) err = stx.SyntacticVerify(ctx) - require.Error(err) + require.ErrorIs(err, secp256k1fx.ErrInputIndicesNotSortedUnique) *input = oldInput // Case: adding to Primary Network diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 7873a7047a12..17c6e5220246 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -710,7 +710,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, secp256k1fx.ErrNotSortedUnique) + require.ErrorIs(err, secp256k1fx.ErrInputIndicesNotSortedUnique) } { diff --git a/vms/secp256k1fx/fx_test.go b/vms/secp256k1fx/fx_test.go index 6c6bdcf472f4..eb92ab50d506 100644 --- a/vms/secp256k1fx/fx_test.go +++ b/vms/secp256k1fx/fx_test.go @@ -1028,7 +1028,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr2}, }, - ErrNotSortedUnique, + ErrInputIndicesNotSortedUnique, }, { "threshold 2, repeated address and repeated sig", @@ -1061,7 +1061,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr2}, }, - ErrNotSortedUnique, + ErrInputIndicesNotSortedUnique, }, { "threshold 1, 1 sig, index out of bounds", diff --git a/vms/secp256k1fx/input.go b/vms/secp256k1fx/input.go index df5511e2900c..d5943a6b686e 100644 --- a/vms/secp256k1fx/input.go +++ b/vms/secp256k1fx/input.go @@ -15,8 +15,8 @@ const ( ) var ( - ErrNilInput = errors.New("nil input") - ErrNotSortedUnique = errors.New("signatures not sorted and unique") + ErrNilInput = errors.New("nil input") + ErrInputIndicesNotSortedUnique = errors.New("address indices not sorted and unique") ) type Input struct { @@ -37,7 +37,7 @@ func (in *Input) Verify() error { case in == nil: return ErrNilInput case !utils.IsSortedAndUniqueOrdered(in.SigIndices): - return ErrNotSortedUnique + return ErrInputIndicesNotSortedUnique default: return nil } diff --git a/vms/secp256k1fx/input_test.go b/vms/secp256k1fx/input_test.go index 40728330727f..0e0efffe0c81 100644 --- a/vms/secp256k1fx/input_test.go +++ b/vms/secp256k1fx/input_test.go @@ -23,12 +23,12 @@ func TestInputVerifyNil(t *testing.T) { { name: "not sorted", in: &Input{SigIndices: []uint32{2, 1}}, - expectedErr: ErrNotSortedUnique, + expectedErr: ErrInputIndicesNotSortedUnique, }, { name: "not unique", in: &Input{SigIndices: []uint32{2, 2}}, - expectedErr: ErrNotSortedUnique, + expectedErr: ErrInputIndicesNotSortedUnique, }, { name: "passes verification", diff --git a/vms/secp256k1fx/mint_operation_test.go b/vms/secp256k1fx/mint_operation_test.go index b3da2edfdd99..ed066f61a156 100644 --- a/vms/secp256k1fx/mint_operation_test.go +++ b/vms/secp256k1fx/mint_operation_test.go @@ -49,7 +49,7 @@ func TestMintOperationVerify(t *testing.T) { MintOutput: validMintOutput, TransferOutput: validTransferOutput, }, - expectedErr: ErrNotSortedUnique, + expectedErr: ErrInputIndicesNotSortedUnique, }, { name: "invalid mint output", diff --git a/vms/secp256k1fx/transfer_input_test.go b/vms/secp256k1fx/transfer_input_test.go index e7fff8782f36..af22ecc090c7 100644 --- a/vms/secp256k1fx/transfer_input_test.go +++ b/vms/secp256k1fx/transfer_input_test.go @@ -60,7 +60,7 @@ func TestTransferInputVerifyDuplicated(t *testing.T) { SigIndices: []uint32{0, 0}, }, } - require.ErrorIs(in.Verify(), ErrNotSortedUnique) + require.ErrorIs(in.Verify(), ErrInputIndicesNotSortedUnique) } func TestTransferInputVerifyUnsorted(t *testing.T) { @@ -71,7 +71,7 @@ func TestTransferInputVerifyUnsorted(t *testing.T) { SigIndices: []uint32{1, 0}, }, } - require.ErrorIs(in.Verify(), ErrNotSortedUnique) + require.ErrorIs(in.Verify(), ErrInputIndicesNotSortedUnique) } func TestTransferInputSerialize(t *testing.T) { From 4881b8c89da678a99d5eb4638f50635f9cf0a447 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 17:48:02 -0400 Subject: [PATCH 54/77] fix add permissionless delegator tx tests --- .../add_permissionless_delegator_tx_test.go | 121 +++++++++--------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/vms/platformvm/txs/add_permissionless_delegator_tx_test.go b/vms/platformvm/txs/add_permissionless_delegator_tx_test.go index 2502cdeaac92..347ec2ab902c 100644 --- a/vms/platformvm/txs/add_permissionless_delegator_tx_test.go +++ b/vms/platformvm/txs/add_permissionless_delegator_tx_test.go @@ -5,9 +5,10 @@ package txs import ( "errors" - "math" "testing" + stdmath "math" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" @@ -15,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/secp256k1fx" @@ -82,6 +84,28 @@ func TestAddPermissionlessDelegatorTxSyntacticVerify(t *testing.T) { }, err: errNoStake, }, + { + name: "invalid BaseTx", + txFunc: func(*gomock.Controller) *AddPermissionlessDelegatorTx { + return &AddPermissionlessDelegatorTx{ + BaseTx: invalidBaseTx, + Validator: Validator{ + NodeID: ids.GenerateTestNodeID(), + }, + StakeOuts: []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: ids.GenerateTestID(), + }, + Out: &secp256k1fx.TransferOutput{ + Amt: 1, + }, + }, + }, + } + }, + err: avax.ErrWrongNetworkID, + }, { name: "invalid rewards owner", txFunc: func(ctrl *gomock.Controller) *AddPermissionlessDelegatorTx { @@ -204,6 +228,42 @@ func TestAddPermissionlessDelegatorTxSyntacticVerify(t *testing.T) { }, err: errOutputsNotSorted, }, + { + name: "stake overflow", + txFunc: func(ctrl *gomock.Controller) *AddPermissionlessDelegatorTx { + rewardsOwner := fx.NewMockOwner(ctrl) + rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() + assetID := ids.GenerateTestID() + return &AddPermissionlessDelegatorTx{ + BaseTx: validBaseTx, + Validator: Validator{ + NodeID: ids.GenerateTestNodeID(), + Wght: 1, + }, + Subnet: ids.GenerateTestID(), + StakeOuts: []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: assetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: stdmath.MaxUint64, + }, + }, + { + Asset: avax.Asset{ + ID: assetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: 2, + }, + }, + }, + DelegationRewardsOwner: rewardsOwner, + } + }, + err: math.ErrOverflow, + }, { name: "weight mismatch", txFunc: func(ctrl *gomock.Controller) *AddPermissionlessDelegatorTx { @@ -321,65 +381,6 @@ func TestAddPermissionlessDelegatorTxSyntacticVerify(t *testing.T) { require.ErrorIs(t, err, tt.err) }) } - - t.Run("invalid BaseTx", func(t *testing.T) { - tx := &AddPermissionlessDelegatorTx{ - BaseTx: invalidBaseTx, - Validator: Validator{ - NodeID: ids.GenerateTestNodeID(), - }, - StakeOuts: []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: ids.GenerateTestID(), - }, - Out: &secp256k1fx.TransferOutput{ - Amt: 1, - }, - }, - }, - } - err := tx.SyntacticVerify(ctx) - require.Error(t, err) - }) - - t.Run("stake overflow", func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - rewardsOwner := fx.NewMockOwner(ctrl) - rewardsOwner.EXPECT().Verify().Return(nil).AnyTimes() - assetID := ids.GenerateTestID() - tx := &AddPermissionlessDelegatorTx{ - BaseTx: validBaseTx, - Validator: Validator{ - NodeID: ids.GenerateTestNodeID(), - Wght: 1, - }, - Subnet: ids.GenerateTestID(), - StakeOuts: []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: assetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, - }, - }, - { - Asset: avax.Asset{ - ID: assetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: 2, - }, - }, - }, - DelegationRewardsOwner: rewardsOwner, - } - err := tx.SyntacticVerify(ctx) - require.Error(t, err) - }) } func TestAddPermissionlessDelegatorTxNotValidatorTx(t *testing.T) { From 9960baa7aaef9f3d3992ce185051bb016152e498 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 18:08:40 -0400 Subject: [PATCH 55/77] fix platformvm block acceptor tests --- vms/platformvm/blocks/executor/acceptor.go | 13 ++- .../blocks/executor/acceptor_test.go | 97 +++++++++++-------- 2 files changed, 64 insertions(+), 46 deletions(-) diff --git a/vms/platformvm/blocks/executor/acceptor.go b/vms/platformvm/blocks/executor/acceptor.go index 5aaa1d82d3fb..5eb98e19e591 100644 --- a/vms/platformvm/blocks/executor/acceptor.go +++ b/vms/platformvm/blocks/executor/acceptor.go @@ -4,6 +4,7 @@ package executor import ( + "errors" "fmt" "go.uber.org/zap" @@ -17,7 +18,11 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/state" ) -var _ blocks.Visitor = (*acceptor)(nil) +var ( + _ blocks.Visitor = (*acceptor)(nil) + + errMissingBlockState = errors.New("missing state of block") +) // acceptor handles the logic for accepting a block. // All errors returned by this struct are fatal and should result in the chain @@ -145,7 +150,7 @@ func (a *acceptor) ApricotAtomicBlock(b *blocks.ApricotAtomicBlock) error { blkState, ok := a.blkIDToState[blkID] if !ok { - return fmt.Errorf("couldn't find state of block %s", blkID) + return fmt.Errorf("%w %s", errMissingBlockState, blkID) } // Update the state to reflect the changes made in [onAcceptState]. @@ -233,7 +238,7 @@ func (a *acceptor) optionBlock(b, parent blocks.Block) error { blkState, ok := a.blkIDToState[blkID] if !ok { - return fmt.Errorf("couldn't find state of block %s", blkID) + return fmt.Errorf("%w %s", errMissingBlockState, blkID) } if err := blkState.onAcceptState.Apply(a.state); err != nil { return err @@ -271,7 +276,7 @@ func (a *acceptor) standardBlock(b blocks.Block) error { blkState, ok := a.blkIDToState[blkID] if !ok { - return fmt.Errorf("couldn't find state of block %s", blkID) + return fmt.Errorf("%w %s", errMissingBlockState, blkID) } // Update the state to reflect the changes made in [onAcceptState]. diff --git a/vms/platformvm/blocks/executor/acceptor_test.go b/vms/platformvm/blocks/executor/acceptor_test.go index 583e3ee6d962..3f382d248a26 100644 --- a/vms/platformvm/blocks/executor/acceptor_test.go +++ b/vms/platformvm/blocks/executor/acceptor_test.go @@ -126,7 +126,7 @@ func TestAcceptorVisitAtomicBlock(t *testing.T) { s.EXPECT().AddStatelessBlock(blk, choices.Accepted).Times(1) err = acceptor.ApricotAtomicBlock(blk) - require.Error(err, "should fail because the block isn't in the state map") + require.ErrorIs(err, errMissingBlockState) // Set [blk]'s state in the map as though it had been verified. onAcceptState := state.NewMockDiff(ctrl) @@ -214,7 +214,7 @@ func TestAcceptorVisitStandardBlock(t *testing.T) { s.EXPECT().AddStatelessBlock(blk, choices.Accepted).Times(1) err = acceptor.BanffStandardBlock(blk) - require.Error(err, "should fail because the block isn't in the state map") + require.ErrorIs(err, errMissingBlockState) // Set [blk]'s state in the map as though it had been verified. onAcceptState := state.NewMockDiff(ctrl) @@ -290,28 +290,9 @@ func TestAcceptorVisitCommitBlock(t *testing.T) { blk, err := blocks.NewApricotCommitBlock(parentID, 1 /*height*/) require.NoError(err) - blkID := blk.ID() err = acceptor.ApricotCommitBlock(blk) - require.Error(err, "should fail because the block isn't in the state map") + require.ErrorIs(err, state.ErrMissingParentState) - // Set [blk]'s state in the map as though it had been verified. - onAcceptState := state.NewMockDiff(ctrl) - childID := ids.GenerateTestID() - acceptor.backend.blkIDToState[blkID] = &blockState{ - onAcceptState: onAcceptState, - } - // Give [blk] a child. - childOnAcceptState := state.NewMockDiff(ctrl) - childOnAbortState := state.NewMockDiff(ctrl) - childOnCommitState := state.NewMockDiff(ctrl) - childState := &blockState{ - onAcceptState: childOnAcceptState, - proposalBlockState: proposalBlockState{ - onAbortState: childOnAbortState, - onCommitState: childOnCommitState, - }, - } - acceptor.backend.blkIDToState[childID] = childState // Set [blk]'s parent in the state map. parentOnAcceptState := state.NewMockDiff(ctrl) parentOnAbortState := state.NewMockDiff(ctrl) @@ -327,6 +308,31 @@ func TestAcceptorVisitCommitBlock(t *testing.T) { } acceptor.backend.blkIDToState[parentID] = parentState + blkID := blk.ID() + // Set expected calls on dependencies. + // Make sure the parent is accepted first. + gomock.InOrder( + parentStatelessBlk.EXPECT().ID().Return(parentID).Times(2), + s.EXPECT().SetLastAccepted(parentID).Times(1), + parentStatelessBlk.EXPECT().Height().Return(blk.Height()-1).Times(1), + s.EXPECT().SetHeight(blk.Height()-1).Times(1), + s.EXPECT().AddStatelessBlock(parentState.statelessBlock, choices.Accepted).Times(1), + + s.EXPECT().SetLastAccepted(blkID).Times(1), + s.EXPECT().SetHeight(blk.Height()).Times(1), + s.EXPECT().AddStatelessBlock(blk, choices.Accepted).Times(1), + ) + + err = acceptor.ApricotCommitBlock(blk) + require.ErrorIs(err, errMissingBlockState) + + // Set [blk]'s state in the map as though it had been verified. + acceptor.backend.blkIDToState[parentID] = parentState + onAcceptState := state.NewMockDiff(ctrl) + acceptor.backend.blkIDToState[blkID] = &blockState{ + onAcceptState: onAcceptState, + } + // Set expected calls on dependencies. // Make sure the parent is accepted first. gomock.InOrder( @@ -380,28 +386,9 @@ func TestAcceptorVisitAbortBlock(t *testing.T) { blk, err := blocks.NewApricotAbortBlock(parentID, 1 /*height*/) require.NoError(err) - blkID := blk.ID() err = acceptor.ApricotAbortBlock(blk) - require.Error(err, "should fail because the block isn't in the state map") + require.ErrorIs(err, state.ErrMissingParentState) - // Set [blk]'s state in the map as though it had been verified. - onAcceptState := state.NewMockDiff(ctrl) - childID := ids.GenerateTestID() - acceptor.backend.blkIDToState[blkID] = &blockState{ - onAcceptState: onAcceptState, - } - // Give [blk] a child. - childOnAcceptState := state.NewMockDiff(ctrl) - childOnAbortState := state.NewMockDiff(ctrl) - childOnCommitState := state.NewMockDiff(ctrl) - childState := &blockState{ - onAcceptState: childOnAcceptState, - proposalBlockState: proposalBlockState{ - onAbortState: childOnAbortState, - onCommitState: childOnCommitState, - }, - } - acceptor.backend.blkIDToState[childID] = childState // Set [blk]'s parent in the state map. parentOnAcceptState := state.NewMockDiff(ctrl) parentOnAbortState := state.NewMockDiff(ctrl) @@ -417,6 +404,32 @@ func TestAcceptorVisitAbortBlock(t *testing.T) { } acceptor.backend.blkIDToState[parentID] = parentState + blkID := blk.ID() + // Set expected calls on dependencies. + // Make sure the parent is accepted first. + gomock.InOrder( + parentStatelessBlk.EXPECT().ID().Return(parentID).Times(2), + s.EXPECT().SetLastAccepted(parentID).Times(1), + parentStatelessBlk.EXPECT().Height().Return(blk.Height()-1).Times(1), + s.EXPECT().SetHeight(blk.Height()-1).Times(1), + s.EXPECT().AddStatelessBlock(parentState.statelessBlock, choices.Accepted).Times(1), + + s.EXPECT().SetLastAccepted(blkID).Times(1), + s.EXPECT().SetHeight(blk.Height()).Times(1), + s.EXPECT().AddStatelessBlock(blk, choices.Accepted).Times(1), + ) + + err = acceptor.ApricotAbortBlock(blk) + require.ErrorIs(err, errMissingBlockState) + + // Set [blk]'s state in the map as though it had been verified. + acceptor.backend.blkIDToState[parentID] = parentState + + onAcceptState := state.NewMockDiff(ctrl) + acceptor.backend.blkIDToState[blkID] = &blockState{ + onAcceptState: onAcceptState, + } + // Set expected calls on dependencies. // Make sure the parent is accepted first. gomock.InOrder( From 2c7d173ededfa0831d8db0be786649b401e6d939 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 18:21:58 -0400 Subject: [PATCH 56/77] fix platformvm regression tests --- .../txs/executor/proposal_tx_executor.go | 2 +- .../txs/executor/staker_tx_verification.go | 134 +++++++++--------- .../executor/staker_tx_verification_test.go | 28 ++-- .../txs/executor/standard_tx_executor_test.go | 34 ++--- vms/platformvm/txs/executor/state_changes.go | 2 +- .../txs/executor/tx_mempool_verifier.go | 2 +- vms/platformvm/vm_regression_test.go | 55 +++---- 7 files changed, 124 insertions(+), 133 deletions(-) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index cd523be70313..efdb325f6b00 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -629,7 +629,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error } transformSubnet, ok := transformSubnetIntf.Unsigned.(*txs.TransformSubnetTx) if !ok { - return errIsNotTransformSubnetTx + return ErrIsNotTransformSubnetTx } expectedUptimePercentage = float64(transformSubnet.UptimeRequirement) / reward.PercentDenominator diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index f9c81749eba4..dd13c8834c65 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -20,24 +20,24 @@ import ( ) var ( - errWeightTooSmall = errors.New("weight of this validator is too low") - errWeightTooLarge = errors.New("weight of this validator is too large") - errInsufficientDelegationFee = errors.New("staker charges an insufficient delegation fee") - errStakeTooShort = errors.New("staking period is too short") - errStakeTooLong = errors.New("staking period is too long") - errFlowCheckFailed = errors.New("flow check failed") - errFutureStakeTime = fmt.Errorf("staker is attempting to start staking more than %s ahead of the current chain time", MaxFutureStartTime) - errValidatorSubset = errors.New("all subnets' staking period must be a subset of the primary network") - errNotValidator = errors.New("isn't a current or pending validator") - errRemovePermissionlessValidator = errors.New("attempting to remove permissionless validator") - errStakeOverflow = errors.New("validator stake exceeds limit") - errOverDelegated = errors.New("validator would be over delegated") - errIsNotTransformSubnetTx = errors.New("is not a transform subnet tx") - errTimestampNotBeforeStartTime = errors.New("chain timestamp not before start time") - errAlreadyValidator = errors.New("already a validator") - errDuplicateValidator = errors.New("duplicate validator") - errDelegateToPermissionedValidator = errors.New("delegation to permissioned validator") - errWrongStakedAssetID = errors.New("incorrect staked assetID") + ErrWeightTooSmall = errors.New("weight of this validator is too low") + ErrWeightTooLarge = errors.New("weight of this validator is too large") + ErrInsufficientDelegationFee = errors.New("staker charges an insufficient delegation fee") + ErrStakeTooShort = errors.New("staking period is too short") + ErrStakeTooLong = errors.New("staking period is too long") + ErrFlowCheckFailed = errors.New("flow check failed") + ErrFutureStakeTime = fmt.Errorf("staker is attempting to start staking more than %s ahead of the current chain time", MaxFutureStartTime) + ErrValidatorSubset = errors.New("all subnets' staking period must be a subset of the primary network") + ErrNotValidator = errors.New("isn't a current or pending validator") + ErrRemovePermissionlessValidator = errors.New("attempting to remove permissionless validator") + ErrStakeOverflow = errors.New("validator stake exceeds limit") + ErrOverDelegated = errors.New("validator would be over delegated") + ErrIsNotTransformSubnetTx = errors.New("is not a transform subnet tx") + ErrTimestampNotBeforeStartTime = errors.New("chain timestamp not before start time") + ErrAlreadyValidator = errors.New("already a validator") + ErrDuplicateValidator = errors.New("duplicate validator") + ErrDelegateToPermissionedValidator = errors.New("delegation to permissioned validator") + ErrWrongStakedAssetID = errors.New("incorrect staked assetID") ) // verifyAddValidatorTx carries out the validation for an AddValidatorTx. @@ -62,23 +62,23 @@ func verifyAddValidatorTx( switch { case tx.Validator.Wght < backend.Config.MinValidatorStake: // Ensure validator is staking at least the minimum amount - return nil, errWeightTooSmall + return nil, ErrWeightTooSmall case tx.Validator.Wght > backend.Config.MaxValidatorStake: // Ensure validator isn't staking too much - return nil, errWeightTooLarge + return nil, ErrWeightTooLarge case tx.DelegationShares < backend.Config.MinDelegationFee: // Ensure the validator fee is at least the minimum amount - return nil, errInsufficientDelegationFee + return nil, ErrInsufficientDelegationFee case duration < backend.Config.MinStakeDuration: // Ensure staking length is not too short - return nil, errStakeTooShort + return nil, ErrStakeTooShort case duration > backend.Config.MaxStakeDuration: // Ensure staking length is not too long - return nil, errStakeTooLong + return nil, ErrStakeTooLong } outs := make([]*avax.TransferableOutput, len(tx.Outs)+len(tx.StakeOuts)) @@ -95,7 +95,7 @@ func verifyAddValidatorTx( if !currentTimestamp.Before(startTime) { return nil, fmt.Errorf( "%w: %s >= %s", - errTimestampNotBeforeStartTime, + ErrTimestampNotBeforeStartTime, currentTimestamp, startTime, ) @@ -106,7 +106,7 @@ func verifyAddValidatorTx( return nil, fmt.Errorf( "%s is %w of the primary network", tx.Validator.NodeID, - errAlreadyValidator, + ErrAlreadyValidator, ) } if err != database.ErrNotFound { @@ -128,14 +128,14 @@ func verifyAddValidatorTx( backend.Ctx.AVAXAssetID: backend.Config.AddPrimaryNetworkValidatorFee, }, ); err != nil { - return nil, fmt.Errorf("%w: %v", errFlowCheckFailed, err) + return nil, fmt.Errorf("%w: %v", ErrFlowCheckFailed, err) } // Make sure the tx doesn't start too far in the future. This is done last // to allow the verifier visitor to explicitly check for this error. maxStartTime := currentTimestamp.Add(MaxFutureStartTime) if startTime.After(maxStartTime) { - return nil, errFutureStakeTime + return nil, ErrFutureStakeTime } return outs, nil @@ -158,11 +158,11 @@ func verifyAddSubnetValidatorTx( switch { case duration < backend.Config.MinStakeDuration: // Ensure staking length is not too short - return errStakeTooShort + return ErrStakeTooShort case duration > backend.Config.MaxStakeDuration: // Ensure staking length is not too long - return errStakeTooLong + return ErrStakeTooLong } if !backend.Bootstrapped.Get() { @@ -175,7 +175,7 @@ func verifyAddSubnetValidatorTx( if !currentTimestamp.Before(validatorStartTime) { return fmt.Errorf( "%w: %s >= %s", - errTimestampNotBeforeStartTime, + ErrTimestampNotBeforeStartTime, currentTimestamp, validatorStartTime, ) @@ -185,7 +185,7 @@ func verifyAddSubnetValidatorTx( if err == nil { return fmt.Errorf( "attempted to issue %w for %s on subnet %s", - errDuplicateValidator, + ErrDuplicateValidator, tx.Validator.NodeID, tx.SubnetValidator.Subnet, ) @@ -203,7 +203,7 @@ func verifyAddSubnetValidatorTx( return fmt.Errorf( "%s %w of the primary network", tx.Validator.NodeID, - errNotValidator, + ErrNotValidator, ) } if err != nil { @@ -217,7 +217,7 @@ func verifyAddSubnetValidatorTx( // Ensure that the period this validator validates the specified subnet // is a subset of the time they validate the primary network. if !tx.Validator.BoundedBy(primaryNetworkValidator.StartTime, primaryNetworkValidator.EndTime) { - return errValidatorSubset + return ErrValidatorSubset } baseTxCreds, err := verifyPoASubnetAuthorization(backend, chainState, sTx, tx.SubnetValidator.Subnet, tx.SubnetAuth) @@ -236,14 +236,14 @@ func verifyAddSubnetValidatorTx( backend.Ctx.AVAXAssetID: backend.Config.AddSubnetValidatorFee, }, ); err != nil { - return fmt.Errorf("%w: %v", errFlowCheckFailed, err) + return fmt.Errorf("%w: %v", ErrFlowCheckFailed, err) } // Make sure the tx doesn't start too far in the future. This is done last // to allow the verifier visitor to explicitly check for this error. maxStartTime := currentTimestamp.Add(MaxFutureStartTime) if validatorStartTime.After(maxStartTime) { - return errFutureStakeTime + return ErrFutureStakeTime } return nil @@ -279,14 +279,14 @@ func removeSubnetValidatorValidation( return nil, false, fmt.Errorf( "%s %w of %s: %v", tx.NodeID, - errNotValidator, + ErrNotValidator, tx.Subnet, err, ) } if !vdr.Priority.IsPermissionedValidator() { - return nil, false, errRemovePermissionlessValidator + return nil, false, ErrRemovePermissionlessValidator } if !backend.Bootstrapped.Get() { @@ -310,7 +310,7 @@ func removeSubnetValidatorValidation( backend.Ctx.AVAXAssetID: backend.Config.TxFee, }, ); err != nil { - return nil, false, fmt.Errorf("%w: %v", errFlowCheckFailed, err) + return nil, false, fmt.Errorf("%w: %v", ErrFlowCheckFailed, err) } return vdr, isCurrentValidator, nil @@ -337,15 +337,15 @@ func verifyAddDelegatorTx( switch { case duration < backend.Config.MinStakeDuration: // Ensure staking length is not too short - return nil, errStakeTooShort + return nil, ErrStakeTooShort case duration > backend.Config.MaxStakeDuration: // Ensure staking length is not too long - return nil, errStakeTooLong + return nil, ErrStakeTooLong case tx.Validator.Wght < backend.Config.MinDelegatorStake: // Ensure validator is staking at least the minimum amount - return nil, errWeightTooSmall + return nil, ErrWeightTooSmall } outs := make([]*avax.TransferableOutput, len(tx.Outs)+len(tx.StakeOuts)) @@ -362,7 +362,7 @@ func verifyAddDelegatorTx( if !currentTimestamp.Before(validatorStartTime) { return nil, fmt.Errorf( "%w: %s >= %s", - errTimestampNotBeforeStartTime, + ErrTimestampNotBeforeStartTime, currentTimestamp, validatorStartTime, ) @@ -379,7 +379,7 @@ func verifyAddDelegatorTx( maximumWeight, err := math.Mul64(MaxValidatorWeightFactor, primaryNetworkValidator.Weight) if err != nil { - return nil, errStakeOverflow + return nil, ErrStakeOverflow } if backend.Config.IsApricotPhase3Activated(currentTimestamp) { @@ -397,7 +397,7 @@ func verifyAddDelegatorTx( return nil, err } if !canDelegate { - return nil, errOverDelegated + return nil, ErrOverDelegated } // Verify the flowcheck @@ -411,14 +411,14 @@ func verifyAddDelegatorTx( backend.Ctx.AVAXAssetID: backend.Config.AddPrimaryNetworkDelegatorFee, }, ); err != nil { - return nil, fmt.Errorf("%w: %v", errFlowCheckFailed, err) + return nil, fmt.Errorf("%w: %v", ErrFlowCheckFailed, err) } // Make sure the tx doesn't start too far in the future. This is done last // to allow the verifier visitor to explicitly check for this error. maxStartTime := currentTimestamp.Add(MaxFutureStartTime) if validatorStartTime.After(maxStartTime) { - return nil, errFutureStakeTime + return nil, ErrFutureStakeTime } return outs, nil @@ -447,7 +447,7 @@ func verifyAddPermissionlessValidatorTx( if !currentTimestamp.Before(startTime) { return fmt.Errorf( "%w: %s >= %s", - errTimestampNotBeforeStartTime, + ErrTimestampNotBeforeStartTime, currentTimestamp, startTime, ) @@ -463,29 +463,29 @@ func verifyAddPermissionlessValidatorTx( switch { case tx.Validator.Wght < validatorRules.minValidatorStake: // Ensure validator is staking at least the minimum amount - return errWeightTooSmall + return ErrWeightTooSmall case tx.Validator.Wght > validatorRules.maxValidatorStake: // Ensure validator isn't staking too much - return errWeightTooLarge + return ErrWeightTooLarge case tx.DelegationShares < validatorRules.minDelegationFee: // Ensure the validator fee is at least the minimum amount - return errInsufficientDelegationFee + return ErrInsufficientDelegationFee case duration < validatorRules.minStakeDuration: // Ensure staking length is not too short - return errStakeTooShort + return ErrStakeTooShort case duration > validatorRules.maxStakeDuration: // Ensure staking length is not too long - return errStakeTooLong + return ErrStakeTooLong case stakedAssetID != validatorRules.assetID: // Wrong assetID used return fmt.Errorf( "%w: %s != %s", - errWrongStakedAssetID, + ErrWrongStakedAssetID, validatorRules.assetID, stakedAssetID, ) @@ -495,7 +495,7 @@ func verifyAddPermissionlessValidatorTx( if err == nil { return fmt.Errorf( "%w: %s on %s", - errDuplicateValidator, + ErrDuplicateValidator, tx.Validator.NodeID, tx.Subnet, ) @@ -523,7 +523,7 @@ func verifyAddPermissionlessValidatorTx( // Ensure that the period this validator validates the specified subnet // is a subset of the time they validate the primary network. if !tx.Validator.BoundedBy(primaryNetworkValidator.StartTime, primaryNetworkValidator.EndTime) { - return errValidatorSubset + return ErrValidatorSubset } txFee = backend.Config.AddSubnetValidatorFee @@ -546,14 +546,14 @@ func verifyAddPermissionlessValidatorTx( backend.Ctx.AVAXAssetID: txFee, }, ); err != nil { - return fmt.Errorf("%w: %v", errFlowCheckFailed, err) + return fmt.Errorf("%w: %v", ErrFlowCheckFailed, err) } // Make sure the tx doesn't start too far in the future. This is done last // to allow the verifier visitor to explicitly check for this error. maxStartTime := currentTimestamp.Add(MaxFutureStartTime) if startTime.After(maxStartTime) { - return errFutureStakeTime + return ErrFutureStakeTime } return nil @@ -590,7 +590,7 @@ func getValidatorRules( } transformSubnet, ok := transformSubnetIntf.Unsigned.(*txs.TransformSubnetTx) if !ok { - return nil, errIsNotTransformSubnetTx + return nil, ErrIsNotTransformSubnetTx } return &addValidatorRules{ @@ -641,21 +641,21 @@ func verifyAddPermissionlessDelegatorTx( switch { case tx.Validator.Wght < delegatorRules.minDelegatorStake: // Ensure delegator is staking at least the minimum amount - return errWeightTooSmall + return ErrWeightTooSmall case duration < delegatorRules.minStakeDuration: // Ensure staking length is not too short - return errStakeTooShort + return ErrStakeTooShort case duration > delegatorRules.maxStakeDuration: // Ensure staking length is not too long - return errStakeTooLong + return ErrStakeTooLong case stakedAssetID != delegatorRules.assetID: // Wrong assetID used return fmt.Errorf( "%w: %s != %s", - errWrongStakedAssetID, + ErrWrongStakedAssetID, delegatorRules.assetID, stakedAssetID, ) @@ -691,7 +691,7 @@ func verifyAddPermissionlessDelegatorTx( return err } if !canDelegate { - return errOverDelegated + return ErrOverDelegated } outs := make([]*avax.TransferableOutput, len(tx.Outs)+len(tx.StakeOuts)) @@ -707,7 +707,7 @@ func verifyAddPermissionlessDelegatorTx( // permissioned validator, so we verify this delegator is // pointing to a permissionless validator. if validator.Priority.IsPermissionedValidator() { - return errDelegateToPermissionedValidator + return ErrDelegateToPermissionedValidator } txFee = backend.Config.AddSubnetDelegatorFee @@ -726,14 +726,14 @@ func verifyAddPermissionlessDelegatorTx( backend.Ctx.AVAXAssetID: txFee, }, ); err != nil { - return fmt.Errorf("%w: %v", errFlowCheckFailed, err) + return fmt.Errorf("%w: %v", ErrFlowCheckFailed, err) } // Make sure the tx doesn't start too far in the future. This is done last // to allow the verifier visitor to explicitly check for this error. maxStartTime := currentTimestamp.Add(MaxFutureStartTime) if startTime.After(maxStartTime) { - return errFutureStakeTime + return ErrFutureStakeTime } return nil @@ -770,7 +770,7 @@ func getDelegatorRules( } transformSubnet, ok := transformSubnetIntf.Unsigned.(*txs.TransformSubnetTx) if !ok { - return nil, errIsNotTransformSubnetTx + return nil, ErrIsNotTransformSubnetTx } return &addDelegatorRules{ diff --git a/vms/platformvm/txs/executor/staker_tx_verification_test.go b/vms/platformvm/txs/executor/staker_tx_verification_test.go index c39a69b12c27..2f32fee48c15 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification_test.go +++ b/vms/platformvm/txs/executor/staker_tx_verification_test.go @@ -152,7 +152,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { txF: func() *txs.AddPermissionlessValidatorTx { return &verifiedTx }, - expectedErr: errTimestampNotBeforeStartTime, + expectedErr: ErrTimestampNotBeforeStartTime, }, { name: "weight too low", @@ -178,7 +178,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { tx.Validator.Wght = unsignedTransformTx.MinValidatorStake - 1 return &tx }, - expectedErr: errWeightTooSmall, + expectedErr: ErrWeightTooSmall, }, { name: "weight too high", @@ -204,7 +204,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { tx.Validator.Wght = unsignedTransformTx.MaxValidatorStake + 1 return &tx }, - expectedErr: errWeightTooLarge, + expectedErr: ErrWeightTooLarge, }, { name: "insufficient delegation fee", @@ -231,7 +231,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { tx.DelegationShares = unsignedTransformTx.MinDelegationFee - 1 return &tx }, - expectedErr: errInsufficientDelegationFee, + expectedErr: ErrInsufficientDelegationFee, }, { name: "duration too short", @@ -261,7 +261,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { tx.Validator.End = uint64(unsignedTransformTx.MinStakeDuration) return &tx }, - expectedErr: errStakeTooShort, + expectedErr: ErrStakeTooShort, }, { name: "duration too long", @@ -291,7 +291,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { tx.Validator.End = 2 + uint64(unsignedTransformTx.MaxStakeDuration) return &tx }, - expectedErr: errStakeTooLong, + expectedErr: ErrStakeTooLong, }, { name: "wrong assetID", @@ -323,7 +323,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { } return &tx }, - expectedErr: errWrongStakedAssetID, + expectedErr: ErrWrongStakedAssetID, }, { name: "duplicate validator", @@ -349,7 +349,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { txF: func() *txs.AddPermissionlessValidatorTx { return &verifiedTx }, - expectedErr: errDuplicateValidator, + expectedErr: ErrDuplicateValidator, }, { name: "validator not subset of primary network validator", @@ -381,7 +381,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { txF: func() *txs.AddPermissionlessValidatorTx { return &verifiedTx }, - expectedErr: errValidatorSubset, + expectedErr: ErrValidatorSubset, }, { name: "flow check fails", @@ -397,7 +397,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { gomock.Any(), gomock.Any(), gomock.Any(), - ).Return(errFlowCheckFailed) + ).Return(ErrFlowCheckFailed) return &Backend{ FlowChecker: flowChecker, @@ -427,7 +427,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { txF: func() *txs.AddPermissionlessValidatorTx { return &verifiedTx }, - expectedErr: errFlowCheckFailed, + expectedErr: ErrFlowCheckFailed, }, { name: "starts too far in the future", @@ -477,7 +477,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { tx.Validator.End = tx.Validator.Start + uint64(unsignedTransformTx.MinStakeDuration) return &tx }, - expectedErr: errFutureStakeTime, + expectedErr: ErrFutureStakeTime, }, { name: "success", @@ -615,7 +615,7 @@ func TestGetValidatorRules(t *testing.T) { return state }, expectedRules: &addValidatorRules{}, - expectedErr: errIsNotTransformSubnetTx, + expectedErr: ErrIsNotTransformSubnetTx, }, { name: "subnet", @@ -733,7 +733,7 @@ func TestGetDelegatorRules(t *testing.T) { return state }, expectedRules: &addDelegatorRules{}, - expectedErr: errIsNotTransformSubnetTx, + expectedErr: ErrIsNotTransformSubnetTx, }, { name: "subnet", diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 17c6e5220246..c28112923494 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -420,7 +420,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errValidatorSubset) + require.ErrorIs(err, ErrValidatorSubset) } { @@ -495,7 +495,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errNotValidator) + require.ErrorIs(err, ErrNotValidator) } staker, err := state.NewCurrentStaker( @@ -537,7 +537,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errValidatorSubset) + require.ErrorIs(err, ErrValidatorSubset) } { @@ -563,7 +563,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errValidatorSubset) + require.ErrorIs(err, ErrValidatorSubset) } { @@ -617,7 +617,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errTimestampNotBeforeStartTime) + require.ErrorIs(err, ErrTimestampNotBeforeStartTime) } // reset the timestamp @@ -672,7 +672,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: duplicateSubnetTx, } err = duplicateSubnetTx.Unsigned.Visit(&executor) - require.ErrorIs(err, errDuplicateValidator) + require.ErrorIs(err, ErrDuplicateValidator) } env.state.DeleteCurrentValidator(staker) @@ -814,7 +814,7 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errDuplicateValidator) + require.ErrorIs(err, ErrDuplicateValidator) } } @@ -853,7 +853,7 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errTimestampNotBeforeStartTime) + require.ErrorIs(err, ErrTimestampNotBeforeStartTime) } { @@ -879,7 +879,7 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errFutureStakeTime) + require.ErrorIs(err, ErrFutureStakeTime) } { @@ -916,7 +916,7 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errAlreadyValidator) + require.ErrorIs(err, ErrAlreadyValidator) } { @@ -952,7 +952,7 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errAlreadyValidator) + require.ErrorIs(err, ErrAlreadyValidator) } { @@ -987,7 +987,7 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errFlowCheckFailed) + require.ErrorIs(err, ErrFlowCheckFailed) } } @@ -1183,7 +1183,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - expectedErr: errNotValidator, + expectedErr: ErrNotValidator, }, { name: "validator is permissionless", @@ -1211,7 +1211,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - expectedErr: errRemovePermissionlessValidator, + expectedErr: ErrRemovePermissionlessValidator, }, { name: "tx has no credentials", @@ -1329,7 +1329,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - expectedErr: errFlowCheckFailed, + expectedErr: ErrFlowCheckFailed, }, } @@ -1553,7 +1553,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { env.fx.EXPECT().VerifyPermission(gomock.Any(), env.unsignedTx.SubnetAuth, env.tx.Creds[len(env.tx.Creds)-1], subnetOwner).Return(nil) env.flowChecker.EXPECT().VerifySpend( gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), - ).Return(errFlowCheckFailed) + ).Return(ErrFlowCheckFailed) e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ @@ -1571,7 +1571,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { e.Bootstrapped.Set(true) return env.unsignedTx, e }, - err: errFlowCheckFailed, + err: ErrFlowCheckFailed, }, { name: "valid tx", diff --git a/vms/platformvm/txs/executor/state_changes.go b/vms/platformvm/txs/executor/state_changes.go index ccf87bce6bbb..2f1cc034a635 100644 --- a/vms/platformvm/txs/executor/state_changes.go +++ b/vms/platformvm/txs/executor/state_changes.go @@ -223,7 +223,7 @@ func GetRewardsCalculator( } transformSubnet, ok := transformSubnetIntf.Unsigned.(*txs.TransformSubnetTx) if !ok { - return nil, errIsNotTransformSubnetTx + return nil, ErrIsNotTransformSubnetTx } return reward.NewCalculator(reward.Config{ diff --git a/vms/platformvm/txs/executor/tx_mempool_verifier.go b/vms/platformvm/txs/executor/tx_mempool_verifier.go index 71a1a61ebf26..934f7c366095 100644 --- a/vms/platformvm/txs/executor/tx_mempool_verifier.go +++ b/vms/platformvm/txs/executor/tx_mempool_verifier.go @@ -88,7 +88,7 @@ func (v *MempoolTxVerifier) standardTx(tx txs.UnsignedTx) error { err = tx.Visit(&executor) // We ignore [errFutureStakeTime] here because the time will be advanced // when this transaction is issued. - if errors.Is(err, errFutureStakeTime) { + if errors.Is(err, ErrFutureStakeTime) { return nil } return err diff --git a/vms/platformvm/vm_regression_test.go b/vms/platformvm/vm_regression_test.go index 73be1eebc026..b704f2baeaff 100644 --- a/vms/platformvm/vm_regression_test.go +++ b/vms/platformvm/vm_regression_test.go @@ -34,9 +34,8 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/reward" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - txexecutor "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor" ) func TestAddDelegatorTxOverDelegatedRegression(t *testing.T) { @@ -48,7 +47,7 @@ func TestAddDelegatorTxOverDelegatedRegression(t *testing.T) { vm.ctx.Lock.Unlock() }() - validatorStartTime := vm.clock.Time().Add(txexecutor.SyncBound).Add(1 * time.Second) + validatorStartTime := vm.clock.Time().Add(executor.SyncBound).Add(1 * time.Second) validatorEndTime := validatorStartTime.Add(360 * 24 * time.Hour) nodeID := ids.GenerateTestNodeID() @@ -84,7 +83,7 @@ func TestAddDelegatorTxOverDelegatedRegression(t *testing.T) { require.NoError(firstAdvanceTimeBlock.Accept(context.Background())) require.NoError(vm.SetPreference(context.Background(), vm.manager.LastAccepted())) - firstDelegatorStartTime := validatorStartTime.Add(txexecutor.SyncBound).Add(1 * time.Second) + firstDelegatorStartTime := validatorStartTime.Add(executor.SyncBound).Add(1 * time.Second) firstDelegatorEndTime := firstDelegatorStartTime.Add(vm.MinStakeDuration) // create valid tx @@ -119,7 +118,7 @@ func TestAddDelegatorTxOverDelegatedRegression(t *testing.T) { secondDelegatorStartTime := firstDelegatorEndTime.Add(2 * time.Second) secondDelegatorEndTime := secondDelegatorStartTime.Add(vm.MinStakeDuration) - vm.clock.Set(secondDelegatorStartTime.Add(-10 * txexecutor.SyncBound)) + vm.clock.Set(secondDelegatorStartTime.Add(-10 * executor.SyncBound)) // create valid tx addSecondDelegatorTx, err := vm.txBuilder.NewAddDelegatorTx( @@ -159,11 +158,11 @@ func TestAddDelegatorTxOverDelegatedRegression(t *testing.T) { // trigger block creation err = vm.Builder.AddUnverifiedTx(addThirdDelegatorTx) - require.Error(err, "should have marked the delegator as being over delegated") + require.ErrorIs(err, executor.ErrOverDelegated) } func TestAddDelegatorTxHeapCorruption(t *testing.T) { - validatorStartTime := banffForkTime.Add(txexecutor.SyncBound).Add(1 * time.Second) + validatorStartTime := banffForkTime.Add(executor.SyncBound).Add(1 * time.Second) validatorEndTime := validatorStartTime.Add(360 * 24 * time.Hour) validatorStake := defaultMaxValidatorStake / 5 @@ -184,19 +183,16 @@ func TestAddDelegatorTxHeapCorruption(t *testing.T) { delegator4Stake := defaultMaxValidatorStake - validatorStake - defaultMinValidatorStake tests := []struct { - name string - ap3Time time.Time - shouldFail bool + name string + ap3Time time.Time }{ { - name: "pre-upgrade is no longer restrictive", - ap3Time: validatorEndTime, - shouldFail: false, + name: "pre-upgrade is no longer restrictive", + ap3Time: validatorEndTime, }, { - name: "post-upgrade calculate max stake correctly", - ap3Time: defaultGenesisTime, - shouldFail: false, + name: "post-upgrade calculate max stake correctly", + ap3Time: defaultGenesisTime, }, } @@ -332,12 +328,6 @@ func TestAddDelegatorTxHeapCorruption(t *testing.T) { // trigger block creation for the fourth add delegator tx addFourthDelegatorBlock, err := vm.Builder.BuildBlock(context.Background()) - - if test.shouldFail { - require.Error(err, "should have failed to allow new delegator") - return - } - require.NoError(err) require.NoError(addFourthDelegatorBlock.Verify(context.Background())) require.NoError(addFourthDelegatorBlock.Accept(context.Background())) @@ -487,7 +477,7 @@ func TestRejectedStateRegressionInvalidValidatorTimestamp(t *testing.T) { vm.ctx.Lock.Unlock() }() - newValidatorStartTime := vm.clock.Time().Add(txexecutor.SyncBound).Add(1 * time.Second) + newValidatorStartTime := vm.clock.Time().Add(executor.SyncBound).Add(1 * time.Second) newValidatorEndTime := newValidatorStartTime.Add(defaultMinStakingDuration) key, err := testKeyFactory.NewPrivateKey() @@ -593,7 +583,7 @@ func TestRejectedStateRegressionInvalidValidatorTimestamp(t *testing.T) { // Because the shared memory UTXO hasn't been populated, this block is // currently invalid. err = importBlk.Verify(context.Background()) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) // Because we no longer ever reject a block in verification, the status // should remain as processing. @@ -711,7 +701,7 @@ func TestRejectedStateRegressionInvalidValidatorReward(t *testing.T) { vm.state.SetCurrentSupply(constants.PrimaryNetworkID, defaultRewardConfig.SupplyCap/2) - newValidatorStartTime0 := vm.clock.Time().Add(txexecutor.SyncBound).Add(1 * time.Second) + newValidatorStartTime0 := vm.clock.Time().Add(executor.SyncBound).Add(1 * time.Second) newValidatorEndTime0 := newValidatorStartTime0.Add(defaultMaxStakingDuration) nodeID0 := ids.NodeID(ids.GenerateTestShortID()) @@ -849,7 +839,7 @@ func TestRejectedStateRegressionInvalidValidatorReward(t *testing.T) { // Because the shared memory UTXO hasn't been populated, this block is // currently invalid. err = importBlk.Verify(context.Background()) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) // Because we no longer ever reject a block in verification, the status // should remain as processing. @@ -889,7 +879,7 @@ func TestRejectedStateRegressionInvalidValidatorReward(t *testing.T) { importBlkStatus = importBlk.Status() require.Equal(choices.Processing, importBlkStatus) - newValidatorStartTime1 := newValidatorStartTime0.Add(txexecutor.SyncBound).Add(1 * time.Second) + newValidatorStartTime1 := newValidatorStartTime0.Add(executor.SyncBound).Add(1 * time.Second) newValidatorEndTime1 := newValidatorStartTime1.Add(defaultMaxStakingDuration) nodeID1 := ids.NodeID(ids.GenerateTestShortID()) @@ -1059,7 +1049,7 @@ func TestValidatorSetAtCacheOverwriteRegression(t *testing.T) { require.Equal(weight, validators[nodeID].Weight) } - newValidatorStartTime0 := vm.clock.Time().Add(txexecutor.SyncBound).Add(1 * time.Second) + newValidatorStartTime0 := vm.clock.Time().Add(executor.SyncBound).Add(1 * time.Second) newValidatorEndTime0 := newValidatorStartTime0.Add(defaultMaxStakingDuration) nodeID5 := ids.GenerateTestNodeID() @@ -1162,7 +1152,7 @@ func TestValidatorSetAtCacheOverwriteRegression(t *testing.T) { func TestAddDelegatorTxAddBeforeRemove(t *testing.T) { require := require.New(t) - validatorStartTime := banffForkTime.Add(txexecutor.SyncBound).Add(1 * time.Second) + validatorStartTime := banffForkTime.Add(executor.SyncBound).Add(1 * time.Second) validatorEndTime := validatorStartTime.Add(360 * 24 * time.Hour) validatorStake := defaultMaxValidatorStake / 5 @@ -1251,13 +1241,14 @@ func TestAddDelegatorTxAddBeforeRemove(t *testing.T) { // attempting to issue the second add delegator tx should fail because the // total stake weight would go over the limit. - require.Error(vm.Builder.AddUnverifiedTx(addSecondDelegatorTx)) + err = vm.Builder.AddUnverifiedTx(addSecondDelegatorTx) + require.ErrorIs(err, executor.ErrOverDelegated) } func TestRemovePermissionedValidatorDuringPendingToCurrentTransitionNotTracked(t *testing.T) { require := require.New(t) - validatorStartTime := banffForkTime.Add(txexecutor.SyncBound).Add(1 * time.Second) + validatorStartTime := banffForkTime.Add(executor.SyncBound).Add(1 * time.Second) validatorEndTime := validatorStartTime.Add(360 * 24 * time.Hour) vm, _, _ := defaultVM() @@ -1379,7 +1370,7 @@ func TestRemovePermissionedValidatorDuringPendingToCurrentTransitionNotTracked(t func TestRemovePermissionedValidatorDuringPendingToCurrentTransitionTracked(t *testing.T) { require := require.New(t) - validatorStartTime := banffForkTime.Add(txexecutor.SyncBound).Add(1 * time.Second) + validatorStartTime := banffForkTime.Add(executor.SyncBound).Add(1 * time.Second) validatorEndTime := validatorStartTime.Add(360 * 24 * time.Hour) vm, _, _ := defaultVM() From 8422653e62885e9ed781c3e8e108b52cd0668f84 Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 18:41:21 -0400 Subject: [PATCH 57/77] fix platformvm vm tests --- vms/platformvm/blocks/builder/builder.go | 12 +++++----- vms/platformvm/blocks/builder/builder_test.go | 4 ++-- vms/platformvm/txs/builder/builder.go | 4 ++-- vms/platformvm/vm_test.go | 23 +++++++++---------- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/vms/platformvm/blocks/builder/builder.go b/vms/platformvm/blocks/builder/builder.go index 947fdf263368..1c93d9ec0e18 100644 --- a/vms/platformvm/blocks/builder/builder.go +++ b/vms/platformvm/blocks/builder/builder.go @@ -34,9 +34,9 @@ const targetBlockSize = 128 * units.KiB var ( _ Builder = (*builder)(nil) - errEndOfTime = errors.New("program time is suspiciously far in the future") - errNoPendingBlocks = errors.New("no pending blocks") - errChainNotSynced = errors.New("chain not synced") + ErrEndOfTime = errors.New("program time is suspiciously far in the future") + ErrNoPendingBlocks = errors.New("no pending blocks") + ErrChainNotSynced = errors.New("chain not synced") ) type Builder interface { @@ -126,7 +126,7 @@ func (b *builder) Preferred() (snowman.Block, error) { // AddUnverifiedTx verifies a transaction and attempts to add it to the mempool func (b *builder) AddUnverifiedTx(tx *txs.Tx) error { if !b.txExecutorBackend.Bootstrapped.Get() { - return errChainNotSynced + return ErrChainNotSynced } txID := tx.ID() @@ -369,7 +369,7 @@ func buildBlock( // If there is no reason to build a block, don't. if !builder.Mempool.HasTxs() && !forceAdvanceTime { builder.txExecutorBackend.Ctx.Log.Debug("no pending txs to issue into a block") - return nil, errNoPendingBlocks + return nil, ErrNoPendingBlocks } // Issue a block with as many transactions as possible. @@ -394,7 +394,7 @@ func getNextStakerToReward( preferredState state.Chain, ) (ids.ID, bool, error) { if !chainTimestamp.Before(mockable.MaxTime) { - return ids.Empty, false, errEndOfTime + return ids.Empty, false, ErrEndOfTime } currentStakerIterator, err := preferredState.GetCurrentStakerIterator() diff --git a/vms/platformvm/blocks/builder/builder_test.go b/vms/platformvm/blocks/builder/builder_test.go index f8193377362c..5eed4d56a3e5 100644 --- a/vms/platformvm/blocks/builder/builder_test.go +++ b/vms/platformvm/blocks/builder/builder_test.go @@ -138,7 +138,7 @@ func TestGetNextStakerToReward(t *testing.T) { stateF: func(ctrl *gomock.Controller) state.Chain { return state.NewMockChain(ctrl) }, - expectedErr: errEndOfTime, + expectedErr: ErrEndOfTime, }, { name: "no stakers", @@ -493,7 +493,7 @@ func TestBuildBlock(t *testing.T) { expectedBlkF: func(*require.Assertions) blocks.Block { return nil }, - expectedErr: errNoPendingBlocks, + expectedErr: ErrNoPendingBlocks, }, { name: "should advance time", diff --git a/vms/platformvm/txs/builder/builder.go b/vms/platformvm/txs/builder/builder.go index 19aa1e3763b8..279202087619 100644 --- a/vms/platformvm/txs/builder/builder.go +++ b/vms/platformvm/txs/builder/builder.go @@ -29,7 +29,7 @@ const MaxPageSize = 1024 var ( _ Builder = (*builder)(nil) - errNoFunds = errors.New("no spendable funds were found") + ErrNoFunds = errors.New("no spendable funds were found") ) type Builder interface { @@ -241,7 +241,7 @@ func (b *builder) NewImportTx( avax.SortTransferableInputsWithSigners(importedInputs, signers) if len(importedAmounts) == 0 { - return nil, errNoFunds // No imported UTXOs were spendable + return nil, ErrNoFunds // No imported UTXOs were spendable } importedAVAX := importedAmounts[b.ctx.AVAXAssetID] diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 3ec161044c32..5edd77938ba1 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -69,7 +69,9 @@ import ( smeng "github.com/ava-labs/avalanchego/snow/engine/snowman" snowgetter "github.com/ava-labs/avalanchego/snow/engine/snowman/getter" timetracker "github.com/ava-labs/avalanchego/snow/networking/tracker" + blockbuilder "github.com/ava-labs/avalanchego/vms/platformvm/blocks/builder" blockexecutor "github.com/ava-labs/avalanchego/vms/platformvm/blocks/executor" + txbuilder "github.com/ava-labs/avalanchego/vms/platformvm/txs/builder" txexecutor "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor" ) @@ -647,20 +649,17 @@ func TestInvalidAddValidatorCommit(t *testing.T) { ) require.NoError(err) - blk := vm.manager.NewBlock(statelessBlk) - require.NoError(err) - - blkBytes := blk.Bytes() + blkBytes := statelessBlk.Bytes() parsedBlock, err := vm.ParseBlock(context.Background(), blkBytes) require.NoError(err) err = parsedBlock.Verify(context.Background()) - require.Error(err) + require.ErrorIs(err, txexecutor.ErrTimestampNotBeforeStartTime) txID := statelessBlk.Txs()[0].ID() reason := vm.Builder.GetDropReason(txID) - require.Error(reason) + require.ErrorIs(reason, txexecutor.ErrTimestampNotBeforeStartTime) } // Reject attempt to add validator to primary network @@ -721,7 +720,7 @@ func TestAddValidatorInvalidNotReissued(t *testing.T) { // Use nodeID that is already in the genesis repeatNodeID := ids.NodeID(keys[0].PublicKey().Address()) - startTime := defaultGenesisTime.Add(txexecutor.SyncBound).Add(1 * time.Second) + startTime := banffForkTime.Add(txexecutor.SyncBound).Add(1 * time.Second) endTime := startTime.Add(defaultMinStakingDuration) // create valid tx @@ -739,7 +738,7 @@ func TestAddValidatorInvalidNotReissued(t *testing.T) { // trigger block creation err = vm.Builder.AddUnverifiedTx(tx) - require.Error(err, "should have erred due to adding a validator with a nodeID that is already in the validator set") + require.ErrorIs(err, txexecutor.ErrAlreadyValidator) } // Accept proposal to add validator to subnet @@ -1134,7 +1133,7 @@ func TestUnneededBuildBlock(t *testing.T) { vm.ctx.Lock.Unlock() }() _, err := vm.Builder.BuildBlock(context.Background()) - require.Error(err) + require.ErrorIs(err, blockbuilder.ErrNoPendingBlocks) } // test acceptance of proposal to create a new chain @@ -1332,7 +1331,7 @@ func TestAtomicImport(t *testing.T) { []*secp256k1.PrivateKey{keys[0]}, ids.ShortEmpty, // change addr ) - require.Error(err, "should have errored due to missing utxos") + require.ErrorIs(err, txbuilder.ErrNoFunds) // Provide the avm UTXO @@ -1443,13 +1442,13 @@ func TestOptimisticAtomicImport(t *testing.T) { blk := vm.manager.NewBlock(statelessBlk) err = blk.Verify(context.Background()) - require.Error(err, "should have erred due to missing UTXOs") + require.ErrorIs(err, database.ErrNotFound) // erred due to missing shared memory UTXOs err = vm.SetState(context.Background(), snow.Bootstrapping) require.NoError(err) err = blk.Verify(context.Background()) - require.NoError(err) + require.NoError(err) // skips shared memory UTXO verification during bootstrapping err = blk.Accept(context.Background()) require.NoError(err) From 9857a15063a51e4887ccde8feb56a5e4db425c8f Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 18:59:27 -0400 Subject: [PATCH 58/77] fix platformvm static service tests --- vms/platformvm/api/static_service.go | 11 +++++----- vms/platformvm/api/static_service_test.go | 25 ++++++++++------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/vms/platformvm/api/static_service.go b/vms/platformvm/api/static_service.go index 9067d6b87431..d06c2e757962 100644 --- a/vms/platformvm/api/static_service.go +++ b/vms/platformvm/api/static_service.go @@ -30,9 +30,10 @@ import ( // state of the network. var ( - errUTXOHasNoValue = errors.New("genesis UTXO has no value") - errValidatorAddsNoValue = errors.New("validator would have already unstaked") - errStakeOverflow = errors.New("validator stake exceeds limit") + errUTXOHasNoValue = errors.New("genesis UTXO has no value") + errValidatorHasNoWeight = errors.New("validator has not weight") + errValidatorAlreadyExited = errors.New("validator would have already unstaked") + errStakeOverflow = errors.New("validator stake exceeds limit") _ utils.Sortable[UTXO] = UTXO{} ) @@ -278,10 +279,10 @@ func (*StaticService) BuildGenesis(_ *http.Request, args *BuildGenesisArgs, repl } if weight == 0 { - return errValidatorAddsNoValue + return errValidatorHasNoWeight } if uint64(vdr.EndTime) <= uint64(args.Time) { - return errValidatorAddsNoValue + return errValidatorAlreadyExited } owner := &secp256k1fx.OutputOwners{ diff --git a/vms/platformvm/api/static_service_test.go b/vms/platformvm/api/static_service_test.go index e11c1a290620..7006d7e345a9 100644 --- a/vms/platformvm/api/static_service_test.go +++ b/vms/platformvm/api/static_service_test.go @@ -16,13 +16,10 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/genesis" ) -const testNetworkID = 10 // To be used in tests - func TestBuildGenesisInvalidUTXOBalance(t *testing.T) { require := require.New(t) nodeID := ids.NodeID{1, 2, 3} - hrp := constants.NetworkIDToHRP[testNetworkID] - addr, err := address.FormatBech32(hrp, nodeID.Bytes()) + addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes()) require.NoError(err) utxo := UTXO{ @@ -59,14 +56,14 @@ func TestBuildGenesisInvalidUTXOBalance(t *testing.T) { reply := BuildGenesisReply{} ss := StaticService{} - require.Error(ss.BuildGenesis(nil, &args, &reply), "should have errored due to an invalid balance") + err = ss.BuildGenesis(nil, &args, &reply) + require.ErrorIs(err, errUTXOHasNoValue) } -func TestBuildGenesisInvalidAmount(t *testing.T) { +func TestBuildGenesisInvalidStakeWeight(t *testing.T) { require := require.New(t) nodeID := ids.NodeID{1, 2, 3} - hrp := constants.NetworkIDToHRP[testNetworkID] - addr, err := address.FormatBech32(hrp, nodeID.Bytes()) + addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes()) require.NoError(err) utxo := UTXO{ @@ -103,14 +100,14 @@ func TestBuildGenesisInvalidAmount(t *testing.T) { reply := BuildGenesisReply{} ss := StaticService{} - require.Error(ss.BuildGenesis(nil, &args, &reply), "should have errored due to an invalid amount") + err = ss.BuildGenesis(nil, &args, &reply) + require.ErrorIs(err, errValidatorHasNoWeight) } func TestBuildGenesisInvalidEndtime(t *testing.T) { require := require.New(t) nodeID := ids.NodeID{1, 2, 3} - hrp := constants.NetworkIDToHRP[testNetworkID] - addr, err := address.FormatBech32(hrp, nodeID.Bytes()) + addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes()) require.NoError(err) utxo := UTXO{ @@ -148,14 +145,14 @@ func TestBuildGenesisInvalidEndtime(t *testing.T) { reply := BuildGenesisReply{} ss := StaticService{} - require.Error(ss.BuildGenesis(nil, &args, &reply), "should have errored due to an invalid end time") + err = ss.BuildGenesis(nil, &args, &reply) + require.ErrorIs(err, errValidatorAlreadyExited) } func TestBuildGenesisReturnsSortedValidators(t *testing.T) { require := require.New(t) nodeID := ids.NodeID{1} - hrp := constants.NetworkIDToHRP[testNetworkID] - addr, err := address.FormatBech32(hrp, nodeID.Bytes()) + addr, err := address.FormatBech32(constants.UnitTestHRP, nodeID.Bytes()) require.NoError(err) utxo := UTXO{ From 65778b04a38c0e2428dbc9fe7e112edb76f4b4fc Mon Sep 17 00:00:00 2001 From: Stephen Date: Wed, 19 Apr 2023 20:07:13 -0400 Subject: [PATCH 59/77] fix proposal block tests --- .../blocks/executor/proposal_block_test.go | 33 ++++++---- vms/platformvm/blocks/executor/verifier.go | 4 +- .../txs/executor/advance_time_test.go | 8 +-- .../txs/executor/atomic_tx_executor.go | 22 +++---- .../txs/executor/proposal_tx_executor.go | 62 +++++++++---------- .../txs/executor/reward_validator_test.go | 8 +-- .../txs/executor/standard_tx_executor.go | 4 +- vms/platformvm/txs/executor/state_changes.go | 8 +-- .../txs/executor/tx_mempool_verifier.go | 4 +- 9 files changed, 83 insertions(+), 70 deletions(-) diff --git a/vms/platformvm/blocks/executor/proposal_block_test.go b/vms/platformvm/blocks/executor/proposal_block_test.go index 3d1569ade0b0..32889928328e 100644 --- a/vms/platformvm/blocks/executor/proposal_block_test.go +++ b/vms/platformvm/blocks/executor/proposal_block_test.go @@ -127,7 +127,9 @@ func TestApricotProposalBlockTimeVerification(t *testing.T) { require.NoError(err) block := env.blkManager.NewBlock(statelessProposalBlock) - require.Error(block.Verify(context.Background())) + + err = block.Verify(context.Background()) + require.ErrorIs(err, errIncorrectBlockHeight) // valid statelessProposalBlock, err = blocks.NewApricotProposalBlock( @@ -262,11 +264,12 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { require.NoError(err) block := env.blkManager.NewBlock(statelessProposalBlock) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, errIncorrectBlockHeight) } { - // wrong version + // wrong block version statelessProposalBlock, err := blocks.NewApricotProposalBlock( parentID, banffParentBlk.Height()+1, @@ -275,7 +278,8 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { require.NoError(err) block := env.blkManager.NewBlock(statelessProposalBlock) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, errApricotBlockIssuedAfterFork) } { @@ -289,14 +293,16 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { require.NoError(err) block := env.blkManager.NewBlock(statelessProposalBlock) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, errChildBlockEarlierThanParent) } { // wrong timestamp, violated synchrony bound - beyondSyncBoundTimeStamp := env.clk.Time().Add(executor.SyncBound).Add(time.Second) + initClkTime := env.clk.Time() + env.clk.Set(parentTime.Add(-executor.SyncBound)) statelessProposalBlock, err := blocks.NewBanffProposalBlock( - beyondSyncBoundTimeStamp, + parentTime.Add(time.Second), parentID, banffParentBlk.Height()+1, blkTx, @@ -304,7 +310,9 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { require.NoError(err) block := env.blkManager.NewBlock(statelessProposalBlock) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, executor.ErrChildBlockBeyondSyncBound) + env.clk.Set(initClkTime) } { @@ -319,7 +327,8 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { require.NoError(err) block := env.blkManager.NewBlock(statelessProposalBlock) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, executor.ErrChildBlockAfterStakerChangeTime) } { @@ -339,7 +348,8 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { require.NoError(err) block := env.blkManager.NewBlock(statelessProposalBlock) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, executor.ErrAdvanceTimeTxIssuedAfterBanff) } { @@ -354,7 +364,8 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { statelessProposalBlock.Transactions = []*txs.Tx{blkTx} block := env.blkManager.NewBlock(statelessProposalBlock) - require.ErrorIs(block.Verify(context.Background()), errBanffProposalBlockWithMultipleTransactions) + err = block.Verify(context.Background()) + require.ErrorIs(err, errBanffProposalBlockWithMultipleTransactions) } { diff --git a/vms/platformvm/blocks/executor/verifier.go b/vms/platformvm/blocks/executor/verifier.go index 9f72b5092ba4..e73b90bc3c40 100644 --- a/vms/platformvm/blocks/executor/verifier.go +++ b/vms/platformvm/blocks/executor/verifier.go @@ -23,6 +23,7 @@ var ( errApricotBlockIssuedAfterFork = errors.New("apricot block issued after fork") errBanffProposalBlockWithMultipleTransactions = errors.New("BanffProposalBlock contains multiple transactions") errBanffStandardBlockWithoutChanges = errors.New("BanffStandardBlock performs no state changes") + errIncorrectBlockHeight = errors.New("incorrect block height") errChildBlockEarlierThanParent = errors.New("proposed timestamp before current chain time") errConflictingBatchTxs = errors.New("block contains conflicting transactions") errConflictingParentTxs = errors.New("block contains a transaction that conflicts with a transaction in a parent block") @@ -307,7 +308,8 @@ func (v *verifier) commonBlock(b blocks.Block) error { height := b.Height() if expectedHeight != height { return fmt.Errorf( - "expected block to have height %d, but found %d", + "%w expected %d, but found %d", + errIncorrectBlockHeight, expectedHeight, height, ) diff --git a/vms/platformvm/txs/executor/advance_time_test.go b/vms/platformvm/txs/executor/advance_time_test.go index 3fdf80fcb0c8..e58392add818 100644 --- a/vms/platformvm/txs/executor/advance_time_test.go +++ b/vms/platformvm/txs/executor/advance_time_test.go @@ -104,7 +104,7 @@ func TestAdvanceTimeTxTimestampTooEarly(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errChildBlockNotAfterParent) + require.ErrorIs(err, ErrChildBlockNotAfterParent) } // Ensure semantic verification fails when proposed timestamp is after next validator set change time @@ -138,7 +138,7 @@ func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errChildBlockAfterStakerChangeTime) + require.ErrorIs(err, ErrChildBlockAfterStakerChangeTime) } err = shutdownEnvironment(env) @@ -172,7 +172,7 @@ func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errChildBlockAfterStakerChangeTime) + require.ErrorIs(err, ErrChildBlockAfterStakerChangeTime) } } @@ -891,7 +891,7 @@ func TestAdvanceTimeTxAfterBanff(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, errAdvanceTimeTxIssuedAfterBanff) + require.ErrorIs(err, ErrAdvanceTimeTxIssuedAfterBanff) } // Ensure marshaling/unmarshaling works diff --git a/vms/platformvm/txs/executor/atomic_tx_executor.go b/vms/platformvm/txs/executor/atomic_tx_executor.go index 266ba4b27fb9..00cb03404009 100644 --- a/vms/platformvm/txs/executor/atomic_tx_executor.go +++ b/vms/platformvm/txs/executor/atomic_tx_executor.go @@ -29,47 +29,47 @@ type AtomicTxExecutor struct { } func (*AtomicTxExecutor) AddValidatorTx(*txs.AddValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) AddSubnetValidatorTx(*txs.AddSubnetValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) AddDelegatorTx(*txs.AddDelegatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) CreateChainTx(*txs.CreateChainTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) CreateSubnetTx(*txs.CreateSubnetTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) AdvanceTimeTx(*txs.AdvanceTimeTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) RewardValidatorTx(*txs.RewardValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) TransformSubnetTx(*txs.TransformSubnetTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) AddPermissionlessValidatorTx(*txs.AddPermissionlessValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*AtomicTxExecutor) AddPermissionlessDelegatorTx(*txs.AddPermissionlessDelegatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (e *AtomicTxExecutor) ImportTx(tx *txs.ImportTx) error { diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index efdb325f6b00..ae423ca9760e 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -32,15 +32,15 @@ const ( var ( _ txs.Visitor = (*ProposalTxExecutor)(nil) - errRemoveStakerTooEarly = errors.New("attempting to remove staker before their end time") - errRemoveWrongStaker = errors.New("attempting to remove wrong staker") - errChildBlockNotAfterParent = errors.New("proposed timestamp not after current chain time") - errInvalidState = errors.New("generated output isn't valid state") - errShouldBePermissionlessStaker = errors.New("expected permissionless staker") - errWrongTxType = errors.New("wrong transaction type") - errInvalidID = errors.New("invalid ID") - errProposedAddStakerTxAfterBanff = errors.New("staker transaction proposed after Banff") - errAdvanceTimeTxIssuedAfterBanff = errors.New("AdvanceTimeTx issued after Banff") + ErrRemoveStakerTooEarly = errors.New("attempting to remove staker before their end time") + ErrRemoveWrongStaker = errors.New("attempting to remove wrong staker") + ErrChildBlockNotAfterParent = errors.New("proposed timestamp not after current chain time") + ErrInvalidState = errors.New("generated output isn't valid state") + ErrShouldBePermissionlessStaker = errors.New("expected permissionless staker") + ErrWrongTxType = errors.New("wrong transaction type") + ErrInvalidID = errors.New("invalid ID") + ErrProposedAddStakerTxAfterBanff = errors.New("staker transaction proposed after Banff") + ErrAdvanceTimeTxIssuedAfterBanff = errors.New("AdvanceTimeTx issued after Banff") ) type ProposalTxExecutor struct { @@ -66,35 +66,35 @@ type ProposalTxExecutor struct { } func (*ProposalTxExecutor) CreateChainTx(*txs.CreateChainTx) error { - return errWrongTxType + return ErrWrongTxType } func (*ProposalTxExecutor) CreateSubnetTx(*txs.CreateSubnetTx) error { - return errWrongTxType + return ErrWrongTxType } func (*ProposalTxExecutor) ImportTx(*txs.ImportTx) error { - return errWrongTxType + return ErrWrongTxType } func (*ProposalTxExecutor) ExportTx(*txs.ExportTx) error { - return errWrongTxType + return ErrWrongTxType } func (*ProposalTxExecutor) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*ProposalTxExecutor) TransformSubnetTx(*txs.TransformSubnetTx) error { - return errWrongTxType + return ErrWrongTxType } func (*ProposalTxExecutor) AddPermissionlessValidatorTx(*txs.AddPermissionlessValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (*ProposalTxExecutor) AddPermissionlessDelegatorTx(*txs.AddPermissionlessDelegatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (e *ProposalTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { @@ -105,7 +105,7 @@ func (e *ProposalTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { if e.Config.IsBanffActivated(currentTimestamp) { return fmt.Errorf( "%w: timestamp (%s) >= Banff fork time (%s)", - errProposedAddStakerTxAfterBanff, + ErrProposedAddStakerTxAfterBanff, currentTimestamp, e.Config.BanffTime, ) @@ -154,7 +154,7 @@ func (e *ProposalTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) if e.Config.IsBanffActivated(currentTimestamp) { return fmt.Errorf( "%w: timestamp (%s) >= Banff fork time (%s)", - errProposedAddStakerTxAfterBanff, + ErrProposedAddStakerTxAfterBanff, currentTimestamp, e.Config.BanffTime, ) @@ -202,7 +202,7 @@ func (e *ProposalTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { if e.Config.IsBanffActivated(currentTimestamp) { return fmt.Errorf( "%w: timestamp (%s) >= Banff fork time (%s)", - errProposedAddStakerTxAfterBanff, + ErrProposedAddStakerTxAfterBanff, currentTimestamp, e.Config.BanffTime, ) @@ -256,7 +256,7 @@ func (e *ProposalTxExecutor) AdvanceTimeTx(tx *txs.AdvanceTimeTx) error { if e.Config.IsBanffActivated(newChainTime) { return fmt.Errorf( "%w: proposed timestamp (%s) >= Banff fork time (%s)", - errAdvanceTimeTxIssuedAfterBanff, + ErrAdvanceTimeTxIssuedAfterBanff, newChainTime, e.Config.BanffTime, ) @@ -266,7 +266,7 @@ func (e *ProposalTxExecutor) AdvanceTimeTx(tx *txs.AdvanceTimeTx) error { if !newChainTime.After(parentChainTime) { return fmt.Errorf( "%w, proposed timestamp (%s), chain time (%s)", - errChildBlockNotAfterParent, + ErrChildBlockNotAfterParent, parentChainTime, parentChainTime, ) @@ -308,7 +308,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error case tx == nil: return txs.ErrNilTx case tx.TxID == ids.Empty: - return errInvalidID + return ErrInvalidID case len(e.Tx.Creds) != 0: return errWrongNumberOfCredentials } @@ -326,7 +326,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error if stakerToRemove.TxID != tx.TxID { return fmt.Errorf( "%w: %s != %s", - errRemoveWrongStaker, + ErrRemoveWrongStaker, stakerToRemove.TxID, tx.TxID, ) @@ -337,7 +337,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error if !stakerToRemove.EndTime.Equal(currentChainTime) { return fmt.Errorf( "%w: TxID = %s with %s < %s", - errRemoveStakerTooEarly, + ErrRemoveStakerTooEarly, tx.TxID, currentChainTime, stakerToRemove.EndTime, @@ -394,7 +394,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error } out, ok := outIntf.(verify.State) if !ok { - return errInvalidState + return ErrInvalidState } utxo := &avax.UTXO{ @@ -429,7 +429,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error } out, ok := outIntf.(verify.State) if !ok { - return errInvalidState + return ErrInvalidState } onCommitUtxo := &avax.UTXO{ @@ -509,7 +509,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error // AddSubnetValidatorTx. vdrTx, ok := vdrTxIntf.Unsigned.(txs.ValidatorTx) if !ok { - return errWrongTxType + return ErrWrongTxType } // Calculate split of reward between delegator/delegatee @@ -534,7 +534,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error } out, ok := outIntf.(verify.State) if !ok { - return errInvalidState + return ErrInvalidState } utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -587,7 +587,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error } out, ok := outIntf.(verify.State) if !ok { - return errInvalidState + return ErrInvalidState } utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -607,7 +607,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error // time and the current chain timestamp is == this staker's // EndTime. This means only permissionless stakers should be // left in the staker set. - return errShouldBePermissionlessStaker + return ErrShouldBePermissionlessStaker } // If the reward is aborted, then the current supply should be decreased. diff --git a/vms/platformvm/txs/executor/reward_validator_test.go b/vms/platformvm/txs/executor/reward_validator_test.go index 470683b3d44c..619ff9052167 100644 --- a/vms/platformvm/txs/executor/reward_validator_test.go +++ b/vms/platformvm/txs/executor/reward_validator_test.go @@ -58,7 +58,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveStakerTooEarly) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), ErrRemoveStakerTooEarly) // Advance chain timestamp to time that next validator leaves env.state.SetTimestamp(stakerToRemove.EndTime) @@ -79,7 +79,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveWrongStaker) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), ErrRemoveWrongStaker) // Case 3: Happy path tx, err = env.txBuilder.NewRewardValidatorTx(stakerToRemove.TxID) @@ -159,7 +159,7 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveStakerTooEarly) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), ErrRemoveStakerTooEarly) // Advance chain timestamp to time that next validator leaves env.state.SetTimestamp(stakerToRemove.EndTime) @@ -174,7 +174,7 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { Backend: &env.backend, Tx: tx, } - require.ErrorIs(tx.Unsigned.Visit(&txExecutor), errRemoveWrongStaker) + require.ErrorIs(tx.Unsigned.Visit(&txExecutor), ErrRemoveWrongStaker) // Case 3: Happy path tx, err = env.txBuilder.NewRewardValidatorTx(stakerToRemove.TxID) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index b498b4bb36d6..81cda736d99c 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -38,11 +38,11 @@ type StandardTxExecutor struct { } func (*StandardTxExecutor) AdvanceTimeTx(*txs.AdvanceTimeTx) error { - return errWrongTxType + return ErrWrongTxType } func (*StandardTxExecutor) RewardValidatorTx(*txs.RewardValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (e *StandardTxExecutor) CreateChainTx(tx *txs.CreateChainTx) error { diff --git a/vms/platformvm/txs/executor/state_changes.go b/vms/platformvm/txs/executor/state_changes.go index 2f1cc034a635..25e662048f23 100644 --- a/vms/platformvm/txs/executor/state_changes.go +++ b/vms/platformvm/txs/executor/state_changes.go @@ -16,8 +16,8 @@ import ( ) var ( - errChildBlockAfterStakerChangeTime = errors.New("proposed timestamp later than next staker change time") - errChildBlockBeyondSyncBound = errors.New("proposed timestamp is too far in the future relative to local time") + ErrChildBlockAfterStakerChangeTime = errors.New("proposed timestamp later than next staker change time") + ErrChildBlockBeyondSyncBound = errors.New("proposed timestamp is too far in the future relative to local time") ) // VerifyNewChainTime returns nil if the [newChainTime] is a valid chain time @@ -38,7 +38,7 @@ func VerifyNewChainTime( if newChainTime.After(nextStakerChangeTime) { return fmt.Errorf( "%w, proposed timestamp (%s), next staker change time (%s)", - errChildBlockAfterStakerChangeTime, + ErrChildBlockAfterStakerChangeTime, newChainTime, nextStakerChangeTime, ) @@ -49,7 +49,7 @@ func VerifyNewChainTime( if newChainTime.After(maxNewChainTime) { return fmt.Errorf( "%w, proposed time (%s), local time (%s)", - errChildBlockBeyondSyncBound, + ErrChildBlockBeyondSyncBound, newChainTime, now, ) diff --git a/vms/platformvm/txs/executor/tx_mempool_verifier.go b/vms/platformvm/txs/executor/tx_mempool_verifier.go index 934f7c366095..206ef6c04424 100644 --- a/vms/platformvm/txs/executor/tx_mempool_verifier.go +++ b/vms/platformvm/txs/executor/tx_mempool_verifier.go @@ -23,11 +23,11 @@ type MempoolTxVerifier struct { } func (*MempoolTxVerifier) AdvanceTimeTx(*txs.AdvanceTimeTx) error { - return errWrongTxType + return ErrWrongTxType } func (*MempoolTxVerifier) RewardValidatorTx(*txs.RewardValidatorTx) error { - return errWrongTxType + return ErrWrongTxType } func (v *MempoolTxVerifier) AddValidatorTx(tx *txs.AddValidatorTx) error { From a665afd73756f1385650532dc07e5b810376bd23 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 01:17:29 -0400 Subject: [PATCH 60/77] remove rng from tests --- vms/platformvm/blocks/executor/proposal_block_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/blocks/executor/proposal_block_test.go b/vms/platformvm/blocks/executor/proposal_block_test.go index 32889928328e..caa93b195245 100644 --- a/vms/platformvm/blocks/executor/proposal_block_test.go +++ b/vms/platformvm/blocks/executor/proposal_block_test.go @@ -394,7 +394,7 @@ func TestBanffProposalBlockUpdateStakers(t *testing.T) { // Staker5: |--------------------| // Staker0 it's here just to allow to issue a proposal block with the chosen endTime. - staker0RewardAddress := ids.GenerateTestShortID() + staker0RewardAddress := ids.ShortID{2} staker0 := staker{ nodeID: ids.NodeID(staker0RewardAddress), rewardAddress: staker0RewardAddress, @@ -410,7 +410,7 @@ func TestBanffProposalBlockUpdateStakers(t *testing.T) { endTime: defaultGenesisTime.Add(10 * defaultMinStakingDuration).Add(1 * time.Minute), } - staker2RewardAddress := ids.GenerateTestShortID() + staker2RewardAddress := ids.ShortID{1} staker2 := staker{ nodeID: ids.NodeID(staker2RewardAddress), rewardAddress: staker2RewardAddress, From 296e7576e36e6e720d323584706d37e0a18f7284 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 02:04:09 -0400 Subject: [PATCH 61/77] fix genesis tests --- genesis/config.go | 9 ++- genesis/genesis.go | 45 ++++++++----- genesis/genesis_test.go | 144 +++++++++++++++++++--------------------- 3 files changed, 103 insertions(+), 95 deletions(-) diff --git a/genesis/config.go b/genesis/config.go index 403522d02cb3..6307ecd82a34 100644 --- a/genesis/config.go +++ b/genesis/config.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -19,7 +20,11 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" ) -var _ utils.Sortable[Allocation] = Allocation{} +var ( + _ utils.Sortable[Allocation] = Allocation{} + + errInvalidGenesisJSON = errors.New("could not unmarshal genesis JSON") +) type LockedAmount struct { Amount uint64 `json:"amount"` @@ -230,7 +235,7 @@ func GetConfigContent(genesisContent string) (*Config, error) { func parseGenesisJSONBytesToConfig(bytes []byte) (*Config, error) { var unparsedConfig UnparsedConfig if err := json.Unmarshal(bytes, &unparsedConfig); err != nil { - return nil, fmt.Errorf("could not unmarshal JSON: %w", err) + return nil, fmt.Errorf("%w: %s", errInvalidGenesisJSON, err) } config, err := unparsedConfig.Parse() diff --git a/genesis/genesis.go b/genesis/genesis.go index d5fbf90be372..a93d5a5a41a7 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -33,13 +33,19 @@ const ( ) var ( - errStakeDurationTooHigh = errors.New("initial stake duration larger than maximum configured") - errNoInitiallyStakedFunds = errors.New("initial staked funds cannot be empty") - errNoSupply = errors.New("initial supply must be > 0") - errNoStakeDuration = errors.New("initial stake duration must be > 0") - errNoStakers = errors.New("initial stakers must be > 0") - errNoCChainGenesis = errors.New("C-Chain genesis cannot be empty") - errNoTxs = errors.New("genesis creates no transactions") + errStakeDurationTooHigh = errors.New("initial stake duration larger than maximum configured") + errNoInitiallyStakedFunds = errors.New("initial staked funds cannot be empty") + errNoSupply = errors.New("initial supply must be > 0") + errNoStakeDuration = errors.New("initial stake duration must be > 0") + errNoStakers = errors.New("initial stakers must be > 0") + errNoCChainGenesis = errors.New("C-Chain genesis cannot be empty") + errNoTxs = errors.New("genesis creates no transactions") + errNoAllocationToStake = errors.New("no allocation to stake") + errDuplicateInitiallyStakedAddress = errors.New("duplicate initially staked address") + errConflictingNetworkIDs = errors.New("conflicting networkIDs") + errFutureStartTime = errors.New("startTime cannot be in the future") + errInitialStakeDurationTooLow = errors.New("initial stake duration is too low") + errOverridesStandardNetworkConfig = errors.New("overrides standard network genesis config") ) // validateInitialStakedFunds ensures all staked @@ -76,7 +82,8 @@ func validateInitialStakedFunds(config *Config) error { } return fmt.Errorf( - "address %s is duplicated in initial staked funds", + "%w: %s", + errDuplicateInitiallyStakedAddress, avaxAddr, ) } @@ -96,7 +103,8 @@ func validateInitialStakedFunds(config *Config) error { } return fmt.Errorf( - "address %s does not have an allocation to stake", + "%w in address %s", + errNoAllocationToStake, avaxAddr, ) } @@ -110,7 +118,8 @@ func validateInitialStakedFunds(config *Config) error { func validateConfig(networkID uint32, config *Config, stakingCfg *StakingConfig) error { if networkID != config.NetworkID { return fmt.Errorf( - "networkID %d specified but genesis config contains networkID %d", + "%w both %d and %d", + errConflictingNetworkIDs, networkID, config.NetworkID, ) @@ -127,7 +136,8 @@ func validateConfig(networkID uint32, config *Config, stakingCfg *StakingConfig) startTime := time.Unix(int64(config.StartTime), 0) if time.Since(startTime) < 0 { return fmt.Errorf( - "start time cannot be in the future: %s", + "%w: %s", + errFutureStartTime, startTime, ) } @@ -153,10 +163,9 @@ func validateConfig(networkID uint32, config *Config, stakingCfg *StakingConfig) offsetTimeRequired := config.InitialStakeDurationOffset * uint64(len(config.InitialStakers)-1) if offsetTimeRequired > config.InitialStakeDuration { return fmt.Errorf( - "initial stake duration is %d but need at least %d with offset of %d", - config.InitialStakeDuration, + "%w must be at least %d", + errInitialStakeDurationTooLow, offsetTimeRequired, - config.InitialStakeDurationOffset, ) } @@ -195,9 +204,9 @@ func FromFile(networkID uint32, filepath string, stakingCfg *StakingConfig) ([]b switch networkID { case constants.MainnetID, constants.TestnetID, constants.LocalID: return nil, ids.ID{}, fmt.Errorf( - "cannot override genesis config for standard network %s (%d)", + "%w: %s", + errOverridesStandardNetworkConfig, constants.NetworkName(networkID), - networkID, ) } @@ -237,9 +246,9 @@ func FromFlag(networkID uint32, genesisContent string, stakingCfg *StakingConfig switch networkID { case constants.MainnetID, constants.TestnetID, constants.LocalID: return nil, ids.ID{}, fmt.Errorf( - "cannot override genesis config for standard network %s (%d)", + "%w: %s", + errOverridesStandardNetworkConfig, constants.NetworkName(networkID), - networkID, ) } diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go index 0a49916a33ed..e64d52558e65 100644 --- a/genesis/genesis_test.go +++ b/genesis/genesis_test.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "os" "path/filepath" "testing" "time" @@ -36,26 +37,29 @@ var ( func TestValidateConfig(t *testing.T) { tests := map[string]struct { - networkID uint32 - config *Config - err string + networkID uint32 + config *Config + expectedErr error }{ "mainnet": { - networkID: 1, - config: &MainnetConfig, + networkID: 1, + config: &MainnetConfig, + expectedErr: nil, }, "fuji": { - networkID: 5, - config: &FujiConfig, + networkID: 5, + config: &FujiConfig, + expectedErr: nil, }, "local": { - networkID: 12345, - config: &LocalConfig, + networkID: 12345, + config: &LocalConfig, + expectedErr: nil, }, "mainnet (networkID mismatch)": { - networkID: 2, - config: &MainnetConfig, - err: "networkID 2 specified but genesis config contains networkID 1", + networkID: 2, + config: &MainnetConfig, + expectedErr: errConflictingNetworkIDs, }, "invalid start time": { networkID: 12345, @@ -64,7 +68,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.StartTime = 999999999999999 return &thisConfig }(), - err: "start time cannot be in the future", + expectedErr: errFutureStartTime, }, "no initial supply": { networkID: 12345, @@ -73,7 +77,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.Allocations = []Allocation{} return &thisConfig }(), - err: errNoSupply.Error(), + expectedErr: errNoSupply, }, "no initial stakers": { networkID: 12345, @@ -82,7 +86,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.InitialStakers = []Staker{} return &thisConfig }(), - err: errNoStakers.Error(), + expectedErr: errNoStakers, }, "invalid initial stake duration": { networkID: 12345, @@ -91,7 +95,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.InitialStakeDuration = 0 return &thisConfig }(), - err: errNoStakeDuration.Error(), + expectedErr: errNoStakeDuration, }, "too large initial stake duration": { networkID: 12345, @@ -100,7 +104,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.InitialStakeDuration = uint64(genesisStakingCfg.MaxStakeDuration+time.Second) / uint64(time.Second) return &thisConfig }(), - err: errStakeDurationTooHigh.Error(), + expectedErr: errStakeDurationTooHigh, }, "invalid stake offset": { networkID: 12345, @@ -109,7 +113,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.InitialStakeDurationOffset = 100000000 return &thisConfig }(), - err: "initial stake duration is 31536000 but need at least 400000000 with offset of 100000000", + expectedErr: errInitialStakeDurationTooLow, }, "empty initial staked funds": { networkID: 12345, @@ -118,7 +122,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.InitialStakedFunds = []ids.ShortID(nil) return &thisConfig }(), - err: errNoInitiallyStakedFunds.Error(), + expectedErr: errNoInitiallyStakedFunds, }, "duplicate initial staked funds": { networkID: 12345, @@ -127,7 +131,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.InitialStakedFunds = append(thisConfig.InitialStakedFunds, thisConfig.InitialStakedFunds[0]) return &thisConfig }(), - err: "duplicated in initial staked funds", + expectedErr: errDuplicateInitiallyStakedAddress, }, "initial staked funds not in allocations": { networkID: 5, @@ -136,7 +140,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.InitialStakedFunds = append(thisConfig.InitialStakedFunds, LocalConfig.InitialStakedFunds[0]) return &thisConfig }(), - err: "does not have an allocation to stake", + expectedErr: errNoAllocationToStake, }, "empty C-Chain genesis": { networkID: 12345, @@ -145,7 +149,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.CChainGenesis = "" return &thisConfig }(), - err: errNoCChainGenesis.Error(), + expectedErr: errNoCChainGenesis, }, "empty message": { networkID: 12345, @@ -154,6 +158,7 @@ func TestValidateConfig(t *testing.T) { thisConfig.Message = "" return &thisConfig }(), + expectedErr: nil, }, } @@ -162,12 +167,7 @@ func TestValidateConfig(t *testing.T) { require := require.New(t) err := validateConfig(test.networkID, test.config, genesisStakingCfg) - if len(test.err) > 0 { - require.Error(err) - require.Contains(err.Error(), test.err) - return - } - require.NoError(err) + require.ErrorIs(err, test.expectedErr) }) } } @@ -177,53 +177,54 @@ func TestGenesisFromFile(t *testing.T) { networkID uint32 customConfig []byte missingFilepath string - err string - expected string + expectedErr error + expectedHash string }{ "mainnet": { networkID: constants.MainnetID, customConfig: customGenesisConfigJSON, - err: "cannot override genesis config for standard network mainnet (1)", + expectedErr: errOverridesStandardNetworkConfig, }, "fuji": { networkID: constants.FujiID, customConfig: customGenesisConfigJSON, - err: "cannot override genesis config for standard network fuji (5)", + expectedErr: errOverridesStandardNetworkConfig, }, "fuji (with custom specified)": { networkID: constants.FujiID, customConfig: localGenesisConfigJSON, // won't load - err: "cannot override genesis config for standard network fuji (5)", + expectedErr: errOverridesStandardNetworkConfig, }, "local": { networkID: constants.LocalID, customConfig: customGenesisConfigJSON, - err: "cannot override genesis config for standard network local (12345)", + expectedErr: errOverridesStandardNetworkConfig, }, "local (with custom specified)": { networkID: constants.LocalID, customConfig: customGenesisConfigJSON, - err: "cannot override genesis config for standard network local (12345)", + expectedErr: errOverridesStandardNetworkConfig, }, "custom": { networkID: 9999, customConfig: customGenesisConfigJSON, - expected: "a1d1838586db85fe94ab1143560c3356df9ba2445794b796bba050be89f4fcb4", + expectedErr: nil, + expectedHash: "a1d1838586db85fe94ab1143560c3356df9ba2445794b796bba050be89f4fcb4", }, "custom (networkID mismatch)": { networkID: 9999, customConfig: localGenesisConfigJSON, - err: "networkID 9999 specified but genesis config contains networkID 12345", + expectedErr: errConflictingNetworkIDs, }, "custom (invalid format)": { networkID: 9999, customConfig: invalidGenesisConfigJSON, - err: "unable to load provided genesis config", + expectedErr: errInvalidGenesisJSON, }, "custom (missing filepath)": { networkID: 9999, missingFilepath: "missing.json", - err: "unable to load provided genesis config", + expectedErr: os.ErrNotExist, }, } @@ -243,18 +244,14 @@ func TestGenesisFromFile(t *testing.T) { } genesisBytes, _, err := FromFile(test.networkID, customFile, genesisStakingCfg) - if len(test.err) > 0 { - require.Error(err) - require.Contains(err.Error(), test.err) - return - } - require.NoError(err) - - genesisHash := fmt.Sprintf("%x", hashing.ComputeHash256(genesisBytes)) - require.Equal(test.expected, genesisHash, "genesis hash mismatch") + require.ErrorIs(err, test.expectedErr) + if test.expectedErr == nil { + genesisHash := fmt.Sprintf("%x", hashing.ComputeHash256(genesisBytes)) + require.Equal(test.expectedHash, genesisHash, "genesis hash mismatch") - _, err = genesis.Parse(genesisBytes) - require.NoError(err) + _, err = genesis.Parse(genesisBytes) + require.NoError(err) + } }) } } @@ -263,44 +260,45 @@ func TestGenesisFromFlag(t *testing.T) { tests := map[string]struct { networkID uint32 customConfig []byte - err string - expected string + expectedErr error + expectedHash string }{ "mainnet": { - networkID: constants.MainnetID, - err: "cannot override genesis config for standard network mainnet (1)", + networkID: constants.MainnetID, + expectedErr: errOverridesStandardNetworkConfig, }, "fuji": { - networkID: constants.FujiID, - err: "cannot override genesis config for standard network fuji (5)", + networkID: constants.FujiID, + expectedErr: errOverridesStandardNetworkConfig, }, "local": { - networkID: constants.LocalID, - err: "cannot override genesis config for standard network local (12345)", + networkID: constants.LocalID, + expectedErr: errOverridesStandardNetworkConfig, }, "local (with custom specified)": { networkID: constants.LocalID, customConfig: customGenesisConfigJSON, - err: "cannot override genesis config for standard network local (12345)", + expectedErr: errOverridesStandardNetworkConfig, }, "custom": { networkID: 9999, customConfig: customGenesisConfigJSON, - expected: "a1d1838586db85fe94ab1143560c3356df9ba2445794b796bba050be89f4fcb4", + expectedErr: nil, + expectedHash: "a1d1838586db85fe94ab1143560c3356df9ba2445794b796bba050be89f4fcb4", }, "custom (networkID mismatch)": { networkID: 9999, customConfig: localGenesisConfigJSON, - err: "networkID 9999 specified but genesis config contains networkID 12345", + expectedErr: errConflictingNetworkIDs, }, "custom (invalid format)": { networkID: 9999, customConfig: invalidGenesisConfigJSON, - err: "unable to load genesis content from flag", + expectedErr: errInvalidGenesisJSON, }, "custom (missing content)": { - networkID: 9999, - err: "unable to load genesis content from flag", + networkID: 9999, + expectedErr: errInvalidGenesisJSON, }, } @@ -332,18 +330,14 @@ func TestGenesisFromFlag(t *testing.T) { content := base64.StdEncoding.EncodeToString(genBytes) genesisBytes, _, err := FromFlag(test.networkID, content, genesisStakingCfg) - if len(test.err) > 0 { - require.Error(err) - require.Contains(err.Error(), test.err) - return - } - require.NoError(err) - - genesisHash := fmt.Sprintf("%x", hashing.ComputeHash256(genesisBytes)) - require.Equal(test.expected, genesisHash, "genesis hash mismatch") + require.ErrorIs(err, test.expectedErr) + if test.expectedErr == nil { + genesisHash := fmt.Sprintf("%x", hashing.ComputeHash256(genesisBytes)) + require.Equal(test.expectedHash, genesisHash, "genesis hash mismatch") - _, err = genesis.Parse(genesisBytes) - require.NoError(err) + _, err = genesis.Parse(genesisBytes) + require.NoError(err) + } }) } } From 06d30c4fd42be372a3558e930c1522caea426ff2 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 02:13:30 -0400 Subject: [PATCH 62/77] fix standard block tests --- .../blocks/executor/standard_block_test.go | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/vms/platformvm/blocks/executor/standard_block_test.go b/vms/platformvm/blocks/executor/standard_block_test.go index a276364c747a..017379f76bfa 100644 --- a/vms/platformvm/blocks/executor/standard_block_test.go +++ b/vms/platformvm/blocks/executor/standard_block_test.go @@ -23,9 +23,8 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - txexecutor "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor" ) func TestApricotStandardBlockTimeVerification(t *testing.T) { @@ -71,7 +70,8 @@ func TestApricotStandardBlockTimeVerification(t *testing.T) { ) require.NoError(err) block := env.blkManager.NewBlock(apricotChildBlk) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, errIncorrectBlockHeight) // valid height apricotChildBlk, err = blocks.NewApricotStandardBlock( @@ -123,7 +123,7 @@ func TestBanffStandardBlockTimeVerification(t *testing.T) { env.mockedState.EXPECT().GetLastAccepted().Return(parentID).AnyTimes() env.mockedState.EXPECT().GetTimestamp().Return(chainTime).AnyTimes() - nextStakerTime := chainTime.Add(txexecutor.SyncBound).Add(-1 * time.Second) + nextStakerTime := chainTime.Add(executor.SyncBound).Add(-1 * time.Second) // store just once current staker to mark next staker time. currentStakerIt := state.NewMockStakerIterator(ctrl) @@ -187,7 +187,8 @@ func TestBanffStandardBlockTimeVerification(t *testing.T) { ) require.NoError(err) block := env.blkManager.NewBlock(banffChildBlk) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, errApricotBlockIssuedAfterFork) } { @@ -201,7 +202,8 @@ func TestBanffStandardBlockTimeVerification(t *testing.T) { ) require.NoError(err) block := env.blkManager.NewBlock(banffChildBlk) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, errIncorrectBlockHeight) } { @@ -215,21 +217,25 @@ func TestBanffStandardBlockTimeVerification(t *testing.T) { ) require.NoError(err) block := env.blkManager.NewBlock(banffChildBlk) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, errChildBlockEarlierThanParent) } { // wrong timestamp, violated synchrony bound - childTimestamp := parentTime.Add(txexecutor.SyncBound).Add(time.Second) + initClkTime := env.clk.Time() + env.clk.Set(parentTime.Add(-executor.SyncBound)) banffChildBlk, err := blocks.NewBanffStandardBlock( - childTimestamp, + parentTime.Add(time.Second), banffParentBlk.ID(), banffParentBlk.Height()+1, []*txs.Tx{tx}, ) require.NoError(err) block := env.blkManager.NewBlock(banffChildBlk) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, executor.ErrChildBlockBeyondSyncBound) + env.clk.Set(initClkTime) } { @@ -243,7 +249,8 @@ func TestBanffStandardBlockTimeVerification(t *testing.T) { ) require.NoError(err) block := env.blkManager.NewBlock(banffChildBlk) - require.Error(block.Verify(context.Background())) + err = block.Verify(context.Background()) + require.ErrorIs(err, executor.ErrChildBlockAfterStakerChangeTime) } { From 5618975be63369be9ff7e6e31c7495d190f187e9 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 02:24:22 -0400 Subject: [PATCH 63/77] simple --- config/config.go | 3 +- config/config_test.go | 74 ++++++++++++-------------------- database/manager/manager_test.go | 4 +- 3 files changed, 31 insertions(+), 50 deletions(-) diff --git a/config/config.go b/config/config.go index e955c749b01b..26d99dadd93a 100644 --- a/config/config.go +++ b/config/config.go @@ -86,6 +86,7 @@ var ( errTracingEndpointEmpty = fmt.Errorf("%s cannot be empty", TracingEndpointKey) errPluginDirNotADirectory = errors.New("plugin dir is not a directory") errZstdNotSupported = errors.New("zstd compression not supported until v1.10") + errCannotReadDirectory = errors.New("cannot read directory") ) func getConsensusConfig(v *viper.Viper) avalanche.Parameters { @@ -1008,7 +1009,7 @@ func getPathFromDirKey(v *viper.Viper, configKey string) (string, error) { } if v.IsSet(configKey) { // user specified a config dir explicitly, but dir does not exist. - return "", fmt.Errorf("cannot read directory: %v", cleanPath) + return "", fmt.Errorf("%w: %s", errCannotReadDirectory, cleanPath) } return "", nil } diff --git a/config/config_test.go b/config/config_test.go index de15d8fe9c4f..3f4e8913f5f5 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -24,10 +24,9 @@ import ( func TestGetChainConfigsFromFiles(t *testing.T) { tests := map[string]struct { - configs map[string]string - upgrades map[string]string - errMessage string - expected map[string]chains.ChainConfig + configs map[string]string + upgrades map[string]string + expected map[string]chains.ChainConfig }{ "no chain configs": { configs: map[string]string{}, @@ -85,14 +84,7 @@ func TestGetChainConfigsFromFiles(t *testing.T) { // Parse config require.Equal(root, v.GetString(ChainConfigDirKey)) chainConfigs, err := getChainConfigs(v) - if len(test.errMessage) > 0 { - require.Error(err) - if err != nil { - require.Contains(err.Error(), test.errMessage) - } - } else { - require.NoError(err) - } + require.NoError(err) require.Equal(test.expected, chainConfigs) }) } @@ -100,32 +92,34 @@ func TestGetChainConfigsFromFiles(t *testing.T) { func TestGetChainConfigsDirNotExist(t *testing.T) { tests := map[string]struct { - structure string - file map[string]string - errMessage string - expected map[string]chains.ChainConfig + structure string + file map[string]string + expectedErr error + expected map[string]chains.ChainConfig }{ "cdir not exist": { - structure: "/", - file: map[string]string{"config.ex": "noeffect"}, - errMessage: "cannot read directory", - expected: nil, + structure: "/", + file: map[string]string{"config.ex": "noeffect"}, + expectedErr: errCannotReadDirectory, + expected: nil, }, "cdir is file ": { - structure: "/", - file: map[string]string{"cdir": "noeffect"}, - errMessage: "cannot read directory", - expected: nil, + structure: "/", + file: map[string]string{"cdir": "noeffect"}, + expectedErr: errCannotReadDirectory, + expected: nil, }, "chain subdir not exist": { - structure: "/cdir/", - file: map[string]string{"config.ex": "noeffect"}, - expected: map[string]chains.ChainConfig{}, + structure: "/cdir/", + file: map[string]string{"config.ex": "noeffect"}, + expectedErr: nil, + expected: map[string]chains.ChainConfig{}, }, "full structure": { - structure: "/cdir/C/", - file: map[string]string{"config.ex": "hello"}, - expected: map[string]chains.ChainConfig{"C": {Config: []byte("hello"), Upgrade: []byte(nil)}}, + structure: "/cdir/C/", + file: map[string]string{"config.ex": "hello"}, + expectedErr: nil, + expected: map[string]chains.ChainConfig{"C": {Config: []byte("hello"), Upgrade: []byte(nil)}}, }, } @@ -150,14 +144,8 @@ func TestGetChainConfigsDirNotExist(t *testing.T) { // don't read with getConfigFromViper since it's very slow. chainConfigs, err := getChainConfigs(v) - switch { - case len(test.errMessage) > 0: - require.Error(err) - require.Contains(err.Error(), test.errMessage) - default: - require.NoError(err) - require.Equal(test.expected, chainConfigs) - } + require.ErrorIs(err, test.expectedErr) + require.Equal(test.expected, chainConfigs) }) } } @@ -183,7 +171,6 @@ func TestSetChainConfigDefaultDir(t *testing.T) { func TestGetChainConfigsFromFlags(t *testing.T) { tests := map[string]struct { fullConfigs map[string]chains.ChainConfig - errMessage string expected map[string]chains.ChainConfig }{ "no chain configs": { @@ -244,14 +231,7 @@ func TestGetChainConfigsFromFlags(t *testing.T) { // Parse config chainConfigs, err := getChainConfigs(v) - if len(test.errMessage) > 0 { - require.Error(err) - if err != nil { - require.Contains(err.Error(), test.errMessage) - } - } else { - require.NoError(err) - } + require.NoError(err) require.Equal(test.expected, chainConfigs) }) } diff --git a/database/manager/manager_test.go b/database/manager/manager_test.go index ffa82bb9d411..0dd092f5e03b 100644 --- a/database/manager/manager_test.go +++ b/database/manager/manager_test.go @@ -414,7 +414,7 @@ func TestNewManagerFromNoDBs(t *testing.T) { require := require.New(t) // Should error if no dbs are given _, err := NewManagerFromDBs(nil) - require.Error(err) + require.ErrorIs(err, errNoDBs) } func TestNewManagerFromNonUniqueDBs(t *testing.T) { @@ -447,5 +447,5 @@ func TestNewManagerFromNonUniqueDBs(t *testing.T) { }, }, }) - require.Error(err) + require.ErrorIs(err, errNonSortedAndUniqueDBs) } From e37782bf90a61356c159513859ee4cd227e88012 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 11:59:18 -0400 Subject: [PATCH 64/77] fix various proposal tx executor tests --- .../txs/executor/proposal_tx_executor_test.go | 99 +++++++------------ 1 file changed, 35 insertions(+), 64 deletions(-) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index 5ea50eb80baa..2bcf85cbdac3 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/hashing" @@ -314,7 +315,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { // (note that keys[0] is a genesis validator) tx, err := env.txBuilder.NewAddSubnetValidatorTx( defaultWeight, - uint64(defaultValidateStartTime.Unix()), + uint64(defaultValidateStartTime.Unix())+1, uint64(defaultValidateEndTime.Unix())+1, ids.NodeID(nodeID), testSubnet1.ID(), @@ -336,7 +337,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator stops validating primary network earlier than subnet") + require.ErrorIs(err, ErrValidatorSubset) } { @@ -346,7 +347,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { // (note that keys[0] is a genesis validator) tx, err := env.txBuilder.NewAddSubnetValidatorTx( defaultWeight, - uint64(defaultValidateStartTime.Unix()+1), + uint64(defaultValidateStartTime.Unix())+1, uint64(defaultValidateEndTime.Unix()), ids.NodeID(nodeID), testSubnet1.ID(), @@ -418,7 +419,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator not in the current or pending validator sets of the primary network") + require.ErrorIs(err, ErrNotValidator) } staker, err := state.NewCurrentStaker( @@ -464,7 +465,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator starts validating primary network before starting to validate primary network") + require.ErrorIs(err, ErrValidatorSubset) } { @@ -494,7 +495,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator stops validating primary network after stops validating primary network") + require.ErrorIs(err, ErrValidatorSubset) } { @@ -557,7 +558,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because starts validating at current timestamp") + require.ErrorIs(err, ErrTimestampNotBeforeStartTime) } // reset the timestamp @@ -592,11 +593,11 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { { // Node with ID nodeIDKey.PublicKey().Address() now validating subnet with ID testSubnet1.ID duplicateSubnetTx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultValidateStartTime.Unix()), // start time - uint64(defaultValidateEndTime.Unix()), // end time - ids.NodeID(nodeID), // node ID - testSubnet1.ID(), // subnet ID + defaultWeight, // weight + uint64(defaultValidateStartTime.Unix())+1, // start time + uint64(defaultValidateEndTime.Unix()), // end time + ids.NodeID(nodeID), // node ID + testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]}, ids.ShortEmpty, // change addr ) @@ -615,7 +616,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: duplicateSubnetTx, } err = duplicateSubnetTx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because validator already validating the specified subnet") + require.ErrorIs(err, ErrDuplicateValidator) } env.state.DeleteCurrentValidator(staker) @@ -623,41 +624,12 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { err = env.state.Commit() require.NoError(err) - { - // Case: Too many signatures - tx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultGenesisTime.Unix()), // start time - uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix())+1, // end time - ids.NodeID(nodeID), // node ID - testSubnet1.ID(), // subnet ID - []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1], testSubnet1ControlKeys[2]}, - ids.ShortEmpty, // change addr - ) - require.NoError(err) - - onCommitState, err := state.NewDiff(lastAcceptedID, env) - require.NoError(err) - - onAbortState, err := state.NewDiff(lastAcceptedID, env) - require.NoError(err) - - executor := ProposalTxExecutor{ - OnCommitState: onCommitState, - OnAbortState: onAbortState, - Backend: &env.backend, - Tx: tx, - } - err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because tx has 3 signatures but only 2 needed") - } - { // Case: Too few signatures tx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultGenesisTime.Unix()), // start time - uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix()), // end time + defaultWeight, // weight + uint64(defaultGenesisTime.Unix())+1, // start time + uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix())+1, // end time ids.NodeID(nodeID), // node ID testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], testSubnet1ControlKeys[2]}, @@ -685,15 +657,15 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because not enough control sigs") + require.ErrorIs(err, errUnauthorizedSubnetModification) } { // Case: Control Signature from invalid key (keys[3] is not a control key) tx, err := env.txBuilder.NewAddSubnetValidatorTx( - defaultWeight, // weight - uint64(defaultGenesisTime.Unix()), // start time - uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix()), // end time + defaultWeight, // weight + uint64(defaultGenesisTime.Unix())+1, // start time + uint64(defaultGenesisTime.Add(defaultMinStakingDuration).Unix())+1, // end time ids.NodeID(nodeID), // node ID testSubnet1.ID(), // subnet ID []*secp256k1.PrivateKey{testSubnet1ControlKeys[0], preFundedKeys[1]}, @@ -704,7 +676,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { // Replace a valid signature with one from keys[3] sig, err := preFundedKeys[3].SignHash(hashing.ComputeHash256(tx.Unsigned.Bytes())) require.NoError(err) - copy(tx.Creds[0].(*secp256k1fx.Credential).Sigs[0][:], sig) + copy(tx.Creds[1].(*secp256k1fx.Credential).Sigs[0][:], sig) onCommitState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) @@ -719,7 +691,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because a control sig is invalid") + require.ErrorIs(err, errUnauthorizedSubnetModification) } { @@ -762,7 +734,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed verification because validator already in pending validator set of the specified subnet") + require.ErrorIs(err, ErrDuplicateValidator) } } @@ -780,7 +752,7 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { // Case: Validator's start time too early tx, err := env.txBuilder.NewAddValidatorTx( env.config.MinValidatorStake, - uint64(defaultValidateStartTime.Unix())-1, + uint64(defaultValidateStartTime.Unix()), uint64(defaultValidateEndTime.Unix()), nodeID, ids.ShortEmpty, @@ -803,7 +775,7 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've errored because start time too early") + require.ErrorIs(err, ErrTimestampNotBeforeStartTime) } { @@ -833,16 +805,16 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've errored because start time too far in the future") + require.ErrorIs(err, ErrFutureStakeTime) } { // Case: Validator already validating primary network tx, err := env.txBuilder.NewAddValidatorTx( env.config.MinValidatorStake, - uint64(defaultValidateStartTime.Unix()), + uint64(defaultValidateStartTime.Unix())+1, uint64(defaultValidateEndTime.Unix()), - nodeID, + ids.NodeID(preFundedKeys[0].Address()), ids.ShortEmpty, reward.PercentDenominator, []*secp256k1.PrivateKey{preFundedKeys[0]}, @@ -863,7 +835,7 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should've errored because validator already validating") + require.ErrorIs(err, ErrAlreadyValidator) } { @@ -881,14 +853,13 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { ) require.NoError(err) - staker, err := state.NewCurrentStaker( + staker, err := state.NewPendingStaker( tx.ID(), tx.Unsigned.(*txs.AddValidatorTx), - 0, ) require.NoError(err) - env.state.PutCurrentValidator(staker) + env.state.PutPendingValidator(staker) env.state.AddTx(tx, status.Committed) dummyHeight := uint64(1) env.state.SetHeight(dummyHeight) @@ -908,14 +879,14 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because validator in pending validator set") + require.ErrorIs(err, ErrAlreadyValidator) } { // Case: Validator doesn't have enough tokens to cover stake amount tx, err := env.txBuilder.NewAddValidatorTx( // create the tx env.config.MinValidatorStake, - uint64(defaultValidateStartTime.Unix()), + uint64(defaultValidateStartTime.Unix())+1, uint64(defaultValidateEndTime.Unix()), nodeID, ids.ShortEmpty, @@ -946,6 +917,6 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.Error(err, "should have failed because tx fee paying key has no funds") + require.ErrorIs(err, database.ErrNotFound) } } From a6a395a01e463175116aa27d5969e592677bc8fd Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 12:00:28 -0400 Subject: [PATCH 65/77] nit --- .../txs/executor/proposal_tx_executor_test.go | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index 2bcf85cbdac3..cf4c64b25180 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -93,6 +93,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { currentTimestamp := dummyH.state.GetTimestamp() type test struct { + description string stakeAmount uint64 startTime uint64 endTime uint64 @@ -102,11 +103,11 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup func(*environment) AP3Time time.Time shouldErr bool - description string } tests := []test{ { + description: "validator stops validating primary network earlier than subnet", stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(defaultValidateStartTime.Unix()), endTime: uint64(defaultValidateEndTime.Unix()) + 1, @@ -116,9 +117,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator stops validating primary network earlier than subnet", }, { + description: fmt.Sprintf("validator should not be added more than (%s) in the future", MaxFutureStartTime), stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(currentTimestamp.Add(MaxFutureStartTime + time.Second).Unix()), endTime: uint64(currentTimestamp.Add(MaxFutureStartTime * 2).Unix()), @@ -128,9 +129,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: fmt.Sprintf("validator should not be added more than (%s) in the future", MaxFutureStartTime), }, { + description: "end time is after the primary network end time", stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(defaultValidateStartTime.Unix()), endTime: uint64(defaultValidateEndTime.Unix()) + 1, @@ -140,9 +141,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "end time is after the primary network end time", }, { + description: "validator not in the current or pending validator sets of the subnet", stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(defaultValidateStartTime.Add(5 * time.Second).Unix()), endTime: uint64(defaultValidateEndTime.Add(-5 * time.Second).Unix()), @@ -152,9 +153,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator not in the current or pending validator sets of the subnet", }, { + description: "validator starts validating subnet before primary network", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime - 1, // start validating subnet before primary network endTime: newValidatorEndTime, @@ -164,9 +165,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: addMinStakeValidator, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator starts validating subnet before primary network", }, { + description: "validator stops validating primary network before subnet", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, endTime: newValidatorEndTime + 1, // stop validating subnet after stopping validating primary network @@ -176,9 +177,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: addMinStakeValidator, AP3Time: defaultGenesisTime, shouldErr: true, - description: "validator stops validating primary network before subnet", }, { + description: "valid", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, // same start time as for primary network endTime: newValidatorEndTime, // same end time as for primary network @@ -188,9 +189,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: addMinStakeValidator, AP3Time: defaultGenesisTime, shouldErr: false, - description: "valid", }, { + description: "starts validating at current timestamp", stakeAmount: dummyH.config.MinDelegatorStake, // weight startTime: uint64(currentTimestamp.Unix()), // start time endTime: uint64(defaultValidateEndTime.Unix()), // end time @@ -200,9 +201,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: nil, AP3Time: defaultGenesisTime, shouldErr: true, - description: "starts validating at current timestamp", }, { + description: "tx fee paying key has no funds", stakeAmount: dummyH.config.MinDelegatorStake, // weight startTime: uint64(defaultValidateStartTime.Unix()), // start time endTime: uint64(defaultValidateEndTime.Unix()), // end time @@ -223,11 +224,11 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { err = target.state.Commit() require.NoError(t, err) }, - AP3Time: defaultGenesisTime, - shouldErr: true, - description: "tx fee paying key has no funds", + AP3Time: defaultGenesisTime, + shouldErr: true, }, { + description: "over delegation before AP3", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, // same start time as for primary network endTime: newValidatorEndTime, // same end time as for primary network @@ -237,9 +238,9 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: addMaxStakeValidator, AP3Time: defaultValidateEndTime, shouldErr: false, - description: "over delegation before AP3", }, { + description: "over delegation after AP3", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, // same start time as for primary network endTime: newValidatorEndTime, // same end time as for primary network @@ -249,7 +250,6 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { setup: addMaxStakeValidator, AP3Time: defaultGenesisTime, shouldErr: true, - description: "over delegation after AP3", }, } From 0ae53f88d17af83e7f8aa89a889b6ebb01e080cc Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 12:54:14 -0400 Subject: [PATCH 66/77] fix error --- vms/platformvm/txs/executor/proposal_tx_executor_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index cf4c64b25180..04c86098891e 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/hashing" @@ -888,7 +887,7 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { env.config.MinValidatorStake, uint64(defaultValidateStartTime.Unix())+1, uint64(defaultValidateEndTime.Unix()), - nodeID, + ids.GenerateTestNodeID(), ids.ShortEmpty, reward.PercentDenominator, []*secp256k1.PrivateKey{preFundedKeys[0]}, @@ -917,6 +916,6 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - require.ErrorIs(err, database.ErrNotFound) + require.ErrorIs(err, ErrFlowCheckFailed) } } From 67d2cc381194695fdcc0cfee34d65ddf6f8d692b Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 13:44:52 -0400 Subject: [PATCH 67/77] fixed proposal tx executor --- vms/platformvm/txs/executor/helpers_test.go | 4 +- .../txs/executor/proposal_tx_executor_test.go | 76 ++++++++----------- .../txs/executor/reward_validator_test.go | 2 +- 3 files changed, 36 insertions(+), 46 deletions(-) diff --git a/vms/platformvm/txs/executor/helpers_test.go b/vms/platformvm/txs/executor/helpers_test.go index 4921977b5364..1342c9e26302 100644 --- a/vms/platformvm/txs/executor/helpers_test.go +++ b/vms/platformvm/txs/executor/helpers_test.go @@ -51,7 +51,7 @@ import ( const ( testNetworkID = 10 // To be used in tests - defaultWeight = 10000 + defaultWeight = 5 * units.MilliAvax ) var ( @@ -59,7 +59,7 @@ var ( defaultMaxStakingDuration = 365 * 24 * time.Hour defaultGenesisTime = time.Date(1997, 1, 1, 0, 0, 0, 0, time.UTC) defaultValidateStartTime = defaultGenesisTime - defaultValidateEndTime = defaultValidateStartTime.Add(10 * defaultMinStakingDuration) + defaultValidateEndTime = defaultValidateStartTime.Add(20 * defaultMinStakingDuration) defaultMinValidatorStake = 5 * units.MilliAvax defaultBalance = 100 * defaultMinValidatorStake preFundedKeys = secp256k1.TestKeys() diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index 04c86098891e..a78e85808707 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/hashing" @@ -91,6 +92,11 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { dummyH := newEnvironment(false /*=postBanff*/, false /*=postCortina*/) currentTimestamp := dummyH.state.GetTimestamp() + _ = nodeID + _ = addMinStakeValidator + _ = addMaxStakeValidator + _ = currentTimestamp + type test struct { description string stakeAmount uint64 @@ -101,48 +107,36 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys []*secp256k1.PrivateKey setup func(*environment) AP3Time time.Time - shouldErr bool + expectedErr error } tests := []test{ { - description: "validator stops validating primary network earlier than subnet", + description: "validator stops validating earlier than delegator", stakeAmount: dummyH.config.MinDelegatorStake, - startTime: uint64(defaultValidateStartTime.Unix()), + startTime: uint64(defaultValidateStartTime.Unix()) + 1, endTime: uint64(defaultValidateEndTime.Unix()) + 1, nodeID: nodeID, rewardAddress: rewardAddress, feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: nil, AP3Time: defaultGenesisTime, - shouldErr: true, + expectedErr: ErrOverDelegated, }, { - description: fmt.Sprintf("validator should not be added more than (%s) in the future", MaxFutureStartTime), + description: fmt.Sprintf("delegator should not be added more than (%s) in the future", MaxFutureStartTime), stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(currentTimestamp.Add(MaxFutureStartTime + time.Second).Unix()), - endTime: uint64(currentTimestamp.Add(MaxFutureStartTime * 2).Unix()), + endTime: uint64(currentTimestamp.Add(MaxFutureStartTime + defaultMinStakingDuration + time.Second).Unix()), nodeID: nodeID, rewardAddress: rewardAddress, feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: nil, AP3Time: defaultGenesisTime, - shouldErr: true, + expectedErr: ErrFutureStakeTime, }, { - description: "end time is after the primary network end time", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: uint64(defaultValidateStartTime.Unix()), - endTime: uint64(defaultValidateEndTime.Unix()) + 1, - nodeID: nodeID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: nil, - AP3Time: defaultGenesisTime, - shouldErr: true, - }, - { - description: "validator not in the current or pending validator sets of the subnet", + description: "validator not in the current or pending validator sets", stakeAmount: dummyH.config.MinDelegatorStake, startTime: uint64(defaultValidateStartTime.Add(5 * time.Second).Unix()), endTime: uint64(defaultValidateEndTime.Add(-5 * time.Second).Unix()), @@ -151,10 +145,10 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: nil, AP3Time: defaultGenesisTime, - shouldErr: true, + expectedErr: database.ErrNotFound, }, { - description: "validator starts validating subnet before primary network", + description: "delegator starts before validator", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime - 1, // start validating subnet before primary network endTime: newValidatorEndTime, @@ -163,10 +157,10 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: addMinStakeValidator, AP3Time: defaultGenesisTime, - shouldErr: true, + expectedErr: ErrOverDelegated, }, { - description: "validator stops validating primary network before subnet", + description: "delegator stops before validator", stakeAmount: dummyH.config.MinDelegatorStake, startTime: newValidatorStartTime, endTime: newValidatorEndTime + 1, // stop validating subnet after stopping validating primary network @@ -175,7 +169,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: addMinStakeValidator, AP3Time: defaultGenesisTime, - shouldErr: true, + expectedErr: ErrOverDelegated, }, { description: "valid", @@ -187,10 +181,10 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: addMinStakeValidator, AP3Time: defaultGenesisTime, - shouldErr: false, + expectedErr: nil, }, { - description: "starts validating at current timestamp", + description: "starts delegating at current timestamp", stakeAmount: dummyH.config.MinDelegatorStake, // weight startTime: uint64(currentTimestamp.Unix()), // start time endTime: uint64(defaultValidateEndTime.Unix()), // end time @@ -199,16 +193,16 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, // tx fee payer setup: nil, AP3Time: defaultGenesisTime, - shouldErr: true, + expectedErr: ErrTimestampNotBeforeStartTime, }, { description: "tx fee paying key has no funds", - stakeAmount: dummyH.config.MinDelegatorStake, // weight - startTime: uint64(defaultValidateStartTime.Unix()), // start time - endTime: uint64(defaultValidateEndTime.Unix()), // end time - nodeID: nodeID, // node ID - rewardAddress: rewardAddress, // Reward Address - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[1]}, // tx fee payer + stakeAmount: dummyH.config.MinDelegatorStake, // weight + startTime: uint64(defaultValidateStartTime.Unix()) + 1, // start time + endTime: uint64(defaultValidateEndTime.Unix()), // end time + nodeID: nodeID, // node ID + rewardAddress: rewardAddress, // Reward Address + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[1]}, // tx fee payer setup: func(target *environment) { // Remove all UTXOs owned by keys[1] utxoIDs, err := target.state.UTXOIDs( preFundedKeys[1].PublicKey().Address().Bytes(), @@ -223,8 +217,8 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { err = target.state.Commit() require.NoError(t, err) }, - AP3Time: defaultGenesisTime, - shouldErr: true, + AP3Time: defaultGenesisTime, + expectedErr: ErrFlowCheckFailed, }, { description: "over delegation before AP3", @@ -236,7 +230,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: addMaxStakeValidator, AP3Time: defaultValidateEndTime, - shouldErr: false, + expectedErr: nil, }, { description: "over delegation after AP3", @@ -248,7 +242,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, setup: addMaxStakeValidator, AP3Time: defaultGenesisTime, - shouldErr: true, + expectedErr: ErrOverDelegated, }, } @@ -289,11 +283,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - if tt.shouldErr { - require.Error(err) - } else { - require.NoError(err) - } + require.ErrorIs(err, tt.expectedErr) }) } } diff --git a/vms/platformvm/txs/executor/reward_validator_test.go b/vms/platformvm/txs/executor/reward_validator_test.go index 619ff9052167..cd34cbdac060 100644 --- a/vms/platformvm/txs/executor/reward_validator_test.go +++ b/vms/platformvm/txs/executor/reward_validator_test.go @@ -121,7 +121,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { onCommitBalance, err := avax.GetBalance(env.state, stakeOwners) require.NoError(err) - require.Equal(oldBalance+stakerToRemove.Weight+27, onCommitBalance) + require.Equal(oldBalance+stakerToRemove.Weight+27697, onCommitBalance) } func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { From f9e34d42b28135c7e248b3d5af35b9e4e93f30c5 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 13:55:28 -0400 Subject: [PATCH 68/77] fix db manager tests --- database/leveldb/db.go | 7 +++++-- database/manager/manager_test.go | 7 ++++--- utils/metric/averager.go | 13 +++++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/database/leveldb/db.go b/database/leveldb/db.go index 4a8b651857d9..c227cfd8be97 100644 --- a/database/leveldb/db.go +++ b/database/leveldb/db.go @@ -69,6 +69,9 @@ var ( _ database.Database = (*Database)(nil) _ database.Batch = (*batch)(nil) _ database.Iterator = (*iter)(nil) + + ErrInvalidConfig = errors.New("invalid config") + ErrCouldNotOpen = errors.New("could not open") ) // Database is a persistent key-value store. Apart from basic data storage @@ -198,7 +201,7 @@ func New(file string, configBytes []byte, log logging.Logger, namespace string, } if len(configBytes) > 0 { if err := json.Unmarshal(configBytes, &parsedConfig); err != nil { - return nil, fmt.Errorf("failed to parse db config: %w", err) + return nil, fmt.Errorf("%w: %s", ErrInvalidConfig, err) } } @@ -228,7 +231,7 @@ func New(file string, configBytes []byte, log logging.Logger, namespace string, db, err = leveldb.RecoverFile(file, nil) } if err != nil { - return nil, err + return nil, fmt.Errorf("%w: %s", ErrCouldNotOpen, err) } wrappedDB := &Database{ diff --git a/database/manager/manager_test.go b/database/manager/manager_test.go index 0dd092f5e03b..e292024d6c5c 100644 --- a/database/manager/manager_test.go +++ b/database/manager/manager_test.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanchego/database/meterdb" "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/metric" "github.com/ava-labs/avalanchego/version" ) @@ -102,7 +103,7 @@ func TestNewInvalidMemberPresent(t *testing.T) { require.NoError(err) _, err = NewLevelDB(dir, nil, logging.NoLog{}, v2, "", prometheus.NewRegistry()) - require.Error(err, "expected to error creating the manager due to an open db") + require.ErrorIs(err, leveldb.ErrCouldNotOpen) err = db1.Close() require.NoError(err) @@ -314,7 +315,7 @@ func TestMeterDBManager(t *testing.T) { // Confirm that the error from a name conflict is handled correctly _, err = m.NewMeterDBManager("", registry) - require.Error(err) + require.ErrorIs(err, metric.ErrFailedRegistering) } func TestCompleteMeterDBManager(t *testing.T) { @@ -363,7 +364,7 @@ func TestCompleteMeterDBManager(t *testing.T) { // Confirm that the error from a name conflict is handled correctly _, err = m.NewCompleteMeterDBManager("", registry) - require.Error(err) + require.ErrorIs(err, metric.ErrFailedRegistering) } func TestNewManagerFromDBs(t *testing.T) { diff --git a/utils/metric/averager.go b/utils/metric/averager.go index 9cc4588dae1e..0293aebb9c58 100644 --- a/utils/metric/averager.go +++ b/utils/metric/averager.go @@ -4,6 +4,7 @@ package metric import ( + "errors" "fmt" "github.com/prometheus/client_golang/prometheus" @@ -11,6 +12,8 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" ) +var ErrFailedRegistering = errors.New("failed registering metric") + type Averager interface { Observe(float64) } @@ -40,10 +43,12 @@ func NewAveragerWithErrs(namespace, name, desc string, reg prometheus.Registerer }), } - errs.Add( - reg.Register(a.count), - reg.Register(a.sum), - ) + if err := reg.Register(a.count); err != nil { + errs.Add(fmt.Errorf("%w: %s", ErrFailedRegistering, err)) + } + if err := reg.Register(a.sum); err != nil { + errs.Add(fmt.Errorf("%w: %s", ErrFailedRegistering, err)) + } return &a } From e372eb2cea1386a3f148ca0ae88f69deefb0f877 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 13:56:27 -0400 Subject: [PATCH 69/77] nit --- vms/platformvm/txs/executor/proposal_tx_executor_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index a78e85808707..458aceb1776d 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -92,11 +92,6 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { dummyH := newEnvironment(false /*=postBanff*/, false /*=postCortina*/) currentTimestamp := dummyH.state.GetTimestamp() - _ = nodeID - _ = addMinStakeValidator - _ = addMaxStakeValidator - _ = currentTimestamp - type test struct { description string stakeAmount uint64 From 3dbd0727a2818ff008396aba0ebbdd5d801c1678 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 14:02:56 -0400 Subject: [PATCH 70/77] Fix standard tx executor --- .../txs/executor/standard_tx_executor_test.go | 251 +++++++++--------- 1 file changed, 121 insertions(+), 130 deletions(-) diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index c28112923494..c88358d7c8ee 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -167,123 +167,119 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { currentTimestamp := dummyH.state.GetTimestamp() type test struct { - description string - stakeAmount uint64 - startTime uint64 - endTime uint64 - nodeID ids.NodeID - rewardAddress ids.ShortID - feeKeys []*secp256k1.PrivateKey - setup func(*environment) - AP3Time time.Time - shouldErr bool + description string + stakeAmount uint64 + startTime uint64 + endTime uint64 + nodeID ids.NodeID + rewardAddress ids.ShortID + feeKeys []*secp256k1.PrivateKey + setup func(*environment) + AP3Time time.Time + expectedExecutionErr error + expectedMempoolErr error } tests := []test{ { - description: "validator stops validating primary network earlier than subnet", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: uint64(defaultValidateStartTime.Unix()), - endTime: uint64(defaultValidateEndTime.Unix()) + 1, - nodeID: nodeID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: nil, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: "validator stops validating earlier than delegator", + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: uint64(defaultValidateStartTime.Unix()) + 1, + endTime: uint64(defaultValidateEndTime.Unix()) + 1, + nodeID: nodeID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: nil, + AP3Time: defaultGenesisTime, + expectedExecutionErr: ErrOverDelegated, + expectedMempoolErr: ErrOverDelegated, }, { - description: fmt.Sprintf("validator should not be added more than (%s) in the future", MaxFutureStartTime), - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: uint64(currentTimestamp.Add(MaxFutureStartTime + time.Second).Unix()), - endTime: uint64(currentTimestamp.Add(MaxFutureStartTime * 2).Unix()), - nodeID: nodeID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: nil, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: fmt.Sprintf("delegator should not be added more than (%s) in the future", MaxFutureStartTime), + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: uint64(currentTimestamp.Add(MaxFutureStartTime + time.Second).Unix()), + endTime: uint64(currentTimestamp.Add(MaxFutureStartTime + defaultMinStakingDuration + time.Second).Unix()), + nodeID: nodeID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: nil, + AP3Time: defaultGenesisTime, + expectedExecutionErr: ErrFutureStakeTime, + expectedMempoolErr: nil, }, { - description: "end time is after the primary network end time", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: uint64(defaultValidateStartTime.Unix()), - endTime: uint64(defaultValidateEndTime.Unix()) + 1, - nodeID: nodeID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: nil, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: "validator not in the current or pending validator sets", + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: uint64(defaultValidateStartTime.Add(5 * time.Second).Unix()), + endTime: uint64(defaultValidateEndTime.Add(-5 * time.Second).Unix()), + nodeID: newValidatorID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: nil, + AP3Time: defaultGenesisTime, + expectedExecutionErr: database.ErrNotFound, + expectedMempoolErr: database.ErrNotFound, }, { - description: "validator not in the current or pending validator sets of the subnet", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: uint64(defaultValidateStartTime.Add(5 * time.Second).Unix()), - endTime: uint64(defaultValidateEndTime.Add(-5 * time.Second).Unix()), - nodeID: newValidatorID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: nil, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: "delegator starts before validator", + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: newValidatorStartTime - 1, // start validating subnet before primary network + endTime: newValidatorEndTime, + nodeID: newValidatorID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: addMinStakeValidator, + AP3Time: defaultGenesisTime, + expectedExecutionErr: ErrOverDelegated, + expectedMempoolErr: ErrOverDelegated, }, { - description: "validator starts validating subnet before primary network", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: newValidatorStartTime - 1, // start validating subnet before primary network - endTime: newValidatorEndTime, - nodeID: newValidatorID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: addMinStakeValidator, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: "delegator stops before validator", + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: newValidatorStartTime, + endTime: newValidatorEndTime + 1, // stop validating subnet after stopping validating primary network + nodeID: newValidatorID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: addMinStakeValidator, + AP3Time: defaultGenesisTime, + expectedExecutionErr: ErrOverDelegated, + expectedMempoolErr: ErrOverDelegated, }, { - description: "validator stops validating primary network before subnet", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: newValidatorStartTime, - endTime: newValidatorEndTime + 1, // stop validating subnet after stopping validating primary network - nodeID: newValidatorID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: addMinStakeValidator, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: "valid", + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: newValidatorStartTime, // same start time as for primary network + endTime: newValidatorEndTime, // same end time as for primary network + nodeID: newValidatorID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: addMinStakeValidator, + AP3Time: defaultGenesisTime, + expectedExecutionErr: nil, + expectedMempoolErr: nil, }, { - description: "valid", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: newValidatorStartTime, // same start time as for primary network - endTime: newValidatorEndTime, // same end time as for primary network - nodeID: newValidatorID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: addMinStakeValidator, - AP3Time: defaultGenesisTime, - shouldErr: false, - }, - { - description: "starts validating at current timestamp", - stakeAmount: dummyH.config.MinDelegatorStake, // weight - startTime: uint64(currentTimestamp.Unix()), // start time - endTime: uint64(defaultValidateEndTime.Unix()), // end time - nodeID: nodeID, // node ID - rewardAddress: rewardAddress, // Reward Address - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, // tx fee payer - setup: nil, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: "starts delegating at current timestamp", + stakeAmount: dummyH.config.MinDelegatorStake, // weight + startTime: uint64(currentTimestamp.Unix()), // start time + endTime: uint64(defaultValidateEndTime.Unix()), // end time + nodeID: nodeID, // node ID + rewardAddress: rewardAddress, // Reward Address + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, // tx fee payer + setup: nil, + AP3Time: defaultGenesisTime, + expectedExecutionErr: ErrTimestampNotBeforeStartTime, + expectedMempoolErr: ErrTimestampNotBeforeStartTime, }, { description: "tx fee paying key has no funds", - stakeAmount: dummyH.config.MinDelegatorStake, // weight - startTime: uint64(defaultValidateStartTime.Unix()), // start time - endTime: uint64(defaultValidateEndTime.Unix()), // end time - nodeID: nodeID, // node ID - rewardAddress: rewardAddress, // Reward Address - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[1]}, // tx fee payer + stakeAmount: dummyH.config.MinDelegatorStake, // weight + startTime: uint64(defaultValidateStartTime.Unix()) + 1, // start time + endTime: uint64(defaultValidateEndTime.Unix()), // end time + nodeID: nodeID, // node ID + rewardAddress: rewardAddress, // Reward Address + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[1]}, // tx fee payer setup: func(target *environment) { // Remove all UTXOs owned by keys[1] utxoIDs, err := target.state.UTXOIDs( preFundedKeys[1].PublicKey().Address().Bytes(), @@ -298,32 +294,35 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { err = target.state.Commit() require.NoError(t, err) }, - AP3Time: defaultGenesisTime, - shouldErr: true, + AP3Time: defaultGenesisTime, + expectedExecutionErr: ErrFlowCheckFailed, + expectedMempoolErr: ErrFlowCheckFailed, }, { - description: "over delegation before AP3", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: newValidatorStartTime, // same start time as for primary network - endTime: newValidatorEndTime, // same end time as for primary network - nodeID: newValidatorID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: addMaxStakeValidator, - AP3Time: defaultValidateEndTime, - shouldErr: false, + description: "over delegation before AP3", + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: newValidatorStartTime, // same start time as for primary network + endTime: newValidatorEndTime, // same end time as for primary network + nodeID: newValidatorID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: addMaxStakeValidator, + AP3Time: defaultValidateEndTime, + expectedExecutionErr: nil, + expectedMempoolErr: nil, }, { - description: "over delegation after AP3", - stakeAmount: dummyH.config.MinDelegatorStake, - startTime: newValidatorStartTime, // same start time as for primary network - endTime: newValidatorEndTime, // same end time as for primary network - nodeID: newValidatorID, - rewardAddress: rewardAddress, - feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, - setup: addMaxStakeValidator, - AP3Time: defaultGenesisTime, - shouldErr: true, + description: "over delegation after AP3", + stakeAmount: dummyH.config.MinDelegatorStake, + startTime: newValidatorStartTime, // same start time as for primary network + endTime: newValidatorEndTime, // same end time as for primary network + nodeID: newValidatorID, + rewardAddress: rewardAddress, + feeKeys: []*secp256k1.PrivateKey{preFundedKeys[0]}, + setup: addMaxStakeValidator, + AP3Time: defaultGenesisTime, + expectedExecutionErr: ErrOverDelegated, + expectedMempoolErr: ErrOverDelegated, }, } @@ -362,11 +361,7 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&executor) - if tt.shouldErr { - require.Error(err) - } else { - require.NoError(err) - } + require.ErrorIs(err, tt.expectedExecutionErr) mempoolExecutor := MempoolTxVerifier{ Backend: &freshTH.backend, @@ -375,11 +370,7 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { Tx: tx, } err = tx.Unsigned.Visit(&mempoolExecutor) - if tt.shouldErr { - require.Error(err) - } else { - require.NoError(err) - } + require.ErrorIs(err, tt.expectedMempoolErr) }) } } From f60207e2edaaf5f3624555257291fef7fd561aa3 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 14:32:22 -0400 Subject: [PATCH 71/77] Fix config tests --- config/config.go | 8 +- config/config_test.go | 111 ++++++++++++------------- snow/consensus/avalanche/parameters.go | 4 +- snow/consensus/snowball/parameters.go | 27 +++--- subnets/config.go | 2 +- 5 files changed, 76 insertions(+), 76 deletions(-) diff --git a/config/config.go b/config/config.go index 26d99dadd93a..8171a347ba46 100644 --- a/config/config.go +++ b/config/config.go @@ -87,6 +87,8 @@ var ( errPluginDirNotADirectory = errors.New("plugin dir is not a directory") errZstdNotSupported = errors.New("zstd compression not supported until v1.10") errCannotReadDirectory = errors.New("cannot read directory") + errUnmarshalling = errors.New("unmarshalling failed") + errFileDoesNotExist = errors.New("file does not exist") ) func getConsensusConfig(v *viper.Viper) avalanche.Parameters { @@ -953,7 +955,7 @@ func getAliases(v *viper.Viper, name string, contentKey string, fileKey string) if !exists { if v.IsSet(fileKey) { - return nil, fmt.Errorf("%s file does not exist in %v", name, aliasFilePath) + return nil, fmt.Errorf("%w: %s", errFileDoesNotExist, aliasFilePath) } return nil, nil } @@ -966,7 +968,7 @@ func getAliases(v *viper.Viper, name string, contentKey string, fileKey string) aliasMap := make(map[ids.ID][]string) if err := json.Unmarshal(fileBytes, &aliasMap); err != nil { - return nil, fmt.Errorf("problem unmarshaling %s: %w", name, err) + return nil, fmt.Errorf("%w on %s: %s", errUnmarshalling, name, err) } return aliasMap, nil } @@ -1162,7 +1164,7 @@ func getSubnetConfigsFromDir(v *viper.Viper, subnetIDs []ids.ID) (map[ids.ID]sub config := getDefaultSubnetConfig(v) if err := json.Unmarshal(file, &config); err != nil { - return nil, err + return nil, fmt.Errorf("%w: %s", errUnmarshalling, err) } if err := config.Valid(); err != nil { diff --git a/config/config_test.go b/config/config_test.go index 3f4e8913f5f5..6ef2568c7c94 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -19,6 +19,7 @@ import ( "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/consensus/snowball" "github.com/ava-labs/avalanchego/subnets" ) @@ -239,14 +240,14 @@ func TestGetChainConfigsFromFlags(t *testing.T) { func TestGetVMAliasesFromFile(t *testing.T) { tests := map[string]struct { - givenJSON string - expected map[ids.ID][]string - errMessage string + givenJSON string + expected map[ids.ID][]string + expectedErr error }{ "wrong vm id": { - givenJSON: `{"wrongVmId": ["vm1","vm2"]}`, - expected: nil, - errMessage: "problem unmarshaling vm aliases", + givenJSON: `{"wrongVmId": ["vm1","vm2"]}`, + expected: nil, + expectedErr: errUnmarshalling, }, "vm id": { givenJSON: `{"2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i": ["vm1","vm2"], @@ -259,7 +260,7 @@ func TestGetVMAliasesFromFile(t *testing.T) { m[id2] = []string{"vm3", "vm4"} return m }(), - errMessage: "", + expectedErr: nil, }, } @@ -273,27 +274,22 @@ func TestGetVMAliasesFromFile(t *testing.T) { setupFile(t, root, "aliases.json", test.givenJSON) v := setupViper(configFilePath) vmAliases, err := getVMAliases(v) - if len(test.errMessage) > 0 { - require.Error(err) - require.Contains(err.Error(), test.errMessage) - } else { - require.NoError(err) - require.Equal(test.expected, vmAliases) - } + require.ErrorIs(err, test.expectedErr) + require.Equal(test.expected, vmAliases) }) } } func TestGetVMAliasesFromFlag(t *testing.T) { tests := map[string]struct { - givenJSON string - expected map[ids.ID][]string - errMessage string + givenJSON string + expected map[ids.ID][]string + expectedErr error }{ "wrong vm id": { - givenJSON: `{"wrongVmId": ["vm1","vm2"]}`, - expected: nil, - errMessage: "problem unmarshaling vm aliases", + givenJSON: `{"wrongVmId": ["vm1","vm2"]}`, + expected: nil, + expectedErr: errUnmarshalling, }, "vm id": { givenJSON: `{"2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i": ["vm1","vm2"], @@ -306,7 +302,7 @@ func TestGetVMAliasesFromFlag(t *testing.T) { m[id2] = []string{"vm3", "vm4"} return m }(), - errMessage: "", + expectedErr: nil, }, } @@ -320,13 +316,8 @@ func TestGetVMAliasesFromFlag(t *testing.T) { v.Set(VMAliasesContentKey, encodedFileContent) vmAliases, err := getVMAliases(v) - if len(test.errMessage) > 0 { - require.Error(err) - require.Contains(err.Error(), test.errMessage) - } else { - require.NoError(err) - require.Equal(test.expected, vmAliases) - } + require.ErrorIs(err, test.expectedErr) + require.Equal(test.expected, vmAliases) }) } } @@ -360,9 +351,8 @@ func TestGetVMAliasesDirNotExists(t *testing.T) { configFilePath := setupConfigJSON(t, root, configJSON) v := setupViper(configFilePath) vmAliases, err := getVMAliases(v) + require.ErrorIs(err, errFileDoesNotExist) require.Nil(vmAliases) - require.Error(err) - require.Contains(err.Error(), "vm aliases file does not exist") // do not set it explicitly configJSON = "{}" @@ -374,11 +364,14 @@ func TestGetVMAliasesDirNotExists(t *testing.T) { } func TestGetSubnetConfigsFromFile(t *testing.T) { + subnetID, err := ids.FromString("2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i") + require.NoError(t, err) + tests := map[string]struct { - givenJSON string - testF func(*require.Assertions, map[ids.ID]subnets.Config) - errMessage string - fileName string + fileName string + givenJSON string + testF func(*require.Assertions, map[ids.ID]subnets.Config) + expectedErr error }{ "wrong config": { fileName: "2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i.json", @@ -386,7 +379,7 @@ func TestGetSubnetConfigsFromFile(t *testing.T) { testF: func(require *require.Assertions, given map[ids.ID]subnets.Config) { require.Nil(given) }, - errMessage: "invalid character", + expectedErr: errUnmarshalling, }, "subnet is not tracked": { fileName: "Gmt4fuNsGJAd2PX86LBvycGaBpgCYKbuULdCLZs3SEs1Jx1LU.json", @@ -394,6 +387,7 @@ func TestGetSubnetConfigsFromFile(t *testing.T) { testF: func(require *require.Assertions, given map[ids.ID]subnets.Config) { require.Empty(given) }, + expectedErr: nil, }, "wrong extension": { fileName: "2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i.yaml", @@ -401,6 +395,7 @@ func TestGetSubnetConfigsFromFile(t *testing.T) { testF: func(require *require.Assertions, given map[ids.ID]subnets.Config) { require.Empty(given) }, + expectedErr: nil, }, "invalid consensus parameters": { fileName: "2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i.json", @@ -408,7 +403,7 @@ func TestGetSubnetConfigsFromFile(t *testing.T) { testF: func(require *require.Assertions, given map[ids.ID]subnets.Config) { require.Nil(given) }, - errMessage: "fails the condition that: alpha <= k", + expectedErr: snowball.ErrParametersInvalid, }, "correct config": { fileName: "2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i.json", @@ -424,7 +419,7 @@ func TestGetSubnetConfigsFromFile(t *testing.T) { // must still respect defaults require.Equal(20, config.ConsensusParameters.K) }, - errMessage: "", + expectedErr: nil, }, "gossip config": { fileName: "2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i.json", @@ -438,27 +433,26 @@ func TestGetSubnetConfigsFromFile(t *testing.T) { require.Equal(20, config.ConsensusParameters.K) require.Equal(uint(10), config.GossipConfig.AppGossipValidatorSize) }, - errMessage: "", + expectedErr: nil, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { require := require.New(t) + root := t.TempDir() subnetPath := filepath.Join(root, "subnets") + configJSON := fmt.Sprintf(`{%q: %q}`, SubnetConfigDirKey, subnetPath) configFilePath := setupConfigJSON(t, root, configJSON) - subnetID, err := ids.FromString("2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i") - require.NoError(err) + setupFile(t, subnetPath, test.fileName, test.givenJSON) + v := setupViper(configFilePath) subnetConfigs, err := getSubnetConfigs(v, []ids.ID{subnetID}) - if len(test.errMessage) > 0 { - require.Error(err) - require.Contains(err.Error(), test.errMessage) - } else { - require.NoError(err) + require.ErrorIs(err, test.expectedErr) + if test.expectedErr == nil { test.testF(require, subnetConfigs) } }) @@ -466,17 +460,20 @@ func TestGetSubnetConfigsFromFile(t *testing.T) { } func TestGetSubnetConfigsFromFlags(t *testing.T) { + subnetID, err := ids.FromString("2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i") + require.NoError(t, err) + tests := map[string]struct { - givenJSON string - testF func(*require.Assertions, map[ids.ID]subnets.Config) - errMessage string + givenJSON string + testF func(*require.Assertions, map[ids.ID]subnets.Config) + expectedErr error }{ "no configs": { givenJSON: `{}`, testF: func(require *require.Assertions, given map[ids.ID]subnets.Config) { require.Empty(given) }, - errMessage: "", + expectedErr: nil, }, "entry with no config": { givenJSON: `{"2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i":{}}`, @@ -488,12 +485,14 @@ func TestGetSubnetConfigsFromFlags(t *testing.T) { // should respect defaults require.Equal(20, config.ConsensusParameters.K) }, + expectedErr: nil, }, "subnet is not tracked": { givenJSON: `{"Gmt4fuNsGJAd2PX86LBvycGaBpgCYKbuULdCLZs3SEs1Jx1LU":{"validatorOnly":true}}`, testF: func(require *require.Assertions, given map[ids.ID]subnets.Config) { require.Empty(given) }, + expectedErr: nil, }, "invalid consensus parameters": { givenJSON: `{ @@ -507,7 +506,7 @@ func TestGetSubnetConfigsFromFlags(t *testing.T) { testF: func(require *require.Assertions, given map[ids.ID]subnets.Config) { require.Empty(given) }, - errMessage: "fails the condition that: alpha <= k", + expectedErr: snowball.ErrParametersInvalid, }, "correct config": { givenJSON: `{ @@ -532,15 +531,14 @@ func TestGetSubnetConfigsFromFlags(t *testing.T) { require.Equal(uint(10), config.GossipConfig.AppGossipValidatorSize) require.Equal(256, config.ConsensusParameters.MaxOutstandingItems) }, - errMessage: "", + expectedErr: nil, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { require := require.New(t) - subnetID, err := ids.FromString("2Ctt6eGAeo4MLqTmGa7AdRecuVMPGWEX9wSsCLBYrLhX4a394i") - require.NoError(err) + encodedFileContent := base64.StdEncoding.EncodeToString([]byte(test.givenJSON)) // build viper config @@ -548,11 +546,8 @@ func TestGetSubnetConfigsFromFlags(t *testing.T) { v.Set(SubnetConfigContentKey, encodedFileContent) subnetConfigs, err := getSubnetConfigs(v, []ids.ID{subnetID}) - if len(test.errMessage) > 0 { - require.Error(err) - require.Contains(err.Error(), test.errMessage) - } else { - require.NoError(err) + require.ErrorIs(err, test.expectedErr) + if test.expectedErr == nil { test.testF(require, subnetConfigs) } }) diff --git a/snow/consensus/avalanche/parameters.go b/snow/consensus/avalanche/parameters.go index 9027df61e0be..4bd2df084cc8 100644 --- a/snow/consensus/avalanche/parameters.go +++ b/snow/consensus/avalanche/parameters.go @@ -21,9 +21,9 @@ type Parameters struct { func (p Parameters) Valid() error { switch { case p.Parents <= 1: - return fmt.Errorf("parents = %d: Fails the condition that: 1 < Parents", p.Parents) + return fmt.Errorf("%w: parents = %d: Fails the condition that: 1 < Parents", snowball.ErrParametersInvalid, p.Parents) case p.BatchSize <= 0: - return fmt.Errorf("batchSize = %d: Fails the condition that: 0 < BatchSize", p.BatchSize) + return fmt.Errorf("%w: batchSize = %d: Fails the condition that: 0 < BatchSize", snowball.ErrParametersInvalid, p.BatchSize) default: return p.Parameters.Verify() } diff --git a/snow/consensus/snowball/parameters.go b/snow/consensus/snowball/parameters.go index 460f9940fafc..e7cc8a6848b6 100644 --- a/snow/consensus/snowball/parameters.go +++ b/snow/consensus/snowball/parameters.go @@ -4,6 +4,7 @@ package snowball import ( + "errors" "fmt" "time" ) @@ -26,6 +27,8 @@ const ( ` \/ \/ \/` + "\n" ) +var ErrParametersInvalid = errors.New("parameters invalid") + // Parameters required for snowball consensus type Parameters struct { K int `json:"k" yaml:"k"` @@ -57,29 +60,29 @@ type Parameters struct { func (p Parameters) Verify() error { switch { case p.Alpha <= p.K/2: - return fmt.Errorf("k = %d, alpha = %d: fails the condition that: k/2 < alpha", p.K, p.Alpha) + return fmt.Errorf("%w: k = %d, alpha = %d: fails the condition that: k/2 < alpha", ErrParametersInvalid, p.K, p.Alpha) case p.K < p.Alpha: - return fmt.Errorf("k = %d, alpha = %d: fails the condition that: alpha <= k", p.K, p.Alpha) + return fmt.Errorf("%w: k = %d, alpha = %d: fails the condition that: alpha <= k", ErrParametersInvalid, p.K, p.Alpha) case p.BetaVirtuous <= 0: - return fmt.Errorf("betaVirtuous = %d: fails the condition that: 0 < betaVirtuous", p.BetaVirtuous) + return fmt.Errorf("%w: betaVirtuous = %d: fails the condition that: 0 < betaVirtuous", ErrParametersInvalid, p.BetaVirtuous) case p.BetaRogue == 3 && p.BetaVirtuous == 28: - return fmt.Errorf("betaVirtuous = %d, betaRogue = %d: fails the condition that: betaVirtuous <= betaRogue\n%s", p.BetaVirtuous, p.BetaRogue, errMsg) + return fmt.Errorf("%w: betaVirtuous = %d, betaRogue = %d: fails the condition that: betaVirtuous <= betaRogue\n%s", ErrParametersInvalid, p.BetaVirtuous, p.BetaRogue, errMsg) case p.BetaRogue < p.BetaVirtuous: - return fmt.Errorf("betaVirtuous = %d, betaRogue = %d: fails the condition that: betaVirtuous <= betaRogue", p.BetaVirtuous, p.BetaRogue) + return fmt.Errorf("%w: betaVirtuous = %d, betaRogue = %d: fails the condition that: betaVirtuous <= betaRogue", ErrParametersInvalid, p.BetaVirtuous, p.BetaRogue) case p.ConcurrentRepolls <= 0: - return fmt.Errorf("concurrentRepolls = %d: fails the condition that: 0 < concurrentRepolls", p.ConcurrentRepolls) + return fmt.Errorf("%w: concurrentRepolls = %d: fails the condition that: 0 < concurrentRepolls", ErrParametersInvalid, p.ConcurrentRepolls) case p.ConcurrentRepolls > p.BetaRogue: - return fmt.Errorf("concurrentRepolls = %d, betaRogue = %d: fails the condition that: concurrentRepolls <= betaRogue", p.ConcurrentRepolls, p.BetaRogue) + return fmt.Errorf("%w: concurrentRepolls = %d, betaRogue = %d: fails the condition that: concurrentRepolls <= betaRogue", ErrParametersInvalid, p.ConcurrentRepolls, p.BetaRogue) case p.OptimalProcessing <= 0: - return fmt.Errorf("optimalProcessing = %d: fails the condition that: 0 < optimalProcessing", p.OptimalProcessing) + return fmt.Errorf("%w: optimalProcessing = %d: fails the condition that: 0 < optimalProcessing", ErrParametersInvalid, p.OptimalProcessing) case p.MaxOutstandingItems <= 0: - return fmt.Errorf("maxOutstandingItems = %d: fails the condition that: 0 < maxOutstandingItems", p.MaxOutstandingItems) + return fmt.Errorf("%w: maxOutstandingItems = %d: fails the condition that: 0 < maxOutstandingItems", ErrParametersInvalid, p.MaxOutstandingItems) case p.MaxItemProcessingTime <= 0: - return fmt.Errorf("maxItemProcessingTime = %d: fails the condition that: 0 < maxItemProcessingTime", p.MaxItemProcessingTime) + return fmt.Errorf("%w: maxItemProcessingTime = %d: fails the condition that: 0 < maxItemProcessingTime", ErrParametersInvalid, p.MaxItemProcessingTime) case p.MixedQueryNumPushVdr > p.K: - return fmt.Errorf("mixedQueryNumPushVdr (%d) > K (%d)", p.MixedQueryNumPushVdr, p.K) + return fmt.Errorf("%w: mixedQueryNumPushVdr (%d) > K (%d)", ErrParametersInvalid, p.MixedQueryNumPushVdr, p.K) case p.MixedQueryNumPushNonVdr > p.K: - return fmt.Errorf("mixedQueryNumPushNonVdr (%d) > K (%d)", p.MixedQueryNumPushNonVdr, p.K) + return fmt.Errorf("%w: mixedQueryNumPushNonVdr (%d) > K (%d)", ErrParametersInvalid, p.MixedQueryNumPushNonVdr, p.K) default: return nil } diff --git a/subnets/config.go b/subnets/config.go index cdec292c957f..c35bb3407098 100644 --- a/subnets/config.go +++ b/subnets/config.go @@ -51,7 +51,7 @@ type Config struct { func (c *Config) Valid() error { if err := c.ConsensusParameters.Valid(); err != nil { - return fmt.Errorf("consensus parameters are invalid: %w", err) + return fmt.Errorf("consensus %w", err) } if !c.ValidatorOnly && c.AllowedNodes.Len() > 0 { return errAllowedNodesWhenNotValidatorOnly From 8926e2fc192ce3c4ec89cfef52d2f32c439481c8 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 20 Apr 2023 14:38:18 -0400 Subject: [PATCH 72/77] Remove require.ErrorContains --- .golangci.yml | 1 + subnets/config_test.go | 17 +++++++---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index c89d83c41b62..fa13accfb720 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -66,6 +66,7 @@ linters-settings: # Forbid the following identifiers (list of regexp). forbid: - 'require\.Error$(# ErrorIs should be used instead)?' + - 'require\.ErrorContains$(# ErrorIs should be used instead)?' exclude_godoc_examples: false # https://golangci-lint.run/usage/linters#gosec gosec: diff --git a/subnets/config_test.go b/subnets/config_test.go index f745a4f41ad1..01a482d3266c 100644 --- a/subnets/config_test.go +++ b/subnets/config_test.go @@ -31,9 +31,9 @@ var validParameters = avalanche.Parameters{ func TestValid(t *testing.T) { tests := []struct { - name string - s Config - err string + name string + s Config + expectedErr error }{ { name: "invalid consensus parameters", @@ -45,7 +45,7 @@ func TestValid(t *testing.T) { }, }, }, - err: "consensus parameters are invalid", + expectedErr: snowball.ErrParametersInvalid, }, { name: "invalid allowed node IDs", @@ -54,7 +54,7 @@ func TestValid(t *testing.T) { ValidatorOnly: false, ConsensusParameters: validParameters, }, - err: errAllowedNodesWhenNotValidatorOnly.Error(), + expectedErr: errAllowedNodesWhenNotValidatorOnly, }, { name: "valid", @@ -62,16 +62,13 @@ func TestValid(t *testing.T) { ConsensusParameters: validParameters, ValidatorOnly: false, }, + expectedErr: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := tt.s.Valid() - if tt.err != "" { - require.ErrorContains(t, err, tt.err) - } else { - require.NoError(t, err) - } + require.ErrorIs(t, err, tt.expectedErr) }) } } From ab7c2bc359489193bfe5740536aca0fd80feb168 Mon Sep 17 00:00:00 2001 From: Stephen Date: Fri, 21 Apr 2023 15:07:53 -0400 Subject: [PATCH 73/77] Improve codec/ error handling --- codec/codec.go | 14 +++++++++++- codec/hierarchycodec/codec.go | 8 +++++-- codec/linearcodec/codec.go | 8 +++++-- codec/manager.go | 14 ++++++------ codec/reflectcodec/struct_fielder.go | 7 +++++- codec/reflectcodec/type_codec.go | 32 +++++++++++++++++----------- codec/registry.go | 4 ++++ codec/test_codec.go | 24 ++++++++++----------- 8 files changed, 75 insertions(+), 36 deletions(-) diff --git a/codec/codec.go b/codec/codec.go index 004b2553437c..413b6d174be2 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -3,7 +3,19 @@ package codec -import "github.com/ava-labs/avalanchego/utils/wrappers" +import ( + "errors" + + "github.com/ava-labs/avalanchego/utils/wrappers" +) + +var ( + ErrUnsupportedType = errors.New("unsupported type") + ErrMaxSliceLenExceeded = errors.New("max slice length exceeded") + ErrDoesNotImplementInterface = errors.New("does not implement interface") + ErrUnexportedField = errors.New("unexported field") + ErrExtraSpace = errors.New("trailing buffer space") +) // Codec marshals and unmarshals type Codec interface { diff --git a/codec/hierarchycodec/codec.go b/codec/hierarchycodec/codec.go index af66bf244690..d1d03d879275 100644 --- a/codec/hierarchycodec/codec.go +++ b/codec/hierarchycodec/codec.go @@ -89,7 +89,7 @@ func (c *hierarchyCodec) RegisterType(val interface{}) error { valType := reflect.TypeOf(val) if _, exists := c.typeToTypeID[valType]; exists { - return fmt.Errorf("type %v has already been registered", valType) + return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType) } valTypeID := typeID{ @@ -142,7 +142,11 @@ func (c *hierarchyCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type } // Ensure type actually does implement the interface if !implementingType.Implements(valueType) { - return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s does not implement interface %s", implementingType, valueType) + return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s %w %s", + implementingType, + codec.ErrDoesNotImplementInterface, + valueType, + ) } return reflect.New(implementingType).Elem(), nil // instance of the proper type } diff --git a/codec/linearcodec/codec.go b/codec/linearcodec/codec.go index 30b317c8a650..d488b3a1d4c0 100644 --- a/codec/linearcodec/codec.go +++ b/codec/linearcodec/codec.go @@ -79,7 +79,7 @@ func (c *linearCodec) RegisterType(val interface{}) error { valType := reflect.TypeOf(val) if _, exists := c.typeToTypeID[valType]; exists { - return fmt.Errorf("type %v has already been registered", valType) + return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType) } c.typeIDToType[c.nextTypeID] = valType @@ -120,7 +120,11 @@ func (c *linearCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type) ( } // Ensure type actually does implement the interface if !implementingType.Implements(valueType) { - return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s does not implement interface %s", implementingType, valueType) + return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s %w %s", + implementingType, + codec.ErrDoesNotImplementInterface, + valueType, + ) } return reflect.New(implementingType).Elem(), nil // instance of the proper type } diff --git a/codec/manager.go b/codec/manager.go index 8cfefc6b99a2..83f2c0b0e183 100644 --- a/codec/manager.go +++ b/codec/manager.go @@ -23,11 +23,13 @@ const ( ) var ( + ErrUnknownVersion = errors.New("unknown codec version") + errMarshalNil = errors.New("can't marshal nil pointer or interface") errUnmarshalNil = errors.New("can't unmarshal nil") + errUnmarshalTooBig = errors.New("byte array exceeds maximum length") errCantPackVersion = errors.New("couldn't pack codec version") errCantUnpackVersion = errors.New("couldn't unpack codec version") - errUnknownVersion = errors.New("unknown codec version") errDuplicatedVersion = errors.New("duplicated codec version") ) @@ -107,7 +109,7 @@ func (m *manager) Size(version uint16, value interface{}) (int, error) { m.lock.RUnlock() if !exists { - return 0, errUnknownVersion + return 0, ErrUnknownVersion } res, err := c.Size(value) @@ -127,7 +129,7 @@ func (m *manager) Marshal(version uint16, value interface{}) ([]byte, error) { m.lock.RUnlock() if !exists { - return nil, errUnknownVersion + return nil, ErrUnknownVersion } p := wrappers.Packer{ @@ -149,9 +151,9 @@ func (m *manager) Unmarshal(bytes []byte, dest interface{}) (uint16, error) { } m.lock.RLock() - if len(bytes) > m.maxSize { + if byteLen := len(bytes); byteLen > m.maxSize { m.lock.RUnlock() - return 0, fmt.Errorf("byte array exceeds maximum length, %d", m.maxSize) + return 0, fmt.Errorf("%w: %d > %d", errUnmarshalTooBig, byteLen, m.maxSize) } p := wrappers.Packer{ @@ -167,7 +169,7 @@ func (m *manager) Unmarshal(bytes []byte, dest interface{}) (uint16, error) { c, exists := m.codecs[version] m.lock.RUnlock() if !exists { - return version, errUnknownVersion + return version, ErrUnknownVersion } return version, c.Unmarshal(p.Bytes[p.Offset:], dest) } diff --git a/codec/reflectcodec/struct_fielder.go b/codec/reflectcodec/struct_fielder.go index 7a54182ccb66..27edb58a1793 100644 --- a/codec/reflectcodec/struct_fielder.go +++ b/codec/reflectcodec/struct_fielder.go @@ -8,6 +8,8 @@ import ( "reflect" "strconv" "sync" + + "github.com/ava-labs/avalanchego/codec" ) const ( @@ -91,7 +93,10 @@ func (s *structFielder) GetSerializedFields(t reflect.Type) ([]FieldDesc, error) continue } if !field.IsExported() { // Can only marshal exported fields - return nil, fmt.Errorf("can't marshal un-exported field %s", field.Name) + return nil, fmt.Errorf("can not marshal %w: %s", + codec.ErrUnexportedField, + field.Name, + ) } sliceLenField := field.Tag.Get(SliceLenTagName) maxSliceLen := s.maxSliceLen diff --git a/codec/reflectcodec/type_codec.go b/codec/reflectcodec/type_codec.go index a92ade189bf5..c4a0afbf32ef 100644 --- a/codec/reflectcodec/type_codec.go +++ b/codec/reflectcodec/type_codec.go @@ -19,12 +19,9 @@ const ( ) var ( - ErrMaxMarshalSliceLimitExceeded = errors.New("maximum marshal slice limit exceeded") - errMarshalNil = errors.New("can't marshal nil pointer or interface") errUnmarshalNil = errors.New("can't unmarshal nil") errNeedPointer = errors.New("argument to unmarshal must be a pointer") - errExtraSpace = errors.New("trailing buffer space") ) var _ codec.Codec = (*genericCodec)(nil) @@ -278,9 +275,10 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice numElts := value.Len() // # elements in the slice/array. 0 if this slice is nil. if uint32(numElts) > maxSliceLen { return fmt.Errorf("%w; slice length, %d, exceeds maximum length, %d", - ErrMaxMarshalSliceLimitExceeded, + codec.ErrMaxSliceLenExceeded, numElts, - maxSliceLen) + maxSliceLen, + ) } p.PackInt(uint32(numElts)) // pack # elements if p.Err != nil { @@ -312,7 +310,11 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice return p.Err } if uint32(numElts) > c.maxSliceLen { - return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", ErrMaxMarshalSliceLimitExceeded, numElts, c.maxSliceLen) + return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", + codec.ErrMaxSliceLenExceeded, + numElts, + c.maxSliceLen, + ) } for i := 0; i < numElts; i++ { // Process each element in the array if err := c.marshal(value.Index(i), p, c.maxSliceLen); err != nil { @@ -332,7 +334,7 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice } return nil default: - return fmt.Errorf("can't marshal unknown kind %s", valueKind) + return fmt.Errorf("%w: %s", codec.ErrUnsupportedType, valueKind) } } @@ -354,7 +356,11 @@ func (c *genericCodec) Unmarshal(bytes []byte, dest interface{}) error { return err } if p.Offset != len(bytes) { - return errExtraSpace + return fmt.Errorf("%w: read %d provided %d", + codec.ErrExtraSpace, + p.Offset, + len(bytes), + ) } return nil } @@ -424,15 +430,17 @@ func (c *genericCodec) unmarshal(p *wrappers.Packer, value reflect.Value, maxSli } if numElts32 > maxSliceLen { return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", - ErrMaxMarshalSliceLimitExceeded, + codec.ErrMaxSliceLenExceeded, numElts32, - maxSliceLen) + maxSliceLen, + ) } if numElts32 > math.MaxInt32 { return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", - ErrMaxMarshalSliceLimitExceeded, + codec.ErrMaxSliceLenExceeded, numElts32, - math.MaxInt32) + math.MaxInt32, + ) } numElts := int(numElts32) diff --git a/codec/registry.go b/codec/registry.go index 9031c94f2421..f0f1c2ff8157 100644 --- a/codec/registry.go +++ b/codec/registry.go @@ -3,6 +3,10 @@ package codec +import "errors" + +var ErrDuplicateType = errors.New("duplicate type registration") + // Registry registers new types that can be marshaled into type Registry interface { RegisterType(interface{}) error diff --git a/codec/test_codec.go b/codec/test_codec.go index 8da7a1be1dc8..b5a5f10f88a3 100644 --- a/codec/test_codec.go +++ b/codec/test_codec.go @@ -157,7 +157,7 @@ func TestRegisterStructTwice(codec GeneralCodec, t testing.TB) { require := require.New(t) require.NoError(codec.RegisterType(&MyInnerStruct{})) - require.Error(codec.RegisterType(&MyInnerStruct{})) + require.ErrorIs(codec.RegisterType(&MyInnerStruct{}), ErrDuplicateType) } func TestUInt32(codec GeneralCodec, t testing.TB) { @@ -193,7 +193,7 @@ func TestUIntPtr(codec GeneralCodec, t testing.TB) { number := uintptr(500) _, err = manager.Marshal(0, number) - require.Error(err) + require.ErrorIs(err, ErrUnsupportedType) } func TestSlice(codec GeneralCodec, t testing.TB) { @@ -562,10 +562,10 @@ func TestSerializeUnexportedField(codec GeneralCodec, t testing.TB) { require.NoError(err) _, err = manager.Marshal(0, myS) - require.Error(err) + require.ErrorIs(err, ErrUnexportedField) _, err = manager.Size(0, myS) - require.Error(err) + require.ErrorIs(err, ErrUnexportedField) } func TestSerializeOfNoSerializeField(codec GeneralCodec, t testing.TB) { @@ -709,7 +709,7 @@ func TestSliceWithEmptySerializationOutOfMemory(codec GeneralCodec, t testing.TB Arr: make([]emptyStruct, math.MaxInt32), } _, err = manager.Marshal(0, val) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) bytesLen, err := manager.Size(0, val) require.NoError(err) @@ -726,7 +726,7 @@ func TestSliceTooLarge(codec GeneralCodec, t testing.TB) { val := []struct{}{} b := []byte{0x00, 0x00, 0xff, 0xff, 0xff, 0xff} _, err = manager.Unmarshal(b, &val) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) } // Ensure serializing structs with negative number members works @@ -774,7 +774,7 @@ func TestTooLargeUnmarshal(codec GeneralCodec, t testing.TB) { s := inner{} _, err = manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, errUnmarshalTooBig) } type outerInterface interface { @@ -813,7 +813,7 @@ func TestUnmarshalInvalidInterface(codec GeneralCodec, t testing.TB) { bytes := []byte{0, 0, 0, 0, 0, 1} s := outer{} _, err := manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, ErrDoesNotImplementInterface) } } @@ -832,11 +832,11 @@ func TestRestrictedSlice(codec GeneralCodec, t testing.TB) { s := inner{} _, err = manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) s.Bytes = []byte{0, 1, 2} _, err = manager.Marshal(0, s) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) } // Test unmarshaling something with extra data @@ -851,7 +851,7 @@ func TestExtraSpace(codec GeneralCodec, t testing.TB) { byteSlice := []byte{0x00, 0x00, 0x01, 0x02} var b byte _, err = manager.Unmarshal(byteSlice, &b) - require.Error(err) + require.ErrorIs(err, ErrExtraSpace) } // Ensure deserializing slices that have been length restricted errors correctly @@ -874,7 +874,7 @@ func TestSliceLengthOverflow(codec GeneralCodec, t testing.TB) { s := inner{} _, err = manager.Unmarshal(bytes, &s) - require.Error(err) + require.ErrorIs(err, ErrMaxSliceLenExceeded) } type MultipleVersionsStruct struct { From de719ad37a1e83581fe9f1eb275227060a87c815 Mon Sep 17 00:00:00 2001 From: Stephen Date: Fri, 21 Apr 2023 15:54:59 -0400 Subject: [PATCH 74/77] Improve utils/ error handling --- .../buffer/bounded_nonblocking_queue_test.go | 2 +- utils/cb58/cb58.go | 12 ++--- utils/compression/compressor_test.go | 14 +++--- utils/compression/type_test.go | 8 ++-- utils/crypto/bls/public.go | 4 +- utils/crypto/bls/public_test.go | 2 +- utils/crypto/bls/signature.go | 4 +- utils/crypto/keychain/keychain_test.go | 12 ++--- utils/crypto/secp256k1/secp256k1.go | 3 +- utils/crypto/secp256k1/secp256k1_test.go | 46 +++++++++++++------ utils/dynamicip/resolver.go | 5 +- utils/dynamicip/resolver_test.go | 34 ++++++-------- utils/hashing/consistent/ring_test.go | 7 +-- utils/metric/averager.go | 13 ++++-- utils/profiler/profiler_test.go | 18 ++++---- utils/sampler/uniform_replacer.go | 2 +- utils/sampler/uniform_resample.go | 2 +- utils/sampler/uniform_test.go | 8 ++-- utils/sampler/weighted.go | 2 +- utils/sampler/weighted_array.go | 2 +- utils/sampler/weighted_heap.go | 2 +- utils/sampler/weighted_linear.go | 2 +- utils/sampler/weighted_test.go | 11 +++-- utils/sampler/weighted_uniform.go | 2 +- .../weighted_without_replacement_test.go | 11 +++-- utils/wrappers/packing.go | 14 +++--- utils/wrappers/packing_test.go | 40 ++++++++-------- 27 files changed, 157 insertions(+), 125 deletions(-) diff --git a/utils/buffer/bounded_nonblocking_queue_test.go b/utils/buffer/bounded_nonblocking_queue_test.go index 402a089b8397..ab2f7e209a5b 100644 --- a/utils/buffer/bounded_nonblocking_queue_test.go +++ b/utils/buffer/bounded_nonblocking_queue_test.go @@ -14,7 +14,7 @@ func TestNewBoundedQueue(t *testing.T) { // Case: maxSize < 1 _, err := NewBoundedQueue[bool](0, nil) - require.Error(err) + require.ErrorIs(err, errInvalidMaxSize) // Case: maxSize == 1 and nil onEvict b, err := NewBoundedQueue[bool](1, nil) diff --git a/utils/cb58/cb58.go b/utils/cb58/cb58.go index 23cf9c49c17f..7fcc58cf249d 100644 --- a/utils/cb58/cb58.go +++ b/utils/cb58/cb58.go @@ -6,6 +6,7 @@ package cb58 import ( "bytes" "errors" + "fmt" "math" "github.com/mr-tron/base58/base58" @@ -13,13 +14,12 @@ import ( "github.com/ava-labs/avalanchego/utils/hashing" ) -const ( - checksumLen = 4 -) +const checksumLen = 4 var ( + ErrBase58Decoding = errors.New("base58 decoding error") + ErrMissingChecksum = errors.New("input string is smaller than the checksum size") errEncodingOverFlow = errors.New("encoding overflow") - errMissingChecksum = errors.New("input string is smaller than the checksum size") errBadChecksum = errors.New("invalid input checksum") ) @@ -41,10 +41,10 @@ func Encode(bytes []byte) (string, error) { func Decode(str string) ([]byte, error) { decodedBytes, err := base58.Decode(str) if err != nil { - return nil, err + return nil, fmt.Errorf("%w: %s", ErrBase58Decoding, err) } if len(decodedBytes) < checksumLen { - return nil, errMissingChecksum + return nil, ErrMissingChecksum } // Verify the checksum rawBytes := decodedBytes[:len(decodedBytes)-checksumLen] diff --git a/utils/compression/compressor_test.go b/utils/compression/compressor_test.go index 341fb4a29bf9..cbd2eb114a4e 100644 --- a/utils/compression/compressor_test.go +++ b/utils/compression/compressor_test.go @@ -114,21 +114,23 @@ func TestSizeLimiting(t *testing.T) { continue } t.Run(compressionType.String(), func(t *testing.T) { + require := require.New(t) + compressor, err := compressorFunc(maxMessageSize) - require.NoError(t, err) + require.NoError(err) data := make([]byte, maxMessageSize+1) _, err = compressor.Compress(data) // should be too large - require.Error(t, err) + require.ErrorIs(err, ErrMsgTooLarge) compressor2, err := compressorFunc(2 * maxMessageSize) - require.NoError(t, err) + require.NoError(err) dataCompressed, err := compressor2.Compress(data) - require.NoError(t, err) + require.NoError(err) _, err = compressor.Decompress(dataCompressed) // should be too large - require.Error(t, err) + require.ErrorIs(err, ErrDecompressedMsgTooLarge) }) } } @@ -178,7 +180,7 @@ func fuzzHelper(f *testing.F, compressionType Type) { if len(data) > maxMessageSize { _, err := compressor.Compress(data) - require.Error(err) + require.ErrorIs(err, ErrMsgTooLarge) } compressed, err := compressor.Compress(data) diff --git a/utils/compression/type_test.go b/utils/compression/type_test.go index aa9a47f3ad96..20313d053824 100644 --- a/utils/compression/type_test.go +++ b/utils/compression/type_test.go @@ -10,15 +10,17 @@ import ( ) func TestTypeString(t *testing.T) { + require := require.New(t) + for _, compressionType := range []Type{TypeNone, TypeGzip, TypeZstd} { s := compressionType.String() parsedType, err := TypeFromString(s) - require.NoError(t, err) - require.Equal(t, compressionType, parsedType) + require.NoError(err) + require.Equal(compressionType, parsedType) } _, err := TypeFromString("unknown") - require.Error(t, err) + require.ErrorIs(err, errUnknownCompressionType) } func TestTypeMarshalJSON(t *testing.T) { diff --git a/utils/crypto/bls/public.go b/utils/crypto/bls/public.go index f17d6127eb64..4a944f94f21a 100644 --- a/utils/crypto/bls/public.go +++ b/utils/crypto/bls/public.go @@ -13,7 +13,7 @@ const PublicKeyLen = blst.BLST_P1_COMPRESS_BYTES var ( ErrNoPublicKeys = errors.New("no public keys") - errFailedPublicKeyDecompress = errors.New("couldn't decompress public key") + ErrFailedPublicKeyDecompress = errors.New("couldn't decompress public key") errInvalidPublicKey = errors.New("invalid public key") errFailedPublicKeyAggregation = errors.New("couldn't aggregate public keys") ) @@ -33,7 +33,7 @@ func PublicKeyToBytes(pk *PublicKey) []byte { func PublicKeyFromBytes(pkBytes []byte) (*PublicKey, error) { pk := new(PublicKey).Uncompress(pkBytes) if pk == nil { - return nil, errFailedPublicKeyDecompress + return nil, ErrFailedPublicKeyDecompress } if !pk.KeyValidate() { return nil, errInvalidPublicKey diff --git a/utils/crypto/bls/public_test.go b/utils/crypto/bls/public_test.go index 02300295630a..9cd886400b2d 100644 --- a/utils/crypto/bls/public_test.go +++ b/utils/crypto/bls/public_test.go @@ -16,7 +16,7 @@ func TestPublicKeyFromBytesWrongSize(t *testing.T) { pkBytes := utils.RandomBytes(PublicKeyLen + 1) _, err := PublicKeyFromBytes(pkBytes) - require.ErrorIs(err, errFailedPublicKeyDecompress) + require.ErrorIs(err, ErrFailedPublicKeyDecompress) } func TestPublicKeyBytes(t *testing.T) { diff --git a/utils/crypto/bls/signature.go b/utils/crypto/bls/signature.go index 7ee03aeff474..cafba33c48e6 100644 --- a/utils/crypto/bls/signature.go +++ b/utils/crypto/bls/signature.go @@ -12,7 +12,7 @@ import ( const SignatureLen = blst.BLST_P2_COMPRESS_BYTES var ( - errFailedSignatureDecompress = errors.New("couldn't decompress signature") + ErrFailedSignatureDecompress = errors.New("couldn't decompress signature") errInvalidSignature = errors.New("invalid signature") errNoSignatures = errors.New("no signatures") errFailedSignatureAggregation = errors.New("couldn't aggregate signatures") @@ -33,7 +33,7 @@ func SignatureToBytes(sig *Signature) []byte { func SignatureFromBytes(sigBytes []byte) (*Signature, error) { sig := new(Signature).Uncompress(sigBytes) if sig == nil { - return nil, errFailedSignatureDecompress + return nil, ErrFailedSignatureDecompress } if !sig.SigValidate(false) { return nil, errInvalidSignature diff --git a/utils/crypto/keychain/keychain_test.go b/utils/crypto/keychain/keychain_test.go index e260e87c6698..5d8b82fcd400 100644 --- a/utils/crypto/keychain/keychain_test.go +++ b/utils/crypto/keychain/keychain_test.go @@ -26,7 +26,7 @@ func TestNewLedgerKeychain(t *testing.T) { // user request invalid number of addresses to derive ledger := NewMockLedger(ctrl) _, err := NewLedgerKeychain(ledger, 0) - require.Equal(err, ErrInvalidNumAddrsToDerive) + require.ErrorIs(err, ErrInvalidNumAddrsToDerive) // ledger does not return expected number of derived addresses ledger = NewMockLedger(ctrl) @@ -38,7 +38,7 @@ func TestNewLedgerKeychain(t *testing.T) { ledger = NewMockLedger(ctrl) ledger.EXPECT().Addresses([]uint32{0}).Return([]ids.ShortID{addr}, errTest).Times(1) _, err = NewLedgerKeychain(ledger, 1) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path ledger = NewMockLedger(ctrl) @@ -160,7 +160,7 @@ func TestLedgerSigner_SignHash(t *testing.T) { require.True(b) _, err = s.SignHash(toSign) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path 1 addr ledger = NewMockLedger(ctrl) @@ -218,7 +218,7 @@ func TestNewLedgerKeychainFromIndices(t *testing.T) { // user request invalid number of indices ledger := NewMockLedger(ctrl) _, err := NewLedgerKeychainFromIndices(ledger, []uint32{}) - require.Equal(err, ErrInvalidIndicesLength) + require.ErrorIs(err, ErrInvalidIndicesLength) // ledger does not return expected number of derived addresses ledger = NewMockLedger(ctrl) @@ -230,7 +230,7 @@ func TestNewLedgerKeychainFromIndices(t *testing.T) { ledger = NewMockLedger(ctrl) ledger.EXPECT().Addresses([]uint32{0}).Return([]ids.ShortID{addr}, errTest).Times(1) _, err = NewLedgerKeychainFromIndices(ledger, []uint32{0}) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path ledger = NewMockLedger(ctrl) @@ -382,7 +382,7 @@ func TestLedgerSignerFromIndices_SignHash(t *testing.T) { require.True(b) _, err = s.SignHash(toSign) - require.Equal(err, errTest) + require.ErrorIs(err, errTest) // good path 1 addr ledger = NewMockLedger(ctrl) diff --git a/utils/crypto/secp256k1/secp256k1.go b/utils/crypto/secp256k1/secp256k1.go index 80de06c09b36..857921bf2ea5 100644 --- a/utils/crypto/secp256k1/secp256k1.go +++ b/utils/crypto/secp256k1/secp256k1.go @@ -44,6 +44,7 @@ const ( ) var ( + ErrInvalidSig = errors.New("invalid signature") errCompressed = errors.New("wasn't expecting a compressed key") errMissingQuotes = errors.New("first and last characters should be quotes") errMissingKeyPrefix = fmt.Errorf("private key missing %s prefix", PrivateKeyPrefix) @@ -108,7 +109,7 @@ func (f *Factory) RecoverHashPublicKey(hash, sig []byte) (*PublicKey, error) { rawPubkey, compressed, err := ecdsa.RecoverCompact(sig, hash) if err != nil { - return nil, err + return nil, ErrInvalidSig } if compressed { diff --git a/utils/crypto/secp256k1/secp256k1_test.go b/utils/crypto/secp256k1/secp256k1_test.go index e8abab31fdbf..8f5e3879d38d 100644 --- a/utils/crypto/secp256k1/secp256k1_test.go +++ b/utils/crypto/secp256k1/secp256k1_test.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/cache" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/cb58" "github.com/ava-labs/avalanchego/utils/hashing" ) @@ -100,7 +101,7 @@ func TestVerifyMutatedSignature(t *testing.T) { copy(sig[32:], newSBytes[:]) _, err = f.RecoverPublicKey(msg, sig) - require.Error(err) + require.ErrorIs(err, errMutatedSig) } func TestPrivateKeySECP256K1RUnmarshalJSON(t *testing.T) { @@ -123,30 +124,47 @@ func TestPrivateKeySECP256K1RUnmarshalJSONError(t *testing.T) { tests := []struct { label string in []byte + err error }{ { - "too short", - []byte(`"`), + label: "too short", + in: []byte(`"`), + err: errMissingQuotes, }, { - "missing start quote", - []byte(`PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + label: "missing start quote", + in: []byte(`PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + err: errMissingQuotes, }, { - "missing end quote", - []byte(`"PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN`), + label: "missing end quote", + in: []byte(`"PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN`), + err: errMissingQuotes, }, { - "incorrect prefix", - []byte(`"PrivateKfy-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + label: "incorrect prefix", + in: []byte(`"PrivateKfy-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"`), + err: errMissingKeyPrefix, }, { - `"PrivateKey-"`, - []byte(`"PrivateKey-"`), + label: `"PrivateKey-"`, + in: []byte(`"PrivateKey-"`), + err: cb58.ErrBase58Decoding, }, { - `"PrivateKey-1"`, - []byte(`"PrivateKey-1"`), + label: `"PrivateKey-1"`, + in: []byte(`"PrivateKey-1"`), + err: cb58.ErrMissingChecksum, + }, + { + label: `"PrivateKey-1"`, + in: []byte(`"PrivateKey-1"`), + err: cb58.ErrMissingChecksum, + }, + { + label: `"PrivateKey-1"`, + in: []byte(`"PrivateKey-45PJLL"`), + err: errInvalidPrivateKeyLength, }, } for _, tt := range tests { @@ -155,7 +173,7 @@ func TestPrivateKeySECP256K1RUnmarshalJSONError(t *testing.T) { foo := PrivateKey{} err := foo.UnmarshalJSON(tt.in) - require.Error(err) + require.ErrorIs(err, tt.err) }) } } diff --git a/utils/dynamicip/resolver.go b/utils/dynamicip/resolver.go index df797e206b36..b3a341cd2121 100644 --- a/utils/dynamicip/resolver.go +++ b/utils/dynamicip/resolver.go @@ -5,6 +5,7 @@ package dynamicip import ( "context" + "errors" "fmt" "net" "strings" @@ -23,6 +24,8 @@ const ( IFConfigMeName = "ifconfigme" ) +var errUnknownResolver = errors.New("unknown resolver") + // Resolver resolves our public IP type Resolver interface { // Resolve and return our public IP. @@ -43,6 +46,6 @@ func NewResolver(resolverName string) (Resolver, error) { case IFConfigMeName: return &ifConfigResolver{url: ifConfigMeURL}, nil default: - return nil, fmt.Errorf("got unknown resolver: %s", resolverName) + return nil, fmt.Errorf("%w: %s", errUnknownResolver, resolverName) } } diff --git a/utils/dynamicip/resolver_test.go b/utils/dynamicip/resolver_test.go index 7606bdd87c11..e5e53d40f9f3 100644 --- a/utils/dynamicip/resolver_test.go +++ b/utils/dynamicip/resolver_test.go @@ -12,44 +12,40 @@ import ( func TestNewResolver(t *testing.T) { type test struct { - service string - validService bool + service string + err error } tests := []test{ { - service: OpenDNSName, - validService: true, + service: OpenDNSName, + err: nil, }, { - service: IFConfigName, - validService: true, + service: IFConfigName, + err: nil, }, { - service: IFConfigCoName, - validService: true, + service: IFConfigCoName, + err: nil, }, { - service: IFConfigMeName, - validService: true, + service: IFConfigMeName, + err: nil, }, { - service: strings.ToUpper(IFConfigMeName), - validService: true, + service: strings.ToUpper(IFConfigMeName), + err: nil, }, { - service: "not a valid resolution service name", - validService: false, + service: "not a valid resolution service name", + err: errUnknownResolver, }, } for _, tt := range tests { t.Run(tt.service, func(t *testing.T) { require := require.New(t) _, err := NewResolver(tt.service) - if tt.validService { - require.NoError(err) - } else { - require.Error(err) - } + require.ErrorIs(err, tt.err) }) } } diff --git a/utils/hashing/consistent/ring_test.go b/utils/hashing/consistent/ring_test.go index d5b59c58936c..a72cbadea478 100644 --- a/utils/hashing/consistent/ring_test.go +++ b/utils/hashing/consistent/ring_test.go @@ -211,11 +211,8 @@ func TestGetOnEmptyRingReturnsError(t *testing.T) { key: "foo", hash: 0, } - - node, err := ring.Get(foo) - - require.Equal(t, nil, node) - require.Equal(t, errEmptyRing, err) + _, err := ring.Get(foo) + require.ErrorIs(t, err, errEmptyRing) } // Tests that trying to call Remove on a node that doesn't exist should return false. diff --git a/utils/metric/averager.go b/utils/metric/averager.go index 9cc4588dae1e..0293aebb9c58 100644 --- a/utils/metric/averager.go +++ b/utils/metric/averager.go @@ -4,6 +4,7 @@ package metric import ( + "errors" "fmt" "github.com/prometheus/client_golang/prometheus" @@ -11,6 +12,8 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" ) +var ErrFailedRegistering = errors.New("failed registering metric") + type Averager interface { Observe(float64) } @@ -40,10 +43,12 @@ func NewAveragerWithErrs(namespace, name, desc string, reg prometheus.Registerer }), } - errs.Add( - reg.Register(a.count), - reg.Register(a.sum), - ) + if err := reg.Register(a.count); err != nil { + errs.Add(fmt.Errorf("%w: %s", ErrFailedRegistering, err)) + } + if err := reg.Register(a.sum); err != nil { + errs.Add(fmt.Errorf("%w: %s", ErrFailedRegistering, err)) + } return &a } diff --git a/utils/profiler/profiler_test.go b/utils/profiler/profiler_test.go index c2c89143c60c..8f04c940532a 100644 --- a/utils/profiler/profiler_test.go +++ b/utils/profiler/profiler_test.go @@ -12,35 +12,37 @@ import ( ) func TestProfiler(t *testing.T) { + require := require.New(t) + dir := t.TempDir() p := New(dir) // Test Start and Stop CPU Profiler err := p.StartCPUProfiler() - require.NoError(t, err) + require.NoError(err) err = p.StopCPUProfiler() - require.NoError(t, err) + require.NoError(err) _, err = os.Stat(filepath.Join(dir, cpuProfileFile)) - require.NoError(t, err) + require.NoError(err) // Test Stop CPU Profiler without it running err = p.StopCPUProfiler() - require.Error(t, err) + require.ErrorIs(err, errCPUProfilerNotRunning) // Test Memory Profiler err = p.MemoryProfile() - require.NoError(t, err) + require.NoError(err) _, err = os.Stat(filepath.Join(dir, memProfileFile)) - require.NoError(t, err) + require.NoError(err) // Test Lock Profiler err = p.LockProfile() - require.NoError(t, err) + require.NoError(err) _, err = os.Stat(filepath.Join(dir, lockProfileFile)) - require.NoError(t, err) + require.NoError(err) } diff --git a/utils/sampler/uniform_replacer.go b/utils/sampler/uniform_replacer.go index a4a16b9dd795..dd1d25ea3809 100644 --- a/utils/sampler/uniform_replacer.go +++ b/utils/sampler/uniform_replacer.go @@ -73,7 +73,7 @@ func (s *uniformReplacer) Reset() { func (s *uniformReplacer) Next() (uint64, error) { if s.drawsCount >= s.length { - return 0, errOutOfRange + return 0, ErrOutOfRange } draw := s.rng.Uint64Inclusive(s.length-1-s.drawsCount) + s.drawsCount diff --git a/utils/sampler/uniform_resample.go b/utils/sampler/uniform_resample.go index 4afc3f7a84d8..ecb5deea0f11 100644 --- a/utils/sampler/uniform_resample.go +++ b/utils/sampler/uniform_resample.go @@ -60,7 +60,7 @@ func (s *uniformResample) Reset() { func (s *uniformResample) Next() (uint64, error) { i := uint64(len(s.drawn)) if i >= s.length { - return 0, errOutOfRange + return 0, ErrOutOfRange } for { diff --git a/utils/sampler/uniform_test.go b/utils/sampler/uniform_test.go index d7f9cf7191a8..fe66bdb9d27d 100644 --- a/utils/sampler/uniform_test.go +++ b/utils/sampler/uniform_test.go @@ -93,7 +93,7 @@ func UniformOutOfRangeTest(t *testing.T, s Uniform) { s.Initialize(0) _, err := s.Sample(1) - require.Error(t, err, "should have reported an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func UniformEmptyTest(t *testing.T, s Uniform) { @@ -101,7 +101,7 @@ func UniformEmptyTest(t *testing.T, s Uniform) { val, err := s.Sample(0) require.NoError(t, err) - require.Len(t, val, 0, "shouldn't have selected any element") + require.Empty(t, val) } func UniformSingletonTest(t *testing.T, s Uniform) { @@ -131,7 +131,7 @@ func UniformOverSampleTest(t *testing.T, s Uniform) { s.Initialize(3) _, err := s.Sample(4) - require.Error(t, err, "should have returned an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func UniformLazilySample(t *testing.T, s Uniform) { @@ -148,7 +148,7 @@ func UniformLazilySample(t *testing.T, s Uniform) { } _, err := s.Next() - require.Error(t, err, "should have returned an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) s.Reset() } diff --git a/utils/sampler/weighted.go b/utils/sampler/weighted.go index 58998d47969b..69212d4351c2 100644 --- a/utils/sampler/weighted.go +++ b/utils/sampler/weighted.go @@ -5,7 +5,7 @@ package sampler import "errors" -var errOutOfRange = errors.New("out of range") +var ErrOutOfRange = errors.New("out of range") // Weighted defines how to sample a specified valued based on a provided // weighted distribution diff --git a/utils/sampler/weighted_array.go b/utils/sampler/weighted_array.go index c6b411b80d9b..0db1dda17af9 100644 --- a/utils/sampler/weighted_array.go +++ b/utils/sampler/weighted_array.go @@ -81,7 +81,7 @@ func (s *weightedArray) Initialize(weights []uint64) error { func (s *weightedArray) Sample(value uint64) (int, error) { if len(s.arr) == 0 || s.arr[len(s.arr)-1].cumulativeWeight <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } minIndex := 0 maxIndex := len(s.arr) - 1 diff --git a/utils/sampler/weighted_heap.go b/utils/sampler/weighted_heap.go index 1457d66539cb..4b7fb84df482 100644 --- a/utils/sampler/weighted_heap.go +++ b/utils/sampler/weighted_heap.go @@ -81,7 +81,7 @@ func (s *weightedHeap) Initialize(weights []uint64) error { func (s *weightedHeap) Sample(value uint64) (int, error) { if len(s.heap) == 0 || s.heap[0].cumulativeWeight <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } index := 0 diff --git a/utils/sampler/weighted_linear.go b/utils/sampler/weighted_linear.go index f58fa22a3239..a5d0e3b16711 100644 --- a/utils/sampler/weighted_linear.go +++ b/utils/sampler/weighted_linear.go @@ -68,7 +68,7 @@ func (s *weightedLinear) Initialize(weights []uint64) error { func (s *weightedLinear) Sample(value uint64) (int, error) { if len(s.arr) == 0 || s.arr[len(s.arr)-1].cumulativeWeight <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } index := 0 diff --git a/utils/sampler/weighted_test.go b/utils/sampler/weighted_test.go index cb22b431aa05..6830a07e387c 100644 --- a/utils/sampler/weighted_test.go +++ b/utils/sampler/weighted_test.go @@ -5,10 +5,13 @@ package sampler import ( "fmt" - "math" "testing" + stdmath "math" + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/utils/math" ) var ( @@ -86,8 +89,8 @@ func TestAllWeighted(t *testing.T) { } func WeightedInitializeOverflowTest(t *testing.T, s Weighted) { - err := s.Initialize([]uint64{1, math.MaxUint64}) - require.Error(t, err, "should have reported an overflow error") + err := s.Initialize([]uint64{1, stdmath.MaxUint64}) + require.ErrorIs(t, err, math.ErrOverflow) } func WeightedOutOfRangeTest(t *testing.T, s Weighted) { @@ -95,7 +98,7 @@ func WeightedOutOfRangeTest(t *testing.T, s Weighted) { require.NoError(t, err) _, err = s.Sample(1) - require.Error(t, err, "should have reported an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func WeightedSingletonTest(t *testing.T, s Weighted) { diff --git a/utils/sampler/weighted_uniform.go b/utils/sampler/weighted_uniform.go index 14620475c2bf..bff76ead34e4 100644 --- a/utils/sampler/weighted_uniform.go +++ b/utils/sampler/weighted_uniform.go @@ -63,7 +63,7 @@ func (s *weightedUniform) Initialize(weights []uint64) error { func (s *weightedUniform) Sample(value uint64) (int, error) { if uint64(len(s.indices)) <= value { - return 0, errOutOfRange + return 0, ErrOutOfRange } return s.indices[int(value)], nil } diff --git a/utils/sampler/weighted_without_replacement_test.go b/utils/sampler/weighted_without_replacement_test.go index 42b5ac2a293b..c62f56215257 100644 --- a/utils/sampler/weighted_without_replacement_test.go +++ b/utils/sampler/weighted_without_replacement_test.go @@ -5,12 +5,15 @@ package sampler import ( "fmt" - "math" "testing" + stdmath "math" + "github.com/stretchr/testify/require" "golang.org/x/exp/slices" + + "github.com/ava-labs/avalanchego/utils/math" ) var ( @@ -84,8 +87,8 @@ func WeightedWithoutReplacementInitializeOverflowTest( t *testing.T, s WeightedWithoutReplacement, ) { - err := s.Initialize([]uint64{1, math.MaxUint64}) - require.Error(t, err, "should have reported an overflow error") + err := s.Initialize([]uint64{1, stdmath.MaxUint64}) + require.ErrorIs(t, err, math.ErrOverflow) } func WeightedWithoutReplacementOutOfRangeTest( @@ -96,7 +99,7 @@ func WeightedWithoutReplacementOutOfRangeTest( require.NoError(t, err) _, err = s.Sample(2) - require.Error(t, err, "should have reported an out of range error") + require.ErrorIs(t, err, ErrOutOfRange) } func WeightedWithoutReplacementEmptyWithoutWeightTest( diff --git a/utils/wrappers/packing.go b/utils/wrappers/packing.go index e6869b1b91e7..891f80e49ab2 100644 --- a/utils/wrappers/packing.go +++ b/utils/wrappers/packing.go @@ -33,11 +33,11 @@ func StringLen(str string) int { } var ( - errBadLength = errors.New("packer has insufficient length for input") - errNegativeOffset = errors.New("negative offset") - errInvalidInput = errors.New("input does not match expected format") - errBadBool = errors.New("unexpected value when unpacking bool") - errOversized = errors.New("size is larger than limit") + ErrInsufficientLength = errors.New("packer has insufficient length for input") + errNegativeOffset = errors.New("negative offset") + errInvalidInput = errors.New("input does not match expected format") + errBadBool = errors.New("unexpected value when unpacking bool") + errOversized = errors.New("size is larger than limit") ) // Packer packs and unpacks a byte array from/to standard values @@ -252,7 +252,7 @@ func (p *Packer) checkSpace(bytes int) { case bytes < 0: p.Add(errInvalidInput) case len(p.Bytes)-p.Offset < bytes: - p.Add(errBadLength) + p.Add(ErrInsufficientLength) } } @@ -266,7 +266,7 @@ func (p *Packer) expand(bytes int) { case neededSize <= len(p.Bytes): // Byte slice has sufficient length already return case neededSize > p.MaxSize: // Lengthening the byte slice would cause it to grow too large - p.Err = errBadLength + p.Err = ErrInsufficientLength return case neededSize <= cap(p.Bytes): // Byte slice has sufficient capacity to lengthen it without mem alloc p.Bytes = p.Bytes[:neededSize] diff --git a/utils/wrappers/packing_test.go b/utils/wrappers/packing_test.go index 1d6740205130..2372e1ed3cfb 100644 --- a/utils/wrappers/packing_test.go +++ b/utils/wrappers/packing_test.go @@ -33,12 +33,12 @@ func TestPackerCheckSpace(t *testing.T) { p = Packer{Bytes: []byte{0x01}, Offset: 1} p.checkSpace(1) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: []byte{0x01}, Offset: 2} p.checkSpace(0) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerExpand(t *testing.T) { @@ -47,7 +47,7 @@ func TestPackerExpand(t *testing.T) { p := Packer{Bytes: []byte{0x01}, Offset: 2} p.expand(1) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: []byte{0x01, 0x02, 0x03}, Offset: 0} p.expand(1) @@ -67,7 +67,7 @@ func TestPackerPackByte(t *testing.T) { p.PackByte(0x02) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackByte(t *testing.T) { @@ -81,7 +81,7 @@ func TestPackerUnpackByte(t *testing.T) { require.Equal(uint8(ByteSentinel), p.UnpackByte()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackShort(t *testing.T) { @@ -105,7 +105,7 @@ func TestPackerUnpackShort(t *testing.T) { require.Equal(uint16(ShortSentinel), p.UnpackShort()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackInt(t *testing.T) { @@ -119,7 +119,7 @@ func TestPackerPackInt(t *testing.T) { p.PackInt(0x05060708) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackInt(t *testing.T) { @@ -133,7 +133,7 @@ func TestPackerUnpackInt(t *testing.T) { require.Equal(uint32(IntSentinel), p.UnpackInt()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackLong(t *testing.T) { @@ -147,7 +147,7 @@ func TestPackerPackLong(t *testing.T) { p.PackLong(0x090a0b0c0d0e0f00) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackLong(t *testing.T) { @@ -161,7 +161,7 @@ func TestPackerUnpackLong(t *testing.T) { require.Equal(uint64(LongSentinel), p.UnpackLong()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackFixedBytes(t *testing.T) { @@ -175,7 +175,7 @@ func TestPackerPackFixedBytes(t *testing.T) { p.PackFixedBytes([]byte("Avax")) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackFixedBytes(t *testing.T) { @@ -189,7 +189,7 @@ func TestPackerUnpackFixedBytes(t *testing.T) { require.Nil(p.UnpackFixedBytes(4)) require.True(p.Errored()) - require.Error(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerPackBytes(t *testing.T) { @@ -203,7 +203,7 @@ func TestPackerPackBytes(t *testing.T) { p.PackBytes([]byte("Avax")) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackBytes(t *testing.T) { @@ -217,7 +217,7 @@ func TestPackerUnpackBytes(t *testing.T) { require.Nil(p.UnpackBytes()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackLimitedBytes(t *testing.T) { @@ -231,7 +231,7 @@ func TestPackerUnpackLimitedBytes(t *testing.T) { require.Nil(p.UnpackLimitedBytes(10)) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) // Reset and don't allow enough bytes p = Packer{Bytes: p.Bytes} @@ -263,7 +263,7 @@ func TestPackerUnpackString(t *testing.T) { require.Equal("", p.UnpackStr()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackLimitedString(t *testing.T) { @@ -277,7 +277,7 @@ func TestPackerUnpackLimitedString(t *testing.T) { require.Equal("", p.UnpackLimitedStr(10)) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) // Reset and don't allow enough bytes p = Packer{Bytes: p.Bytes} @@ -301,7 +301,7 @@ func TestPacker(t *testing.T) { p.PackShort(1) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: p.Bytes} require.Equal(uint16(17), p.UnpackShort()) @@ -340,7 +340,7 @@ func TestPackerPackBool(t *testing.T) { p.PackBool(false) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) } func TestPackerUnpackBool(t *testing.T) { @@ -355,7 +355,7 @@ func TestPackerUnpackBool(t *testing.T) { require.Equal(BoolSentinel, p.UnpackBool()) require.True(p.Errored()) - require.ErrorIs(p.Err, errBadLength) + require.ErrorIs(p.Err, ErrInsufficientLength) p = Packer{Bytes: []byte{0x42}, Offset: 0} require.Equal(false, p.UnpackBool()) From b49ca6f2fe406d6dda0c3c6e07de09079c4f110a Mon Sep 17 00:00:00 2001 From: Stephen Date: Fri, 21 Apr 2023 17:34:15 -0400 Subject: [PATCH 75/77] Improve consensus error handling --- snow/choices/status_test.go | 6 +--- snow/engine/avalanche/vertex/builder_test.go | 18 ++++++---- snow/engine/avalanche/vertex/parser_test.go | 5 +-- snow/engine/common/queue/jobs_test.go | 2 +- snow/uptime/manager_test.go | 13 ++++---- .../gvalidators/validator_state_test.go | 12 ++++--- snow/validators/set_test.go | 21 +++++++----- vms/avm/index_test.go | 8 ++--- vms/avm/service_test.go | 6 ++-- vms/components/chain/state.go | 14 +++++--- vms/components/chain/state_test.go | 33 ++++++++++--------- vms/components/index/index.go | 13 ++++---- vms/components/keystore/user_test.go | 9 ++--- vms/components/message/message_test.go | 7 ++-- vms/proposervm/batched_vm_test.go | 8 ++--- vms/proposervm/block/block.go | 4 ++- vms/proposervm/block/block_test.go | 4 +-- vms/proposervm/block/build_test.go | 4 +-- vms/proposervm/block/parse_test.go | 5 +-- vms/proposervm/indexer/height_indexer_test.go | 2 +- vms/proposervm/summary/parse_test.go | 4 ++- vms/registry/vm_registerer.go | 9 +++-- vms/registry/vm_registerer_test.go | 4 +-- vms/rpcchainvm/state_syncable_vm_test.go | 14 ++++---- 24 files changed, 125 insertions(+), 100 deletions(-) diff --git a/snow/choices/status_test.go b/snow/choices/status_test.go index 960af7b46744..de7d60fe6ade 100644 --- a/snow/choices/status_test.go +++ b/snow/choices/status_test.go @@ -17,8 +17,7 @@ func TestStatusValid(t *testing.T) { require.NoError(Rejected.Valid()) require.NoError(Processing.Valid()) require.NoError(Unknown.Valid()) - - require.Error(Status(math.MaxInt32).Valid()) + require.ErrorIs(Status(math.MaxInt32).Valid(), errUnknownStatus) } func TestStatusDecided(t *testing.T) { @@ -28,7 +27,6 @@ func TestStatusDecided(t *testing.T) { require.True(Rejected.Decided()) require.False(Processing.Decided()) require.False(Unknown.Decided()) - require.False(Status(math.MaxInt32).Decided()) } @@ -39,7 +37,6 @@ func TestStatusFetched(t *testing.T) { require.True(Rejected.Fetched()) require.True(Processing.Fetched()) require.False(Unknown.Fetched()) - require.False(Status(math.MaxInt32).Fetched()) } @@ -50,6 +47,5 @@ func TestStatusString(t *testing.T) { require.Equal("Rejected", Rejected.String()) require.Equal("Processing", Processing.String()) require.Equal("Unknown", Unknown.String()) - require.Equal("Invalid status", Status(math.MaxInt32).String()) } diff --git a/snow/engine/avalanche/vertex/builder_test.go b/snow/engine/avalanche/vertex/builder_test.go index 7ed6a9a59365..132ccbc33f73 100644 --- a/snow/engine/avalanche/vertex/builder_test.go +++ b/snow/engine/avalanche/vertex/builder_test.go @@ -11,7 +11,9 @@ import ( "github.com/ava-labs/avalanchego/ids" ) -func TestBuildInvalid(t *testing.T) { +func TestBuildDuplicateTxs(t *testing.T) { + require := require.New(t) + chainID := ids.ID{1} height := uint64(2) parentIDs := []ids.ID{{4}, {5}} @@ -22,10 +24,12 @@ func TestBuildInvalid(t *testing.T) { parentIDs, txs, ) - require.Error(t, err, "build should have errored because restrictions were provided in epoch 0") + require.ErrorIs(err, errInvalidTxs) } func TestBuildValid(t *testing.T) { + require := require.New(t) + chainID := ids.ID{1} height := uint64(2) parentIDs := []ids.ID{{4}, {5}} @@ -36,9 +40,9 @@ func TestBuildValid(t *testing.T) { parentIDs, txs, ) - require.NoError(t, err) - require.Equal(t, chainID, vtx.ChainID()) - require.Equal(t, height, vtx.Height()) - require.Equal(t, parentIDs, vtx.ParentIDs()) - require.Equal(t, txs, vtx.Txs()) + require.NoError(err) + require.Equal(chainID, vtx.ChainID()) + require.Equal(height, vtx.Height()) + require.Equal(parentIDs, vtx.ParentIDs()) + require.Equal(txs, vtx.Txs()) } diff --git a/snow/engine/avalanche/vertex/parser_test.go b/snow/engine/avalanche/vertex/parser_test.go index 8f1f2e9e3ef6..acffb5c8d66f 100644 --- a/snow/engine/avalanche/vertex/parser_test.go +++ b/snow/engine/avalanche/vertex/parser_test.go @@ -8,13 +8,14 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" ) func TestParseInvalid(t *testing.T) { - vtxBytes := []byte{} + vtxBytes := []byte{1, 2, 3, 4, 5} _, err := Parse(vtxBytes) - require.Error(t, err, "parse on an invalid vertex should have errored") + require.ErrorIs(t, err, codec.ErrUnknownVersion) } func TestParseValid(t *testing.T) { diff --git a/snow/engine/common/queue/jobs_test.go b/snow/engine/common/queue/jobs_test.go index 296266eed2f9..7ad245905e45 100644 --- a/snow/engine/common/queue/jobs_test.go +++ b/snow/engine/common/queue/jobs_test.go @@ -390,7 +390,7 @@ func TestHandleJobWithMissingDependencyOnRunnableStack(t *testing.T) { _, err = jobs.ExecuteAll(context.Background(), snow.DefaultConsensusContextTest(), &common.Halter{}, false) // Assert that the database closed error on job1 causes ExecuteAll // to fail in the middle of execution. - require.Error(err) + require.ErrorIs(err, database.ErrClosed) require.True(executed0) require.False(executed1) diff --git a/snow/uptime/manager_test.go b/snow/uptime/manager_test.go index bea1533e71b0..1f5a854e819a 100644 --- a/snow/uptime/manager_test.go +++ b/snow/uptime/manager_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" ) @@ -56,7 +57,7 @@ func TestStartTrackingDBError(t *testing.T) { up.clock.Set(currentTime) err := up.StartTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, errTest) } func TestStartTrackingNonValidator(t *testing.T) { @@ -69,7 +70,7 @@ func TestStartTrackingNonValidator(t *testing.T) { subnetID := ids.GenerateTestID() err := up.StartTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } func TestStartTrackingInThePast(t *testing.T) { @@ -182,7 +183,7 @@ func TestStopTrackingDisconnectedNonValidator(t *testing.T) { require.NoError(err) err = up.StopTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } func TestStopTrackingConnectedDBError(t *testing.T) { @@ -204,7 +205,7 @@ func TestStopTrackingConnectedDBError(t *testing.T) { s.dbReadError = errTest err = up.StopTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, errTest) } func TestStopTrackingNonConnectedPast(t *testing.T) { @@ -256,7 +257,7 @@ func TestStopTrackingNonConnectedDBError(t *testing.T) { s.dbWriteError = errTest err = up.StopTracking([]ids.NodeID{nodeID0}, subnetID) - require.Error(err) + require.ErrorIs(err, errTest) } func TestConnectAndDisconnect(t *testing.T) { @@ -552,7 +553,7 @@ func TestCalculateUptimeNonValidator(t *testing.T) { up := NewManager(s).(*manager) _, err := up.CalculateUptimePercentFrom(nodeID0, subnetID, startTime) - require.Error(err) + require.ErrorIs(err, database.ErrNotFound) } func TestCalculateUptimePercentageDivBy0(t *testing.T) { diff --git a/snow/validators/gvalidators/validator_state_test.go b/snow/validators/gvalidators/validator_state_test.go index 4cfb2d021db0..136919e1c230 100644 --- a/snow/validators/gvalidators/validator_state_test.go +++ b/snow/validators/gvalidators/validator_state_test.go @@ -82,7 +82,8 @@ func TestGetMinimumHeight(t *testing.T) { state.server.EXPECT().GetMinimumHeight(gomock.Any()).Return(expectedHeight, errCustom) _, err = state.client.GetMinimumHeight(context.Background()) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } func TestGetCurrentHeight(t *testing.T) { @@ -105,7 +106,8 @@ func TestGetCurrentHeight(t *testing.T) { state.server.EXPECT().GetCurrentHeight(gomock.Any()).Return(expectedHeight, errCustom) _, err = state.client.GetCurrentHeight(context.Background()) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } func TestGetSubnetID(t *testing.T) { @@ -129,7 +131,8 @@ func TestGetSubnetID(t *testing.T) { state.server.EXPECT().GetSubnetID(gomock.Any(), chainID).Return(expectedSubnetID, errCustom) _, err = state.client.GetSubnetID(context.Background(), chainID) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } func TestGetValidatorSet(t *testing.T) { @@ -180,7 +183,8 @@ func TestGetValidatorSet(t *testing.T) { state.server.EXPECT().GetValidatorSet(gomock.Any(), height, subnetID).Return(expectedVdrs, errCustom) _, err = state.client.GetValidatorSet(context.Background(), height, subnetID) - require.Error(err) + // TODO: require specific error + require.Error(err) //nolint:forbidigo // currently returns grpc error } func TestPublicKeyDeserialize(t *testing.T) { diff --git a/snow/validators/set_test.go b/snow/validators/set_test.go index 645a521535ce..59d6b1e57555 100644 --- a/snow/validators/set_test.go +++ b/snow/validators/set_test.go @@ -4,13 +4,16 @@ package validators import ( - "math" "testing" + stdmath "math" + "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/sampler" "github.com/ava-labs/avalanchego/utils/set" ) @@ -42,8 +45,8 @@ func TestSetAddOverflow(t *testing.T) { err := s.Add(ids.GenerateTestNodeID(), nil, ids.Empty, 1) require.NoError(err) - err = s.Add(ids.GenerateTestNodeID(), nil, ids.Empty, math.MaxUint64) - require.Error(err) + err = s.Add(ids.GenerateTestNodeID(), nil, ids.Empty, stdmath.MaxUint64) + require.ErrorIs(err, math.ErrOverflow) weight := s.Weight() require.EqualValues(1, weight) @@ -74,8 +77,8 @@ func TestSetAddWeightOverflow(t *testing.T) { err = s.Add(nodeID, nil, ids.Empty, 1) require.NoError(err) - err = s.AddWeight(nodeID, math.MaxUint64-1) - require.Error(err) + err = s.AddWeight(nodeID, stdmath.MaxUint64-1) + require.ErrorIs(err, math.ErrOverflow) weight := s.Weight() require.EqualValues(2, weight) @@ -166,7 +169,7 @@ func TestSetRemoveWeightUnderflow(t *testing.T) { require.NoError(err) err = s.RemoveWeight(nodeID, 2) - require.Error(err) + require.ErrorIs(err, math.ErrUnderflow) weight := s.Weight() require.EqualValues(2, weight) @@ -384,10 +387,10 @@ func TestSetSample(t *testing.T) { require.Equal([]ids.NodeID{nodeID0}, sampled) _, err = s.Sample(2) - require.Error(err) + require.ErrorIs(err, sampler.ErrOutOfRange) nodeID1 := ids.GenerateTestNodeID() - err = s.Add(nodeID1, nil, ids.Empty, math.MaxInt64-1) + err = s.Add(nodeID1, nil, ids.Empty, stdmath.MaxInt64-1) require.NoError(err) sampled, err = s.Sample(1) @@ -416,7 +419,7 @@ func TestSetString(t *testing.T) { err := s.Add(nodeID0, nil, ids.Empty, 1) require.NoError(err) - err = s.Add(nodeID1, nil, ids.Empty, math.MaxInt64-1) + err = s.Add(nodeID1, nil, ids.Empty, stdmath.MaxInt64-1) require.NoError(err) expected := "Validator Set: (Size = 2, Weight = 9223372036854775807)\n" + diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 8a2b681c8a67..f8b18900862d 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -415,7 +415,7 @@ func TestIndexingNewInitWithIndexingEnabled(t *testing.T) { // now disable indexing with allow-incomplete set to false _, err = index.NewNoIndexer(db, false) - require.Error(t, err) + require.ErrorIs(t, err, index.ErrCausesIncompleteIndex) // now disable indexing with allow-incomplete set to true _, err = index.NewNoIndexer(db, true) @@ -432,7 +432,7 @@ func TestIndexingNewInitWithIndexingDisabled(t *testing.T) { // It's not OK to have an incomplete index when allowIncompleteIndices is false _, err = index.NewIndexer(db, ctx.Log, "", prometheus.NewRegistry(), false) - require.Error(t, err) + require.ErrorIs(t, err, index.ErrIndexingRequiredFromGenesis) // It's OK to have an incomplete index when allowIncompleteIndices is true _, err = index.NewIndexer(db, ctx.Log, "", prometheus.NewRegistry(), true) @@ -457,12 +457,12 @@ func TestIndexingAllowIncomplete(t *testing.T) { _, err := index.NewNoIndexer(db, false) require.NoError(t, err) - // we initialise with indexing enabled now and allow incomplete indexing as false + // we initialize with indexing enabled now and allow incomplete indexing as false _, err = index.NewIndexer(db, ctx.Log, "", prometheus.NewRegistry(), false) // we should get error because: // - indexing was disabled previously // - node now is asked to enable indexing with allow incomplete set to false - require.Error(t, err) + require.ErrorIs(t, err, index.ErrIndexingRequiredFromGenesis) } func buildPlatformUTXO(utxoID avax.UTXOID, txAssetID avax.Asset, addr ids.ShortID) *avax.UTXO { diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index b148ed3479b4..d7d174a6dc37 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -1664,7 +1664,7 @@ func TestServiceGetNilTx(t *testing.T) { reply := api.GetTxReply{} err := s.GetTx(nil, &api.GetTxArgs{}, &reply) - require.Error(t, err, "Nil TxID should have returned an error") + require.ErrorIs(t, err, errNilTxID) } func TestServiceGetUnknownTx(t *testing.T) { @@ -1677,8 +1677,8 @@ func TestServiceGetUnknownTx(t *testing.T) { }() reply := api.GetTxReply{} - err := s.GetTx(nil, &api.GetTxArgs{TxID: ids.Empty}, &reply) - require.Error(t, err, "Unknown TxID should have returned an error") + err := s.GetTx(nil, &api.GetTxArgs{TxID: ids.GenerateTestID()}, &reply) + require.ErrorIs(t, err, database.ErrNotFound) } func TestServiceGetUTXOs(t *testing.T) { diff --git a/vms/components/chain/state.go b/vms/components/chain/state.go index fe499194a495..d18fa8f954d4 100644 --- a/vms/components/chain/state.go +++ b/vms/components/chain/state.go @@ -5,6 +5,7 @@ package chain import ( "context" + "errors" "fmt" "github.com/prometheus/client_golang/prometheus" @@ -194,14 +195,17 @@ func NewMeteredState( return c, nil } -// SetLastAcceptedBlock sets the last accepted block to [lastAcceptedBlock]. This should be called -// with an internal block - not a wrapped block returned from state. +var errSetAcceptedWithProcessing = errors.New("cannot set last accepted block with blocks processing") + +// SetLastAcceptedBlock sets the last accepted block to [lastAcceptedBlock]. +// This should be called with an internal block - not a wrapped block returned +// from state. // -// This also flushes [lastAcceptedBlock] from missingBlocks and unverifiedBlocks to -// ensure that their contents stay valid. +// This also flushes [lastAcceptedBlock] from missingBlocks and unverifiedBlocks +// to ensure that their contents stay valid. func (s *State) SetLastAcceptedBlock(lastAcceptedBlock snowman.Block) error { if len(s.verifiedBlocks) != 0 { - return fmt.Errorf("cannot set chain state last accepted block with non-zero number of verified blocks in processing: %d", len(s.verifiedBlocks)) + return fmt.Errorf("%w: %d", errSetAcceptedWithProcessing, len(s.verifiedBlocks)) } // [lastAcceptedBlock] is no longer missing or unverified, so we evict it from the corresponding diff --git a/vms/components/chain/state_test.go b/vms/components/chain/state_test.go index 448fcb44d5f2..100c9d0a2ab8 100644 --- a/vms/components/chain/state_test.go +++ b/vms/components/chain/state_test.go @@ -682,6 +682,8 @@ func TestMeteredCache(t *testing.T) { // Test the bytesToIDCache func TestStateBytesToIDCache(t *testing.T) { + require := require.New(t) + testBlks := NewTestBlocks(3) genesisBlock := testBlks[0] genesisBlock.SetStatus(choices.Accepted) @@ -708,27 +710,27 @@ func TestStateBytesToIDCache(t *testing.T) { // Shouldn't have blk1 ID to start with _, err := chainState.GetBlock(context.Background(), blk1.ID()) - require.Error(t, err) + require.ErrorIs(err, database.ErrNotFound) _, ok := chainState.bytesToIDCache.Get(string(blk1.Bytes())) - require.False(t, ok) + require.False(ok) // Parse blk1 from bytes _, err = chainState.ParseBlock(context.Background(), blk1.Bytes()) - require.NoError(t, err) + require.NoError(err) // blk1 should be in cache now _, ok = chainState.bytesToIDCache.Get(string(blk1.Bytes())) - require.True(t, ok) + require.True(ok) // Parse another block _, err = chainState.ParseBlock(context.Background(), blk2.Bytes()) - require.NoError(t, err) + require.NoError(err) // Should have bumped blk1 from cache _, ok = chainState.bytesToIDCache.Get(string(blk2.Bytes())) - require.True(t, ok) + require.True(ok) _, ok = chainState.bytesToIDCache.Get(string(blk1.Bytes())) - require.False(t, ok) + require.False(ok) } // TestSetLastAcceptedBlock ensures chainState's last accepted block @@ -823,6 +825,8 @@ func TestSetLastAcceptedBlock(t *testing.T) { } func TestSetLastAcceptedBlockWithProcessingBlocksErrors(t *testing.T) { + require := require.New(t) + testBlks := NewTestBlocks(5) genesisBlock := testBlks[0] genesisBlock.SetStatus(choices.Accepted) @@ -849,19 +853,16 @@ func TestSetLastAcceptedBlockWithProcessingBlocksErrors(t *testing.T) { }) builtBlk, err := chainState.BuildBlock(context.Background()) - if err != nil { - t.Fatal(err) - } - require.Len(t, chainState.verifiedBlocks, 0) + require.NoError(err) + require.Empty(chainState.verifiedBlocks) - if err := builtBlk.Verify(context.Background()); err != nil { - t.Fatalf("Built block failed verification due to %s", err) - } - require.Len(t, chainState.verifiedBlocks, 1) + require.NoError(builtBlk.Verify(context.Background())) + require.Len(chainState.verifiedBlocks, 1) checkProcessingBlock(t, chainState, builtBlk) - require.Error(t, chainState.SetLastAcceptedBlock(resetBlk), "should have errored resetting chain state with processing block") + err = chainState.SetLastAcceptedBlock(resetBlk) + require.ErrorIs(err, errSetAcceptedWithProcessing) } func TestStateParseTransitivelyAcceptedBlock(t *testing.T) { diff --git a/vms/components/index/index.go b/vms/components/index/index.go index 0597f836cafe..25f004dd3f7b 100644 --- a/vms/components/index/index.go +++ b/vms/components/index/index.go @@ -23,10 +23,11 @@ import ( ) var ( - idxKey = []byte("idx") - idxCompleteKey = []byte("complete") - errIndexingRequiredFromGenesis = errors.New("running would create incomplete index. Allow incomplete indices or re-sync from genesis with indexing enabled") - errCausesIncompleteIndex = errors.New("running would create incomplete index. Allow incomplete indices or enable indexing") + ErrIndexingRequiredFromGenesis = errors.New("running would create incomplete index. Allow incomplete indices or re-sync from genesis with indexing enabled") + ErrCausesIncompleteIndex = errors.New("running would create incomplete index. Allow incomplete indices or enable indexing") + + idxKey = []byte("idx") + idxCompleteKey = []byte("complete") _ AddressTxsIndexer = (*indexer)(nil) _ AddressTxsIndexer = (*noIndexer)(nil) @@ -229,7 +230,7 @@ func checkIndexStatus(db database.KeyValueReaderWriter, enableIndexing, allowInc if !idxComplete && enableIndexing && !allowIncomplete { // In a previous run, we did not index so it's incomplete. // indexing was disabled before but now we want to index. - return errIndexingRequiredFromGenesis + return ErrIndexingRequiredFromGenesis } else if !idxComplete { // either indexing is disabled, or incomplete indices are ok, so we don't care that index is incomplete return nil @@ -237,7 +238,7 @@ func checkIndexStatus(db database.KeyValueReaderWriter, enableIndexing, allowInc // the index is complete if !enableIndexing && !allowIncomplete { // indexing is disabled this run - return errCausesIncompleteIndex + return ErrCausesIncompleteIndex } else if !enableIndexing { // running without indexing makes it incomplete return database.PutBool(db, idxCompleteKey, false) diff --git a/vms/components/keystore/user_test.go b/vms/components/keystore/user_test.go index 38c40b78ab2e..379897e9d2a8 100644 --- a/vms/components/keystore/user_test.go +++ b/vms/components/keystore/user_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/encdb" "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/ids" @@ -29,20 +30,20 @@ func TestUserClosedDB(t *testing.T) { u := NewUserFromDB(db) _, err = u.GetAddresses() - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) _, err = u.GetKey(ids.ShortEmpty) - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) _, err = GetKeychain(u, nil) - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) factory := secp256k1.Factory{} sk, err := factory.NewPrivateKey() require.NoError(err) err = u.PutKeys(sk) - require.Error(err, "closed db should have caused an error") + require.ErrorIs(err, database.ErrClosed) } func TestUser(t *testing.T) { diff --git a/vms/components/message/message_test.go b/vms/components/message/message_test.go index dbaf15432f21..163a8f8b04a2 100644 --- a/vms/components/message/message_test.go +++ b/vms/components/message/message_test.go @@ -8,12 +8,11 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/codec" ) func TestParseGibberish(t *testing.T) { - randomBytes := utils.RandomBytes(256 * units.KiB) + randomBytes := []byte{0, 1, 2, 3, 4, 5} _, err := Parse(randomBytes) - require.Error(t, err) + require.ErrorIs(t, err, codec.ErrUnknownVersion) } diff --git a/vms/proposervm/batched_vm_test.go b/vms/proposervm/batched_vm_test.go index b61b9062538c..c5202a634ce9 100644 --- a/vms/proposervm/batched_vm_test.go +++ b/vms/proposervm/batched_vm_test.go @@ -34,18 +34,18 @@ func TestCoreVMNotRemote(t *testing.T) { maxBlocksNum := 1000 // an high value to get all built blocks maxBlocksSize := 1000000 // an high value to get all built blocks maxBlocksRetrivalTime := time.Duration(1000000) // an high value to get all built blocks - _, errAncestors := proVM.GetAncestors( + _, err := proVM.GetAncestors( context.Background(), blkID, maxBlocksNum, maxBlocksSize, maxBlocksRetrivalTime, ) - require.Error(errAncestors) + require.ErrorIs(err, block.ErrRemoteVMNotImplemented) var blks [][]byte - _, errBatchedParse := proVM.BatchedParseBlock(context.Background(), blks) - require.Error(errBatchedParse) + _, err = proVM.BatchedParseBlock(context.Background(), blks) + require.ErrorIs(err, block.ErrRemoteVMNotImplemented) } func TestGetAncestorsPreForkOnly(t *testing.T) { diff --git a/vms/proposervm/block/block.go b/vms/proposervm/block/block.go index 17e56493054a..a64ec2e87979 100644 --- a/vms/proposervm/block/block.go +++ b/vms/proposervm/block/block.go @@ -6,6 +6,7 @@ package block import ( "crypto/x509" "errors" + "fmt" "time" "github.com/ava-labs/avalanchego/ids" @@ -18,6 +19,7 @@ var ( errUnexpectedProposer = errors.New("expected no proposer but one was provided") errMissingProposer = errors.New("expected proposer but none was provided") + errInvalidCertificate = errors.New("invalid certificate") ) type Block interface { @@ -91,7 +93,7 @@ func (b *statelessBlock) initialize(bytes []byte) error { cert, err := x509.ParseCertificate(b.StatelessBlock.Certificate) if err != nil { - return err + return fmt.Errorf("%w: %s", errInvalidCertificate, err) } b.cert = cert diff --git a/vms/proposervm/block/block_test.go b/vms/proposervm/block/block_test.go index 7b6b6de5c041..d0b1a817b941 100644 --- a/vms/proposervm/block/block_test.go +++ b/vms/proposervm/block/block_test.go @@ -41,10 +41,10 @@ func TestVerifyNoCertWithSignature(t *testing.T) { builtBlock.Signature = []byte{0} err = builtBlock.Verify(false, ids.Empty) - require.Error(err) + require.ErrorIs(err, errUnexpectedProposer) err = builtBlock.Verify(true, ids.Empty) - require.Error(err) + require.ErrorIs(err, errMissingProposer) } func TestBlockSizeLimit(t *testing.T) { diff --git a/vms/proposervm/block/build_test.go b/vms/proposervm/block/build_test.go index c2d89cffa556..a4136c7089ca 100644 --- a/vms/proposervm/block/build_test.go +++ b/vms/proposervm/block/build_test.go @@ -49,7 +49,7 @@ func TestBuild(t *testing.T) { require.NoError(err) err = builtBlock.Verify(false, chainID) - require.Error(err) + require.ErrorIs(err, errUnexpectedProposer) } func TestBuildUnsigned(t *testing.T) { @@ -73,7 +73,7 @@ func TestBuildUnsigned(t *testing.T) { require.NoError(err) err = builtBlock.Verify(true, ids.Empty) - require.Error(err) + require.ErrorIs(err, errMissingProposer) } func TestBuildHeader(t *testing.T) { diff --git a/vms/proposervm/block/parse_test.go b/vms/proposervm/block/parse_test.go index f74996011630..777b4d16d70a 100644 --- a/vms/proposervm/block/parse_test.go +++ b/vms/proposervm/block/parse_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/staking" ) @@ -60,7 +61,7 @@ func TestParseDuplicateExtension(t *testing.T) { require.NoError(err) _, err = Parse(blockBytes) - require.Error(err) // Do not check for errDuplicateExtension to support g1.19 + require.ErrorIs(err, errInvalidCertificate) } func TestParseHeader(t *testing.T) { @@ -130,5 +131,5 @@ func TestParseGibberish(t *testing.T) { bytes := []byte{0, 1, 2, 3, 4, 5} _, err := Parse(bytes) - require.Error(err) + require.ErrorIs(err, codec.ErrUnknownVersion) } diff --git a/vms/proposervm/indexer/height_indexer_test.go b/vms/proposervm/indexer/height_indexer_test.go index 3c1e671f1b71..bffdc7a81a6c 100644 --- a/vms/proposervm/indexer/height_indexer_test.go +++ b/vms/proposervm/indexer/height_indexer_test.go @@ -177,7 +177,7 @@ func TestHeightBlockIndexAcrossFork(t *testing.T) { require.True(loadedForkHeight == forkHeight) for height := uint64(0); height < forkHeight; height++ { _, err := storedState.GetBlockIDAtHeight(height) - require.Error(err, database.ErrNotFound) + require.ErrorIs(err, database.ErrNotFound) } for height := forkHeight; height <= blkNumber; height++ { _, err := storedState.GetBlockIDAtHeight(height) diff --git a/vms/proposervm/summary/parse_test.go b/vms/proposervm/summary/parse_test.go index 3d527e27754d..b22be83582e2 100644 --- a/vms/proposervm/summary/parse_test.go +++ b/vms/proposervm/summary/parse_test.go @@ -7,6 +7,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/codec" ) func TestParse(t *testing.T) { @@ -35,5 +37,5 @@ func TestParseGibberish(t *testing.T) { bytes := []byte{0, 1, 2, 3, 4, 5} _, err := Parse(bytes) - require.Error(err) + require.ErrorIs(err, codec.ErrUnknownVersion) } diff --git a/vms/registry/vm_registerer.go b/vms/registry/vm_registerer.go index 6a6fdd85f421..09221457009d 100644 --- a/vms/registry/vm_registerer.go +++ b/vms/registry/vm_registerer.go @@ -5,6 +5,7 @@ package registry import ( "context" + "errors" "fmt" "path" "sync" @@ -19,7 +20,11 @@ import ( "github.com/ava-labs/avalanchego/vms" ) -var _ VMRegisterer = (*vmRegisterer)(nil) +var ( + _ VMRegisterer = (*vmRegisterer)(nil) + + errNotVM = errors.New("not a VM") +) // VMRegisterer defines functionality to install a virtual machine. type VMRegisterer interface { @@ -97,7 +102,7 @@ func (r *vmRegisterer) createStaticHandlers( commonVM, ok := vm.(common.VM) if !ok { - return nil, fmt.Errorf("%s doesn't implement VM", vmID) + return nil, fmt.Errorf("%s is %w", vmID, errNotVM) } handlers, err := commonVM.CreateStaticHandlers(ctx) diff --git a/vms/registry/vm_registerer_test.go b/vms/registry/vm_registerer_test.go index e469277b21c5..58df3f9f7dec 100644 --- a/vms/registry/vm_registerer_test.go +++ b/vms/registry/vm_registerer_test.go @@ -48,7 +48,7 @@ func TestRegisterBadVM(t *testing.T) { // Since this factory produces a bad vm, we should get an error. vmFactory.EXPECT().New(logging.NoLog{}).Times(1).Return(vm, nil) - require.Error(t, resources.registerer.Register(context.Background(), id, vmFactory)) + require.ErrorIs(t, resources.registerer.Register(context.Background(), id, vmFactory), errNotVM) } // Tests Register if creating endpoints for a VM fails + shutdown fails @@ -245,7 +245,7 @@ func TestRegisterWithReadLockBadVM(t *testing.T) { // Since this factory produces a bad vm, we should get an error. vmFactory.EXPECT().New(logging.NoLog{}).Times(1).Return(vm, nil) - require.Error(t, resources.registerer.RegisterWithReadLock(context.Background(), id, vmFactory)) + require.ErrorIs(t, resources.registerer.RegisterWithReadLock(context.Background(), id, vmFactory), errNotVM) } // Tests RegisterWithReadLock if creating endpoints for a VM fails + shutdown fails diff --git a/vms/rpcchainvm/state_syncable_vm_test.go b/vms/rpcchainvm/state_syncable_vm_test.go index d2c47856757c..4be3941815ee 100644 --- a/vms/rpcchainvm/state_syncable_vm_test.go +++ b/vms/rpcchainvm/state_syncable_vm_test.go @@ -326,7 +326,7 @@ func TestStateSyncEnabled(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.StateSyncEnabled(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestGetOngoingSyncStateSummary(t *testing.T) { @@ -351,7 +351,7 @@ func TestGetOngoingSyncStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.GetOngoingSyncStateSummary(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestGetLastStateSummary(t *testing.T) { @@ -376,7 +376,7 @@ func TestGetLastStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.GetLastStateSummary(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestParseStateSummary(t *testing.T) { @@ -400,12 +400,12 @@ func TestParseStateSummary(t *testing.T) { // test parsing nil summary _, err = vm.ParseStateSummary(context.Background(), nil) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors // test a non-special error. // TODO: retrieve exact error _, err = vm.ParseStateSummary(context.Background(), mockedSummary.Bytes()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestGetStateSummary(t *testing.T) { @@ -430,7 +430,7 @@ func TestGetStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = vm.GetStateSummary(context.Background(), mockedSummary.Height()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } func TestAcceptStateSummary(t *testing.T) { @@ -458,7 +458,7 @@ func TestAcceptStateSummary(t *testing.T) { // test a non-special error. // TODO: retrieve exact error _, err = summary.Accept(context.Background()) - require.Error(err) + require.Error(err) //nolint:forbidigo // currently returns grpc errors } // Show that LastAccepted call returns the right answer after a StateSummary From eb8bf7df6b7d0cd6676e38872b2854ac66fb92b4 Mon Sep 17 00:00:00 2001 From: Stephen Date: Fri, 21 Apr 2023 17:40:14 -0400 Subject: [PATCH 76/77] Improve secp256k1fx error handling + merkledb error handling --- vms/secp256k1fx/fx_test.go | 20 +++---- vms/secp256k1fx/input.go | 8 +-- vms/secp256k1fx/input_test.go | 6 +- vms/secp256k1fx/mint_operation_test.go | 10 ++-- vms/secp256k1fx/mint_output.go | 2 +- vms/secp256k1fx/mint_output_test.go | 4 +- vms/secp256k1fx/output_owners.go | 22 +++---- vms/secp256k1fx/output_owners_test.go | 12 ++-- vms/secp256k1fx/transfer_input.go | 2 +- vms/secp256k1fx/transfer_input_test.go | 6 +- vms/secp256k1fx/transfer_output.go | 2 +- vms/secp256k1fx/transfer_output_test.go | 10 ++-- x/merkledb/db_test.go | 15 ++--- x/merkledb/history_test.go | 10 ++-- x/merkledb/trie_test.go | 80 +++++++++++++------------ 15 files changed, 107 insertions(+), 102 deletions(-) diff --git a/vms/secp256k1fx/fx_test.go b/vms/secp256k1fx/fx_test.go index cc48fb640796..eb92ab50d506 100644 --- a/vms/secp256k1fx/fx_test.go +++ b/vms/secp256k1fx/fx_test.go @@ -260,7 +260,7 @@ func TestFxVerifyTransferInvalidOutput(t *testing.T) { }, } - require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), errOutputUnoptimized) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), ErrOutputUnoptimized) } func TestFxVerifyTransferWrongAmounts(t *testing.T) { @@ -296,7 +296,7 @@ func TestFxVerifyTransferWrongAmounts(t *testing.T) { }, } - require.Error(fx.VerifyTransfer(tx, in, cred, out)) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), ErrMismatchedAmounts) } func TestFxVerifyTransferTimelocked(t *testing.T) { @@ -479,7 +479,7 @@ func TestFxVerifyTransferInvalidSignature(t *testing.T) { require.NoError(fx.VerifyTransfer(tx, in, cred, out)) require.NoError(fx.Bootstrapped()) - require.Error(fx.VerifyTransfer(tx, in, cred, out), errAddrsNotSortedUnique) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), secp256k1.ErrInvalidSig) } func TestFxVerifyTransferWrongSigner(t *testing.T) { @@ -518,7 +518,7 @@ func TestFxVerifyTransferWrongSigner(t *testing.T) { require.NoError(fx.VerifyTransfer(tx, in, cred, out)) require.NoError(fx.Bootstrapped()) - require.Error(fx.VerifyTransfer(tx, in, cred, out)) + require.ErrorIs(fx.VerifyTransfer(tx, in, cred, out), ErrWrongSig) } func TestFxVerifyTransferSigIndexOOB(t *testing.T) { @@ -881,7 +881,7 @@ func TestFxVerifyOperationInvalidOperationVerify(t *testing.T) { } utxos := []interface{}{utxo} - require.ErrorIs(fx.VerifyOperation(tx, op, cred, utxos), errOutputUnspendable) + require.ErrorIs(fx.VerifyOperation(tx, op, cred, utxos), ErrOutputUnspendable) } func TestFxVerifyOperationMismatchedMintOutputs(t *testing.T) { @@ -962,7 +962,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 0, Addrs: []ids.ShortID{addr}, }, - errOutputUnoptimized, + ErrOutputUnoptimized, }, { "threshold 0, no sigs, no addrs", @@ -995,7 +995,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 0, Addrs: []ids.ShortID{addr}, }, - errOutputUnoptimized, + ErrOutputUnoptimized, }, { "threshold 1, 0 sigs (too few sigs)", @@ -1028,7 +1028,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr2}, }, - errNotSortedUnique, + ErrInputIndicesNotSortedUnique, }, { "threshold 2, repeated address and repeated sig", @@ -1039,7 +1039,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr}, }, - errAddrsNotSortedUnique, + ErrAddrsNotSortedUnique, }, { "threshold 2, 2 sigs", @@ -1061,7 +1061,7 @@ func TestVerifyPermission(t *testing.T) { Threshold: 2, Addrs: []ids.ShortID{addr, addr2}, }, - errNotSortedUnique, + ErrInputIndicesNotSortedUnique, }, { "threshold 1, 1 sig, index out of bounds", diff --git a/vms/secp256k1fx/input.go b/vms/secp256k1fx/input.go index 5659727c672c..d5943a6b686e 100644 --- a/vms/secp256k1fx/input.go +++ b/vms/secp256k1fx/input.go @@ -15,8 +15,8 @@ const ( ) var ( - errNilInput = errors.New("nil input") - errNotSortedUnique = errors.New("signatures not sorted and unique") + ErrNilInput = errors.New("nil input") + ErrInputIndicesNotSortedUnique = errors.New("address indices not sorted and unique") ) type Input struct { @@ -35,9 +35,9 @@ func (in *Input) Cost() (uint64, error) { func (in *Input) Verify() error { switch { case in == nil: - return errNilInput + return ErrNilInput case !utils.IsSortedAndUniqueOrdered(in.SigIndices): - return errNotSortedUnique + return ErrInputIndicesNotSortedUnique default: return nil } diff --git a/vms/secp256k1fx/input_test.go b/vms/secp256k1fx/input_test.go index 72088530027b..0e0efffe0c81 100644 --- a/vms/secp256k1fx/input_test.go +++ b/vms/secp256k1fx/input_test.go @@ -18,17 +18,17 @@ func TestInputVerifyNil(t *testing.T) { { name: "nil input", in: nil, - expectedErr: errNilInput, + expectedErr: ErrNilInput, }, { name: "not sorted", in: &Input{SigIndices: []uint32{2, 1}}, - expectedErr: errNotSortedUnique, + expectedErr: ErrInputIndicesNotSortedUnique, }, { name: "not unique", in: &Input{SigIndices: []uint32{2, 2}}, - expectedErr: errNotSortedUnique, + expectedErr: ErrInputIndicesNotSortedUnique, }, { name: "passes verification", diff --git a/vms/secp256k1fx/mint_operation_test.go b/vms/secp256k1fx/mint_operation_test.go index 9b68b1c8725a..ed066f61a156 100644 --- a/vms/secp256k1fx/mint_operation_test.go +++ b/vms/secp256k1fx/mint_operation_test.go @@ -49,7 +49,7 @@ func TestMintOperationVerify(t *testing.T) { MintOutput: validMintOutput, TransferOutput: validTransferOutput, }, - expectedErr: errNotSortedUnique, + expectedErr: ErrInputIndicesNotSortedUnique, }, { name: "invalid mint output", @@ -63,7 +63,7 @@ func TestMintOperationVerify(t *testing.T) { }, TransferOutput: validTransferOutput, }, - expectedErr: errOutputUnspendable, + expectedErr: ErrOutputUnspendable, }, { name: "invalid transfer output", @@ -78,7 +78,7 @@ func TestMintOperationVerify(t *testing.T) { }, }, }, - expectedErr: errOutputUnoptimized, + expectedErr: ErrOutputUnoptimized, }, { name: "addresses not unique", @@ -93,7 +93,7 @@ func TestMintOperationVerify(t *testing.T) { }, }, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "addresses not sorted", @@ -108,7 +108,7 @@ func TestMintOperationVerify(t *testing.T) { }, }, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "passes verification", diff --git a/vms/secp256k1fx/mint_output.go b/vms/secp256k1fx/mint_output.go index 7655fc5c3574..84dc6c44df4e 100644 --- a/vms/secp256k1fx/mint_output.go +++ b/vms/secp256k1fx/mint_output.go @@ -16,7 +16,7 @@ type MintOutput struct { func (out *MintOutput) Verify() error { switch { case out == nil: - return errNilOutput + return ErrNilOutput default: return out.OutputOwners.Verify() } diff --git a/vms/secp256k1fx/mint_output_test.go b/vms/secp256k1fx/mint_output_test.go index 7bd55cc0f1c0..c9547fd8a317 100644 --- a/vms/secp256k1fx/mint_output_test.go +++ b/vms/secp256k1fx/mint_output_test.go @@ -20,7 +20,7 @@ func TestMintOutputVerify(t *testing.T) { { name: "nil", out: nil, - expectedErr: errNilOutput, + expectedErr: ErrNilOutput, }, { name: "invalid output owners", @@ -30,7 +30,7 @@ func TestMintOutputVerify(t *testing.T) { Addrs: []ids.ShortID{ids.GenerateTestShortID()}, }, }, - expectedErr: errOutputUnspendable, + expectedErr: ErrOutputUnspendable, }, { name: "passes verification", diff --git a/vms/secp256k1fx/output_owners.go b/vms/secp256k1fx/output_owners.go index eb601eb3773e..39c076d65635 100644 --- a/vms/secp256k1fx/output_owners.go +++ b/vms/secp256k1fx/output_owners.go @@ -17,11 +17,11 @@ import ( ) var ( - errNilOutput = errors.New("nil output") - errOutputUnspendable = errors.New("output is unspendable") - errOutputUnoptimized = errors.New("output representation should be optimized") - errAddrsNotSortedUnique = errors.New("addresses not sorted and unique") - errMarshal = errors.New("cannot marshal without ctx") + ErrNilOutput = errors.New("nil output") + ErrOutputUnspendable = errors.New("output is unspendable") + ErrOutputUnoptimized = errors.New("output representation should be optimized") + ErrAddrsNotSortedUnique = errors.New("addresses not sorted and unique") + ErrMarshal = errors.New("cannot marshal without ctx") _ verify.State = (*OutputOwners)(nil) ) @@ -57,13 +57,13 @@ func (out *OutputOwners) MarshalJSON() ([]byte, error) { } // Fields returns JSON keys in a map that can be used with marshal JSON -// to serialise OutputOwners struct +// to serialize OutputOwners struct func (out *OutputOwners) Fields() (map[string]interface{}, error) { addrsLen := len(out.Addrs) // we need out.ctx to do this, if its absent, throw error if addrsLen > 0 && out.ctx == nil { - return nil, errMarshal + return nil, ErrMarshal } addresses := make([]string, addrsLen) @@ -123,13 +123,13 @@ func (out *OutputOwners) Equals(other *OutputOwners) bool { func (out *OutputOwners) Verify() error { switch { case out == nil: - return errNilOutput + return ErrNilOutput case out.Threshold > uint32(len(out.Addrs)): - return errOutputUnspendable + return ErrOutputUnspendable case out.Threshold == 0 && len(out.Addrs) > 0: - return errOutputUnoptimized + return ErrOutputUnoptimized case !utils.IsSortedAndUniqueSortable(out.Addrs): - return errAddrsNotSortedUnique + return ErrAddrsNotSortedUnique default: return nil } diff --git a/vms/secp256k1fx/output_owners_test.go b/vms/secp256k1fx/output_owners_test.go index db8e8436b5d7..cf67d2688f65 100644 --- a/vms/secp256k1fx/output_owners_test.go +++ b/vms/secp256k1fx/output_owners_test.go @@ -20,7 +20,7 @@ func TestOutputOwnersVerify(t *testing.T) { { name: "nil", out: nil, - expectedErr: errNilOutput, + expectedErr: ErrNilOutput, }, { name: "threshold > num addrs", @@ -28,7 +28,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 1, Addrs: []ids.ShortID{}, }, - expectedErr: errOutputUnspendable, + expectedErr: ErrOutputUnspendable, }, { name: "unoptimized", @@ -36,7 +36,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 0, Addrs: []ids.ShortID{ids.GenerateTestShortID()}, }, - expectedErr: errOutputUnoptimized, + expectedErr: ErrOutputUnoptimized, }, { name: "not sorted", @@ -44,7 +44,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 1, Addrs: []ids.ShortID{{2}, {1}}, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "not unique", @@ -52,7 +52,7 @@ func TestOutputOwnersVerify(t *testing.T) { Threshold: 1, Addrs: []ids.ShortID{{2}, {2}}, }, - expectedErr: errAddrsNotSortedUnique, + expectedErr: ErrAddrsNotSortedUnique, }, { name: "passes verification", @@ -160,7 +160,7 @@ func TestMarshalJSONRequiresCtxWhenAddrsArePresent(t *testing.T) { } _, err := out.MarshalJSON() - require.ErrorIs(err, errMarshal) + require.ErrorIs(err, ErrMarshal) } func TestMarshalJSONDoesNotRequireCtxWhenAddrsAreAbsent(t *testing.T) { diff --git a/vms/secp256k1fx/transfer_input.go b/vms/secp256k1fx/transfer_input.go index 2fb69c64345f..6dadd558fc49 100644 --- a/vms/secp256k1fx/transfer_input.go +++ b/vms/secp256k1fx/transfer_input.go @@ -27,7 +27,7 @@ func (in *TransferInput) Amount() uint64 { func (in *TransferInput) Verify() error { switch { case in == nil: - return errNilInput + return ErrNilInput case in.Amt == 0: return ErrNoValueInput default: diff --git a/vms/secp256k1fx/transfer_input_test.go b/vms/secp256k1fx/transfer_input_test.go index 96d2c40e2dbf..af22ecc090c7 100644 --- a/vms/secp256k1fx/transfer_input_test.go +++ b/vms/secp256k1fx/transfer_input_test.go @@ -38,7 +38,7 @@ func TestTransferInputVerify(t *testing.T) { func TestTransferInputVerifyNil(t *testing.T) { require := require.New(t) in := (*TransferInput)(nil) - require.ErrorIs(in.Verify(), errNilInput) + require.ErrorIs(in.Verify(), ErrNilInput) } func TestTransferInputVerifyNoValue(t *testing.T) { @@ -60,7 +60,7 @@ func TestTransferInputVerifyDuplicated(t *testing.T) { SigIndices: []uint32{0, 0}, }, } - require.ErrorIs(in.Verify(), errNotSortedUnique) + require.ErrorIs(in.Verify(), ErrInputIndicesNotSortedUnique) } func TestTransferInputVerifyUnsorted(t *testing.T) { @@ -71,7 +71,7 @@ func TestTransferInputVerifyUnsorted(t *testing.T) { SigIndices: []uint32{1, 0}, }, } - require.ErrorIs(in.Verify(), errNotSortedUnique) + require.ErrorIs(in.Verify(), ErrInputIndicesNotSortedUnique) } func TestTransferInputSerialize(t *testing.T) { diff --git a/vms/secp256k1fx/transfer_output.go b/vms/secp256k1fx/transfer_output.go index 285ffef5a9fe..dc57d2305b6c 100644 --- a/vms/secp256k1fx/transfer_output.go +++ b/vms/secp256k1fx/transfer_output.go @@ -43,7 +43,7 @@ func (out *TransferOutput) Amount() uint64 { func (out *TransferOutput) Verify() error { switch { case out == nil: - return errNilOutput + return ErrNilOutput case out.Amt == 0: return ErrNoValueOutput default: diff --git a/vms/secp256k1fx/transfer_output_test.go b/vms/secp256k1fx/transfer_output_test.go index 08bfd173bfa6..650c1da833fc 100644 --- a/vms/secp256k1fx/transfer_output_test.go +++ b/vms/secp256k1fx/transfer_output_test.go @@ -47,7 +47,7 @@ func TestOutputVerify(t *testing.T) { func TestOutputVerifyNil(t *testing.T) { require := require.New(t) out := (*TransferOutput)(nil) - require.ErrorIs(out.Verify(), errNilOutput) + require.ErrorIs(out.Verify(), ErrNilOutput) } func TestOutputVerifyNoValue(t *testing.T) { @@ -77,7 +77,7 @@ func TestOutputVerifyUnspendable(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errOutputUnspendable) + require.ErrorIs(out.Verify(), ErrOutputUnspendable) } func TestOutputVerifyUnoptimized(t *testing.T) { @@ -92,7 +92,7 @@ func TestOutputVerifyUnoptimized(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errOutputUnoptimized) + require.ErrorIs(out.Verify(), ErrOutputUnoptimized) } func TestOutputVerifyUnsorted(t *testing.T) { @@ -108,7 +108,7 @@ func TestOutputVerifyUnsorted(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errAddrsNotSortedUnique) + require.ErrorIs(out.Verify(), ErrAddrsNotSortedUnique) } func TestOutputVerifyDuplicated(t *testing.T) { @@ -124,7 +124,7 @@ func TestOutputVerifyDuplicated(t *testing.T) { }, }, } - require.ErrorIs(out.Verify(), errAddrsNotSortedUnique) + require.ErrorIs(out.Verify(), ErrAddrsNotSortedUnique) } func TestOutputSerialize(t *testing.T) { diff --git a/x/merkledb/db_test.go b/x/merkledb/db_test.go index 8a0f98d3b4fb..cca72733d490 100644 --- a/x/merkledb/db_test.go +++ b/x/merkledb/db_test.go @@ -374,21 +374,22 @@ func Test_MerkleDB_InsertNil(t *testing.T) { } func Test_MerkleDB_InsertAndRetrieve(t *testing.T) { + require := require.New(t) + db, err := getBasicDB() - require.NoError(t, err) + require.NoError(err) // value hasn't been inserted so shouldn't exist value, err := db.Get([]byte("key")) - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) - require.Nil(t, value) + require.ErrorIs(err, database.ErrNotFound) + require.Nil(value) err = db.Put([]byte("key"), []byte("value")) - require.NoError(t, err) + require.NoError(err) value, err = db.Get([]byte("key")) - require.NoError(t, err) - require.Equal(t, []byte("value"), value) + require.NoError(err) + require.Equal([]byte("value"), value) } func Test_MerkleDB_HealthCheck(t *testing.T) { diff --git a/x/merkledb/history_test.go b/x/merkledb/history_test.go index 29da9974fc62..0151cde1774e 100644 --- a/x/merkledb/history_test.go +++ b/x/merkledb/history_test.go @@ -223,10 +223,10 @@ func Test_History_Bad_GetValueChanges_Input(t *testing.T) { require.NoError(err) _, err = db.history.getValueChanges(startRoot, endRoot, nil, nil, -1) - require.Error(err, ErrInvalidMaxLength) + require.ErrorIs(err, ErrInvalidMaxLength) _, err = db.history.getValueChanges(endRoot, startRoot, nil, nil, 1) - require.Error(err, ErrStartRootNotFound) + require.ErrorIs(err, ErrStartRootNotFound) // trigger the first root to be deleted by exiting the lookback window batch = db.NewBatch() @@ -235,9 +235,9 @@ func Test_History_Bad_GetValueChanges_Input(t *testing.T) { err = batch.Write() require.NoError(err) - // now this root should no lnger be present + // now this root should no longer be present _, err = db.history.getValueChanges(toBeDeletedRoot, endRoot, nil, nil, 1) - require.Error(err, ErrRootIDNotPresent) + require.ErrorIs(err, ErrStartRootNotFound) // same start/end roots should yield an empty changelist changes, err := db.history.getValueChanges(endRoot, endRoot, nil, nil, 10) @@ -304,7 +304,7 @@ func Test_History_Trigger_History_Queue_Looping(t *testing.T) { // proof from first root shouldn't be generatable since it should have been removed from the history _, err = db.GetRangeProofAtRoot(context.Background(), origRootID, []byte("k"), []byte("key3"), 10) - require.Error(err, ErrRootIDNotPresent) + require.ErrorIs(err, ErrRootIDNotPresent) } func Test_History_Values_Lookup_Over_Queue_Break(t *testing.T) { diff --git a/x/merkledb/trie_test.go b/x/merkledb/trie_test.go index 530a2db633fc..e7c75e52bf4e 100644 --- a/x/merkledb/trie_test.go +++ b/x/merkledb/trie_test.go @@ -251,53 +251,59 @@ func Test_Trie_Partial_Commit_Leaves_Valid_Tries(t *testing.T) { } func Test_Trie_WriteToDB(t *testing.T) { + require := require.New(t) + dbTrie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, dbTrie) + require.NoError(err) + require.NotNil(dbTrie) + trie, err := dbTrie.NewView() - require.NoError(t, err) + require.NoError(err) // value hasn't been inserted so shouldn't exist value, err := trie.GetValue(context.Background(), []byte("key")) - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) - require.Nil(t, value) + require.ErrorIs(err, database.ErrNotFound) + require.Nil(value) err = trie.Insert(context.Background(), []byte("key"), []byte("value")) - require.NoError(t, err) + require.NoError(err) value, err = getNodeValue(trie, "key") - require.NoError(t, err) - require.Equal(t, []byte("value"), value) + require.NoError(err) + require.Equal([]byte("value"), value) err = trie.CommitToDB(context.Background()) - require.NoError(t, err) + require.NoError(err) + p := newPath([]byte("key")) rawBytes, err := dbTrie.nodeDB.Get(p.Bytes()) - require.NoError(t, err) + require.NoError(err) + node, err := parseNode(p, rawBytes) - require.NoError(t, err) - require.Equal(t, []byte("value"), node.value.value) + require.NoError(err) + require.Equal([]byte("value"), node.value.value) } func Test_Trie_InsertAndRetrieve(t *testing.T) { + require := require.New(t) + dbTrie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, dbTrie) + require.NoError(err) + require.NotNil(dbTrie) + trie := Trie(dbTrie) // value hasn't been inserted so shouldn't exist value, err := dbTrie.Get([]byte("key")) - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) - require.Nil(t, value) + require.ErrorIs(err, database.ErrNotFound) + require.Nil(value) err = trie.Insert(context.Background(), []byte("key"), []byte("value")) - require.NoError(t, err) + require.NoError(err) value, err = getNodeValue(trie, "key") - require.NoError(t, err) - require.Equal(t, []byte("value"), value) + require.NoError(err) + require.Equal([]byte("value"), value) } func Test_Trie_Overwrite(t *testing.T) { @@ -637,32 +643,30 @@ func Test_Trie_CommitChanges(t *testing.T) { } func Test_Trie_BatchApply(t *testing.T) { + require := require.New(t) + dbTrie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, dbTrie) + require.NoError(err) + require.NotNil(dbTrie) + trie, err := dbTrie.NewView() - require.NoError(t, err) + require.NoError(err) - err = trie.Insert(context.Background(), []byte("key1"), []byte("value1")) - require.NoError(t, err) - err = trie.Insert(context.Background(), []byte("key12"), []byte("value12")) - require.NoError(t, err) - err = trie.Insert(context.Background(), []byte("key134"), []byte("value134")) - require.NoError(t, err) - err = trie.Remove(context.Background(), []byte("key1")) - require.NoError(t, err) + require.NoError(trie.Insert(context.Background(), []byte("key1"), []byte("value1"))) + require.NoError(trie.Insert(context.Background(), []byte("key12"), []byte("value12"))) + require.NoError(trie.Insert(context.Background(), []byte("key134"), []byte("value134"))) + require.NoError(trie.Remove(context.Background(), []byte("key1"))) value, err := getNodeValue(trie, "key12") - require.NoError(t, err) - require.Equal(t, []byte("value12"), value) + require.NoError(err) + require.Equal([]byte("value12"), value) value, err = getNodeValue(trie, "key134") - require.NoError(t, err) - require.Equal(t, []byte("value134"), value) + require.NoError(err) + require.Equal([]byte("value134"), value) _, err = getNodeValue(trie, "key1") - require.Error(t, err) - require.Equal(t, database.ErrNotFound, err) + require.ErrorIs(err, database.ErrNotFound) } func Test_Trie_ChainDeletion(t *testing.T) { From 892943ec0d2ae569b8c6afd823675e5ce48e7c30 Mon Sep 17 00:00:00 2001 From: Stephen Date: Sat, 22 Apr 2023 15:32:26 -0400 Subject: [PATCH 77/77] ok --- vms/platformvm/txs/executor/import_test.go | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/vms/platformvm/txs/executor/import_test.go b/vms/platformvm/txs/executor/import_test.go index 479fad577c86..9c618d80bd62 100644 --- a/vms/platformvm/txs/executor/import_test.go +++ b/vms/platformvm/txs/executor/import_test.go @@ -28,12 +28,12 @@ func TestNewImportTx(t *testing.T) { }() type test struct { - description string - sourceChainID ids.ID - sharedMemory atomic.SharedMemory - sourceKeys []*secp256k1.PrivateKey - timestamp time.Time - expectedBuildError error + description string + sourceChainID ids.ID + sharedMemory atomic.SharedMemory + sourceKeys []*secp256k1.PrivateKey + timestamp time.Time + expectedErr error } factory := secp256k1.Factory{} @@ -104,8 +104,8 @@ func TestNewImportTx(t *testing.T) { env.ctx.AVAXAssetID: env.config.TxFee - 1, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - expectedBuildError: utxo.ErrInsufficientFunds, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + expectedErr: utxo.ErrInsufficientFunds, }, { description: "can barely pay fee", @@ -116,8 +116,8 @@ func TestNewImportTx(t *testing.T) { env.ctx.AVAXAssetID: env.config.TxFee, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - expectedBuildError: nil, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + expectedErr: nil, }, { description: "attempting to import from C-chain", @@ -128,9 +128,9 @@ func TestNewImportTx(t *testing.T) { env.ctx.AVAXAssetID: env.config.TxFee, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - timestamp: env.config.ApricotPhase5Time, - expectedBuildError: nil, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + timestamp: env.config.ApricotPhase5Time, + expectedErr: nil, }, { description: "attempting to import non-avax from X-chain", @@ -142,9 +142,9 @@ func TestNewImportTx(t *testing.T) { customAssetID: 1, }, ), - sourceKeys: []*secp256k1.PrivateKey{sourceKey}, - timestamp: env.config.BanffTime, - expectedBuildError: nil, + sourceKeys: []*secp256k1.PrivateKey{sourceKey}, + timestamp: env.config.BanffTime, + expectedErr: nil, }, } @@ -160,8 +160,8 @@ func TestNewImportTx(t *testing.T) { tt.sourceKeys, ids.ShortEmpty, ) - require.ErrorIs(err, tt.expectedBuildError) - if tt.expectedBuildError != nil { + require.ErrorIs(err, tt.expectedErr) + if tt.expectedErr != nil { return } require.NoError(err)