diff --git a/.bazelrc b/.bazelrc index 6a8f445b43be..3e93f9ab623e 100644 --- a/.bazelrc +++ b/.bazelrc @@ -217,3 +217,6 @@ build:remote --remote_local_fallback # Ignore GoStdLib with remote caching build --modify_execution_info='GoStdlib.*=+no-remote-cache' + +# Set bazel gotag +build --define gotags=bazel diff --git a/BUILD.bazel b/BUILD.bazel index 77be99443248..419322ce4cd2 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -16,6 +16,8 @@ exports_files([ # gazelle:map_kind go_library go_library @prysm//tools/go:def.bzl # gazelle:map_kind go_test go_test @prysm//tools/go:def.bzl # gazelle:map_kind go_repository go_repository @prysm//tools/go:def.bzl +# gazelle:build_tags bazel +# gazelle:exclude tools/analyzers/**/testdata/** gazelle( name = "gazelle", prefix = prefix, @@ -125,6 +127,7 @@ nogo( "//tools/analyzers/ineffassign:go_default_library", "//tools/analyzers/properpermissions:go_default_library", "//tools/analyzers/recursivelock:go_default_library", + "//tools/analyzers/uintcast:go_default_library", ] + select({ # nogo checks that fail with coverage enabled. ":coverage_enabled": [], diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index 4ab9036e701e..c4ae838cd80b 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -166,7 +166,7 @@ func (s *Service) Status() error { func (s *Service) startFromSavedState(saved state.BeaconState) error { log.Info("Blockchain data already exists in DB, initializing...") - s.genesisTime = time.Unix(int64(saved.GenesisTime()), 0) + s.genesisTime = time.Unix(int64(saved.GenesisTime()), 0) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime. s.cfg.AttService.SetGenesisTime(saved.GenesisTime()) originRoot, err := s.originRootFromSavedState(s.ctx) diff --git a/beacon-chain/cache/active_balance.go b/beacon-chain/cache/active_balance.go index 053a7514f5da..babbfb627cd7 100644 --- a/beacon-chain/cache/active_balance.go +++ b/beacon-chain/cache/active_balance.go @@ -1,3 +1,4 @@ +//go:build !fuzz // +build !fuzz package cache @@ -17,10 +18,12 @@ import ( "github.com/prysmaticlabs/prysm/config/params" ) -var ( +const ( // maxBalanceCacheSize defines the max number of active balances can cache. - maxBalanceCacheSize = uint64(4) + maxBalanceCacheSize = int(4) +) +var ( // BalanceCacheMiss tracks the number of balance requests that aren't present in the cache. balanceCacheMiss = promauto.NewCounter(prometheus.CounterOpts{ Name: "total_effective_balance_cache_miss", @@ -42,7 +45,7 @@ type BalanceCache struct { // NewEffectiveBalanceCache creates a new effective balance cache for storing/accessing total balance by epoch. func NewEffectiveBalanceCache() *BalanceCache { return &BalanceCache{ - cache: lruwrpr.New(int(maxBalanceCacheSize)), + cache: lruwrpr.New(maxBalanceCacheSize), } } diff --git a/beacon-chain/cache/committee.go b/beacon-chain/cache/committee.go index 3babe26564d8..4c237fc59512 100644 --- a/beacon-chain/cache/committee.go +++ b/beacon-chain/cache/committee.go @@ -1,3 +1,4 @@ +//go:build !fuzz // +build !fuzz package cache @@ -19,11 +20,13 @@ import ( mathutil "github.com/prysmaticlabs/prysm/math" ) -var ( +const ( // maxCommitteesCacheSize defines the max number of shuffled committees on per randao basis can cache. // Due to reorgs and long finality, it's good to keep the old cache around for quickly switch over. - maxCommitteesCacheSize = uint64(32) + maxCommitteesCacheSize = int(32) +) +var ( // CommitteeCacheMiss tracks the number of committee requests that aren't present in the cache. CommitteeCacheMiss = promauto.NewCounter(prometheus.CounterOpts{ Name: "committee_cache_miss", @@ -55,7 +58,7 @@ func committeeKeyFn(obj interface{}) (string, error) { // NewCommitteesCache creates a new committee cache for storing/accessing shuffled indices of a committee. func NewCommitteesCache() *CommitteeCache { return &CommitteeCache{ - CommitteeCache: lruwrpr.New(int(maxCommitteesCacheSize)), + CommitteeCache: lruwrpr.New(maxCommitteesCacheSize), inProgress: make(map[string]bool), } } diff --git a/beacon-chain/cache/committee_fuzz_test.go b/beacon-chain/cache/committee_fuzz_test.go index 1db6a00c6789..a7a59ed5c8d2 100644 --- a/beacon-chain/cache/committee_fuzz_test.go +++ b/beacon-chain/cache/committee_fuzz_test.go @@ -33,7 +33,7 @@ func TestCommitteeCache_FuzzCommitteesByEpoch(t *testing.T) { require.NoError(t, err) } - assert.Equal(t, maxCommitteesCacheSize, uint64(len(cache.CommitteeCache.Keys())), "Incorrect key size") + assert.Equal(t, maxCommitteesCacheSize, len(cache.CommitteeCache.Keys()), "Incorrect key size") } func TestCommitteeCache_FuzzActiveIndices(t *testing.T) { @@ -50,5 +50,5 @@ func TestCommitteeCache_FuzzActiveIndices(t *testing.T) { assert.DeepEqual(t, c.SortedIndices, indices) } - assert.Equal(t, maxCommitteesCacheSize, uint64(len(cache.CommitteeCache.Keys())), "Incorrect key size") + assert.Equal(t, maxCommitteesCacheSize, len(cache.CommitteeCache.Keys()), "Incorrect key size") } diff --git a/beacon-chain/cache/committee_test.go b/beacon-chain/cache/committee_test.go index 1127a06d3c6a..4110a1c575c5 100644 --- a/beacon-chain/cache/committee_test.go +++ b/beacon-chain/cache/committee_test.go @@ -102,7 +102,7 @@ func TestCommitteeCache_CanRotate(t *testing.T) { } k := cache.CommitteeCache.Keys() - assert.Equal(t, maxCommitteesCacheSize, uint64(len(k))) + assert.Equal(t, maxCommitteesCacheSize, len(k)) sort.Slice(k, func(i, j int) bool { return k[i].(string) < k[j].(string) diff --git a/beacon-chain/cache/subnet_ids.go b/beacon-chain/cache/subnet_ids.go index ddb88fadf9f8..a361259eb6b6 100644 --- a/beacon-chain/cache/subnet_ids.go +++ b/beacon-chain/cache/subnet_ids.go @@ -27,7 +27,7 @@ var SubnetIDs = newSubnetIDs() func newSubnetIDs() *subnetIDs { // Given a node can calculate committee assignments of current epoch and next epoch. // Max size is set to 2 epoch length. - cacheSize := int(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxCommitteesPerSlot * 2)) + cacheSize := int(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxCommitteesPerSlot * 2)) // lint:ignore uintcast -- constant values that would panic on startup if negative. attesterCache := lruwrpr.New(cacheSize) aggregatorCache := lruwrpr.New(cacheSize) epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot)) diff --git a/beacon-chain/core/blocks/deposit.go b/beacon-chain/core/blocks/deposit.go index 9864d7598ead..ceb7684bc076 100644 --- a/beacon-chain/core/blocks/deposit.go +++ b/beacon-chain/core/blocks/deposit.go @@ -225,7 +225,7 @@ func verifyDeposit(beaconState state.ReadOnlyBeaconState, deposit *ethpb.Deposit if ok := trie.VerifyMerkleProofWithDepth( receiptRoot, leaf[:], - int(beaconState.Eth1DepositIndex()), + beaconState.Eth1DepositIndex(), deposit.Proof, params.BeaconConfig().DepositContractTreeDepth, ); !ok { diff --git a/beacon-chain/core/transition/transition.go b/beacon-chain/core/transition/transition.go index dba705c4c540..2dd4ae0b7007 100644 --- a/beacon-chain/core/transition/transition.go +++ b/beacon-chain/core/transition/transition.go @@ -92,7 +92,7 @@ func ExecuteStateTransition( func ProcessSlot(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlot") defer span.End() - span.AddAttributes(trace.Int64Attribute("slot", int64(state.Slot()))) + span.AddAttributes(trace.Int64Attribute("slot", int64(state.Slot()))) // lint:ignore uintcast -- This is OK for tracing. prevStateRoot, err := state.HashTreeRoot(ctx) if err != nil { @@ -190,7 +190,7 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot) if state == nil || state.IsNil() { return nil, errors.New("nil state") } - span.AddAttributes(trace.Int64Attribute("slots", int64(slot)-int64(state.Slot()))) + span.AddAttributes(trace.Int64Attribute("slots", int64(slot)-int64(state.Slot()))) // lint:ignore uintcast -- This is OK for tracing. // The block must have a higher slot than parent state. if state.Slot() >= slot { @@ -354,7 +354,7 @@ func VerifyOperationLengths(_ context.Context, state state.BeaconState, b block. func ProcessEpochPrecompute(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { ctx, span := trace.StartSpan(ctx, "core.state.ProcessEpochPrecompute") defer span.End() - span.AddAttributes(trace.Int64Attribute("epoch", int64(time.CurrentEpoch(state)))) + span.AddAttributes(trace.Int64Attribute("epoch", int64(time.CurrentEpoch(state)))) // lint:ignore uintcast -- This is OK for tracing. if state == nil || state.IsNil() { return nil, errors.New("nil state") diff --git a/beacon-chain/forkchoice/protoarray/BUILD.bazel b/beacon-chain/forkchoice/protoarray/BUILD.bazel index e0536488634a..4a8d71e347c6 100644 --- a/beacon-chain/forkchoice/protoarray/BUILD.bazel +++ b/beacon-chain/forkchoice/protoarray/BUILD.bazel @@ -21,6 +21,7 @@ go_library( deps = [ "//config/fieldparams:go_default_library", "//config/params:go_default_library", + "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/forkchoice/protoarray/helpers.go b/beacon-chain/forkchoice/protoarray/helpers.go index b3aeb8561631..1cdcfa0d990b 100644 --- a/beacon-chain/forkchoice/protoarray/helpers.go +++ b/beacon-chain/forkchoice/protoarray/helpers.go @@ -4,6 +4,7 @@ import ( "context" "github.com/prysmaticlabs/prysm/config/params" + pmath "github.com/prysmaticlabs/prysm/math" "go.opencensus.io/trace" ) @@ -46,19 +47,27 @@ func computeDeltas( if ok { // Protection against out of bound, the `nextDeltaIndex` which defines // the block location in the dag can not exceed the total `delta` length. - if int(nextDeltaIndex) >= len(deltas) { + if nextDeltaIndex >= uint64(len(deltas)) { return nil, nil, errInvalidNodeDelta } - deltas[nextDeltaIndex] += int(newBalance) + delta, err := pmath.Int(newBalance) + if err != nil { + return nil, nil, err + } + deltas[nextDeltaIndex] += delta } currentDeltaIndex, ok := blockIndices[vote.currentRoot] if ok { // Protection against out of bound (same as above) - if int(currentDeltaIndex) >= len(deltas) { + if currentDeltaIndex >= uint64(len(deltas)) { return nil, nil, errInvalidNodeDelta } - deltas[currentDeltaIndex] -= int(oldBalance) + delta, err := pmath.Int(oldBalance) + if err != nil { + return nil, nil, err + } + deltas[currentDeltaIndex] -= delta } } diff --git a/beacon-chain/forkchoice/protoarray/store.go b/beacon-chain/forkchoice/protoarray/store.go index a9ba4c7bdcf2..a9fc43b5ec28 100644 --- a/beacon-chain/forkchoice/protoarray/store.go +++ b/beacon-chain/forkchoice/protoarray/store.go @@ -9,6 +9,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" + pmath "github.com/prysmaticlabs/prysm/math" pbrpc "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "go.opencensus.io/trace" ) @@ -446,7 +447,11 @@ func (s *Store) applyWeightChanges( s.proposerBoostLock.Unlock() return err } - nodeDelta = nodeDelta + int(proposerScore) + iProposerScore, err := pmath.Int(proposerScore) + if err != nil { + return err + } + nodeDelta = nodeDelta + iProposerScore } s.proposerBoostLock.Unlock() diff --git a/beacon-chain/node/config.go b/beacon-chain/node/config.go index c5aeff33c178..c42e9104a41e 100644 --- a/beacon-chain/node/config.go +++ b/beacon-chain/node/config.go @@ -35,7 +35,7 @@ func configureHistoricalSlasher(cliCtx *cli.Context) { params.OverrideBeaconConfig(c) cmdConfig := cmd.Get() // Allow up to 4096 attestations at a time to be requested from the beacon nde. - cmdConfig.MaxRPCPageSize = int(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)) + cmdConfig.MaxRPCPageSize = int(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)) // lint:ignore uintcast -- Page size should not exceed int64 with these constants. cmd.Init(cmdConfig) log.Warnf( "Setting %d slots per archive point and %d max RPC page size for historical slasher usage. This requires additional storage", diff --git a/beacon-chain/p2p/broadcaster.go b/beacon-chain/p2p/broadcaster.go index 411e33ef1370..a935a8836bd9 100644 --- a/beacon-chain/p2p/broadcaster.go +++ b/beacon-chain/p2p/broadcaster.go @@ -104,8 +104,8 @@ func (s *Service) broadcastAttestation(ctx context.Context, subnet uint64, att * span.AddAttributes( trace.BoolAttribute("hasPeer", hasPeer), - trace.Int64Attribute("slot", int64(att.Data.Slot)), - trace.Int64Attribute("subnet", int64(subnet)), + trace.Int64Attribute("slot", int64(att.Data.Slot)), // lint:ignore uintcast -- It's safe to do this for tracing. + trace.Int64Attribute("subnet", int64(subnet)), // lint:ignore uintcast -- It's safe to do this for tracing. ) if !hasPeer { @@ -160,8 +160,8 @@ func (s *Service) broadcastSyncCommittee(ctx context.Context, subnet uint64, sMs span.AddAttributes( trace.BoolAttribute("hasPeer", hasPeer), - trace.Int64Attribute("slot", int64(sMsg.Slot)), - trace.Int64Attribute("subnet", int64(subnet)), + trace.Int64Attribute("slot", int64(sMsg.Slot)), // lint:ignore uintcast -- It's safe to do this for tracing. + trace.Int64Attribute("subnet", int64(subnet)), // lint:ignore uintcast -- It's safe to do this for tracing. ) if !hasPeer { @@ -213,7 +213,9 @@ func (s *Service) broadcastObject(ctx context.Context, obj ssz.Marshaler, topic if span.IsRecordingEvents() { id := hash.FastSum64(buf.Bytes()) messageLen := int64(buf.Len()) - span.AddMessageSendEvent(int64(id), messageLen /*uncompressed*/, messageLen /*compressed*/) + // lint:ignore uintcast -- It's safe to do this for tracing. + iid := int64(id) + span.AddMessageSendEvent(iid, messageLen /*uncompressed*/, messageLen /*compressed*/) } if err := s.PublishToTopic(ctx, topic+s.Encoding().ProtocolSuffix(), buf.Bytes()); err != nil { err := errors.Wrap(err, "could not publish message") diff --git a/beacon-chain/p2p/encoder/BUILD.bazel b/beacon-chain/p2p/encoder/BUILD.bazel index 130714c9c53d..a0631bb7182c 100644 --- a/beacon-chain/p2p/encoder/BUILD.bazel +++ b/beacon-chain/p2p/encoder/BUILD.bazel @@ -14,6 +14,7 @@ go_library( ], deps = [ "//config/params:go_default_library", + "//math:go_default_library", "@com_github_ferranbt_fastssz//:go_default_library", "@com_github_gogo_protobuf//proto:go_default_library", "@com_github_golang_snappy//:go_default_library", diff --git a/beacon-chain/p2p/encoder/ssz.go b/beacon-chain/p2p/encoder/ssz.go index ac118df5fe3d..6fe6308f8d57 100644 --- a/beacon-chain/p2p/encoder/ssz.go +++ b/beacon-chain/p2p/encoder/ssz.go @@ -3,7 +3,6 @@ package encoder import ( "fmt" "io" - "math" "sync" fastssz "github.com/ferranbt/fastssz" @@ -11,6 +10,7 @@ import ( "github.com/golang/snappy" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/math" ) var _ NetworkEncoding = (*SszNetworkEncoder)(nil) @@ -145,11 +145,11 @@ func (_ SszNetworkEncoder) ProtocolSuffix() string { // MaxLength specifies the maximum possible length of an encoded // chunk of data. func (_ SszNetworkEncoder) MaxLength(length uint64) (int, error) { - // Defensive check to prevent potential issues when casting to int64. - if length > math.MaxInt64 { - return 0, errors.Errorf("invalid length provided: %d", length) + il, err := math.Int(length) + if err != nil { + return 0, errors.Wrap(err, "invalid length provided") } - maxLen := snappy.MaxEncodedLen(int(length)) + maxLen := snappy.MaxEncodedLen(il) if maxLen < 0 { return 0, errors.Errorf("max encoded length is negative: %d", maxLen) } diff --git a/beacon-chain/p2p/message_id.go b/beacon-chain/p2p/message_id.go index 6cb0e4c84e89..eea9324384e8 100644 --- a/beacon-chain/p2p/message_id.go +++ b/beacon-chain/p2p/message_id.go @@ -7,6 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/math" "github.com/prysmaticlabs/prysm/network/forks" ) @@ -72,8 +73,8 @@ func MsgID(genesisValidatorsRoot []byte, pmsg *pubsub_pb.Message) string { // the topic byte string, and the raw message data: i.e. SHA256(MESSAGE_DOMAIN_INVALID_SNAPPY + uint_to_bytes(uint64(len(message.topic))) + message.topic + message.data)[:20]. func postAltairMsgID(pmsg *pubsub_pb.Message, fEpoch types.Epoch) string { topic := *pmsg.Topic - topicLen := uint64(len(topic)) - topicLenBytes := bytesutil.Uint64ToBytesLittleEndian(topicLen) + topicLen := len(topic) + topicLenBytes := bytesutil.Uint64ToBytesLittleEndian(uint64(topicLen)) // topicLen cannot be negative // beyond Bellatrix epoch, allow 10 Mib gossip data size gossipPubSubSize := params.BeaconNetworkConfig().GossipMaxSize @@ -83,7 +84,25 @@ func postAltairMsgID(pmsg *pubsub_pb.Message, fEpoch types.Epoch) string { decodedData, err := encoder.DecodeSnappy(pmsg.Data, gossipPubSubSize) if err != nil { - totalLength := len(params.BeaconNetworkConfig().MessageDomainInvalidSnappy) + len(topicLenBytes) + int(topicLen) + len(pmsg.Data) + totalLength, err := math.AddInt( + len(params.BeaconNetworkConfig().MessageDomainValidSnappy), + len(topicLenBytes), + topicLen, + len(pmsg.Data), + ) + if err != nil { + log.WithError(err).Error("Failed to sum lengths of message domain and topic") + // should never happen + msg := make([]byte, 20) + copy(msg, "invalid") + return string(msg) + } + if uint64(totalLength) > gossipPubSubSize { + // this should never happen + msg := make([]byte, 20) + copy(msg, "invalid") + return string(msg) + } combinedData := make([]byte, 0, totalLength) combinedData = append(combinedData, params.BeaconNetworkConfig().MessageDomainInvalidSnappy[:]...) combinedData = append(combinedData, topicLenBytes...) @@ -92,7 +111,19 @@ func postAltairMsgID(pmsg *pubsub_pb.Message, fEpoch types.Epoch) string { h := hash.Hash(combinedData) return string(h[:20]) } - totalLength := len(params.BeaconNetworkConfig().MessageDomainValidSnappy) + len(topicLenBytes) + int(topicLen) + len(decodedData) + totalLength, err := math.AddInt( + len(params.BeaconNetworkConfig().MessageDomainValidSnappy), + len(topicLenBytes), + topicLen, + len(decodedData), + ) + if err != nil { + log.WithError(err).Error("Failed to sum lengths of message domain and topic") + // should never happen + msg := make([]byte, 20) + copy(msg, "invalid") + return string(msg) + } combinedData := make([]byte, 0, totalLength) combinedData = append(combinedData, params.BeaconNetworkConfig().MessageDomainValidSnappy[:]...) combinedData = append(combinedData, topicLenBytes...) diff --git a/beacon-chain/p2p/peers/BUILD.bazel b/beacon-chain/p2p/peers/BUILD.bazel index d04e468a7067..a64dd628ddfa 100644 --- a/beacon-chain/p2p/peers/BUILD.bazel +++ b/beacon-chain/p2p/peers/BUILD.bazel @@ -2,7 +2,10 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = ["status.go"], + srcs = [ + "log.go", + "status.go", + ], importpath = "github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers", visibility = ["//beacon-chain:__subpackages__"], deps = [ @@ -11,6 +14,7 @@ go_library( "//config/features:go_default_library", "//config/params:go_default_library", "//crypto/rand:go_default_library", + "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/metadata:go_default_library", "//time:go_default_library", @@ -22,6 +26,7 @@ go_library( "@com_github_multiformats_go_multiaddr//net:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", ], ) diff --git a/beacon-chain/p2p/peers/log.go b/beacon-chain/p2p/peers/log.go new file mode 100644 index 000000000000..eca49d07c11f --- /dev/null +++ b/beacon-chain/p2p/peers/log.go @@ -0,0 +1,5 @@ +package peers + +import "github.com/sirupsen/logrus" + +var log = logrus.WithField("prefix", "peers") diff --git a/beacon-chain/p2p/peers/status.go b/beacon-chain/p2p/peers/status.go index 391d0ecf48cf..2795fe51bdff 100644 --- a/beacon-chain/p2p/peers/status.go +++ b/beacon-chain/p2p/peers/status.go @@ -40,6 +40,7 @@ import ( "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/rand" + pmath "github.com/prysmaticlabs/prysm/math" pb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/metadata" prysmTime "github.com/prysmaticlabs/prysm/time" @@ -749,12 +750,12 @@ func (p *Status) PeersToPrune() []peer.ID { return p.deprecatedPeersToPrune() } connLimit := p.ConnectedPeerLimit() - inBoundLimit := p.InboundLimit() + inBoundLimit := uint64(p.InboundLimit()) activePeers := p.Active() - numInboundPeers := len(p.InboundConnected()) + numInboundPeers := uint64(len(p.InboundConnected())) // Exit early if we are still below our max // limit. - if len(activePeers) <= int(connLimit) { + if uint64(len(activePeers)) <= connLimit { return []peer.ID{} } p.store.Lock() @@ -784,10 +785,15 @@ func (p *Status) PeersToPrune() []peer.ID { // Determine amount of peers to prune using our // max connection limit. - amountToPrune := len(activePeers) - int(connLimit) + amountToPrune, err := pmath.Sub64(uint64(len(activePeers)), connLimit) + if err != nil { + // This should never happen. + log.WithError(err).Error("Failed to determine amount of peers to prune") + return []peer.ID{} + } // Also check for inbound peers above our limit. - excessInbound := 0 + excessInbound := uint64(0) if numInboundPeers > inBoundLimit { excessInbound = numInboundPeers - inBoundLimit } @@ -796,7 +802,7 @@ func (p *Status) PeersToPrune() []peer.ID { if excessInbound > amountToPrune { amountToPrune = excessInbound } - if amountToPrune < len(peersToPrune) { + if amountToPrune < uint64(len(peersToPrune)) { peersToPrune = peersToPrune[:amountToPrune] } ids := make([]peer.ID, 0, len(peersToPrune)) @@ -815,7 +821,7 @@ func (p *Status) deprecatedPeersToPrune() []peer.ID { numInboundPeers := len(p.InboundConnected()) // Exit early if we are still below our max // limit. - if len(activePeers) <= int(connLimit) { + if uint64(len(activePeers)) <= connLimit { return []peer.ID{} } p.store.Lock() @@ -845,18 +851,23 @@ func (p *Status) deprecatedPeersToPrune() []peer.ID { // Determine amount of peers to prune using our // max connection limit. - amountToPrune := len(activePeers) - int(connLimit) + amountToPrune, err := pmath.Sub64(uint64(len(activePeers)), connLimit) + if err != nil { + // This should never happen + log.WithError(err).Error("Failed to determine amount of peers to prune") + return []peer.ID{} + } // Also check for inbound peers above our limit. - excessInbound := 0 + excessInbound := uint64(0) if numInboundPeers > inBoundLimit { - excessInbound = numInboundPeers - inBoundLimit + excessInbound = uint64(numInboundPeers - inBoundLimit) } // Prune the largest amount between excess peers and // excess inbound peers. if excessInbound > amountToPrune { amountToPrune = excessInbound } - if amountToPrune < len(peersToPrune) { + if amountToPrune < uint64(len(peersToPrune)) { peersToPrune = peersToPrune[:amountToPrune] } ids := make([]peer.ID, 0, len(peersToPrune)) diff --git a/beacon-chain/p2p/subnets.go b/beacon-chain/p2p/subnets.go index f5dd1a43d50f..1d2ea2c0d557 100644 --- a/beacon-chain/p2p/subnets.go +++ b/beacon-chain/p2p/subnets.go @@ -40,7 +40,7 @@ func (s *Service) FindPeersWithSubnet(ctx context.Context, topic string, ctx, span := trace.StartSpan(ctx, "p2p.FindPeersWithSubnet") defer span.End() - span.AddAttributes(trace.Int64Attribute("index", int64(index))) + span.AddAttributes(trace.Int64Attribute("index", int64(index))) // lint:ignore uintcast -- It's safe to do this for tracing. if s.dv5Listener == nil { // return if discovery isn't set @@ -138,7 +138,7 @@ func (s *Service) hasPeerWithSubnet(topic string) bool { // In the event peer threshold is lower, we will choose the lower // threshold. minPeers := mathutil.Min(1, uint64(flags.Get().MinimumPeersPerSubnet)) - return len(s.pubsub.ListPeers(topic+s.Encoding().ProtocolSuffix())) >= int(minPeers) + return len(s.pubsub.ListPeers(topic+s.Encoding().ProtocolSuffix())) >= int(minPeers) // lint:ignore uintcast -- Min peers can be safely cast to int. } // Updates the service's discv5 listener record's attestation subnet @@ -195,6 +195,7 @@ func attSubnets(record *enr.Record) ([]uint64, error) { if err != nil { return nil, err } + // lint:ignore uintcast -- subnet count can be safely cast to int. if len(bitV) != byteCount(int(attestationSubnetCount)) { return []uint64{}, errors.Errorf("invalid bitvector provided, it has a size of %d", len(bitV)) } @@ -214,6 +215,7 @@ func syncSubnets(record *enr.Record) ([]uint64, error) { if err != nil { return nil, err } + // lint:ignore uintcast -- subnet count can be safely cast to int. if len(bitV) != byteCount(int(syncCommsSubnetCount)) { return []uint64{}, errors.Errorf("invalid bitvector provided, it has a size of %d", len(bitV)) } diff --git a/beacon-chain/powchain/block_reader.go b/beacon-chain/powchain/block_reader.go index 3f5bad3e5854..ba9cab706845 100644 --- a/beacon-chain/powchain/block_reader.go +++ b/beacon-chain/powchain/block_reader.go @@ -122,7 +122,7 @@ func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.Hea } // Initialize a pointer to eth1 chain's history to start our search // from. - cursorNum := big.NewInt(int64(latestBlkHeight)) + cursorNum := big.NewInt(0).SetUint64(latestBlkHeight) cursorTime := latestBlkTime numOfBlocks := uint64(0) @@ -168,9 +168,9 @@ func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.Hea return s.retrieveHeaderInfo(ctx, cursorNum.Uint64()) } if cursorTime > time { - return s.findLessTargetEth1Block(ctx, big.NewInt(int64(estimatedBlk)), time) + return s.findLessTargetEth1Block(ctx, big.NewInt(0).SetUint64(estimatedBlk), time) } - return s.findMoreTargetEth1Block(ctx, big.NewInt(int64(estimatedBlk)), time) + return s.findMoreTargetEth1Block(ctx, big.NewInt(0).SetUint64(estimatedBlk), time) } // Performs a search to find a target eth1 block which is earlier than or equal to the @@ -214,7 +214,7 @@ func (s *Service) findMoreTargetEth1Block(ctx context.Context, startBlk *big.Int } func (s *Service) retrieveHeaderInfo(ctx context.Context, bNum uint64) (*types.HeaderInfo, error) { - bn := big.NewInt(int64(bNum)) + bn := big.NewInt(0).SetUint64(bNum) exists, info, err := s.headerCache.HeaderInfoByHeight(bn) if err != nil { return nil, err diff --git a/beacon-chain/powchain/log_processing.go b/beacon-chain/powchain/log_processing.go index 60263e0d7607..b28c29c09911 100644 --- a/beacon-chain/powchain/log_processing.go +++ b/beacon-chain/powchain/log_processing.go @@ -109,7 +109,7 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo // This can happen sometimes when we receive the same log twice from the // ETH1.0 network, and prevents us from updating our trie // with the same log twice, causing an inconsistent state root. - index := int64(binary.LittleEndian.Uint64(merkleTreeIndex)) + index := int64(binary.LittleEndian.Uint64(merkleTreeIndex)) // lint:ignore uintcast -- MerkleTreeIndex should not exceed int64 in your lifetime. if index <= s.lastReceivedMerkleIndex { return nil } @@ -211,7 +211,7 @@ func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte, s.chainStartData.Chainstarted = true s.chainStartData.GenesisBlock = blockNumber.Uint64() - chainStartTime := time.Unix(int64(genesisTime), 0) + chainStartTime := time.Unix(int64(genesisTime), 0) // lint:ignore uintcast -- Genesis time wont exceed int64 in your lifetime. for i := range s.chainStartData.ChainstartDeposits { proof, err := s.depositTrie.MerkleProof(i) @@ -303,8 +303,8 @@ func (s *Service) processPastLogs(ctx context.Context) error { Addresses: []common.Address{ s.cfg.depositContractAddr, }, - FromBlock: big.NewInt(int64(start)), - ToBlock: big.NewInt(int64(end)), + FromBlock: big.NewInt(0).SetUint64(start), + ToBlock: big.NewInt(0).SetUint64(end), } remainingLogs := logCount - uint64(s.lastReceivedMerkleIndex+1) // only change the end block if the remaining logs are below the required log limit. @@ -312,7 +312,7 @@ func (s *Service) processPastLogs(ctx context.Context) error { withinLimit := remainingLogs < depositlogRequestLimit aboveFollowHeight := end >= latestFollowHeight if withinLimit && aboveFollowHeight { - query.ToBlock = big.NewInt(int64(latestFollowHeight)) + query.ToBlock = big.NewInt(0).SetUint64(latestFollowHeight) end = latestFollowHeight } logs, err := s.httpLogger.FilterLogs(ctx, query) @@ -391,7 +391,7 @@ func (s *Service) processPastLogs(ctx context.Context) error { } } if fState != nil && !fState.IsNil() && fState.Eth1DepositIndex() > 0 { - s.cfg.depositCache.PrunePendingDeposits(ctx, int64(fState.Eth1DepositIndex())) + s.cfg.depositCache.PrunePendingDeposits(ctx, int64(fState.Eth1DepositIndex())) // lint:ignore uintcast -- Deposit index should not exceed int64 in your lifetime. } return nil } @@ -413,11 +413,11 @@ func (s *Service) requestBatchedHeadersAndLogs(ctx context.Context) error { } for i := s.latestEth1Data.LastRequestedBlock + 1; i <= requestedBlock; i++ { // Cache eth1 block header here. - _, err := s.BlockHashByHeight(ctx, big.NewInt(int64(i))) + _, err := s.BlockHashByHeight(ctx, big.NewInt(0).SetUint64(i)) if err != nil { return err } - err = s.ProcessETH1Block(ctx, big.NewInt(int64(i))) + err = s.ProcessETH1Block(ctx, big.NewInt(0).SetUint64(i)) if err != nil { return err } diff --git a/beacon-chain/powchain/service.go b/beacon-chain/powchain/service.go index 9fbb6bf64396..a61e3468f473 100644 --- a/beacon-chain/powchain/service.go +++ b/beacon-chain/powchain/service.go @@ -613,8 +613,10 @@ func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositCo // accumulates. we finalize them here before we are ready to receive a block. // Otherwise, the first few blocks will be slower to compute as we will // hold the lock and be busy finalizing the deposits. - s.cfg.depositCache.InsertFinalizedDeposits(ctx, int64(currIndex)) + s.cfg.depositCache.InsertFinalizedDeposits(ctx, int64(currIndex)) // lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime. // Deposit proofs are only used during state transition and can be safely removed to save space. + + // lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime. if err = s.cfg.depositCache.PruneProofs(ctx, int64(currIndex)); err != nil { return errors.Wrap(err, "could not prune deposit proofs") } @@ -662,7 +664,7 @@ func (s *Service) batchRequestHeaders(startBlock, endBlock uint64) ([]*gethTypes err := error(nil) elems = append(elems, gethRPC.BatchElem{ Method: "eth_getBlockByNumber", - Args: []interface{}{hexutil.EncodeBig(big.NewInt(int64(i))), false}, + Args: []interface{}{hexutil.EncodeBig(big.NewInt(0).SetUint64(i)), false}, Result: header, Error: err, }) @@ -1088,7 +1090,7 @@ func dedupEndpoints(endpoints []string) []string { func eth1HeadIsBehind(timestamp uint64) bool { timeout := prysmTime.Now().Add(-eth1Threshold) // check that web3 client is syncing - return time.Unix(int64(timestamp), 0).Before(timeout) + return time.Unix(int64(timestamp), 0).Before(timeout) // lint:ignore uintcast -- timestamp will not exceed int64 in your lifetime. } func (s *Service) primaryConnected() bool { diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go index b3941cceb902..94e9e6bb432f 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_stream.go @@ -545,7 +545,7 @@ func (is *infostream) depositQueueTimestamp(eth1BlockNumber *big.Int) (uint64, e is.eth1BlocktimesMutex.Unlock() followTime := time.Duration(params.BeaconConfig().Eth1FollowDistance*params.BeaconConfig().SecondsPerETH1Block) * time.Second - eth1UnixTime := time.Unix(int64(blockTimestamp), 0).Add(followTime) + eth1UnixTime := time.Unix(int64(blockTimestamp), 0).Add(followTime) // lint:ignore uintcast -- timestamp will not exceed int64 in your lifetime period := uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod.Mul(uint64(params.BeaconConfig().SlotsPerEpoch))) votingPeriod := time.Duration(period*params.BeaconConfig().SecondsPerSlot) * time.Second diff --git a/beacon-chain/state/fieldtrie/BUILD.bazel b/beacon-chain/state/fieldtrie/BUILD.bazel index dcdfe41b5910..2a1f73c0bfb9 100644 --- a/beacon-chain/state/fieldtrie/BUILD.bazel +++ b/beacon-chain/state/fieldtrie/BUILD.bazel @@ -15,6 +15,7 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", + "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/state/fieldtrie/field_trie.go b/beacon-chain/state/fieldtrie/field_trie.go index 25dad9cf0328..040a37d65fb1 100644 --- a/beacon-chain/state/fieldtrie/field_trie.go +++ b/beacon-chain/state/fieldtrie/field_trie.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + pmath "github.com/prysmaticlabs/prysm/math" ) // FieldTrie is the representation of the representative @@ -110,11 +111,15 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b if err != nil { return [32]byte{}, err } + iNumOfElems, err := pmath.Int(numOfElems) + if err != nil { + return [32]byte{}, err + } // We remove the duplicates here in order to prevent // duplicated insertions into the trie. newIndices := []uint64{} indexExists := make(map[uint64]bool) - newRoots := make([][32]byte, 0, len(fieldRoots)/int(numOfElems)) + newRoots := make([][32]byte, 0, len(fieldRoots)/iNumOfElems) for i, idx := range indices { startIdx := idx / numOfElems if indexExists[startIdx] { diff --git a/beacon-chain/state/fieldtrie/field_trie_helpers.go b/beacon-chain/state/fieldtrie/field_trie_helpers.go index ca4355310b94..53f5a813e131 100644 --- a/beacon-chain/state/fieldtrie/field_trie_helpers.go +++ b/beacon-chain/state/fieldtrie/field_trie_helpers.go @@ -12,6 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/encoding/ssz" + pmath "github.com/prysmaticlabs/prysm/math" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime/version" ) @@ -57,7 +58,7 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements length *= comLength } val := reflect.Indirect(reflect.ValueOf(elements)) - if val.Len() > int(length) { + if uint64(val.Len()) > length { return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(version.Phase0), val.Len(), length) } return nil @@ -318,6 +319,10 @@ func handleBalanceSlice(val, indices []uint64, convertAll bool) ([][32]byte, err if err != nil { return nil, err } + iNumOfElems, err := pmath.Int(numOfElems) + if err != nil { + return nil, err + } roots := [][32]byte{} for _, idx := range indices { // We split the indexes into their relevant groups. Balances @@ -325,14 +330,14 @@ func handleBalanceSlice(val, indices []uint64, convertAll bool) ([][32]byte, err startIdx := idx / numOfElems startGroup := startIdx * numOfElems chunk := [32]byte{} - sizeOfElem := len(chunk) / int(numOfElems) + sizeOfElem := len(chunk) / iNumOfElems for i, j := 0, startGroup; j < startGroup+numOfElems; i, j = i+sizeOfElem, j+1 { wantedVal := uint64(0) // We are adding chunks in sets of 4, if the set is at the edge of the array // then you will need to zero out the rest of the chunk. Ex : 41 indexes, // so 41 % 4 = 1 . There are 3 indexes, which do not exist yet but we // have to add in as a root. These 3 indexes are then given a 'zero' value. - if int(j) < len(val) { + if j < uint64(len(val)) { wantedVal = val[j] } binary.LittleEndian.PutUint64(chunk[i:i+sizeOfElem], wantedVal) diff --git a/beacon-chain/state/state-native/v1/getters_validator.go b/beacon-chain/state/state-native/v1/getters_validator.go index 343b70801b8d..f36f2280a5c9 100644 --- a/beacon-chain/state/state-native/v1/getters_validator.go +++ b/beacon-chain/state/state-native/v1/getters_validator.go @@ -123,7 +123,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by numOfVals := len(b.validators) idx, ok := b.valMapHandler.Get(key) - if ok && numOfVals <= int(idx) { + if ok && types.ValidatorIndex(numOfVals) <= idx { return types.ValidatorIndex(0), false } return idx, ok diff --git a/beacon-chain/state/state-native/v2/getters_validator.go b/beacon-chain/state/state-native/v2/getters_validator.go index 4e1374f0302c..d51495eabadf 100644 --- a/beacon-chain/state/state-native/v2/getters_validator.go +++ b/beacon-chain/state/state-native/v2/getters_validator.go @@ -130,7 +130,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by numOfVals := len(b.validators) idx, ok := b.valMapHandler.Get(key) - if ok && numOfVals <= int(idx) { + if ok && types.ValidatorIndex(numOfVals) <= idx { return types.ValidatorIndex(0), false } return idx, ok diff --git a/beacon-chain/state/state-native/v3/getters_validator.go b/beacon-chain/state/state-native/v3/getters_validator.go index 4e90d4510183..71f9a0f5fa61 100644 --- a/beacon-chain/state/state-native/v3/getters_validator.go +++ b/beacon-chain/state/state-native/v3/getters_validator.go @@ -124,7 +124,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by numOfVals := len(b.validators) idx, ok := b.valMapHandler.Get(key) - if ok && numOfVals <= int(idx) { + if ok && types.ValidatorIndex(numOfVals) <= idx { return types.ValidatorIndex(0), false } return idx, ok diff --git a/beacon-chain/state/stateutil/trie_helpers.go b/beacon-chain/state/stateutil/trie_helpers.go index 7ff845d192ae..7aea685ea759 100644 --- a/beacon-chain/state/stateutil/trie_helpers.go +++ b/beacon-chain/state/stateutil/trie_helpers.go @@ -64,7 +64,7 @@ func ReturnTrieLayerVariable(elements [][32]byte, length uint64) [][]*[32]byte { buffer := bytes.NewBuffer([]byte{}) buffer.Grow(64) - for i := 0; i < int(depth); i++ { + for i := uint8(0); i < depth; i++ { layerLen := len(layers[i]) oddNodeLength := layerLen%2 == 1 if features.Get().EnableVectorizedHTR { @@ -126,10 +126,13 @@ func RecomputeFromLayer(changedLeaves [][32]byte, changedIdx []uint64, layer [][ } root := *layer[0][0] - var err error for _, idx := range changedIdx { - root, layer, err = recomputeRootFromLayer(int(idx), layer, leaves, hasher) + ii, err := math.Int(idx) + if err != nil { + return [32]byte{}, nil, err + } + root, layer, err = recomputeRootFromLayer(ii, layer, leaves, hasher) if err != nil { return [32]byte{}, nil, err } @@ -144,10 +147,13 @@ func RecomputeFromLayerVariable(changedLeaves [][32]byte, changedIdx []uint64, l return *layer[0][0], layer, nil } root := *layer[len(layer)-1][0] - var err error for i, idx := range changedIdx { - root, layer, err = recomputeRootFromLayerVariable(int(idx), changedLeaves[i], layer, hasher) + ii, err := math.Int(idx) + if err != nil { + return [32]byte{}, nil, err + } + root, layer, err = recomputeRootFromLayerVariable(ii, changedLeaves[i], layer, hasher) if err != nil { return [32]byte{}, nil, err } diff --git a/beacon-chain/state/v1/getters_validator.go b/beacon-chain/state/v1/getters_validator.go index 746bd20303f7..9239446cff23 100644 --- a/beacon-chain/state/v1/getters_validator.go +++ b/beacon-chain/state/v1/getters_validator.go @@ -138,7 +138,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by numOfVals := len(b.state.Validators) idx, ok := b.valMapHandler.Get(key) - if ok && numOfVals <= int(idx) { + if ok && types.ValidatorIndex(numOfVals) <= idx { return types.ValidatorIndex(0), false } return idx, ok diff --git a/beacon-chain/state/v2/getters_validator.go b/beacon-chain/state/v2/getters_validator.go index 31255a33c981..e59cf57b2f62 100644 --- a/beacon-chain/state/v2/getters_validator.go +++ b/beacon-chain/state/v2/getters_validator.go @@ -139,7 +139,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by numOfVals := len(b.state.Validators) idx, ok := b.valMapHandler.Get(key) - if ok && numOfVals <= int(idx) { + if ok && types.ValidatorIndex(numOfVals) <= idx { return types.ValidatorIndex(0), false } return idx, ok diff --git a/beacon-chain/state/v3/getters_validator.go b/beacon-chain/state/v3/getters_validator.go index c8b9d8a61868..227618f6449e 100644 --- a/beacon-chain/state/v3/getters_validator.go +++ b/beacon-chain/state/v3/getters_validator.go @@ -139,7 +139,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by numOfVals := len(b.state.Validators) idx, ok := b.valMapHandler.Get(key) - if ok && numOfVals <= int(idx) { + if ok && types.ValidatorIndex(numOfVals) <= idx { return types.ValidatorIndex(0), false } return idx, ok diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go b/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go index a9d519a08070..d10cfcff48a6 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go @@ -108,7 +108,7 @@ func (f *blocksFetcher) nonSkippedSlotAfterWithPeersTarget( return 0, err } for ind := slot + 1; ind < upperBoundSlot; ind += (slotsPerEpoch * slotsPerEpoch) / 2 { - start := ind.Add(uint64(f.rand.Intn(int(slotsPerEpoch)))) + start := ind.Add(uint64(f.rand.Intn(int(slotsPerEpoch)))) // lint:ignore uintcast -- Slots per epoch will never exceed int64. nextSlot, err := fetch(peers[pidInd%len(peers)], start, uint64(slotsPerEpoch/2), uint64(slotsPerEpoch)) if err != nil { return 0, err diff --git a/beacon-chain/sync/initial-sync/service.go b/beacon-chain/sync/initial-sync/service.go index 1f6d6407d61e..953e7ab762bf 100644 --- a/beacon-chain/sync/initial-sync/service.go +++ b/beacon-chain/sync/initial-sync/service.go @@ -151,8 +151,8 @@ func (s *Service) Resync() error { // Set it to false since we are syncing again. s.synced.UnSet() - defer func() { s.synced.Set() }() // Reset it at the end of the method. - genesis := time.Unix(int64(headState.GenesisTime()), 0) + defer func() { s.synced.Set() }() // Reset it at the end of the method. + genesis := time.Unix(int64(headState.GenesisTime()), 0) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime. s.waitForMinimumPeers() if err = s.roundRobinSync(genesis); err != nil { diff --git a/beacon-chain/sync/pending_blocks_queue.go b/beacon-chain/sync/pending_blocks_queue.go index a0bf2ab1e6b3..088935c48e94 100644 --- a/beacon-chain/sync/pending_blocks_queue.go +++ b/beacon-chain/sync/pending_blocks_queue.go @@ -69,7 +69,7 @@ func (s *Service) processPendingBlocks(ctx context.Context) error { } ctx, span := trace.StartSpan(ctx, "processPendingBlocks.InnerLoop") - span.AddAttributes(trace.Int64Attribute("slot", int64(slot))) + span.AddAttributes(trace.Int64Attribute("slot", int64(slot))) // lint:ignore uintcast -- This conversion is OK for tracing. s.pendingQueueLock.RLock() bs := s.pendingBlocksInCache(slot) diff --git a/beacon-chain/sync/rpc_beacon_blocks_by_range.go b/beacon-chain/sync/rpc_beacon_blocks_by_range.go index 830d9e58281b..e148de3b2544 100644 --- a/beacon-chain/sync/rpc_beacon_blocks_by_range.go +++ b/beacon-chain/sync/rpc_beacon_blocks_by_range.go @@ -60,8 +60,8 @@ func (s *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa } remainingBucketCapacity := blockLimiter.Remaining(stream.Conn().RemotePeer().String()) span.AddAttributes( - trace.Int64Attribute("start", int64(startSlot)), - trace.Int64Attribute("end", int64(endReqSlot)), + trace.Int64Attribute("start", int64(startSlot)), // lint:ignore uintcast -- This conversion is OK for tracing. + trace.Int64Attribute("end", int64(endReqSlot)), // lint:ignore uintcast -- This conversion is OK for tracing. trace.Int64Attribute("step", int64(m.Step)), trace.Int64Attribute("count", int64(m.Count)), trace.StringAttribute("peer", stream.Conn().RemotePeer().Pretty()), diff --git a/beacon-chain/sync/rpc_status.go b/beacon-chain/sync/rpc_status.go index a82d825032df..9fe77e3b6ddf 100644 --- a/beacon-chain/sync/rpc_status.go +++ b/beacon-chain/sync/rpc_status.go @@ -79,7 +79,7 @@ func (s *Service) maintainPeerStatuses() { // resyncIfBehind checks periodically to see if we are in normal sync but have fallen behind our peers // by more than an epoch, in which case we attempt a resync using the initial sync method to catch up. func (s *Service) resyncIfBehind() { - millisecondsPerEpoch := int64(params.BeaconConfig().SlotsPerEpoch.Mul(1000).Mul(params.BeaconConfig().SecondsPerSlot)) + millisecondsPerEpoch := params.BeaconConfig().SlotsPerEpoch.Mul(1000).Mul(params.BeaconConfig().SecondsPerSlot) // Run sixteen times per epoch. interval := time.Duration(millisecondsPerEpoch/16) * time.Millisecond async.RunEvery(s.ctx, interval, func() { diff --git a/build/bazel/BUILD.bazel b/build/bazel/BUILD.bazel new file mode 100644 index 000000000000..cd9054934684 --- /dev/null +++ b/build/bazel/BUILD.bazel @@ -0,0 +1,23 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + testonly = True, + srcs = [ + "bazel.go", + "data_path.go", + ], + importpath = "github.com/prysmaticlabs/prysm/build/bazel", + visibility = ["//visibility:public"], + deps = [ + "//testing/require:go_default_library", + "@io_bazel_rules_go//go/tools/bazel:go_default_library", + ], +) + +go_test( + name = "go_default_test", + size = "small", + srcs = ["bazel_test.go"], + deps = [":go_default_library"], +) diff --git a/build/bazel/bazel.go b/build/bazel/bazel.go new file mode 100644 index 000000000000..665b0b96c553 --- /dev/null +++ b/build/bazel/bazel.go @@ -0,0 +1,103 @@ +// Copyright 2015 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +//go:build bazel +// +build bazel + +package bazel + +import ( + "fmt" + "os" + "path" + "path/filepath" + "strings" + + inner "github.com/bazelbuild/rules_go/go/tools/bazel" +) + +// Return true iff this library was built with Bazel. +func BuiltWithBazel() bool { + return true +} + +// FindBinary is a convenience wrapper around the rules_go variant. +func FindBinary(pkg, name string) (string, bool) { + return inner.FindBinary(pkg, name) +} + +// Runfile is a convenience wrapper around the rules_go variant. +func Runfile(path string) (string, error) { + return inner.Runfile(path) +} + +// RunfilesPath is a convenience wrapper around the rules_go variant. +func RunfilesPath() (string, error) { + return inner.RunfilesPath() +} + +// TestTmpDir is a convenience wrapper around the rules_go variant. +func TestTmpDir() string { + return inner.TestTmpDir() +} + +// NewTmpDir is a convenience wrapper around the rules_go variant. +// The caller is responsible for cleaning the directory up after use. +func NewTmpDir(prefix string) (string, error) { + return inner.NewTmpDir(prefix) +} + +// Updates the current environment to use the Go toolchain that Bazel built this +// binary/test with (updates the `PATH`/`GOROOT`/`GOCACHE` environment +// variables). +// If you want to use this function, your binary/test target MUST have +// `@go_sdk//:files` in its `data` -- this will make sure the whole toolchain +// gets pulled into the sandbox as well. Generally, this function should only +// be called in init(). +func SetGoEnv() { + gobin, err := Runfile("bin/go") + if err != nil { + panic(err) + } + if err := os.Setenv("PATH", fmt.Sprintf("%s%c%s", filepath.Dir(gobin), os.PathListSeparator, os.Getenv("PATH"))); err != nil { + panic(err) + } + // GOPATH has to be set to some value (not equal to GOROOT) in order for `go env` to work. + // See https://github.com/golang/go/issues/43938 for the details. + // Specify a name under the system TEMP/TMP directory in order to be platform agnostic. + if err := os.Setenv("GOPATH", filepath.Join(os.TempDir(), "nonexist-gopath")); err != nil { + panic(err) + } + if err := os.Setenv("GOROOT", filepath.Dir(filepath.Dir(gobin))); err != nil { + panic(err) + } + if err := os.Setenv("GOCACHE", path.Join(inner.TestTmpDir(), ".gocache")); err != nil { + panic(err) + } +} + +// Name of the environment variable containing the bazel target path +// (//pkg/cmd/foo:bar). +const testTargetEnv = "TEST_TARGET" + +// RelativeTestTargetPath returns relative path to the package +// of the current test. +func RelativeTestTargetPath() string { + target := os.Getenv(testTargetEnv) + if target == "" { + return "" + } + + // Drop target name. + if last := strings.LastIndex(target, ":"); last > 0 { + target = target[:last] + } + return strings.TrimPrefix(target, "//") +} diff --git a/build/bazel/bazel_test.go b/build/bazel/bazel_test.go new file mode 100644 index 000000000000..8eb49278fd0d --- /dev/null +++ b/build/bazel/bazel_test.go @@ -0,0 +1,13 @@ +package bazel_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/build/bazel" +) + +func TestBuildWithBazel(t *testing.T) { + if !bazel.BuiltWithBazel() { + t.Error("not built with Bazel") + } +} diff --git a/build/bazel/data_path.go b/build/bazel/data_path.go new file mode 100644 index 000000000000..186c9cb17208 --- /dev/null +++ b/build/bazel/data_path.go @@ -0,0 +1,41 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package bazel + +import ( + "path" + "path/filepath" + "testing" + + "github.com/prysmaticlabs/prysm/testing/require" +) + +// TestDataPath returns a path to an asset in the testdata directory. It knows +// to access accesses the right path when executing under bazel. +// +// For example, if there is a file testdata/a.txt, you can get a path to that +// file using TestDataPath(t, "a.txt"). +func TestDataPath(t testing.TB, relative ...string) string { + relative = append([]string{"testdata"}, relative...) + // dev notifies the library that the test is running in a subdirectory of the + // workspace with the environment variable below. + if BuiltWithBazel() { + runfiles, err := RunfilesPath() + require.NoError(t, err) + return path.Join(runfiles, RelativeTestTargetPath(), path.Join(relative...)) + } + + // Otherwise we're in the package directory and can just return a relative path. + ret := path.Join(relative...) + ret, err := filepath.Abs(ret) + require.NoError(t, err) + return ret +} diff --git a/build/bazel/non_bazel.go b/build/bazel/non_bazel.go new file mode 100644 index 000000000000..534e2683fbaa --- /dev/null +++ b/build/bazel/non_bazel.go @@ -0,0 +1,57 @@ +// Copyright 2015 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +//go:build !bazel +// +build !bazel + +package bazel + +// This file contains stub implementations for non-bazel builds. +// See bazel.go for full documentation on the contracts of these functions. + +// BuiltWithBazel returns true iff this library was built with Bazel. +func BuiltWithBazel() bool { + return false +} + +// FindBinary is not implemented. +func FindBinary(pkg, name string) (string, bool) { + panic("not build with Bazel") +} + +// Runfile is not implemented. +func Runfile(string) (string, error) { + panic("not built with Bazel") +} + +// RunfilesPath is not implemented. +func RunfilesPath() (string, error) { + panic("not built with Bazel") +} + +// TestTmpDir is not implemented. +func TestTmpDir() string { + panic("not built with Bazel") +} + +// NewTmpDir is not implemented. +func NewTmpDir(prefix string) (string, error) { + panic("not built with Bazel") +} + +// RelativeTestTargetPath is not implemented. +func RelativeTestTargetPath() string { + panic("not built with Bazel") +} + +// SetGoEnv is not implemented. +func SetGoEnv() { + panic("not built with Bazel") +} diff --git a/container/trie/sparse_merkle.go b/container/trie/sparse_merkle.go index cedb2c299596..502d33d9dcb2 100644 --- a/container/trie/sparse_merkle.go +++ b/container/trie/sparse_merkle.go @@ -181,13 +181,13 @@ func (m *SparseMerkleTrie) ToProto() *protodb.SparseMerkleTrie { } // VerifyMerkleProofWithDepth verifies a Merkle branch against a root of a trie. -func VerifyMerkleProofWithDepth(root, item []byte, merkleIndex int, proof [][]byte, depth uint64) bool { - if len(proof) != int(depth)+1 { +func VerifyMerkleProofWithDepth(root, item []byte, merkleIndex uint64, proof [][]byte, depth uint64) bool { + if uint64(len(proof)) != depth+1 { return false } node := bytesutil.ToBytes32(item) - for i := 0; i <= int(depth); i++ { - if (uint64(merkleIndex) / math.PowerOf2(uint64(i)) % 2) != 0 { + for i := uint64(0); i <= depth; i++ { + if (merkleIndex / math.PowerOf2(i) % 2) != 0 { node = hash.Hash(append(proof[i], node[:]...)) } else { node = hash.Hash(append(node[:], proof[i]...)) diff --git a/deps.bzl b/deps.bzl index 3c589c55cfaf..8faa17165844 100644 --- a/deps.bzl +++ b/deps.bzl @@ -1327,6 +1327,18 @@ def prysm_deps(): sum = "h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=", version = "v1.4.2", ) + go_repository( + name = "com_github_gostaticanalysis_comment", + importpath = "github.com/gostaticanalysis/comment", + sum = "h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q=", + version = "v1.4.2", + ) + go_repository( + name = "com_github_gostaticanalysis_testutil", + importpath = "github.com/gostaticanalysis/testutil", + sum = "h1:d2/eIbH9XjD1fFwD5SHv8x168fjbQ9PB8hvs8DSEC08=", + version = "v0.3.1-0.20210208050101-bfb5c8eec0e4", + ) go_repository( name = "com_github_graph_gophers_graphql_go", @@ -1461,8 +1473,8 @@ def prysm_deps(): go_repository( name = "com_github_hashicorp_go_version", importpath = "github.com/hashicorp/go-version", - sum = "h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=", - version = "v1.2.0", + sum = "h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=", + version = "v1.2.1", ) go_repository( @@ -2822,6 +2834,25 @@ def prysm_deps(): sum = "h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=", version = "v0.2.2", ) + go_repository( + name = "com_github_otiai10_copy", + importpath = "github.com/otiai10/copy", + sum = "h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k=", + version = "v1.2.0", + ) + go_repository( + name = "com_github_otiai10_curr", + importpath = "github.com/otiai10/curr", + sum = "h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI=", + version = "v1.0.0", + ) + go_repository( + name = "com_github_otiai10_mint", + importpath = "github.com/otiai10/mint", + sum = "h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc=", + version = "v1.3.1", + ) + go_repository( name = "com_github_pact_foundation_pact_go", importpath = "github.com/pact-foundation/pact-go", @@ -3464,6 +3495,19 @@ def prysm_deps(): sum = "h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=", version = "v0.0.0-20191217153810-f85b25db303b", ) + go_repository( + name = "com_github_tenntenn_modver", + importpath = "github.com/tenntenn/modver", + sum = "h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA=", + version = "v1.0.1", + ) + go_repository( + name = "com_github_tenntenn_text_transform", + importpath = "github.com/tenntenn/text/transform", + sum = "h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag=", + version = "v0.0.0-20200319021203-7eef512accb3", + ) + go_repository( name = "com_github_thomaso_mirodin_intmath", importpath = "github.com/thomaso-mirodin/intmath", diff --git a/encoding/bytesutil/bytes.go b/encoding/bytesutil/bytes.go index 45d155a74d55..31b6ba4a0793 100644 --- a/encoding/bytesutil/bytes.go +++ b/encoding/bytesutil/bytes.go @@ -190,7 +190,7 @@ func ToLowInt64(x []byte) int64 { } // Use the first 8 bytes. x = x[:8] - return int64(binary.LittleEndian.Uint64(x)) + return int64(binary.LittleEndian.Uint64(x)) // lint:ignore uintcast -- A negative number might be the expected result. } // SafeCopyRootAtIndex takes a copy of an 32-byte slice in a slice of byte slices. Returns error if index out of range. diff --git a/encoding/ssz/merkleize.go b/encoding/ssz/merkleize.go index d9126f8722df..c795e1a7b312 100644 --- a/encoding/ssz/merkleize.go +++ b/encoding/ssz/merkleize.go @@ -206,7 +206,7 @@ func MerkleizeVector(elements [][32]byte, length uint64) [32]byte { if len(elements) == 0 { return trie.ZeroHashes[depth] } - for i := 0; i < int(depth); i++ { + for i := uint8(0); i < depth; i++ { layerLen := len(elements) oddNodeLength := layerLen%2 == 1 if oddNodeLength { diff --git a/go.mod b/go.mod index 509df1cabc3c..7d3eefcca406 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/google/gofuzz v1.2.0 github.com/google/uuid v1.3.0 github.com/gorilla/mux v1.8.0 + github.com/gostaticanalysis/comment v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 diff --git a/go.sum b/go.sum index 6d1348584d89..732888e98f3f 100644 --- a/go.sum +++ b/go.sum @@ -465,6 +465,9 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 h1:sezaKhEfPFg8W0Enm61B9Gs911H8iesGY5R8NDPtd1M= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -500,6 +503,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -1032,6 +1036,11 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= @@ -1247,6 +1256,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45 github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e h1:cR8/SYRgyQCt5cNCMniB/ZScMkhI9nk8U5C7SbISXjo= github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e/go.mod h1:Tu4lItkATkonrYuvtVjG0/rhy15qrNGNTjPdaphtZ/8= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= @@ -1431,6 +1442,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -1700,6 +1712,7 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= diff --git a/math/math_helper.go b/math/math_helper.go index ce24758aaa35..d1ca6d40861e 100644 --- a/math/math_helper.go +++ b/math/math_helper.go @@ -9,6 +9,19 @@ import ( "github.com/thomaso-mirodin/intmath/u64" ) +func init() { + // The Int function assumes that the operating system is 64 bit. In any case, Ethereum + // consensus layer uses 64 bit values almost exclusively so 64 bit OS requirement should + // already be established. This panic is a strict fail fast feedback to alert 32 bit users + // that they are not supported. + if stdmath.MaxUint < stdmath.MaxUint64 { + panic("Prysm is only supported on 64 bit OS") + } +} + +// ErrOverflow occurs when an operation exceeds max or minimum values. +var ErrOverflow = errors.New("integer overflow") + // Common square root values. var squareRootTable = map[uint64]uint64{ 4: 2, @@ -121,3 +134,28 @@ func Sub64(a, b uint64) (uint64, error) { } return res, nil } + +// Int returns the integer value of the uint64 argument. If there is an overlow, then an error is +// returned. +func Int(u uint64) (int, error) { + if u > stdmath.MaxInt { + return 0, ErrOverflow + } + return int(u), nil // lint:ignore uintcast -- This is the preferred method of casting uint64 to int. +} + +// AddInt adds two or more integers and checks for integer overflows. +func AddInt(i ...int) (int, error) { + var sum int + for _, ii := range i { + if ii > 0 && sum > stdmath.MaxInt-ii { + return 0, ErrOverflow + } else if ii < 0 && sum < stdmath.MinInt-ii { + return 0, ErrOverflow + } + + sum += ii + + } + return sum, nil +} diff --git a/math/math_helper_test.go b/math/math_helper_test.go index f2971d6e2b10..4351888b1222 100644 --- a/math/math_helper_test.go +++ b/math/math_helper_test.go @@ -1,6 +1,7 @@ package math_test import ( + "fmt" stdmath "math" "testing" @@ -366,3 +367,87 @@ func TestMath_Sub64(t *testing.T) { } } } + +func TestInt(t *testing.T) { + tests := []struct { + arg uint64 + want int + wantErr bool + }{ + { + arg: 0, + want: 0, + }, + { + arg: 10000000, + want: 10000000, + }, + { + arg: stdmath.MaxInt64, + want: stdmath.MaxInt64, + }, + { + arg: stdmath.MaxInt64 + 1, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(fmt.Sprint(tt.arg), func(t *testing.T) { + got, err := math.Int(tt.arg) + if (err != nil) != tt.wantErr { + t.Errorf("Int() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Int() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestAddInt(t *testing.T) { + tests := []struct { + name string + args []int + want int + wantErr bool + }{ + { + name: "no overflow", + args: []int{1, 2, 3, 4, 5}, + want: 15, + }, + { + name: "overflow", + args: []int{1, stdmath.MaxInt}, + wantErr: true, + }, + { + name: "underflow", + args: []int{-1, stdmath.MinInt}, + wantErr: true, + }, + { + name: "max int", + args: []int{1, stdmath.MaxInt - 1}, + want: stdmath.MaxInt, + }, + { + name: "min int", + args: []int{-1, stdmath.MinInt + 1}, + want: stdmath.MinInt, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := math.AddInt(tt.args...) + if (err != nil) != tt.wantErr { + t.Errorf("AddInt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("AddInt() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/nogo_config.json b/nogo_config.json index bde6fafcb3f9..d860436bd53f 100644 --- a/nogo_config.json +++ b/nogo_config.json @@ -163,5 +163,12 @@ ".*_test\\.go": "Tests are ok", "io/file/fileutil.go": "Package which defines the proper rules" } + }, + "uintcast": { + "exclude_files": { + "external/.*": "Third party code", + "rules_go_work-.*": "Third party code", + ".*_test\\.go": "Tests are ok" + } } } diff --git a/proto/prysm/v1alpha1/attestation/aggregation/testing/BUILD.bazel b/proto/prysm/v1alpha1/attestation/aggregation/testing/BUILD.bazel index 97536c51c677..8a924e871604 100644 --- a/proto/prysm/v1alpha1/attestation/aggregation/testing/BUILD.bazel +++ b/proto/prysm/v1alpha1/attestation/aggregation/testing/BUILD.bazel @@ -2,6 +2,7 @@ load("@prysm//tools/go:def.bzl", "go_library") go_library( name = "go_default_library", + testonly = True, srcs = ["bitlistutils.go"], importpath = "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation/aggregation/testing", visibility = ["//visibility:public"], diff --git a/proto/prysm/v1alpha1/attestation/aggregation/testing/bitlistutils.go b/proto/prysm/v1alpha1/attestation/aggregation/testing/bitlistutils.go index 06c0b01f73d7..4cfdce55ca95 100644 --- a/proto/prysm/v1alpha1/attestation/aggregation/testing/bitlistutils.go +++ b/proto/prysm/v1alpha1/attestation/aggregation/testing/bitlistutils.go @@ -50,7 +50,7 @@ func BitlistsWithMultipleBitSet(t testing.TB, n, length, count uint64) []bitfiel lists := make([]bitfield.Bitlist, n) for i := uint64(0); i < n; i++ { b := bitfield.NewBitlist(length) - keys := rand.Perm(int(length)) + keys := rand.Perm(int(length)) // lint:ignore uintcast -- This is safe in test code. for _, key := range keys[:count] { b.SetBitAt(uint64(key), true) } @@ -67,7 +67,7 @@ func Bitlists64WithMultipleBitSet(t testing.TB, n, length, count uint64) []*bitf lists := make([]*bitfield.Bitlist64, n) for i := uint64(0); i < n; i++ { b := bitfield.NewBitlist64(length) - keys := rand.Perm(int(length)) + keys := rand.Perm(int(length)) // lint:ignore uintcast -- This is safe in test code. for _, key := range keys[:count] { b.SetBitAt(uint64(key), true) } diff --git a/runtime/interop/generate_keys.go b/runtime/interop/generate_keys.go index 6e02f1412318..ba3274f47102 100644 --- a/runtime/interop/generate_keys.go +++ b/runtime/interop/generate_keys.go @@ -27,6 +27,7 @@ func DeterministicallyGenerateKeys(startIndex, numKeys uint64) ([]bls.SecretKey, secrets []bls.SecretKey publics []bls.PublicKey } + // lint:ignore uintcast -- this is safe because we can reasonably expect that the number of keys is less than max int64. results, err := async.Scatter(int(numKeys), func(offset int, entries int, _ *sync.RWMutex) (interface{}, error) { secs, pubs, err := deterministicallyGenerateKeys(uint64(offset)+startIndex, uint64(entries)) return &keys{secrets: secs, publics: pubs}, err diff --git a/testing/endtoend/components/eth1/miner.go b/testing/endtoend/components/eth1/miner.go index 1d4cfc3c498e..787634ff8063 100644 --- a/testing/endtoend/components/eth1/miner.go +++ b/testing/endtoend/components/eth1/miner.go @@ -197,7 +197,7 @@ func (m *Miner) Start(ctx context.Context) error { if err != nil { return err } - txOpts.Nonce = big.NewInt(int64(nonce)) + txOpts.Nonce = big.NewInt(0).SetUint64(nonce) txOpts.Context = ctx contractAddr, tx, _, err := contracts.DeployDepositContract(txOpts, web3) if err != nil { diff --git a/testing/endtoend/components/validator.go b/testing/endtoend/components/validator.go index 886219958c9e..d886f1c23a20 100644 --- a/testing/endtoend/components/validator.go +++ b/testing/endtoend/components/validator.go @@ -252,7 +252,7 @@ func sendDeposits(web3 *ethclient.Client, keystoreBytes []byte, num, offset int, if err != nil { return err } - txOps.Nonce = big.NewInt(int64(nonce)) + txOps.Nonce = big.NewInt(0).SetUint64(nonce) contract, err := contracts.NewDepositContract(e2e.TestParams.ContractAddress, web3) if err != nil { diff --git a/testing/util/deposits.go b/testing/util/deposits.go index dd37a058945f..13cd7dbd17e0 100644 --- a/testing/util/deposits.go +++ b/testing/util/deposits.go @@ -75,7 +75,7 @@ func DeterministicDepositsAndKeys(numDeposits uint64) ([]*ethpb.Deposit, []bls.S } } - depositTrie, _, err := DeterministicDepositTrie(int(numDeposits)) + depositTrie, _, err := DeterministicDepositTrie(int(numDeposits)) // lint:ignore uintcast if err != nil { return nil, nil, errors.Wrap(err, "failed to create deposit trie") } @@ -126,6 +126,7 @@ func DepositsWithBalance(balances []uint64) ([]*ethpb.Deposit, *trie.SparseMerkl // Create the new deposits and add them to the trie. for i := uint64(0); i < numDeposits; i++ { balance := params.BeaconConfig().MaxEffectiveBalance + // lint:ignore uintcast -- test code if len(balances) == int(numDeposits) { balance = balances[i] } @@ -140,12 +141,13 @@ func DepositsWithBalance(balances []uint64) ([]*ethpb.Deposit, *trie.SparseMerkl return nil, nil, errors.Wrap(err, "could not tree hash deposit data") } + // lint:ignore uintcast -- test code if err = sparseTrie.Insert(hashedDeposit[:], int(i)); err != nil { return nil, nil, err } } - depositTrie, _, err := DepositTrieSubset(sparseTrie, int(numDeposits)) + depositTrie, _, err := DepositTrieSubset(sparseTrie, int(numDeposits)) // lint:ignore uintcast -- test code if err != nil { return nil, nil, errors.Wrap(err, "failed to create deposit trie") } @@ -374,6 +376,7 @@ func DeterministicDepositsAndKeysSameValidator(numDeposits uint64) ([]*ethpb.Dep } } + // lint:ignore uintcast -- test code depositTrie, _, err := DeterministicDepositTrie(int(numDeposits)) if err != nil { return nil, nil, errors.Wrap(err, "failed to create deposit trie") diff --git a/testing/util/deposits_test.go b/testing/util/deposits_test.go index 6309501d4f62..2f6b433d926a 100644 --- a/testing/util/deposits_test.go +++ b/testing/util/deposits_test.go @@ -258,6 +258,7 @@ func TestDeterministicGenesisState_100Validators(t *testing.T) { activeValidators, err := helpers.ActiveValidatorCount(context.Background(), beaconState, 0) require.NoError(t, err) + // lint:ignore uintcast -- test code if len(privKeys) != int(validatorCount) { t.Fatalf("expected amount of private keys %d to match requested amount of validators %d", len(privKeys), validatorCount) } diff --git a/time/slots/slottime.go b/time/slots/slottime.go index 70aa2b1894a6..c8e8af57a6ab 100644 --- a/time/slots/slottime.go +++ b/time/slots/slottime.go @@ -20,7 +20,7 @@ const MaxSlotBuffer = uint64(1 << 7) // value. func StartTime(genesis uint64, slot types.Slot) time.Time { duration := time.Second * time.Duration(slot.Mul(params.BeaconConfig().SecondsPerSlot)) - startTime := time.Unix(int64(genesis), 0).Add(duration) + startTime := time.Unix(int64(genesis), 0).Add(duration) // lint:ignore uintcast -- Genesis timestamp will not exceed int64 in your lifetime. return startTime } @@ -153,7 +153,7 @@ func ToTime(genesisTimeSec uint64, slot types.Slot) (time.Time, error) { if err != nil { return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %w", slot, err) } - return time.Unix(int64(sTime), 0), nil + return time.Unix(int64(sTime), 0), nil // lint:ignore uintcast -- A timestamp will not exceed int64 in your lifetime. } // Since computes the number of time slots that have occurred since the given timestamp. @@ -165,7 +165,7 @@ func Since(time time.Time) types.Slot { // provided genesis time. func CurrentSlot(genesisTimeSec uint64) types.Slot { now := prysmTime.Now().Unix() - genesis := int64(genesisTimeSec) + genesis := int64(genesisTimeSec) // lint:ignore uintcast -- Genesis timestamp will not exceed int64 in your lifetime. if now < genesis { return 0 } diff --git a/tools/analyzers/comparesame/BUILD.bazel b/tools/analyzers/comparesame/BUILD.bazel index a7253608c57f..043c611777f7 100644 --- a/tools/analyzers/comparesame/BUILD.bazel +++ b/tools/analyzers/comparesame/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -12,4 +12,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/comparesame/analyzer_test.go b/tools/analyzers/comparesame/analyzer_test.go index d51cee9cbf35..e14648abd353 100644 --- a/tools/analyzers/comparesame/analyzer_test.go +++ b/tools/analyzers/comparesame/analyzer_test.go @@ -3,9 +3,18 @@ package comparesame import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/comparesame/testdata/BUILD.bazel b/tools/analyzers/comparesame/testdata/BUILD.bazel deleted file mode 100644 index 833040e68559..000000000000 --- a/tools/analyzers/comparesame/testdata/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["compare_len.go"], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/comparesame/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/cryptorand/BUILD.bazel b/tools/analyzers/cryptorand/BUILD.bazel index 3850de629b9f..1afcb2fdc034 100644 --- a/tools/analyzers/cryptorand/BUILD.bazel +++ b/tools/analyzers/cryptorand/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -12,4 +12,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/cryptorand/analyzer_test.go b/tools/analyzers/cryptorand/analyzer_test.go index 545adf8f66f8..5a13d87afc54 100644 --- a/tools/analyzers/cryptorand/analyzer_test.go +++ b/tools/analyzers/cryptorand/analyzer_test.go @@ -3,9 +3,18 @@ package cryptorand import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/cryptorand/testdata/BUILD.bazel b/tools/analyzers/cryptorand/testdata/BUILD.bazel deleted file mode 100644 index 49b7794a3fa5..000000000000 --- a/tools/analyzers/cryptorand/testdata/BUILD.bazel +++ /dev/null @@ -1,11 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "custom_import.go", - "rand_new.go", - ], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/cryptorand/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/ineffassign/BUILD.bazel b/tools/analyzers/ineffassign/BUILD.bazel index 70ed1469da1e..27b24c6d9f30 100644 --- a/tools/analyzers/ineffassign/BUILD.bazel +++ b/tools/analyzers/ineffassign/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -15,4 +15,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/ineffassign/analyzer_test.go b/tools/analyzers/ineffassign/analyzer_test.go index 2676f3e85786..0c7928a2d473 100644 --- a/tools/analyzers/ineffassign/analyzer_test.go +++ b/tools/analyzers/ineffassign/analyzer_test.go @@ -3,9 +3,18 @@ package ineffassign import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/ineffassign/testdata/BUILD.bazel b/tools/analyzers/ineffassign/testdata/BUILD.bazel deleted file mode 100644 index 9b6ff10120fb..000000000000 --- a/tools/analyzers/ineffassign/testdata/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["ctx_assignment.go"], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/ineffassign/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/maligned/maligned.go b/tools/analyzers/maligned/maligned.go index d88016962f13..42e179f3bcb7 100644 --- a/tools/analyzers/maligned/maligned.go +++ b/tools/analyzers/maligned/maligned.go @@ -176,7 +176,7 @@ func (s *gcSizes) Sizeof(T types.Type) int64 { k := t.Kind() if int(k) < len(basicSizes) { if s := basicSizes[k]; s > 0 { - return int64(s) + return int64(s) // lint:ignore uintcast -- a byte will never exceed int64 } } if k == types.String { diff --git a/tools/analyzers/nop/BUILD.bazel b/tools/analyzers/nop/BUILD.bazel index 94960147ac3b..d447e773e085 100644 --- a/tools/analyzers/nop/BUILD.bazel +++ b/tools/analyzers/nop/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -12,4 +12,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/nop/analyzer_test.go b/tools/analyzers/nop/analyzer_test.go index be1180af81d4..dd01a66ee38f 100644 --- a/tools/analyzers/nop/analyzer_test.go +++ b/tools/analyzers/nop/analyzer_test.go @@ -3,9 +3,18 @@ package nop import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/nop/testdata/BUILD.bazel b/tools/analyzers/nop/testdata/BUILD.bazel deleted file mode 100644 index d22fd1d81a4e..000000000000 --- a/tools/analyzers/nop/testdata/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["no_op.go"], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/nop/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/properpermissions/BUILD.bazel b/tools/analyzers/properpermissions/BUILD.bazel index 99c121697c89..8010c6524c2b 100644 --- a/tools/analyzers/properpermissions/BUILD.bazel +++ b/tools/analyzers/properpermissions/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -12,4 +12,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/properpermissions/analyzer_test.go b/tools/analyzers/properpermissions/analyzer_test.go index fc90cb8f47d9..a167ce031585 100644 --- a/tools/analyzers/properpermissions/analyzer_test.go +++ b/tools/analyzers/properpermissions/analyzer_test.go @@ -3,9 +3,18 @@ package properpermissions import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/properpermissions/testdata/BUILD.bazel b/tools/analyzers/properpermissions/testdata/BUILD.bazel deleted file mode 100644 index c36798bf40db..000000000000 --- a/tools/analyzers/properpermissions/testdata/BUILD.bazel +++ /dev/null @@ -1,11 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "custom_imports.go", - "regular_imports.go", - ], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/properpermissions/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/recursivelock/BUILD.bazel b/tools/analyzers/recursivelock/BUILD.bazel index 6352087f2752..36c994df4d3f 100644 --- a/tools/analyzers/recursivelock/BUILD.bazel +++ b/tools/analyzers/recursivelock/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -14,4 +14,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/recursivelock/analyzer_test.go b/tools/analyzers/recursivelock/analyzer_test.go index 32056ce65aa8..833386c01efd 100644 --- a/tools/analyzers/recursivelock/analyzer_test.go +++ b/tools/analyzers/recursivelock/analyzer_test.go @@ -3,9 +3,18 @@ package recursivelock import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/recursivelock/testdata/BUILD.bazel b/tools/analyzers/recursivelock/testdata/BUILD.bazel deleted file mode 100644 index a969140d00c8..000000000000 --- a/tools/analyzers/recursivelock/testdata/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "badlockswithmethods.go", - "badlockswithstructs.go", - "complexlocks.go", - "globallocks.go", - "nonrlocks.go", - "types.go", - ], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/recursivelock/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/shadowpredecl/BUILD.bazel b/tools/analyzers/shadowpredecl/BUILD.bazel index b923bdf5a182..53efbae4fc52 100644 --- a/tools/analyzers/shadowpredecl/BUILD.bazel +++ b/tools/analyzers/shadowpredecl/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -12,4 +12,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/shadowpredecl/analyzer_test.go b/tools/analyzers/shadowpredecl/analyzer_test.go index 270f6c5bf8e4..87d4dde00901 100644 --- a/tools/analyzers/shadowpredecl/analyzer_test.go +++ b/tools/analyzers/shadowpredecl/analyzer_test.go @@ -3,9 +3,18 @@ package shadowpredecl import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/shadowpredecl/testdata/BUILD.bazel b/tools/analyzers/shadowpredecl/testdata/BUILD.bazel deleted file mode 100644 index 18d1b5bffba2..000000000000 --- a/tools/analyzers/shadowpredecl/testdata/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["shadow.go"], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/shadowpredecl/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/slicedirect/BUILD.bazel b/tools/analyzers/slicedirect/BUILD.bazel index 54a0ae7fade4..0f940aff7bef 100644 --- a/tools/analyzers/slicedirect/BUILD.bazel +++ b/tools/analyzers/slicedirect/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -12,4 +12,15 @@ go_library( ], ) -# gazelle:exclude analyzer_test.go +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + embed = [":go_default_library"], + deps = [ + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/slicedirect/analyzer_test.go b/tools/analyzers/slicedirect/analyzer_test.go index 072ca37514f9..84196e9352d2 100644 --- a/tools/analyzers/slicedirect/analyzer_test.go +++ b/tools/analyzers/slicedirect/analyzer_test.go @@ -3,9 +3,18 @@ package slicedirect import ( "testing" + "github.com/prysmaticlabs/prysm/build/bazel" "golang.org/x/tools/go/analysis/analysistest" ) +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + func TestAnalyzer(t *testing.T) { - analysistest.Run(t, analysistest.TestData(), Analyzer) + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, Analyzer) } diff --git a/tools/analyzers/slicedirect/testdata/BUILD.bazel b/tools/analyzers/slicedirect/testdata/BUILD.bazel deleted file mode 100644 index 6fa86bfa3334..000000000000 --- a/tools/analyzers/slicedirect/testdata/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["slice.go"], - importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/slicedirect/testdata", - visibility = ["//visibility:public"], -) diff --git a/tools/analyzers/uintcast/BUILD.bazel b/tools/analyzers/uintcast/BUILD.bazel new file mode 100644 index 000000000000..90166f26ac37 --- /dev/null +++ b/tools/analyzers/uintcast/BUILD.bazel @@ -0,0 +1,27 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["analyzer.go"], + importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/uintcast", + visibility = ["//visibility:public"], + deps = [ + "@com_github_gostaticanalysis_comment//:go_default_library", + "@org_golang_x_tools//go/analysis:go_default_library", + "@org_golang_x_tools//go/analysis/passes/inspect:go_default_library", + "@org_golang_x_tools//go/ast/inspector:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["analyzer_test.go"], + data = glob(["testdata/**"]) + [ + "@go_sdk//:files", + ], + deps = [ + ":go_default_library", + "//build/bazel:go_default_library", + "@org_golang_x_tools//go/analysis/analysistest:go_default_library", + ], +) diff --git a/tools/analyzers/uintcast/analyzer.go b/tools/analyzers/uintcast/analyzer.go new file mode 100644 index 000000000000..f8669fd3a6b6 --- /dev/null +++ b/tools/analyzers/uintcast/analyzer.go @@ -0,0 +1,107 @@ +package uintcast + +import ( + "errors" + "go/ast" + "go/types" + "strings" + + "github.com/gostaticanalysis/comment" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +// Doc explaining the tool. +const Doc = "Ensure that uint variables are not cast improperly where the value could overflow. " + + "This check can be suppressed with the `lint:ignore uintcast` comment with proper justification." + +// Analyzer runs static analysis. +var Analyzer = &analysis.Analyzer{ + Name: "uintcast", + Doc: Doc, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Run: run, +} + +func run(pass *analysis.Pass) (interface{}, error) { + inspection, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + if !ok { + return nil, errors.New("analyzer is not type *inspector.Inspector") + } + + nodeFilter := []ast.Node{ + (*ast.CallExpr)(nil), + } + + commentMap := comment.New(pass.Fset, pass.Files) + + inspection.Preorder(nodeFilter, func(node ast.Node) { + cg := commentMap.CommentsByPosLine(pass.Fset, node.Pos()) + for _, c := range cg { + if strings.Contains(c.Text(), "lint:ignore uintcast") { + return + } + } + + switch node := node.(type) { + case *ast.CallExpr: + // Cast/conversion calls have one argument and no ellipsis. + if len(node.Args) != 1 || node.Ellipsis.IsValid() { + return + } + + var typ *types.Basic + switch arg := node.Args[0].(type) { + case *ast.Ident: + typ, ok = basicType(pass.TypesInfo.Types[arg].Type) + case *ast.CallExpr: + // Check if the call is a builtin conversion/anon identifier. + typ, ok = basicType(pass.TypesInfo.Types[arg].Type) + if !ok { + // Otherwise, it might be a declared function call with a return type. + typ, ok = funcReturnType(pass.TypesInfo.Types[arg.Fun].Type) + } + } + if typ == nil || !ok { + return + } + + // Ignore types that are not uint variants. + if typ.Kind() < types.Uint || typ.Kind() > types.Uint64 { + return + } + + if fnTyp, ok := pass.TypesInfo.Types[node.Fun].Type.(*types.Basic); ok { + if fnTyp.Kind() >= types.Int && fnTyp.Kind() <= types.Int64 { + pass.Reportf(node.Args[0].Pos(), "Unsafe cast from %s to %s.", typ, fnTyp) + } + } + } + }) + + return nil, nil +} + +func basicType(obj types.Type) (*types.Basic, bool) { + if obj == nil { + return nil, false + } + fromTyp, ok := obj.(*types.Basic) + if !ok && obj.Underlying() != nil { + // Try to get the underlying type + fromTyp, ok = obj.Underlying().(*types.Basic) + } + return fromTyp, ok +} + +func funcReturnType(obj types.Type) (*types.Basic, bool) { + if obj == nil { + return nil, false + } + fnTyp, ok := obj.(*types.Signature) + if !ok { + return nil, ok + } + return basicType(fnTyp.Results().At(0).Type()) +} diff --git a/tools/analyzers/uintcast/analyzer_test.go b/tools/analyzers/uintcast/analyzer_test.go new file mode 100644 index 000000000000..f37b3c8beb63 --- /dev/null +++ b/tools/analyzers/uintcast/analyzer_test.go @@ -0,0 +1,21 @@ +package uintcast_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/build/bazel" + "github.com/prysmaticlabs/prysm/tools/analyzers/uintcast" + "golang.org/x/tools/go/analysis/analysistest" +) + +func init() { + if bazel.BuiltWithBazel() { + bazel.SetGoEnv() + } +} + +func TestAnalyzer(t *testing.T) { + testdata := bazel.TestDataPath(t) + analysistest.TestData = func() string { return testdata } + analysistest.Run(t, testdata, uintcast.Analyzer) +} diff --git a/tools/analyzers/uintcast/testdata/data.go b/tools/analyzers/uintcast/testdata/data.go new file mode 100644 index 000000000000..1bf1fe6889e6 --- /dev/null +++ b/tools/analyzers/uintcast/testdata/data.go @@ -0,0 +1,87 @@ +package testdata + +import ( + "math" + "time" +) + +// Uint64CastToInt -- +func Uint64CastToInt() { + a := uint64(math.MaxUint64) + b := int(a) // want "Unsafe cast from uint64 to int." + + _ = b +} + +// Uint64CastToIntIfStatement -- +func Uint64CastToIntIfStatement() { + var b []string + a := uint64(math.MaxUint64) + + if len(b) < int(a) { // want "Unsafe cast from uint64 to int." + return + } +} + +type Slot = uint64 + +// BaseTypes should alert on alias like Slot. +func BaseTypes() { + var slot Slot + bad := int(slot) // want "Unsafe cast from uint64 to int." + _ = bad +} + +func Uint64CastInStruct() { + type S struct { + a int + } + s := S{ + a: int(uint64(5)), // want "Unsafe cast from uint64 to int." + } + _ = s +} + +func Uint64CastFunctionReturn() { + fn := func() uint64 { + return 5 + } + a := int(fn()) // want "Unsafe cast from uint64 to int." + _ = a +} + +// IgnoredResult should not report an error. +func IgnoredResult() { + a := uint64(math.MaxUint64) + b := int(a) // lint:ignore uintcast -- test code + + _ = b +} + +// IgnoredIfStatement should not report an error. +func IgnoredIfStatement() { + var balances []int + var numDeposits uint64 + var i int + var balance int + + // lint:ignore uintcast -- test code + if len(balances) == int(numDeposits) { + balance = balances[i] + } + + _ = balance +} + +func IgnoreInFunctionCall() bool { + var timestamp uint64 + var timeout time.Time + return time.Unix(int64(timestamp), 0).Before(timeout) // lint:ignore uintcast -- test code +} + +func IgnoreWithOtherComments() bool { + var timestamp uint64 + var timeout time.Time + // I plan to live forever. Maybe we should not do this? + return time.Unix(int64(timestamp), 0).Before(timeout) // lint:ignore uintcast -- timestamp will not exceed int64 in your lifetime. +} diff --git a/tools/blocktree/main.go b/tools/blocktree/main.go index dd98a6858691..1b6ce62d0c5e 100644 --- a/tools/blocktree/main.go +++ b/tools/blocktree/main.go @@ -83,7 +83,7 @@ func main() { // Construct label of each node. rStr := hex.EncodeToString(r[:2]) - label := "slot: " + strconv.Itoa(int(b.Block().Slot())) + "\n root: " + rStr + label := "slot: " + strconv.Itoa(int(b.Block().Slot())) + "\n root: " + rStr // lint:ignore uintcast -- this is OK for logging. dotN := graph.Node(rStr).Box().Attr("label", label) n := &node{ diff --git a/tools/eth1voting/BUILD.bazel b/tools/eth1voting/BUILD.bazel index f560997f6e14..6c17dffa34e2 100644 --- a/tools/eth1voting/BUILD.bazel +++ b/tools/eth1voting/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "//proto/prysm/v1alpha1/block:go_default_library", "//proto/prysm/v1alpha1/wrapper:go_default_library", "//time/slots:go_default_library", + "@com_github_prysmaticlabs_eth2_types//:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", ], diff --git a/tools/eth1voting/main.go b/tools/eth1voting/main.go index 38eb40c391a5..dda062ea08a7 100644 --- a/tools/eth1voting/main.go +++ b/tools/eth1voting/main.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/config/params" v1alpha1 "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" @@ -47,7 +48,7 @@ func main() { } fmt.Printf("Next period starts at epoch %d (%s)\n", nextStart, time.Until(nextStartTime)) - for i := 0; i < int(current.Sub(uint64(start))); i++ { + for i := types.Epoch(0); i < current.Sub(uint64(start)); i++ { j := i g.Go(func() error { resp, err := c.ListBeaconBlocks(ctx, &v1alpha1.ListBlocksRequest{ diff --git a/tools/exploredb/main.go b/tools/exploredb/main.go index 3d9435e5d37e..9db6a25d6b6f 100644 --- a/tools/exploredb/main.go +++ b/tools/exploredb/main.go @@ -324,7 +324,7 @@ func printStates(stateC <-chan *modifiedState, doneC chan<- bool) { log.Infof("---- row = %04d, slot = %8d, epoch = %8d, key = %s ----", mst.rowCount, st.Slot(), st.Slot()/params.BeaconConfig().SlotsPerEpoch, hexutils.BytesToHex(mst.key)) log.Infof("key : %s", hexutils.BytesToHex(mst.key)) log.Infof("value : compressed size = %s", humanize.Bytes(mst.valueSize)) - t := time.Unix(int64(st.GenesisTime()), 0) + t := time.Unix(int64(st.GenesisTime()), 0) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime. log.Infof("genesis_time : %s", t.Format(time.UnixDate)) log.Infof("genesis_validators_root : %s", hexutils.BytesToHex(st.GenesisValidatorsRoot())) log.Infof("slot : %d", st.Slot()) diff --git a/validator/accounts/petnames/names.go b/validator/accounts/petnames/names.go index bd0eed7f618b..dfa0117b8cd2 100644 --- a/validator/accounts/petnames/names.go +++ b/validator/accounts/petnames/names.go @@ -18,7 +18,7 @@ var ( func DeterministicName(seed []byte, separator string) string { rng := rand.NewDeterministicGenerator() hashedValue := hash.FastSum64(seed) - rng.Seed(int64(hashedValue)) + rng.Seed(int64(hashedValue)) // lint:ignore uintcast -- It's safe to do this for deterministic naming. adverb := adverbs[rng.Intn(len(adverbs)-1)] adjective := adjectives[rng.Intn(len(adjectives)-1)] name := names[rng.Intn(len(names)-1)] diff --git a/validator/client/attest.go b/validator/client/attest.go index 3c14d0411e27..89ebb35a4be2 100644 --- a/validator/client/attest.go +++ b/validator/client/attest.go @@ -165,7 +165,7 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot types.Slot, pubK } span.AddAttributes( - trace.Int64Attribute("slot", int64(slot)), + trace.Int64Attribute("slot", int64(slot)), // lint:ignore uintcast -- This conversion is OK for tracing. trace.StringAttribute("attestationHash", fmt.Sprintf("%#x", attResp.AttestationDataRoot)), trace.Int64Attribute("committeeIndex", int64(data.CommitteeIndex)), trace.StringAttribute("blockRoot", fmt.Sprintf("%#x", data.BeaconBlockRoot)), diff --git a/validator/client/runner.go b/validator/client/runner.go index ab2a152a7e2e..38305a85c127 100644 --- a/validator/client/runner.go +++ b/validator/client/runner.go @@ -145,7 +145,7 @@ func run(ctx context.Context, v iface.Validator) { } } case slot := <-v.NextSlot(): - span.AddAttributes(trace.Int64Attribute("slot", int64(slot))) + span.AddAttributes(trace.Int64Attribute("slot", int64(slot))) // lint:ignore uintcast -- This conversion is OK for tracing. remoteKm, ok := km.(remote.RemoteKeymanager) if ok {