diff --git a/.circleci/config.yml b/.circleci/config.yml index 7f91c78040f97..6307c24c787ac 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,32 +7,13 @@ slack-nightly-build-fail-post-step: &slack-nightly-build-fail-post-step - slack/notify: channel: $SLACK_DEFAULT_CHANNEL event: fail - custom: | - { - "text": "", - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "🔴 Nightly build failed!" - } - }, - { - "type": "actions", - "elements": [ - { - "type": "button", - "text": { - "type": "plain_text", - "text": "View Job" - }, - "url": "${CIRCLE_BUILD_URL}" - } - ] - } - ] - } + template: basic_fail-1 + +executors: + go-builder: + docker: + - image: ethereumoptimism/go-builder:latest + commands: build-dockerfile: parameters: @@ -56,6 +37,27 @@ commands: echo -n "$STACKMAN_REPO_AUTH" | docker login -u _json_key --password-stdin https://us-east4-docker.pkg.dev docker build -t "$STACKMAN_REPO/<>:nightly" -f <> <<#parameters.target>>--target <><> . docker push "$STACKMAN_REPO/<>:nightly" + + go-lint-test: + parameters: + working_directory: + description: Working directory + type: string + steps: + - checkout + - run: + name: Lint + command: golangci-lint run -E goimports -E sqlclosecheck -E bodyclose -E asciicheck ./... + working_directory: <> + - run: + name: Test + command: | + mkdir -p /test-results + gotestsum --junitfile /test-results/tests.xml + working_directory: <> + - store_test_results: + path: /test-results + jobs: build-dtl: docker: @@ -168,8 +170,294 @@ jobs: command: | echo "Dummy job." + go-lint-test: + parameters: + working_directory: + description: Working directory + type: string + docker: + - image: ethereumoptimism/go-builder:latest + - image: cimg/postgres:14.1 + steps: + - go-lint-test: + working_directory: <> + + go-lint-test-build: + parameters: + binary_name: + description: Binary name to build + type: string + working_directory: + description: Working directory + type: string + docker: + - image: ethereumoptimism/go-builder:latest + - image: cimg/postgres:14.1 + steps: + - go-lint-test: + working_directory: <> + - run: + name: Build + command: make <> + working_directory: <> + + yarn-monorepo: + docker: + - image: ethereumoptimism/js-builder:latest + steps: + - restore_cache: + keys: + - v1-source-{{ .Branch }}-{{ .Revision }} + - v1-source-{{ .Branch }} + - checkout + - save_cache: + key: v1-source-{{ .Branch }}-{{ .Revision }} + paths: + - ".git" + - restore_cache: + keys: + - v1-yarn-install-{{ checksum "yarn.lock" }} + - v1-yarn-install + - run: + name: Install dependencies + command: yarn --frozen-lockfile + - save_cache: + key: v1-yarn-install-{{ checksum "yarn.lock" }} + paths: + - node_modules + - packages/common-ts/node_modules + - packages/contracts/node_modules + - packages/core-utils/node_modules + - packages/data-transport-layer/node_modules + - packages/message-relayer/node_modules + - packages/replica-healthcheck/node_modules + - packages/sdk/node_modules + - integration-tests/node_modules + - run: + name: Build monorepo + command: yarn build + - save_cache: + key: v1-yarn-build-{{ .Revision }} + paths: + - "." + + contracts-slither: + docker: + - image: ethereumoptimism/js-builder:latest + steps: + - restore_cache: + keys: + - v1-yarn-build-{{ .Revision }} + - checkout + - run: + name: Run Slither + command: yarn test:slither + working_directory: packages/contracts + + contracts-tests: + docker: + - image: ethereumoptimism/js-builder:latest + resource_class: xlarge + steps: + - restore_cache: + keys: + - v1-yarn-build-{{ .Revision }} + - checkout + - run: + name: Lint + command: yarn lint:check + working_directory: packages/contracts + - run: + name: Slither + command: yarn test:slither + working_directory: packages/contracts + - run: + name: Test + command: yarn test:coverage + working_directory: packages/contracts + + dtl-tests: + docker: + - image: ethereumoptimism/js-builder:latest + steps: + - restore_cache: + keys: + - v1-yarn-build-{{ .Revision }} + - checkout + - run: + name: Test + command: yarn test:coverage + working_directory: packages/data-transport-layer + + geth-tests: + docker: + - image: ethereumoptimism/go-builder:latest + steps: + - checkout + - run: + name: Test + command: make test + working_directory: l2geth + + depcheck: + docker: + - image: ethereumoptimism/js-builder:latest + steps: + - restore_cache: + keys: + - v1-yarn-build-{{ .Revision }} + - checkout + # Note: The below needs to be manually configured whenever we + # add a new package to CI. + - run: + name: Check contracts + command: npx depcheck + working_directory: packages/contracts + - run: + name: Check core-utils + command: npx depcheck + working_directory: packages/core-utils + - run: + name: Check data-transport-layer + command: npx depcheck + working_directory: packages/data-transport-layer + - run: + name: Check sdk + command: npx depcheck + working_directory: packages/sdk + - run: + name: Check integration-tests + command: npx depcheck + working_directory: integration-tests + + bss-core-tests: + docker: + - image: ethereumoptimism/go-builder:latest + steps: + - checkout + - run: + name: Lint + command: golangci-lint run -E goimports -E sqlclosecheck -E bodyclose -E asciicheck ./... + working_directory: go/bss-core + - run: + name: Test + command: | + mkdir -p /test-results + gotestsum --junitfile /test-results/tests.xml + working_directory: go/bss-core + - store_test_results: + path: /test-results + + integration-tests: + machine: + image: ubuntu-2004:202111-02 + docker_layer_caching: true + environment: + DOCKER_BUILDKIT: 1 + parallelism: 3 + steps: + - checkout + - run: + name: Bring up the stack + command: | + docker-compose build --progress=plain + docker-compose up -d --scale replica-healthcheck=1 + working_directory: ops + - run: + name: Wait for sequencer + command: bash scripts/wait-for-sequencer.sh + working_directory: ops + - run: + name: Run integration tests + command: | + circleci tests glob "../integration-tests/test/*.spec.ts" | circleci tests split | tee splits.txt + docker-compose run integration_tests $(cat splits.txt) + working_directory: ops + + js-lint-test: + parameters: + package_name: + description: Package name + type: string + docker: + - image: ethereumoptimism/js-builder:latest + steps: + - restore_cache: + keys: + - v1-yarn-build-{{ .Revision }} + - checkout + - run: + name: Lint + command: yarn lint:check + working_directory: packages/<> + - run: + name: Test + command: yarn test:coverage + working_directory: packages/<> + workflows: + main: + jobs: + - yarn-monorepo + - go-lint-test-build: + name: batch-submitter-tests + binary_name: batch-submitter + working_directory: go/batch-submitter + - go-lint-test-build: + name: proxyd-tests + binary_name: proxyd + working_directory: go/proxyd + - go-lint-test-build: + name: teleportr-tests + binary_name: teleportr + working_directory: go/teleportr + - go-lint-test-build: + name: gas-oracle-tests + binary_name: gas-oracle + working_directory: go/gas-oracle + - go-lint-test-build: + name: indexer-tests + binary_name: indexer + working_directory: go/indexer + - go-lint-test: + name: bss-core-tests + working_directory: go/bss-core + - contracts-tests: + requires: + - yarn-monorepo + - js-lint-test: + name: dtl-tests + package_name: data-transport-layer + requires: + - yarn-monorepo + - js-lint-test: + name: core-utils-tests + package_name: core-utils + requires: + - yarn-monorepo + - js-lint-test: + name: sdk-tests + package_name: sdk + requires: + - yarn-monorepo + - js-lint-test: + name: message-relayer-tests + package_name: message-relayer + requires: + - yarn-monorepo + - js-lint-test: + name: replica-healthcheck-tests + package_name: replica-healthcheck + requires: + - yarn-monorepo + - depcheck: + requires: + - yarn-monorepo + - geth-tests + - integration-tests + + nightly-itests: triggers: - schedule: diff --git a/go/indexer/db/db.go b/go/indexer/db/db.go index 30a2a752d24cc..354d515bb5fca 100644 --- a/go/indexer/db/db.go +++ b/go/indexer/db/db.go @@ -38,38 +38,27 @@ func (d *Database) GetL1TokenByAddress(address string) (*Token, error) { var token *Token err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectL1TokenStatement) - if err != nil { - return err - } - - rows, err := queryStmt.Query(address) - if err != nil { - return err - } - - if !rows.Next() { - return nil + row := tx.QueryRow(selectL1TokenStatement, address) + if row.Err() != nil { + return row.Err() } var name string var symbol string var decimals uint8 - err = rows.Scan(&name, &symbol, &decimals) + err := row.Scan(&name, &symbol, &decimals) + if errors.Is(err, sql.ErrNoRows) { + return nil + } if err != nil { return err } - if rows.Next() { - return errors.New("address should be unique") - } - token = &Token{ Name: name, Symbol: symbol, Decimals: decimals, } - return nil }) if err != nil { @@ -88,32 +77,22 @@ func (d *Database) GetL2TokenByAddress(address string) (*Token, error) { var token *Token err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectL2TokenStatement) - if err != nil { - return err - } - - rows, err := queryStmt.Query(address) - if err != nil { - return err - } - - if !rows.Next() { - return nil + row := tx.QueryRow(selectL2TokenStatement, address) + if row.Err() != nil { + return row.Err() } var name string var symbol string var decimals uint8 - err = rows.Scan(&name, &symbol, &decimals) + err := row.Scan(&name, &symbol, &decimals) + if errors.Is(err, sql.ErrNoRows) { + return nil + } if err != nil { return err } - if rows.Next() { - return errors.New("address should be unique") - } - token = &Token{ Name: name, Symbol: symbol, @@ -141,22 +120,14 @@ func (d *Database) AddL1Token(address string, token *Token) error { ` return txn(d.db, func(tx *sql.Tx) error { - tokenStmt, err := tx.Prepare(insertTokenStatement) - if err != nil { - return err - } - - _, err = tokenStmt.Exec( + _, err := tx.Exec( + insertTokenStatement, address, token.Name, token.Symbol, token.Decimals, ) - if err != nil { - return err - } - - return nil + return err }) } @@ -172,22 +143,14 @@ func (d *Database) AddL2Token(address string, token *Token) error { ` return txn(d.db, func(tx *sql.Tx) error { - tokenStmt, err := tx.Prepare(insertTokenStatement) - if err != nil { - return err - } - - _, err = tokenStmt.Exec( + _, err := tx.Exec( + insertTokenStatement, address, token.Name, token.Symbol, token.Decimals, ) - if err != nil { - return err - } - - return nil + return err }) } @@ -209,12 +172,8 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error { ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ` return txn(d.db, func(tx *sql.Tx) error { - blockStmt, err := tx.Prepare(insertBlockStatement) - if err != nil { - return err - } - - _, err = blockStmt.Exec( + _, err := tx.Exec( + insertBlockStatement, block.Hash.String(), block.ParentHash.String(), block.Number, @@ -228,13 +187,9 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error { return nil } - depositStmt, err := tx.Prepare(insertDepositStatement) - if err != nil { - return err - } - for _, deposit := range block.Deposits { - _, err = depositStmt.Exec( + _, err = tx.Exec( + insertDepositStatement, NewGUID(), deposit.FromAddress.String(), deposit.ToAddress.String(), @@ -273,12 +228,8 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error { ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ` return txn(d.db, func(tx *sql.Tx) error { - blockStmt, err := tx.Prepare(insertBlockStatement) - if err != nil { - return err - } - - _, err = blockStmt.Exec( + _, err := tx.Exec( + insertBlockStatement, block.Hash.String(), block.ParentHash.String(), block.Number, @@ -292,13 +243,9 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error { return nil } - withdrawalStmt, err := tx.Prepare(insertWithdrawalStatement) - if err != nil { - return err - } - for _, withdrawal := range block.Withdrawals { - _, err = withdrawalStmt.Exec( + _, err = tx.Exec( + insertWithdrawalStatement, NewGUID(), withdrawal.FromAddress.String(), withdrawal.ToAddress.String(), @@ -330,13 +277,9 @@ func (d *Database) AddStateBatch(batches []StateBatch) error { ` return txn(d.db, func(tx *sql.Tx) error { - stateBatchStmt, err := tx.Prepare(insertStateBatchStatement) - if err != nil { - return err - } - for _, sb := range batches { - _, err = stateBatchStmt.Exec( + _, err := tx.Exec( + insertStateBatchStatement, sb.Index.Uint64(), sb.Root.String(), sb.Size.Uint64(), @@ -371,15 +314,11 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP var deposits []DepositJSON err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectDepositsStatement) - if err != nil { - return err - } - - rows, err := queryStmt.Query(address.String(), page.Limit, page.Offset) + rows, err := tx.Query(selectDepositsStatement, address.String(), page.Limit, page.Offset) if err != nil { return err } + defer rows.Close() for rows.Next() { var deposit DepositJSON @@ -397,9 +336,8 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP deposits = append(deposits, deposit) } - return nil + return rows.Err() }) - if err != nil { return nil, err } @@ -414,21 +352,17 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP ` var count uint64 - err = txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectDepositCountStatement) + row := tx.QueryRow(selectDepositCountStatement, address.String()) if err != nil { return err } - row := queryStmt.QueryRow(address.String()) - if err != nil { - return err - } - - row.Scan(&count) - return nil + return row.Scan(&count) }) + if err != nil { + return nil, err + } page.Total = count @@ -458,12 +392,7 @@ func (d *Database) GetWithdrawalBatch(hash l2common.Hash) (*StateBatchJSON, erro var batch *StateBatchJSON err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectWithdrawalBatchStatement) - if err != nil { - return err - } - - row := queryStmt.QueryRow(hash.String()) + row := tx.QueryRow(selectWithdrawalBatchStatement, hash.String()) if row.Err() != nil { return row.Err() } @@ -471,7 +400,7 @@ func (d *Database) GetWithdrawalBatch(hash l2common.Hash) (*StateBatchJSON, erro var index, size, prevTotal, blockNumber, blockTimestamp uint64 var root, blockHash string var extraData []byte - err = row.Scan(&index, &root, &size, &prevTotal, &extraData, &blockHash, + err := row.Scan(&index, &root, &size, &prevTotal, &extraData, &blockHash, &blockNumber, &blockTimestamp) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -519,15 +448,11 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina var withdrawals []WithdrawalJSON err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectWithdrawalsStatement) - if err != nil { - return err - } - - rows, err := queryStmt.Query(address.String(), page.Limit, page.Offset) + rows, err := tx.Query(selectWithdrawalsStatement, address.String(), page.Limit, page.Offset) if err != nil { return err } + defer rows.Close() for rows.Next() { var withdrawal WithdrawalJSON @@ -545,7 +470,7 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina withdrawals = append(withdrawals, withdrawal) } - return nil + return rows.Err() }) if err != nil { @@ -567,21 +492,17 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina ` var count uint64 - err = txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectWithdrawalCountStatement) - if err != nil { - return err - } - - row := queryStmt.QueryRow(address.String()) + row := tx.QueryRow(selectWithdrawalCountStatement, address.String()) if err != nil { return err } - row.Scan(&count) - return nil + return row.Scan(&count) }) + if err != nil { + return nil, err + } page.Total = count @@ -599,19 +520,14 @@ func (d *Database) GetHighestL1Block() (*L1BlockLocator, error) { var highestBlock *L1BlockLocator err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectHighestBlockStatement) - if err != nil { - return err - } - - row := queryStmt.QueryRow() + row := tx.QueryRow(selectHighestBlockStatement) if row.Err() != nil { return row.Err() } var number uint64 var hash string - err = row.Scan(&number, &hash) + err := row.Scan(&number, &hash) if err != nil { if errors.Is(err, sql.ErrNoRows) { highestBlock = nil @@ -642,19 +558,14 @@ func (d *Database) GetHighestL2Block() (*L2BlockLocator, error) { var highestBlock *L2BlockLocator err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectHighestBlockStatement) - if err != nil { - return err - } - - row := queryStmt.QueryRow() + row := tx.QueryRow(selectHighestBlockStatement) if row.Err() != nil { return row.Err() } var number uint64 var hash string - err = row.Scan(&number, &hash) + err := row.Scan(&number, &hash) if err != nil { if errors.Is(err, sql.ErrNoRows) { highestBlock = nil @@ -688,25 +599,20 @@ func (d *Database) GetIndexedL1BlockByHash(hash common.Hash) (*IndexedL1Block, e var block *IndexedL1Block err := txn(d.db, func(tx *sql.Tx) error { - queryStmt, err := tx.Prepare(selectBlockByHashStatement) - if err != nil { - return err - } - - row := queryStmt.QueryRow(hash.String()) - if errors.Is(row.Err(), sql.ErrNoRows) { - return nil - } + row := tx.QueryRow(selectBlockByHashStatement, hash.String()) if row.Err() != nil { - return err + return row.Err() } var hash string var parentHash string var number uint64 var timestamp uint64 - err = row.Scan(&hash, &parentHash, &number, ×tamp) + err := row.Scan(&hash, &parentHash, &number, ×tamp) if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil + } return err } diff --git a/go/indexer/metrics/metrics.go b/go/indexer/metrics/metrics.go index 35e6b6164005b..71d7f3fe4585c 100644 --- a/go/indexer/metrics/metrics.go +++ b/go/indexer/metrics/metrics.go @@ -2,12 +2,13 @@ package metrics import ( "fmt" + "net/http" + l2common "github.com/ethereum-optimism/optimism/l2geth/common" "github.com/ethereum/go-ethereum/common" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" - "net/http" ) const metricsNamespace = "indexer" diff --git a/go/indexer/services/l1/bridge/addresses.go b/go/indexer/services/l1/bridge/addresses.go index 15a6aba0144de..00927ec7b05b2 100644 --- a/go/indexer/services/l1/bridge/addresses.go +++ b/go/indexer/services/l1/bridge/addresses.go @@ -2,6 +2,7 @@ package bridge import ( "fmt" + "github.com/ethereum-optimism/optimism/go/indexer/bindings/address_manager" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" diff --git a/go/indexer/services/l1/bridge/eth_bridge.go b/go/indexer/services/l1/bridge/eth_bridge.go index 679552e499831..0004c27ebfb3e 100644 --- a/go/indexer/services/l1/bridge/eth_bridge.go +++ b/go/indexer/services/l1/bridge/eth_bridge.go @@ -2,6 +2,7 @@ package bridge import ( "context" + "github.com/ethereum-optimism/optimism/go/indexer/bindings/l1bridge" "github.com/ethereum-optimism/optimism/go/indexer/db" "github.com/ethereum/go-ethereum/accounts/abi/bind" diff --git a/go/indexer/services/l1/query.go b/go/indexer/services/l1/query.go index b0989f9c04fa0..c3e3fdae3ea24 100644 --- a/go/indexer/services/l1/query.go +++ b/go/indexer/services/l1/query.go @@ -2,6 +2,7 @@ package l1 import ( "context" + "github.com/ethereum-optimism/optimism/go/indexer/bindings/l1erc20" "github.com/ethereum/go-ethereum/ethclient" @@ -40,7 +41,6 @@ func QueryERC20(address common.Address, client *ethclient.Client) (*db.Token, er }, nil } - func QueryStateBatches(filterer *scc.StateCommitmentChainFilterer, startHeight, endHeight uint64, ctx context.Context) (map[common.Hash][]db.StateBatch, error) { batches := make(map[common.Hash][]db.StateBatch) diff --git a/go/proxyd/backend.go b/go/proxyd/backend.go index 5f4e0ac16706f..41dca997daa8b 100644 --- a/go/proxyd/backend.go +++ b/go/proxyd/backend.go @@ -255,7 +255,7 @@ func (b *Backend) ProxyWS(clientConn *websocket.Conn, methodWhitelist *StringSet return nil, ErrBackendOverCapacity } - backendConn, _, err := b.dialer.Dial(b.wsURL, nil) + backendConn, _, err := b.dialer.Dial(b.wsURL, nil) // nolint:bodyclose if err != nil { b.setOffline() if err := b.rateLimiter.DecBackendWSConns(b.Name); err != nil { @@ -513,7 +513,9 @@ func (w *WSProxier) clientPump(ctx context.Context, errC chan error) { msgType, msg, err := w.clientConn.ReadMessage() if err != nil { errC <- err - outConn.WriteMessage(websocket.CloseMessage, formatWSError(err)) + if err := outConn.WriteMessage(websocket.CloseMessage, formatWSError(err)); err != nil { + log.Error("error writing backendConn message", "err", err) + } return } @@ -575,7 +577,9 @@ func (w *WSProxier) backendPump(ctx context.Context, errC chan error) { msgType, msg, err := w.backendConn.ReadMessage() if err != nil { errC <- err - w.clientConn.WriteMessage(websocket.CloseMessage, formatWSError(err)) + if err := w.clientConn.WriteMessage(websocket.CloseMessage, formatWSError(err)); err != nil { + log.Error("error writing clientConn message", "err", err) + } return } diff --git a/go/proxyd/integration_tests/caching_test.go b/go/proxyd/integration_tests/caching_test.go index 4cdf0f03747d5..13b94b0e80759 100644 --- a/go/proxyd/integration_tests/caching_test.go +++ b/go/proxyd/integration_tests/caching_test.go @@ -3,12 +3,13 @@ package integration_tests import ( "bytes" "fmt" - "github.com/alicebob/miniredis" - "github.com/ethereum-optimism/optimism/go/proxyd" - "github.com/stretchr/testify/require" "os" "testing" "time" + + "github.com/alicebob/miniredis" + "github.com/ethereum-optimism/optimism/go/proxyd" + "github.com/stretchr/testify/require" ) func TestCaching(t *testing.T) { diff --git a/go/proxyd/integration_tests/failover_test.go b/go/proxyd/integration_tests/failover_test.go index 112162790dd14..a6f9743afe596 100644 --- a/go/proxyd/integration_tests/failover_test.go +++ b/go/proxyd/integration_tests/failover_test.go @@ -2,13 +2,14 @@ package integration_tests import ( "fmt" - "github.com/ethereum-optimism/optimism/go/proxyd" - "github.com/stretchr/testify/require" "net/http" "os" "sync/atomic" "testing" "time" + + "github.com/ethereum-optimism/optimism/go/proxyd" + "github.com/stretchr/testify/require" ) const ( @@ -39,7 +40,7 @@ func TestFailover(t *testing.T) { "backend responds 200 with non-JSON response", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) - w.Write([]byte("this data is not JSON!")) + _, _ = w.Write([]byte("this data is not JSON!")) }), }, { @@ -87,7 +88,7 @@ func TestFailover(t *testing.T) { t.Run("backend times out and falls back to another", func(t *testing.T) { badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) - w.Write([]byte("{}")) + _, _ = w.Write([]byte("{}")) })) res, statusCode, err := client.SendRPC("eth_chainId", nil) require.NoError(t, err) @@ -133,7 +134,7 @@ func TestRetries(t *testing.T) { w.WriteHeader(500) return } - w.Write([]byte(goodResponse)) + _, _ = w.Write([]byte(goodResponse)) })) // test case where request eventually succeeds @@ -169,7 +170,7 @@ func TestOutOfServiceInterval(t *testing.T) { defer shutdown() okHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(goodResponse)) + _, _ = w.Write([]byte(goodResponse)) }) badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(503) @@ -190,10 +191,12 @@ func TestOutOfServiceInterval(t *testing.T) { require.Equal(t, 2, len(badBackend.Requests())) require.Equal(t, 2, len(goodBackend.Requests())) - res, statusCode, err = client.SendBatchRPC( + _, statusCode, err = client.SendBatchRPC( NewRPCReq("1", "eth_chainId", nil), NewRPCReq("1", "eth_chainId", nil), ) + require.NoError(t, err) + require.Equal(t, 200, statusCode) require.Equal(t, 2, len(badBackend.Requests())) require.Equal(t, 4, len(goodBackend.Requests())) diff --git a/go/proxyd/integration_tests/mock_backend_test.go b/go/proxyd/integration_tests/mock_backend_test.go index 773b3d4b02e29..a39ebccaa949e 100644 --- a/go/proxyd/integration_tests/mock_backend_test.go +++ b/go/proxyd/integration_tests/mock_backend_test.go @@ -4,11 +4,12 @@ import ( "bytes" "context" "encoding/json" - "github.com/ethereum-optimism/optimism/go/proxyd" "io/ioutil" "net/http" "net/http/httptest" "sync" + + "github.com/ethereum-optimism/optimism/go/proxyd" ) type RecordedRequest struct { @@ -27,7 +28,7 @@ type MockBackend struct { func SingleResponseHandler(code int, response string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(code) - w.Write([]byte(response)) + _, _ = w.Write([]byte(response)) } } diff --git a/go/proxyd/integration_tests/rate_limit_test.go b/go/proxyd/integration_tests/rate_limit_test.go index 05e2ef64e2b18..0d5a26ce6e36f 100644 --- a/go/proxyd/integration_tests/rate_limit_test.go +++ b/go/proxyd/integration_tests/rate_limit_test.go @@ -1,10 +1,11 @@ package integration_tests import ( - "github.com/ethereum-optimism/optimism/go/proxyd" - "github.com/stretchr/testify/require" "os" "testing" + + "github.com/ethereum-optimism/optimism/go/proxyd" + "github.com/stretchr/testify/require" ) type resWithCode struct { diff --git a/go/proxyd/integration_tests/util_test.go b/go/proxyd/integration_tests/util_test.go index 65f9c23960fe5..3f21c3eec5f68 100644 --- a/go/proxyd/integration_tests/util_test.go +++ b/go/proxyd/integration_tests/util_test.go @@ -4,12 +4,13 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/BurntSushi/toml" - "github.com/ethereum-optimism/optimism/go/proxyd" - "github.com/stretchr/testify/require" "io/ioutil" "net/http" "testing" + + "github.com/BurntSushi/toml" + "github.com/ethereum-optimism/optimism/go/proxyd" + "github.com/stretchr/testify/require" ) type ProxydClient struct { diff --git a/go/proxyd/integration_tests/validation_test.go b/go/proxyd/integration_tests/validation_test.go index 1af8fa4585ff1..ee3de4c9b0702 100644 --- a/go/proxyd/integration_tests/validation_test.go +++ b/go/proxyd/integration_tests/validation_test.go @@ -1,11 +1,12 @@ package integration_tests import ( - "github.com/ethereum-optimism/optimism/go/proxyd" - "github.com/stretchr/testify/require" "os" "strings" "testing" + + "github.com/ethereum-optimism/optimism/go/proxyd" + "github.com/stretchr/testify/require" ) const ( diff --git a/go/proxyd/proxyd.go b/go/proxyd/proxyd.go index d0e098b6646d1..68ef4a664f709 100644 --- a/go/proxyd/proxyd.go +++ b/go/proxyd/proxyd.go @@ -217,7 +217,11 @@ func Start(config *Config) (func(), error) { if config.Metrics.Enabled { addr := fmt.Sprintf("%s:%d", config.Metrics.Host, config.Metrics.Port) log.Info("starting metrics server", "addr", addr) - go http.ListenAndServe(addr, promhttp.Handler()) + go func() { + if err := http.ListenAndServe(addr, promhttp.Handler()); err != nil { + log.Error("error starting metrics server", "err", err) + } + }() } // To allow integration tests to cleanly come up, wait diff --git a/go/proxyd/rate_limiter.go b/go/proxyd/rate_limiter.go index 45fbd31ccb672..5c4a4d6260387 100644 --- a/go/proxyd/rate_limiter.go +++ b/go/proxyd/rate_limiter.go @@ -5,10 +5,11 @@ import ( "crypto/rand" "encoding/hex" "fmt" - "github.com/ethereum/go-ethereum/log" - "github.com/go-redis/redis/v8" "sync" "time" + + "github.com/ethereum/go-ethereum/log" + "github.com/go-redis/redis/v8" ) const MaxRPSScript = ` diff --git a/go/proxyd/rpc_test.go b/go/proxyd/rpc_test.go index 5ebcd906cb23b..0d38decf08bd9 100644 --- a/go/proxyd/rpc_test.go +++ b/go/proxyd/rpc_test.go @@ -2,8 +2,9 @@ package proxyd import ( "encoding/json" - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestRPCResJSON(t *testing.T) { diff --git a/go/proxyd/server.go b/go/proxyd/server.go index 46cf8ae32b236..7c44eab1c537f 100644 --- a/go/proxyd/server.go +++ b/go/proxyd/server.go @@ -107,15 +107,15 @@ func (s *Server) WSListenAndServe(host string, port int) error { func (s *Server) Shutdown() { if s.rpcServer != nil { - s.rpcServer.Shutdown(context.Background()) + _ = s.rpcServer.Shutdown(context.Background()) } if s.wsServer != nil { - s.wsServer.Shutdown(context.Background()) + _ = s.wsServer.Shutdown(context.Background()) } } func (s *Server) HandleHealthz(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("OK")) + _, _ = w.Write([]byte("OK")) } func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) { @@ -159,7 +159,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) { return } - batchRes := make([]*RPCRes, len(reqs), len(reqs)) + batchRes := make([]*RPCRes, len(reqs)) var batchContainsCached bool for i := 0; i < len(reqs); i++ { req, err := ParseRPCReq(reqs[i]) @@ -301,7 +301,7 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context } return context.WithValue( r.Context(), - ContextKeyReqID, + ContextKeyReqID, // nolint:staticcheck randStr(10), ) } @@ -321,11 +321,11 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context } } - ctx := context.WithValue(r.Context(), ContextKeyAuth, s.authenticatedPaths[authorization]) - ctx = context.WithValue(ctx, ContextKeyXForwardedFor, xff) + ctx := context.WithValue(r.Context(), ContextKeyAuth, s.authenticatedPaths[authorization]) // nolint:staticcheck + ctx = context.WithValue(ctx, ContextKeyXForwardedFor, xff) // nolint:staticcheck return context.WithValue( ctx, - ContextKeyReqID, + ContextKeyReqID, // nolint:staticcheck randStr(10), ) } @@ -413,17 +413,6 @@ func GetXForwardedFor(ctx context.Context) string { return xff } -type recordLenReader struct { - io.Reader - Len int -} - -func (r *recordLenReader) Read(p []byte) (n int, err error) { - n, err = r.Reader.Read(p) - r.Len += n - return -} - type recordLenWriter struct { io.Writer Len int diff --git a/go/teleportr/cmd/teleportr/main.go b/go/teleportr/cmd/teleportr/main.go index f8bd0990cab63..3815abbd7f254 100644 --- a/go/teleportr/cmd/teleportr/main.go +++ b/go/teleportr/cmd/teleportr/main.go @@ -35,8 +35,8 @@ func main() { app.Description = "Teleportr bridge from L1 to L2" app.Commands = []cli.Command{ { - Name: "migrate", - Usage: "Migrates teleportr's database", + Name: "migrate", + Usage: "Migrates teleportr's database", Action: teleportr.Migrate(), }, } diff --git a/go/teleportr/teleportr.go b/go/teleportr/teleportr.go index 8dfb872aa9be8..de1e4fb680694 100644 --- a/go/teleportr/teleportr.go +++ b/go/teleportr/teleportr.go @@ -181,4 +181,4 @@ func Migrate() func(ctx *cli.Context) error { log.Info("Done") return nil } -} \ No newline at end of file +} diff --git a/ops/docker/go-builder/Dockerfile b/ops/docker/go-builder/Dockerfile new file mode 100644 index 0000000000000..ef43b0d5d4b5d --- /dev/null +++ b/ops/docker/go-builder/Dockerfile @@ -0,0 +1,7 @@ +FROM golang:1.17.8-alpine3.15 + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq curl bash gzip ca-certificates openssh && \ + go install gotest.tools/gotestsum@latest && \ + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.44.2 + +CMD ["bash"] diff --git a/ops/docker/js-builder/Dockerfile b/ops/docker/js-builder/Dockerfile new file mode 100644 index 0000000000000..774de88038fc4 --- /dev/null +++ b/ops/docker/js-builder/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.8.12-slim-buster + +RUN apt-get update && \ + apt-get install -y curl openssh-client git build-essential ca-certificates && \ + curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh && \ + bash nodesource_setup.sh && \ + apt-get install -y nodejs && \ + npm i -g yarn && \ + npm i -g depcheck && \ + pip install slither-analyzer diff --git a/ops/scripts/integration-tests.sh b/ops/scripts/integration-tests.sh index f4564525837ea..4f0d5f3421969 100755 --- a/ops/scripts/integration-tests.sh +++ b/ops/scripts/integration-tests.sh @@ -23,4 +23,4 @@ curl \ --output /dev/null \ $L2_URL -npx hardhat test --network optimism --no-compile +npx hardhat test --network optimism --no-compile "$@" diff --git a/ops/scripts/wait-for-sequencer.sh b/ops/scripts/wait-for-sequencer.sh index dc86b19f290d0..1f5ea579e644f 100755 --- a/ops/scripts/wait-for-sequencer.sh +++ b/ops/scripts/wait-for-sequencer.sh @@ -1,11 +1,11 @@ #!/bin/bash CONTAINER=l2geth -RETRIES=30 +RETRIES=90 i=0 until docker-compose logs l2geth | grep -q "Starting Sequencer Loop"; do - sleep 3 + sleep 1 if [ $i -eq $RETRIES ]; then echo 'Timed out waiting for sequencer' break diff --git a/packages/contracts/.eslintrc.js b/packages/contracts/.eslintrc.js index bfd2057be80bd..f8cede27c483c 100644 --- a/packages/contracts/.eslintrc.js +++ b/packages/contracts/.eslintrc.js @@ -1,3 +1,7 @@ module.exports = { extends: '../../.eslintrc.js', + ignorePatterns: [ + 'src/contract-artifacts.ts', + 'src/contract-deployed-artifacts.ts', + ], } diff --git a/packages/message-relayer/package.json b/packages/message-relayer/package.json index a83cff3594b60..e58d6e36fc3a3 100644 --- a/packages/message-relayer/package.json +++ b/packages/message-relayer/package.json @@ -10,6 +10,7 @@ ], "scripts": { "start": "ts-node ./src/service.ts", + "test:coverage": "echo 'No tests defined.'", "build": "tsc -p ./tsconfig.build.json", "clean": "rimraf dist/ ./tsconfig.build.tsbuildinfo", "lint": "yarn lint:fix && yarn lint:check", diff --git a/packages/replica-healthcheck/package.json b/packages/replica-healthcheck/package.json index 9b7feb50c9fed..f207f5c3bc304 100644 --- a/packages/replica-healthcheck/package.json +++ b/packages/replica-healthcheck/package.json @@ -10,6 +10,7 @@ ], "scripts": { "start": "ts-node ./src/service", + "test:coverage": "echo 'No tests defined.'", "build": "tsc -p tsconfig.build.json", "clean": "rimraf ./dist ./tsconfig.build.tsbuildinfo", "lint": "yarn run lint:fix && yarn run lint:check",