diff --git a/.custom-gcl.yml b/.custom-gcl.yml index 04280ce0eb..0d2860a229 100644 --- a/.custom-gcl.yml +++ b/.custom-gcl.yml @@ -4,3 +4,7 @@ plugins: # partitiontest plugin from local source - module: 'github.com/algorand/go-algorand/cmd/partitiontest_linter' path: ./cmd/partitiontest_linter + # errortype plugin for error handling consistency + - module: fillmore-labs.com/errortype + import: fillmore-labs.com/errortype/gclplugin + version: v0.0.7 diff --git a/.golangci-warnings.yml b/.golangci-warnings.yml index d94ffb0d54..2bc88696f2 100644 --- a/.golangci-warnings.yml +++ b/.golangci-warnings.yml @@ -6,6 +6,7 @@ linters: enable: - gosec - partitiontest + - errortype settings: gosec: excludes: [G101, G103, G104, G107, G112, G114, G115, G202, G204, G301, G302, G303, G304, G306, G307, G404] @@ -13,6 +14,16 @@ linters: partitiontest: type: "module" description: This custom linter ensures test functions call 'partitiontest.PartitionTest(t)' + errortype: + type: module + description: "errortype helps prevent subtle bugs in error handling." + original-url: "https://fillmore-labs.com/errortype" + settings: + style-check: false + deep-is-check: true + check-is: true + unchecked-assert: false + check-unused: true exclusions: generated: lax rules: diff --git a/ledger/ledgercore/error.go b/ledger/ledgercore/error.go index f12af37dc7..d39890df6b 100644 --- a/ledger/ledgercore/error.go +++ b/ledger/ledgercore/error.go @@ -27,6 +27,17 @@ import ( // ErrNoSpace indicates insufficient space for transaction in block var ErrNoSpace = errors.New("block does not have space for transaction") +// Verify each custom error type implements the error interface, and declare which are pointer/value receivers. +var ( + _ error = (*TxnNotWellFormedError)(nil) + _ error = (*TransactionInLedgerError)(nil) + _ error = (*LeaseInLedgerError)(nil) + _ error = BlockInLedgerError{} + _ error = ErrNoEntry{} + _ error = ErrNonSequentialBlockEval{} + _ error = (*TxGroupMalformedError)(nil) +) + // TxnNotWellFormedError indicates a transaction was not well-formed when evaluated by the BlockEvaluator // //msgp:ignore TxnNotWellFormedError @@ -44,7 +55,7 @@ type TransactionInLedgerError struct { } // Error satisfies builtin interface `error` -func (tile TransactionInLedgerError) Error() string { +func (tile *TransactionInLedgerError) Error() string { return fmt.Sprintf("transaction already in ledger: %v", tile.Txid) } diff --git a/util/db/initialize.go b/util/db/initialize.go index 33ee093884..2996b76437 100644 --- a/util/db/initialize.go +++ b/util/db/initialize.go @@ -38,7 +38,7 @@ func Initialize(accessor Accessor, migrations []Migration) error { return InitializeWithContext(ctx, tx, migrations) }) - var sqlError *sqlite3.Error + var sqlError sqlite3.Error if errors.As(err, &sqlError) { return fmt.Errorf("%w. Sql error - Code: %d, Extended Code: %d", err, sqlError.Code, sqlError.ExtendedCode) }