diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index f1d0376830..7e5de28d1c 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -63,7 +63,6 @@ jobs: - "lint" - "slither" - "gosec" - - "nilaway" - "markdownlint" - "generate-check" - "tidy-sync-check" diff --git a/Dockerfile b/Dockerfile index 623a4d1f18..93c438993b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ ### Stage 0 - Build Arguments ### ####################################################### -ARG GO_VERSION=1.23.0 +ARG GO_VERSION=1.23.4 ARG RUNNER_IMAGE=alpine:3.20 ARG BUILD_TAGS="netgo,muslc,blst,bls12381,pebbledb" ARG NAME=beacond diff --git a/cli/commands/server/start.go b/cli/commands/server/start.go index fb08d9e748..19fe168c90 100644 --- a/cli/commands/server/start.go +++ b/cli/commands/server/start.go @@ -23,6 +23,7 @@ package server import ( "context" + "errors" pruningtypes "cosmossdk.io/store/pruning/types" types "github.com/berachain/beacon-kit/cli/commands/server/types" @@ -106,6 +107,10 @@ custom: allow pruning options to be manually specified through 'pruning-keep-rec RunE: func(cmd *cobra.Command, _ []string) error { logger := clicontext.GetLoggerFromCmd[LoggerT](cmd) cfg := clicontext.GetConfigFromCmd(cmd) + if cfg.Consensus.TimeoutCommit == 0 { + return errors.New("please edit your config.toml file and set timeout_commit to 1s") + } + v := clicontext.GetViperFromCmd(cmd) _, err := GetPruningOptionsFromFlags(v) if err != nil { diff --git a/cmd/beacond/defaults.go b/cmd/beacond/defaults.go index e70745e508..b44249ed37 100644 --- a/cmd/beacond/defaults.go +++ b/cmd/beacond/defaults.go @@ -24,7 +24,7 @@ import ( "github.com/berachain/beacon-kit/node-core/components" ) -//nolint:funlen // happens +//nolint:funlen func DefaultComponents() []any { c := []any{ components.ProvideAttributesFactory[ diff --git a/go.mod b/go.mod index 73db790ba1..9c33e49797 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,6 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 - github.com/supranational/blst v0.3.13 github.com/umbracle/fastrlp v0.1.0 go.uber.org/automaxprocs v1.6.0 go.uber.org/nilaway v0.0.0-20241010202415-ba14292918d8 @@ -418,6 +417,7 @@ require ( github.com/stoewer/go-strcase v1.3.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tdakkota/asciicheck v0.2.0 // indirect github.com/tendermint/go-amino v0.16.0 // indirect diff --git a/node-core/components/depinject.go b/node-core/components/depinject.go index 3d94b530af..dffb76b199 100644 --- a/node-core/components/depinject.go +++ b/node-core/components/depinject.go @@ -21,17 +21,93 @@ package components import ( + "context" + "cosmossdk.io/core/store" - "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/runtime" + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) -var storeKey = types.NewKVStoreKey("beacon") +//nolint:gochecknoglobals // storeKey is a singleton. +var storeKey = storetypes.NewKVStoreKey("beacon") -func ProvideKVStoreKey() *types.KVStoreKey { +func ProvideKVStoreKey() *storetypes.KVStoreKey { return storeKey } -func ProvideKVStoreService(storeKey *types.KVStoreKey) store.KVStoreService { - return runtime.NewKVStoreService(storeKey) +func ProvideKVStoreService( + storeKey *storetypes.KVStoreKey, +) store.KVStoreService { + // skips modules that have no store + return kvStoreService{key: storeKey} +} + +func NewKVStoreService(storeKey *storetypes.KVStoreKey) store.KVStoreService { + return &kvStoreService{key: storeKey} +} + +type kvStoreService struct { + key *storetypes.KVStoreKey +} + +func (k kvStoreService) OpenKVStore(ctx context.Context) store.KVStore { + return NewKVStore(sdk.UnwrapSDKContext(ctx).KVStore(k.key)) +} + +// CoreKVStore is a wrapper of Core/Store kvstore interface +// Remove after https://github.com/cosmos/cosmos-sdk/issues/14714 is closed. +type coreKVStore struct { + kvStore storetypes.KVStore +} + +// NewKVStore returns a wrapper of Core/Store kvstore interface +// Remove once store migrates to core/store kvstore interface. +func NewKVStore(store storetypes.KVStore) store.KVStore { + return coreKVStore{kvStore: store} +} + +// Get returns nil iff key doesn't exist. Errors on nil key. +func (store coreKVStore) Get(key []byte) ([]byte, error) { + return store.kvStore.Get(key), nil +} + +// Has checks if a key exists. Errors on nil key. +func (store coreKVStore) Has(key []byte) (bool, error) { + return store.kvStore.Has(key), nil +} + +// Set sets the key. Errors on nil key or value. +func (store coreKVStore) Set(key, value []byte) error { + store.kvStore.Set(key, value) + return nil +} + +// Delete deletes the key. Errors on nil key. +func (store coreKVStore) Delete(key []byte) error { + store.kvStore.Delete(key) + return nil +} + +// Iterator iterates over a domain of keys in ascending order. End is exclusive. +// Start must be less than end, or the Iterator is invalid. +// Iterator must be closed by caller. +// To iterate over entire domain, use store.Iterator(nil, nil) +// CONTRACT: No writes may happen within a domain while an iterator exists over +// it. +// Exceptionally allowed for cachekv.Store, safe to write in the modules. +func (store coreKVStore) Iterator(start, end []byte) (store.Iterator, error) { + return store.kvStore.Iterator(start, end), nil +} + +// ReverseIterator iterates over a domain of keys in descending order. End is +// exclusive. +// Start must be less than end, or the Iterator is invalid. +// Iterator must be closed by caller. +// CONTRACT: No writes may happen within a domain while an iterator exists over +// it. +// Exceptionally allowed for cachekv.Store, safe to write in the modules. +func (store coreKVStore) ReverseIterator( + start, end []byte, +) (store.Iterator, error) { + return store.kvStore.ReverseIterator(start, end), nil } diff --git a/node-core/components/signer/signer.go b/node-core/components/signer/signer.go index 2375a5d22b..f85ff4a9a5 100644 --- a/node-core/components/signer/signer.go +++ b/node-core/components/signer/signer.go @@ -85,7 +85,7 @@ func (f BLSSigner) VerifySignature( ) error { pk, err := bls12381.NewPublicKeyFromCompressedBytes(pubKey[:]) if err != nil { - return fmt.Errorf("verifying signature: %s", err) + return fmt.Errorf("verifying signature: %w", err) } if !pk.VerifySignature(msg, signature[:]) { return ErrInvalidSignature diff --git a/scripts/build/linting.mk b/scripts/build/linting.mk index 3664b09790..819c8afa53 100644 --- a/scripts/build/linting.mk +++ b/scripts/build/linting.mk @@ -15,14 +15,14 @@ lint: ## run all configured linters # TODO: Remove GODEBUG override once: https://github.com/golang/go/issues/68877 is resolved. golangci: @echo "--> Running linter on all modules" - (GODEBUG=gotypesalias=0 go run github.com/golangci/golangci-lint/cmd/golangci-lint run --config $(ROOT_DIR)/.golangci.yaml --timeout=10m --concurrency 8) || exit 1; + (GODEBUG=gotypesalias=0 go run github.com/golangci/golangci-lint/cmd/golangci-lint --build-tags bls12381 run --config $(ROOT_DIR)/.golangci.yaml --timeout=10m --concurrency 8) || exit 1; @printf "All modules complete\n" # TODO: Remove GODEBUG override once: https://github.com/golang/go/issues/68877 is resolved. golangci-fix: @echo "--> Running linter with fixes on all modules" - (GODEBUG=gotypesalias=0 go run github.com/golangci/golangci-lint/cmd/golangci-lint run --config $(ROOT_DIR)/.golangci.yaml --timeout=10m --fix --concurrency 8) || exit 1; + (GODEBUG=gotypesalias=0 go run github.com/golangci/golangci-lint/cmd/golangci-lint --build-tags bls12381 run --config $(ROOT_DIR)/.golangci.yaml --timeout=10m --fix --concurrency 8) || exit 1; @printf "All modules complete\n" ################# @@ -53,7 +53,7 @@ license-fix: nilaway: @echo "--> Running nilaway" - (go run go.uber.org/nilaway/cmd/nilaway -exclude-errors-in-files "geth-primitives/deposit/" -v ./...) || exit 1; + (go run go.uber.org/nilaway/cmd/nilaway --tags bls12381 -exclude-errors-in-files "geth-primitives/deposit/" -v ./...) || exit 1; @printf "Nilaway check complete\n" ################# @@ -62,7 +62,7 @@ nilaway: gosec: @echo "--> Running gosec" - @go run github.com/cosmos/gosec/v2/cmd/gosec -exclude G702 ./... + @go run github.com/cosmos/gosec/v2/cmd/gosec -tags bls12381 -exclude-dir node-core/components/signer -exclude G702 ./... ################# # slither # diff --git a/scripts/build/testing.mk b/scripts/build/testing.mk index 2606ab8bc3..c035ded162 100644 --- a/scripts/build/testing.mk +++ b/scripts/build/testing.mk @@ -251,32 +251,33 @@ SHORT_FUZZ_TIME=10s MEDIUM_FUZZ_TIME=30s LONG_FUZZ_TIME=3m + test: @$(MAKE) test-unit test-forge-fuzz test-unit: ## run golang unit tests @echo "Running unit tests..." @go list -f '{{.Dir}}/...' -m | xargs \ - go test -race + go test --tags bls12381 -race test-unit-cover: ## run golang unit tests with coverage @echo "Running unit tests with coverage..." @go list -f '{{.Dir}}/...' -m | xargs \ - go test -race -coverprofile=test-unit-cover.txt + go test --tags bls12381 -race -coverprofile=test-unit-cover.txt test-unit-bench: ## run golang unit benchmarks @echo "Running unit tests with benchmarks..." @go list -f '{{.Dir}}/...' -m | xargs \ - go test -bench=. -run=^$ -benchmem + go test --tags bls12381 -bench=. -run=^$ -benchmem # On MacOS, if there is a linking issue on the fuzz tests, # use the old linker with flags -ldflags=-extldflags=-Wl,-ld_classic test-unit-fuzz: ## run fuzz tests @echo "Running fuzz tests with coverage..." - go test -run ^FuzzPayloadIDCacheBasic -fuzztime=${SHORT_FUZZ_TIME} github.com/berachain/beacon-kit/payload/cache - go test -run ^FuzzPayloadIDInvalidInput -fuzztime=${SHORT_FUZZ_TIME} github.com/berachain/beacon-kit/payload/cache - go test -run ^FuzzPayloadIDCacheConcurrency -fuzztime=${SHORT_FUZZ_TIME} github.com/berachain/beacon-kit/payload/cache - go test -run ^FuzzHashTreeRoot -fuzztime=${MEDIUM_FUZZ_TIME} github.com/berachain/beacon-kit/primitives/merkle + go test --tags bls12381 -run ^FuzzPayloadIDCacheBasic -fuzztime=${SHORT_FUZZ_TIME} github.com/berachain/beacon-kit/payload/cache + go test --tags bls12381 -run ^FuzzPayloadIDInvalidInput -fuzztime=${SHORT_FUZZ_TIME} github.com/berachain/beacon-kit/payload/cache + go test --tags bls12381 -run ^FuzzPayloadIDCacheConcurrency -fuzztime=${SHORT_FUZZ_TIME} github.com/berachain/beacon-kit/payload/cache + go test --tags bls12381 -run ^FuzzHashTreeRoot -fuzztime=${MEDIUM_FUZZ_TIME} github.com/berachain/beacon-kit/primitives/merkle test-e2e: ## run e2e tests @$(MAKE) build-docker VERSION=kurtosis-local test-e2e-no-build diff --git a/state-transition/core/core_test.go b/state-transition/core/core_test.go index f11c3ff04c..b162287eae 100644 --- a/state-transition/core/core_test.go +++ b/state-transition/core/core_test.go @@ -21,9 +21,11 @@ package core_test import ( + "context" "fmt" "testing" + corestore "cosmossdk.io/core/store" "cosmossdk.io/log" "cosmossdk.io/store" "cosmossdk.io/store/metrics" @@ -46,7 +48,6 @@ import ( depositstore "github.com/berachain/beacon-kit/storage/deposit" "github.com/berachain/beacon-kit/storage/encoding" dbm "github.com/cosmos/cosmos-db" - "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -70,6 +71,17 @@ type ( ] ) +type testKVStoreService struct { + ctx sdk.Context +} + +func (kvs *testKVStoreService) OpenKVStore(context.Context) corestore.KVStore { + //nolint:contextcheck // fine with tests + return components.NewKVStore( + sdk.UnwrapSDKContext(kvs.ctx).KVStore(testStoreKey), + ) +} + var ( testStoreKey = storetypes.NewKVStoreKey("state-transition-tests") testCodec = &encoding.SSZInterfaceCodec[*types.ExecutionPayloadHeader]{} @@ -96,12 +108,12 @@ func initTestStores() (*beacondb.KVStore, *depositstore.KVStore, error) { return nil, nil, fmt.Errorf("failed to load latest version: %w", err) } - sdkCtx := sdk.NewContext(cms, true, nopLog) - testStoreService := runtime.NewKVStoreService(testStoreKey) + ctx := sdk.NewContext(cms, true, nopLog) + testStoreService := &testKVStoreService{ctx: ctx} return beacondb.New( testStoreService, testCodec, - ).WithContext(sdkCtx), + ), depositstore.NewStore(testStoreService, nopLog), nil } diff --git a/storage/beacondb/registry_test.go b/storage/beacondb/registry_test.go index 0856c50a70..e73632168a 100644 --- a/storage/beacondb/registry_test.go +++ b/storage/beacondb/registry_test.go @@ -21,25 +21,38 @@ package beacondb_test import ( + "context" "fmt" "testing" + corestore "cosmossdk.io/core/store" "cosmossdk.io/log" "cosmossdk.io/store" "cosmossdk.io/store/metrics" storetypes "cosmossdk.io/store/types" "github.com/berachain/beacon-kit/consensus-types/types" + "github.com/berachain/beacon-kit/node-core/components" "github.com/berachain/beacon-kit/primitives/bytes" "github.com/berachain/beacon-kit/primitives/math" "github.com/berachain/beacon-kit/storage/beacondb" "github.com/berachain/beacon-kit/storage/db" "github.com/berachain/beacon-kit/storage/encoding" dbm "github.com/cosmos/cosmos-db" - "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" ) +type testKVStoreService struct { + ctx sdk.Context +} + +func (kvs *testKVStoreService) OpenKVStore(context.Context) corestore.KVStore { + //nolint:contextcheck // fine with tests + return components.NewKVStore( + sdk.UnwrapSDKContext(kvs.ctx).KVStore(testStoreKey), + ) +} + var ( testStoreKey = storetypes.NewKVStoreKey("storage-tests") testCodec = &encoding.SSZInterfaceCodec[*types.ExecutionPayloadHeader]{} @@ -205,9 +218,12 @@ func initTestStore() (*beacondb.KVStore, error) { return nil, fmt.Errorf("failed to load latest version: %w", err) } - sdkCtx := sdk.NewContext(cms, true, nopLog) + ctx := sdk.NewContext(cms, true, nopLog) + testStoreService := &testKVStoreService{ + ctx: ctx, + } return beacondb.New( - runtime.NewKVStoreService(testStoreKey), + testStoreService, testCodec, - ).WithContext(sdkCtx), nil + ), nil } diff --git a/testing/e2e/e2e_staking_test.go b/testing/e2e/e2e_staking_test.go index 0b27384572..f7d15813e5 100644 --- a/testing/e2e/e2e_staking_test.go +++ b/testing/e2e/e2e_staking_test.go @@ -29,6 +29,7 @@ import ( "github.com/berachain/beacon-kit/geth-primitives/deposit" "github.com/berachain/beacon-kit/primitives/common" "github.com/berachain/beacon-kit/testing/e2e/config" + "github.com/cometbft/cometbft/crypto/bls12381" "github.com/ethereum/go-ethereum/accounts/abi/bind" gethcommon "github.com/ethereum/go-ethereum/common" coretypes "github.com/ethereum/go-ethereum/core/types" @@ -98,14 +99,22 @@ func (s *BeaconKitE2ESuite) TestDepositRobustness() { // Create a deposit transaction. Use the default validators' pubkeys // if exists, otherwise pubkey is a random 48 byte slice. var pubkey []byte + var pk *bls12381.PubKey + switch i { case 0: pubkey, err = client.GetPubKey(s.Ctx()) s.Require().NoError(err) + pk, err = bls12381.NewPublicKeyFromBytes(pubkey) + s.Require().NoError(err) + pubkey = pk.Compress() s.Require().Len(pubkey, 48) case 1: pubkey, err = client2.GetPubKey(s.Ctx()) s.Require().NoError(err) + pk, err = bls12381.NewPublicKeyFromBytes(pubkey) + s.Require().NoError(err) + pubkey = pk.Compress() s.Require().Len(pubkey, 48) default: pubkey = make([]byte, 48)