From a5010737399826811952a97852ae55753958b2fb Mon Sep 17 00:00:00 2001 From: Ran Mishael Date: Sun, 24 Mar 2024 16:38:10 +0100 Subject: [PATCH 1/3] Split payment --- ecosystem/cache/handlers.go | 4 +- ecosystem/cache/server.go | 4 +- protocol/chaintracker/chain_tracker.go | 6 +- .../lavaprotocol/finalization_consensus.go | 4 +- protocol/lavaprotocol/response_builder.go | 4 +- protocol/lavasession/common.go | 2 +- protocol/lavasession/consumer_types.go | 1 + .../lavasession/provider_session_manager.go | 4 +- protocol/monitoring/health_results.go | 8 +- .../provideroptimizer/provider_optimizer.go | 4 +- .../rpcprovider/rewardserver/reward_server.go | 138 +++++++++++------- protocol/rpcprovider/rpcprovider_server.go | 8 +- protocol/statetracker/tx_sender.go | 5 +- .../statetracker/updaters/payment_updater.go | 5 + testutil/common/tester.go | 8 +- utils/{slices => lavaslices}/slices.go | 37 ++++- utils/{slices => lavaslices}/slices_test.go | 24 ++- .../keeper/msg_server_detection_test.go | 4 +- x/dualstaking/keeper/delegate.go | 2 +- x/dualstaking/keeper/delegator_reward.go | 4 +- x/dualstaking/types/delegate.go | 8 +- x/pairing/keeper/cu_tracker_test.go | 20 +-- x/pairing/keeper/delegator_rewards_test.go | 4 +- .../msg_server_relay_payment_gov_test.go | 16 +- .../keeper/msg_server_relay_payment_test.go | 22 +-- x/pairing/keeper/pairing.go | 12 +- x/pairing/keeper/pairing_immediately_test.go | 6 +- x/pairing/keeper/pairing_subscription_test.go | 8 +- x/pairing/keeper/pairing_test.go | 66 ++++----- .../keeper/unresponsive_provider_test.go | 12 +- x/plans/types/geolocation_test.go | 4 +- x/plans/types/policy.go | 4 +- x/rewards/client/cli/tx.go | 4 +- .../keeper/msg_server_auto_renewal.go | 4 +- x/subscription/keeper/subscription.go | 6 +- 35 files changed, 282 insertions(+), 190 deletions(-) rename utils/{slices => lavaslices}/slices.go (83%) rename utils/{slices => lavaslices}/slices_test.go (95%) diff --git a/ecosystem/cache/handlers.go b/ecosystem/cache/handlers.go index a604894890..54c6e21de9 100644 --- a/ecosystem/cache/handlers.go +++ b/ecosystem/cache/handlers.go @@ -16,7 +16,7 @@ import ( "github.com/lavanet/lava/protocol/lavaprotocol" "github.com/lavanet/lava/protocol/parser" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" pairingtypes "github.com/lavanet/lava/x/pairing/types" spectypes "github.com/lavanet/lava/x/spec/types" emptypb "google.golang.org/protobuf/types/known/emptypb" @@ -128,7 +128,7 @@ func (s *RelayerCacheServer) GetRelay(ctx context.Context, relayCacheGet *pairin waitGroup.Wait() if err == nil { // in case we got a hit validate seen block of the reply. // validate that the response seen block is larger or equal to our expectations. - if cacheReply.SeenBlock < slices.Min([]int64{relayCacheGet.SeenBlock, relayCacheGet.RequestedBlock}) { // TODO unitest this. + if cacheReply.SeenBlock < lavaslices.Min([]int64{relayCacheGet.SeenBlock, relayCacheGet.RequestedBlock}) { // TODO unitest this. // Error, our reply seen block is not larger than our expectations, meaning we got an old response // this can happen only in the case relayCacheGet.SeenBlock < relayCacheGet.RequestedBlock // by setting the err variable we will get a cache miss, and the relay will continue to the node. diff --git a/ecosystem/cache/server.go b/ecosystem/cache/server.go index 4c801047ba..516bdec837 100644 --- a/ecosystem/cache/server.go +++ b/ecosystem/cache/server.go @@ -9,7 +9,7 @@ import ( "os/signal" "time" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/dgraph-io/ristretto" "github.com/improbable-eng/grpc-web/go/grpcweb" @@ -115,7 +115,7 @@ func (cs *CacheServer) Serve(ctx context.Context, func (cs *CacheServer) ExpirationForChain(averageBlockTimeForChain time.Duration) time.Duration { eighthBlock := averageBlockTimeForChain / 8 - return slices.Max([]time.Duration{eighthBlock, cs.ExpirationNonFinalized}) // return the maximum TTL between an eighth block and expiration + return lavaslices.Max([]time.Duration{eighthBlock, cs.ExpirationNonFinalized}) // return the maximum TTL between an eighth block and expiration } func Server( diff --git a/protocol/chaintracker/chain_tracker.go b/protocol/chaintracker/chain_tracker.go index 65aeae66ab..22ff149bb1 100644 --- a/protocol/chaintracker/chain_tracker.go +++ b/protocol/chaintracker/chain_tracker.go @@ -21,7 +21,7 @@ import ( "github.com/lavanet/lava/protocol/lavasession" "github.com/lavanet/lava/protocol/metrics" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" grpc "google.golang.org/grpc" @@ -467,8 +467,8 @@ func (ct *ChainTracker) updatePollingTimeBasedOnBlockGap(pollingTime time.Durati if blockGapsLen > PollingUpdateLength { // check we have enough samples // smaller times give more resolution to indentify changes, and also make block arrival predictions more optimistic // so we take a 0.33 percentile because we want to be on the safe side by have a smaller time than expected - percentileTime := slices.Percentile(ct.blockEventsGap, 0.33) - stability := slices.Stability(ct.blockEventsGap, percentileTime) + percentileTime := lavaslices.Percentile(ct.blockEventsGap, 0.33) + stability := lavaslices.Stability(ct.blockEventsGap, percentileTime) if debug { utils.LavaFormatDebug("block gaps", utils.Attribute{Key: "block gaps", Value: ct.blockEventsGap}, utils.Attribute{Key: "specID", Value: ct.endpoint.ChainID}) } diff --git a/protocol/lavaprotocol/finalization_consensus.go b/protocol/lavaprotocol/finalization_consensus.go index 3351afdf82..88107fecff 100644 --- a/protocol/lavaprotocol/finalization_consensus.go +++ b/protocol/lavaprotocol/finalization_consensus.go @@ -9,7 +9,7 @@ import ( "github.com/lavanet/lava/protocol/chainlib" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" conflicttypes "github.com/lavanet/lava/x/conflict/types" pairingtypes "github.com/lavanet/lava/x/pairing/types" ) @@ -251,7 +251,7 @@ func (fc *FinalizationConsensus) ExpectedBlockHeight(chainParser chainlib.ChainP data[i] = latestBlock i++ } - return slices.Median(data) + return lavaslices.Median(data) } medianOfExpectedBlocks := median(mapExpectedBlockHeights) providersMedianOfLatestBlock := medianOfExpectedBlocks + int64(blockDistanceForFinalizedData) diff --git a/protocol/lavaprotocol/response_builder.go b/protocol/lavaprotocol/response_builder.go index a6f472278d..cf24891477 100644 --- a/protocol/lavaprotocol/response_builder.go +++ b/protocol/lavaprotocol/response_builder.go @@ -8,8 +8,8 @@ import ( btcSecp256k1 "github.com/btcsuite/btcd/btcec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" conflicttypes "github.com/lavanet/lava/x/conflict/types" pairingtypes "github.com/lavanet/lava/x/pairing/types" spectypes "github.com/lavanet/lava/x/spec/types" @@ -87,7 +87,7 @@ func VerifyFinalizationData(reply *pairingtypes.RelayReply, relayRequest *pairin providerLatestBlock := reply.LatestBlock seenBlock := relayRequest.RelayData.SeenBlock requestBlock := relayRequest.RelayData.RequestBlock - if providerLatestBlock < slices.Min([]int64{seenBlock, requestBlock}) { + if providerLatestBlock < lavaslices.Min([]int64{seenBlock, requestBlock}) { return nil, nil, utils.LavaFormatError("provider response does not meet consistency requirements", ProviderFinzalizationDataError, utils.LogAttr("ProviderAddress", relayRequest.RelaySession.Provider), utils.LogAttr("providerLatestBlock", providerLatestBlock), utils.LogAttr("seenBlock", seenBlock), utils.LogAttr("requestBlock", requestBlock), utils.Attribute{Key: "provider address", Value: providerAddr}) } return finalizedBlocks, finalizationConflict, errRet diff --git a/protocol/lavasession/common.go b/protocol/lavasession/common.go index 5aeed0a0a4..464e84bc31 100644 --- a/protocol/lavasession/common.go +++ b/protocol/lavasession/common.go @@ -26,7 +26,7 @@ import ( const ( MaxConsecutiveConnectionAttempts = 5 TimeoutForEstablishingAConnection = 1 * time.Second - MaxSessionsAllowedPerProvider = 1000 // Max number of sessions allowed per provider + MaxSessionsAllowedPerProvider = 100000 // Max number of sessions allowed per provider MaxAllowedBlockListedSessionPerProvider = 3 MaximumNumberOfFailuresAllowedPerConsumerSession = 3 RelayNumberIncrement = 1 diff --git a/protocol/lavasession/consumer_types.go b/protocol/lavasession/consumer_types.go index 18a578844f..8b7a5a3c3d 100644 --- a/protocol/lavasession/consumer_types.go +++ b/protocol/lavasession/consumer_types.go @@ -285,6 +285,7 @@ func (cswp *ConsumerSessionsWithProvider) GetConsumerSessionInstanceFromEndpoint // try to lock an existing session, if can't create a new one var numberOfBlockedSessions uint64 = 0 for sessionID, session := range cswp.Sessions { + break if sessionID == DataReliabilitySessionId { continue // we cant use the data reliability session. which is located at key DataReliabilitySessionId } diff --git a/protocol/lavasession/provider_session_manager.go b/protocol/lavasession/provider_session_manager.go index 72854cfe62..c7042fca09 100644 --- a/protocol/lavasession/provider_session_manager.go +++ b/protocol/lavasession/provider_session_manager.go @@ -6,7 +6,7 @@ import ( "sync/atomic" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" pairingtypes "github.com/lavanet/lava/x/pairing/types" ) @@ -109,7 +109,7 @@ func getBadgeEpochDataFromProviderSessionWithConsumer(badgeUser string, provider func registerBadgeEpochDataToProviderSessionWithConsumer(badgeUser string, badgeCuAllocation uint64, providerSessionsWithConsumer *ProviderSessionsWithConsumerProject) *ProviderSessionsEpochData { providerSessionsWithConsumer.Lock.Lock() defer providerSessionsWithConsumer.Lock.Unlock() - providerSessionsWithConsumer.badgeEpochData[badgeUser] = &ProviderSessionsEpochData{MaxComputeUnits: slices.Min([]uint64{providerSessionsWithConsumer.epochData.MaxComputeUnits, badgeCuAllocation})} + providerSessionsWithConsumer.badgeEpochData[badgeUser] = &ProviderSessionsEpochData{MaxComputeUnits: lavaslices.Min([]uint64{providerSessionsWithConsumer.epochData.MaxComputeUnits, badgeCuAllocation})} return providerSessionsWithConsumer.badgeEpochData[badgeUser] } diff --git a/protocol/monitoring/health_results.go b/protocol/monitoring/health_results.go index 9cb0632185..7f135a641b 100644 --- a/protocol/monitoring/health_results.go +++ b/protocol/monitoring/health_results.go @@ -5,7 +5,7 @@ import ( "time" "github.com/lavanet/lava/protocol/common" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" spectypes "github.com/lavanet/lava/x/spec/types" ) @@ -88,7 +88,7 @@ func (healthResults *HealthResults) updateLatestBlock(specId string, latestBlock if !ok { healthResults.LatestBlocks[specId] = latestBlock } else { - healthResults.LatestBlocks[specId] = slices.Max([]int64{existing, latestBlock}) + healthResults.LatestBlocks[specId] = lavaslices.Max([]int64{existing, latestBlock}) } } @@ -150,9 +150,9 @@ func (healthResults *HealthResults) SetProviderData(providerKey LavaEntity, late if existing.Block == 0 { existing.Block = latestData.Block } else { - latestData.Block = slices.Min([]int64{existing.Block, latestData.Block}) + latestData.Block = lavaslices.Min([]int64{existing.Block, latestData.Block}) } - latestData.Latency = slices.Max([]time.Duration{existing.Latency, latestData.Latency}) + latestData.Latency = lavaslices.Max([]time.Duration{existing.Latency, latestData.Latency}) } healthResults.ProviderData[providerKey] = latestData } diff --git a/protocol/provideroptimizer/provider_optimizer.go b/protocol/provideroptimizer/provider_optimizer.go index e78d7d1b6b..9ffd9d923c 100644 --- a/protocol/provideroptimizer/provider_optimizer.go +++ b/protocol/provideroptimizer/provider_optimizer.go @@ -10,9 +10,9 @@ import ( "github.com/dgraph-io/ristretto" "github.com/lavanet/lava/protocol/common" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/rand" "github.com/lavanet/lava/utils/score" - "github.com/lavanet/lava/utils/slices" pairingtypes "github.com/lavanet/lava/x/pairing/types" "gonum.org/v1/gonum/mathext" ) @@ -188,7 +188,7 @@ func (po *ProviderOptimizer) calculateSyncLag(latestSync uint64, timeSync time.T } // lag on first block timeLag := sampleTime.Sub(timeSync) // received the latest block at time X, this provider provided the entry at time Y, which is X-Y time after - firstBlockLag := slices.Min([]time.Duration{po.averageBlockTime, timeLag}) + firstBlockLag := lavaslices.Min([]time.Duration{po.averageBlockTime, timeLag}) blocksGap := latestSync - providerBlock - 1 // latestSync > providerBlock blocksGapTime := time.Duration(blocksGap) * po.averageBlockTime // the provider is behind by X blocks, so is expected to catch up in averageBlockTime * X timeLag = firstBlockLag + blocksGapTime diff --git a/protocol/rpcprovider/rewardserver/reward_server.go b/protocol/rpcprovider/rewardserver/reward_server.go index 7fdc0f24d1..30c0c86070 100644 --- a/protocol/rpcprovider/rewardserver/reward_server.go +++ b/protocol/rpcprovider/rewardserver/reward_server.go @@ -15,6 +15,7 @@ import ( "github.com/lavanet/lava/protocol/lavasession" "github.com/lavanet/lava/protocol/metrics" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/rand" "github.com/lavanet/lava/utils/sigs" pairingtypes "github.com/lavanet/lava/x/pairing/types" @@ -32,6 +33,7 @@ const ( DefaultRewardsSnapshotTimeoutSec = 30 MaxPaymentRequestsRetiresForSession = 3 RewardServerMaxRelayRetires = 3 + splitRewardsIntoChunksSize = 500 // if the reward array is larger than this it will split it into chunks and send multiple requests instead of a huge one ) type PaymentRequest struct { @@ -75,6 +77,11 @@ type RelaySessionsToRetryAttempts struct { paymentRequestRetryAttempts uint64 } +type PaymentConfiguration struct { + relaySessionChunks [][]*pairingtypes.RelaySession // small chunks of relay session to request payments for + shouldAddExpectedPayment bool +} + type RewardServer struct { rewardsTxSender RewardsTxSender lock sync.RWMutex @@ -223,61 +230,91 @@ func (rws *RewardServer) sendRewardsClaim(ctx context.Context, epoch uint64) err return utils.LavaFormatError("sendRewardsClaim failed to get earliest block in memory", err) } + // Handle Failed rewards claim with retry failedRewardRequestsToRetry := rws.gatherFailedRequestPaymentsToRetry(earliestSavedEpoch) if len(failedRewardRequestsToRetry) > 0 { utils.LavaFormatDebug("Found failed reward claims, retrying", utils.LogAttr("number_of_rewards", len((failedRewardRequestsToRetry)))) - specs := map[string]struct{}{} - for _, relay := range failedRewardRequestsToRetry { - utils.LavaFormatDebug("[sendRewardsClaim] retrying failed id", utils.LogAttr("id", relay.SessionId)) - specs[relay.SpecId] = struct{}{} - } - - err = rws.rewardsTxSender.TxRelayPayment(ctx, failedRewardRequestsToRetry, strconv.FormatUint(rws.serverID, 10), rws.latestBlockReports(specs)) - if err != nil { - rws.updatePaymentRequestAttempt(failedRewardRequestsToRetry, false) - utils.LavaFormatError("failed sending previously failed payment requests", err) - } else { - rws.updatePaymentRequestAttempt(failedRewardRequestsToRetry, true) - } + } + failedRewardsToClaimChunks := lavaslices.SplitGenericSliceIntoChunks(failedRewardRequestsToRetry, splitRewardsIntoChunksSize) + failedRewardsLength := len(failedRewardsToClaimChunks) + if failedRewardsLength > 1 { + utils.LavaFormatDebug("Splitting Failed Reward claims into chunks", utils.LogAttr("chunk_size", splitRewardsIntoChunksSize), utils.LogAttr("number_of_chunks", failedRewardsLength)) } - rewardsToClaim, err := rws.gatherRewardsForClaim(ctx, epoch, earliestSavedEpoch) + // Handle new claims + gatheredRewardsToClaim, err := rws.gatherRewardsForClaim(ctx, epoch, earliestSavedEpoch) if err != nil { return err } - - specs := map[string]struct{}{} - for _, relay := range rewardsToClaim { - consumerAddr, err := sigs.ExtractSignerAddress(relay) - if err != nil { - utils.LavaFormatError("invalid consumer address extraction from relay", err, utils.Attribute{Key: "relay", Value: relay}) - continue - } - expectedPay := PaymentRequest{ - ChainID: relay.SpecId, - CU: relay.CuSum, - BlockHeightDeadline: relay.Epoch, - Amount: sdk.Coin{}, - Client: consumerAddr, - UniqueIdentifier: relay.SessionId, - Description: strconv.FormatUint(rws.serverID, 10), - ConsumerRewardsKey: getKeyForConsumerRewards(relay.SpecId, consumerAddr.String()), - } - rws.addExpectedPayment(expectedPay) - rws.updateCUServiced(relay.CuSum) - specs[relay.SpecId] = struct{}{} - } - if len(rewardsToClaim) > 0 { - err = rws.rewardsTxSender.TxRelayPayment(ctx, rewardsToClaim, strconv.FormatUint(rws.serverID, 10), rws.latestBlockReports(specs)) - if err != nil { - rws.updatePaymentRequestAttempt(rewardsToClaim, false) - return utils.LavaFormatError("failed sending rewards claim", err) + rewardsToClaimChunks := lavaslices.SplitGenericSliceIntoChunks(gatheredRewardsToClaim, splitRewardsIntoChunksSize) + newRewardsLength := len(rewardsToClaimChunks) + if newRewardsLength > 1 { + utils.LavaFormatDebug("Splitting Reward claims into chunks", utils.LogAttr("chunk_size", splitRewardsIntoChunksSize), utils.LogAttr("number_of_chunks", newRewardsLength)) + } + + // payment chunk configurations + paymentConfiguration := []*PaymentConfiguration{ + { // adding the new rewards. + relaySessionChunks: rewardsToClaimChunks, + shouldAddExpectedPayment: true, + }, + { // adding the failed rewards. + relaySessionChunks: failedRewardsToClaimChunks, + shouldAddExpectedPayment: false, + }, + } + + // add expected pay and ask for rewards + for _, paymentConfig := range paymentConfiguration { + for _, rewardsToClaim := range paymentConfig.relaySessionChunks { + if len(rewardsToClaim) == 0 { + if paymentConfig.shouldAddExpectedPayment { + utils.LavaFormatDebug("no new rewards to claim") + } else { + utils.LavaFormatDebug("no failed rewards to claim") + } + continue + } + go func(rewards []*pairingtypes.RelaySession, payment *PaymentConfiguration) { // send rewards asynchronously + specs := map[string]struct{}{} + if payment.shouldAddExpectedPayment { + for _, relay := range rewards { + consumerAddr, err := sigs.ExtractSignerAddress(relay) + if err != nil { + utils.LavaFormatError("invalid consumer address extraction from relay", err, utils.Attribute{Key: "relay", Value: relay}) + continue + } + expectedPay := PaymentRequest{ + ChainID: relay.SpecId, + CU: relay.CuSum, + BlockHeightDeadline: relay.Epoch, + Amount: sdk.Coin{}, + Client: consumerAddr, + UniqueIdentifier: relay.SessionId, + Description: strconv.FormatUint(rws.serverID, 10), + ConsumerRewardsKey: getKeyForConsumerRewards(relay.SpecId, consumerAddr.String()), + } + rws.addExpectedPayment(expectedPay) + rws.updateCUServiced(relay.CuSum) + specs[relay.SpecId] = struct{}{} + utils.LavaFormatDebug("Adding Payment for Spec", utils.LogAttr("spec", relay.SpecId), utils.LogAttr("Cu Sum", relay.CuSum), utils.LogAttr("epoch", relay.Epoch), utils.LogAttr("consumerAddr", consumerAddr), utils.LogAttr("number_of_relays_served", relay.RelayNum)) + } + } else { // just add the specs + for _, relay := range failedRewardRequestsToRetry { + utils.LavaFormatDebug("[sendRewardsClaim] retrying failed id", utils.LogAttr("id", relay.SessionId)) + specs[relay.SpecId] = struct{}{} + } + } + err = rws.rewardsTxSender.TxRelayPayment(ctx, rewards, strconv.FormatUint(rws.serverID, 10), rws.latestBlockReports(specs)) + if err != nil { + rws.updatePaymentRequestAttempt(rewards, false) + utils.LavaFormatError("failed sending rewards claim", err) + return + } + rws.updatePaymentRequestAttempt(rewards, true) + utils.LavaFormatDebug("Sent rewards claim", utils.Attribute{Key: "number_of_relay_sessions_sent", Value: len(rewards)}) + }(rewardsToClaim, paymentConfig) } - rws.updatePaymentRequestAttempt(rewardsToClaim, true) - - utils.LavaFormatDebug("Sent rewards claim", utils.Attribute{Key: "number_of_relay_sessions_sent", Value: len(rewardsToClaim)}) - } else { - utils.LavaFormatDebug("no rewards to claim") } return nil } @@ -444,14 +481,9 @@ func (rws *RewardServer) PaymentHandler(payment *PaymentRequest) { if !removedPayment { utils.LavaFormatWarning("tried removing payment that wasn't expected", nil, utils.Attribute{Key: "payment", Value: payment}) } - - utils.LavaFormatDebug("Reward Server detected successful payment request, deleting claimed rewards", utils.Attribute{Key: "payment-uid", Value: payment.UniqueIdentifier}) - err = rws.rewardDB.DeleteClaimedRewards(payment.PaymentEpoch, payment.Client.String(), payment.UniqueIdentifier, payment.ConsumerRewardsKey) if err != nil { utils.LavaFormatWarning("failed deleting claimed rewards", err) - } else { - utils.LavaFormatDebug("deleted claimed rewards successfully", utils.Attribute{Key: "payment-uid", Value: payment.UniqueIdentifier}) } } } @@ -621,13 +653,11 @@ func (rws *RewardServer) gatherFailedRequestPaymentsToRetry(earliestSavedEpoch u func (rws *RewardServer) updatePaymentRequestAttempt(paymentRequests []*pairingtypes.RelaySession, success bool) { rws.lock.Lock() defer rws.lock.Unlock() - for _, relaySession := range paymentRequests { sessionId := relaySession.SessionId sessionWithAttempts, found := rws.failedRewardsPaymentRequests[sessionId] if !found { if !success { - utils.LavaFormatDebug("Adding new session to failedRewardsPaymentRequests", utils.Attribute{Key: "sessionId", Value: sessionId}) rws.failedRewardsPaymentRequests[sessionId] = &RelaySessionsToRetryAttempts{ relaySession: relaySession, paymentRequestRetryAttempts: 1, @@ -637,7 +667,6 @@ func (rws *RewardServer) updatePaymentRequestAttempt(paymentRequests []*pairingt } if success { - utils.LavaFormatDebug("Removing session from failedRewardsPaymentRequests", utils.Attribute{Key: "sessionId", Value: sessionId}) delete(rws.failedRewardsPaymentRequests, sessionId) continue } @@ -648,7 +677,6 @@ func (rws *RewardServer) updatePaymentRequestAttempt(paymentRequests []*pairingt utils.Attribute{Key: "sessionIds", Value: sessionId}, utils.Attribute{Key: "maxRetriesAllowed", Value: MaxPaymentRequestsRetiresForSession}, ) - delete(rws.failedRewardsPaymentRequests, sessionId) rws.deleteRelaySessionFromRewardDB(relaySession) continue diff --git a/protocol/rpcprovider/rpcprovider_server.go b/protocol/rpcprovider/rpcprovider_server.go index 0a364c24a4..f4f9c396b3 100644 --- a/protocol/rpcprovider/rpcprovider_server.go +++ b/protocol/rpcprovider/rpcprovider_server.go @@ -25,9 +25,9 @@ import ( "github.com/lavanet/lava/protocol/provideroptimizer" "github.com/lavanet/lava/protocol/upgrade" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/protocopy" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" pairingtypes "github.com/lavanet/lava/x/pairing/types" spectypes "github.com/lavanet/lava/x/spec/types" grpc "google.golang.org/grpc" @@ -824,7 +824,7 @@ func (rpcps *RPCProviderServer) TryRelay(ctx context.Context, request *pairingty } // else: we updated the chain message to request the specific latestBlock we fetched earlier, so use the previously fetched latest block and hashes if proofBlock < modifiedReqBlock && proofBlock < request.RelayData.SeenBlock { // we requested with a newer block, but don't necessarily have the finaliziation proof, chaintracker might be behind - proofBlock = slices.Min([]int64{modifiedReqBlock, request.RelayData.SeenBlock}) + proofBlock = lavaslices.Min([]int64{modifiedReqBlock, request.RelayData.SeenBlock}) proofBlock, requestedHashes, err = rpcps.GetBlockDataForOptimisticFetch(ctx, relayTimeout, proofBlock, blockDistanceToFinalization, blocksInFinalizationData, averageBlockTime) if err != nil { @@ -864,7 +864,7 @@ func (rpcps *RPCProviderServer) GetBlockDataForOptimisticFetch(ctx context.Conte } timeSlept := 0 * time.Millisecond refreshTime := (averageBlockTime / chaintracker.MostFrequentPollingMultiplier) / 2 - sleepTime := slices.Min([]time.Duration{10 * refreshTime, timeCanWait, relayBaseTimeout / 2}) + sleepTime := lavaslices.Min([]time.Duration{10 * refreshTime, timeCanWait, relayBaseTimeout / 2}) sleepContext, cancel := context.WithTimeout(context.Background(), sleepTime) fetchedWithoutError := func() bool { timeSlept += refreshTime @@ -976,7 +976,7 @@ func (rpcps *RPCProviderServer) SleepUntilTimeOrConditionReached(ctx context.Con var sleeping time.Duration deadline, ok := ctx.Deadline() if ok { - sleeping = slices.Min([]time.Duration{queryTime, time.Until(deadline) / 4}) + sleeping = lavaslices.Min([]time.Duration{queryTime, time.Until(deadline) / 4}) } else { sleeping = queryTime } diff --git a/protocol/statetracker/tx_sender.go b/protocol/statetracker/tx_sender.go index be08f0ebd2..16791703bb 100644 --- a/protocol/statetracker/tx_sender.go +++ b/protocol/statetracker/tx_sender.go @@ -198,7 +198,7 @@ func (ts *TxSender) SendTxAndVerifyCommit(txfactory tx.Factory, msg sdk.Msg) (pa utils.LavaFormatDebug("transaction results", utils.Attribute{Key: "jsonParsedResult", Value: jsonParsedResult}) } resultData, err := common.ParseTransactionResult(jsonParsedResult) - utils.LavaFormatDebug("Sent Transaction", utils.LogAttr("Hash", hex.EncodeToString(resultData.Txhash))) + utils.LavaFormatInfo("Sent Transaction", utils.LogAttr("Hash", hex.EncodeToString(resultData.Txhash))) if err != nil { return common.TxResultData{}, err } @@ -218,6 +218,8 @@ func (ts *TxSender) waitForTxCommit(resultData common.TxResultData) (common.TxRe timeOutReached := false go func() { for { + // we will never catch the tx hash in the first attempt as not enough time have passed, so we sleep at the beginning of the loop + time.Sleep(5 * time.Second) if timeOutReached { utils.LavaFormatWarning("Timeout waiting for transaction", nil, utils.LogAttr("hash", resultData.Txhash)) return @@ -234,7 +236,6 @@ func (ts *TxSender) waitForTxCommit(resultData common.TxResultData) (common.TxRe if debug { utils.LavaFormatWarning("Tx query got error", err, utils.Attribute{Key: "GUID", Value: ctx}, utils.Attribute{Key: "resultData", Value: resultData}) } - time.Sleep(5 * time.Second) } }() select { diff --git a/protocol/statetracker/updaters/payment_updater.go b/protocol/statetracker/updaters/payment_updater.go index 5d25e78e70..fa285d3c19 100644 --- a/protocol/statetracker/updaters/payment_updater.go +++ b/protocol/statetracker/updaters/payment_updater.go @@ -4,6 +4,7 @@ import ( "sync" "github.com/lavanet/lava/protocol/rpcprovider/rewardserver" + "github.com/lavanet/lava/utils" "golang.org/x/net/context" ) @@ -43,12 +44,16 @@ func (pu *PaymentUpdater) updateInner() { if err != nil { return } + utils.LavaFormatDebug("Detected payment events", utils.Attribute{Key: "number_of_payment_events_detected", Value: len(payments)}) + relevantPayments := 0 for _, payment := range payments { updatable, foundUpdatable := pu.paymentUpdatable[payment.Description] if foundUpdatable { + relevantPayments += 1 (*updatable).PaymentHandler(payment) } } + utils.LavaFormatDebug("relevant payment events", utils.Attribute{Key: "number_of_relevant_payments_detected", Value: relevantPayments}) } func (pu *PaymentUpdater) Reset(latestBlock int64) { diff --git a/testutil/common/tester.go b/testutil/common/tester.go index edc59be163..8bd0f23de6 100644 --- a/testutil/common/tester.go +++ b/testutil/common/tester.go @@ -15,8 +15,8 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" testkeeper "github.com/lavanet/lava/testutil/keeper" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" dualstakingante "github.com/lavanet/lava/x/dualstaking/ante" dualstakingtypes "github.com/lavanet/lava/x/dualstaking/types" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" @@ -297,7 +297,7 @@ func NewCoin(tokenDenom string, amount int64) sdk.Coin { } func NewCoins(tokenDenom string, amount ...int64) []sdk.Coin { - return slices.Map(amount, func(a int64) sdk.Coin { return NewCoin(tokenDenom, a) }) + return lavaslices.Map(amount, func(a int64) sdk.Coin { return NewCoin(tokenDenom, a) }) } // keeper helpers @@ -648,7 +648,7 @@ func (ts *Tester) TxPairingRelayPayment(addr string, rs ...*pairingtypes.RelaySe func (ts *Tester) TxPairingFreezeProvider(addr, chainID string) (*pairingtypes.MsgFreezeProviderResponse, error) { msg := &pairingtypes.MsgFreezeProvider{ Creator: addr, - ChainIds: slices.Slice(chainID), + ChainIds: lavaslices.Slice(chainID), Reason: "test", } return ts.Servers.PairingServer.FreezeProvider(ts.GoCtx, msg) @@ -658,7 +658,7 @@ func (ts *Tester) TxPairingFreezeProvider(addr, chainID string) (*pairingtypes.M func (ts *Tester) TxPairingUnfreezeProvider(addr, chainID string) (*pairingtypes.MsgUnfreezeProviderResponse, error) { msg := &pairingtypes.MsgUnfreezeProvider{ Creator: addr, - ChainIds: slices.Slice(chainID), + ChainIds: lavaslices.Slice(chainID), } return ts.Servers.PairingServer.UnfreezeProvider(ts.GoCtx, msg) } diff --git a/utils/slices/slices.go b/utils/lavaslices/slices.go similarity index 83% rename from utils/slices/slices.go rename to utils/lavaslices/slices.go index c7e32a17e9..d93c41ee03 100644 --- a/utils/slices/slices.go +++ b/utils/lavaslices/slices.go @@ -1,6 +1,8 @@ -package slices +package lavaslices import ( + "math" + "golang.org/x/exp/constraints" "golang.org/x/exp/slices" ) @@ -261,3 +263,36 @@ func UnorderedEqual[T comparable](slices ...[]T) bool { return true } + +// splitSliceGeneric splits a slice into smaller slices of at most chunkSize length. +// for example len(arr) == 1400 and chunk size 500 will return [500, 500, 400] +func SplitGenericSliceIntoChunks[T any](arr []T, chunkSize int) [][]T { + var result [][]T + + // Calculate the number of chunks needed + numChunks := int(math.Ceil(float64(len(arr)) / float64(chunkSize))) + + // Iterate over the original slice and slice it into chunks + for i := 0; i < numChunks; i++ { + start := i * chunkSize + end := start + chunkSize + + // Ensure end doesn't exceed the length of the slice + if end > len(arr) { + end = len(arr) + } + + // Create a chunk with preallocated capacity + chunk := make([]T, 0, chunkSize) + + // Append elements to the chunk + for j := start; j < end; j++ { + chunk = append(chunk, arr[j]) + } + + // Append the chunk to the result slice + result = append(result, chunk) + } + + return result +} diff --git a/utils/slices/slices_test.go b/utils/lavaslices/slices_test.go similarity index 95% rename from utils/slices/slices_test.go rename to utils/lavaslices/slices_test.go index 1ed4ca363a..5101457b08 100644 --- a/utils/slices/slices_test.go +++ b/utils/lavaslices/slices_test.go @@ -1,4 +1,4 @@ -package slices +package lavaslices import ( "math" @@ -419,3 +419,25 @@ func TestFilter(t *testing.T) { require.Equal(t, []int{}, Filter([]int{1}, filter)) require.Equal(t, []int{2, 4}, Filter([]int{1, 2, 3, 4}, filter)) } + +func TestSliceSplitter(t *testing.T) { + // Sample usage + originalSliceSize := 1400 + testSlice := make([]int, originalSliceSize) // Assuming this is your original array + for i := 0; i < originalSliceSize; i++ { + testSlice[i] = i + } + testSizes := []int{500, 333, 200, 20, 1} + for _, i := range testSizes { + originalSizeCopy := originalSliceSize + retSlice := SplitGenericSliceIntoChunks(testSlice, i) + for _, k := range retSlice { + if originalSizeCopy < i { + require.Len(t, k, originalSizeCopy) + } else { + require.Len(t, k, i) + } + originalSizeCopy -= i + } + } +} diff --git a/x/conflict/keeper/msg_server_detection_test.go b/x/conflict/keeper/msg_server_detection_test.go index 2e512396e8..1a61d0bf84 100644 --- a/x/conflict/keeper/msg_server_detection_test.go +++ b/x/conflict/keeper/msg_server_detection_test.go @@ -7,8 +7,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" conflicttypes "github.com/lavanet/lava/x/conflict/types" conflictconstruct "github.com/lavanet/lava/x/conflict/types/construct" "github.com/lavanet/lava/x/pairing/types" @@ -182,5 +182,5 @@ func TestFrozenProviderDetection(t *testing.T) { require.NotEqual(t, 0, len(votersList)) // the frozen provider should not be part of the voters list - require.False(t, slices.Contains(votersList, frozenProvider)) + require.False(t, lavaslices.Contains(votersList, frozenProvider)) } diff --git a/x/dualstaking/keeper/delegate.go b/x/dualstaking/keeper/delegate.go index bd583f9614..76051250ea 100644 --- a/x/dualstaking/keeper/delegate.go +++ b/x/dualstaking/keeper/delegate.go @@ -24,7 +24,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/utils" - lavaslices "github.com/lavanet/lava/utils/slices" + lavaslices "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/dualstaking/types" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "golang.org/x/exp/slices" diff --git a/x/dualstaking/keeper/delegator_reward.go b/x/dualstaking/keeper/delegator_reward.go index 08f317e22d..81ca598be0 100644 --- a/x/dualstaking/keeper/delegator_reward.go +++ b/x/dualstaking/keeper/delegator_reward.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/dualstaking/types" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" spectypes "github.com/lavanet/lava/x/spec/types" @@ -207,7 +207,7 @@ func (k Keeper) RewardProvidersAndDelegators(ctx sdk.Context, providerAddr sdk.A } } - relevantDelegations := slices.Filter(delegations, + relevantDelegations := lavaslices.Filter(delegations, func(d types.Delegation) bool { return d.ChainID == chainID && d.IsFirstMonthPassed(ctx.BlockTime().UTC().Unix()) && d.Delegator != d.Provider }) diff --git a/x/dualstaking/types/delegate.go b/x/dualstaking/types/delegate.go index bac2fdefc5..96b4ce6572 100644 --- a/x/dualstaking/types/delegate.go +++ b/x/dualstaking/types/delegate.go @@ -5,7 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" ) func NewDelegation(delegator, provider, chainID string, blockTime time.Time, tokenDenom string) Delegation { @@ -51,14 +51,14 @@ func NewDelegator(delegator, provider string) Delegator { } func (delegator *Delegator) AddProvider(provider string) { - if !slices.Contains(delegator.Providers, provider) { + if !lavaslices.Contains(delegator.Providers, provider) { delegator.Providers = append(delegator.Providers, provider) } } func (delegator *Delegator) DelProvider(provider string) { - if slices.Contains(delegator.Providers, provider) { - delegator.Providers, _ = slices.Remove(delegator.Providers, provider) + if lavaslices.Contains(delegator.Providers, provider) { + delegator.Providers, _ = lavaslices.Remove(delegator.Providers, provider) } } diff --git a/x/pairing/keeper/cu_tracker_test.go b/x/pairing/keeper/cu_tracker_test.go index 9cd2273574..5546197446 100644 --- a/x/pairing/keeper/cu_tracker_test.go +++ b/x/pairing/keeper/cu_tracker_test.go @@ -8,8 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" testkeeper "github.com/lavanet/lava/testutil/keeper" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" "github.com/lavanet/lava/x/pairing/types" planstypes "github.com/lavanet/lava/x/plans/types" "github.com/stretchr/testify/require" @@ -87,7 +87,7 @@ func TestAddingTrackedCuWithoutPay(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider1Addr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -242,13 +242,13 @@ func TestTrackedCuWithQos(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider1, - Relays: slices.Slice(relaySession1), + Relays: lavaslices.Slice(relaySession1), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) relayPaymentMessage2 := types.MsgRelayPayment{ Creator: provider2, - Relays: slices.Slice(relaySession2), + Relays: lavaslices.Slice(relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage2, true) @@ -314,7 +314,7 @@ func TestTrackedCuMultipleChains(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider1, - Relays: slices.Slice(relaySession, relaySession1), + Relays: lavaslices.Slice(relaySession, relaySession1), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -327,7 +327,7 @@ func TestTrackedCuMultipleChains(t *testing.T) { relayPaymentMessage2 := types.MsgRelayPayment{ Creator: provider2, - Relays: slices.Slice(relaySession2), + Relays: lavaslices.Slice(relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage2, true) @@ -428,7 +428,7 @@ func TestProviderMonthlyPayoutQuery(t *testing.T) { relaySession2.Sig = sig relayPaymentMessage := types.MsgRelayPayment{ Creator: provider, - Relays: slices.Slice(relaySession, relaySession2), + Relays: lavaslices.Slice(relaySession, relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -446,7 +446,7 @@ func TestProviderMonthlyPayoutQuery(t *testing.T) { for _, p := range res.Details { details = append(details, *p) } - require.True(t, slices.UnorderedEqual(expectedPayouts, details)) + require.True(t, lavaslices.UnorderedEqual(expectedPayouts, details)) // check the expected subscrription payout subRes, err := ts.QueryPairingSubscriptionMonthlyPayout(client) @@ -555,7 +555,7 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { relaySession2.Sig = sig relayPaymentMessage := types.MsgRelayPayment{ Creator: provider, - Relays: slices.Slice(relaySession, relaySession2), + Relays: lavaslices.Slice(relaySession, relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -574,7 +574,7 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { for _, p := range res.Details { details = append(details, *p) } - require.True(t, slices.UnorderedEqual(expectedPayouts, details)) + require.True(t, lavaslices.UnorderedEqual(expectedPayouts, details)) // check the expected subscrription payout subRes, err := ts.QueryPairingSubscriptionMonthlyPayout(client) diff --git a/x/pairing/keeper/delegator_rewards_test.go b/x/pairing/keeper/delegator_rewards_test.go index 489dd79365..f0a14b222e 100644 --- a/x/pairing/keeper/delegator_rewards_test.go +++ b/x/pairing/keeper/delegator_rewards_test.go @@ -6,8 +6,8 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" dualstakingtypes "github.com/lavanet/lava/x/dualstaking/types" "github.com/lavanet/lava/x/pairing/types" subscriptiontypes "github.com/lavanet/lava/x/subscription/types" @@ -281,7 +281,7 @@ func TestProviderRewardWithCommission(t *testing.T) { // the expected reward for the provider with 100% commission is the total rewards (delegators get nothing) currentTimestamp := ts.Ctx.BlockTime().UTC().Unix() - relevantDelegations := slices.Filter(res.Delegations, + relevantDelegations := lavaslices.Filter(res.Delegations, func(d dualstakingtypes.Delegation) bool { return d.ChainID == ts.spec.Index && d.IsFirstMonthPassed(currentTimestamp) }) diff --git a/x/pairing/keeper/msg_server_relay_payment_gov_test.go b/x/pairing/keeper/msg_server_relay_payment_gov_test.go index 6fb969045b..0d397b3a7d 100644 --- a/x/pairing/keeper/msg_server_relay_payment_gov_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_gov_test.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" pairingtypes "github.com/lavanet/lava/x/pairing/types" "github.com/stretchr/testify/require" @@ -169,7 +169,7 @@ func TestRelayPaymentGovEpochBlocksDecrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -242,7 +242,7 @@ func TestRelayPaymentGovEpochBlocksIncrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -320,7 +320,7 @@ func TestRelayPaymentGovEpochToSaveDecrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, tt.valid, 100) @@ -390,7 +390,7 @@ func TestRelayPaymentGovEpochToSaveIncrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -471,7 +471,7 @@ func TestRelayPaymentGovEpochBlocksMultipleChanges(t *testing.T) { require.NoError(t, err) payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -514,7 +514,7 @@ func TestStakePaymentUnstake(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, true, 100) @@ -578,7 +578,7 @@ func TestRelayPaymentMemoryTransferAfterEpochChangeWithGovParamChange(t *testing payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, true) diff --git a/x/pairing/keeper/msg_server_relay_payment_test.go b/x/pairing/keeper/msg_server_relay_payment_test.go index 47c5663a57..4d475ca14f 100644 --- a/x/pairing/keeper/msg_server_relay_payment_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_test.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" commonconsts "github.com/lavanet/lava/testutil/common/consts" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" "github.com/lavanet/lava/x/pairing/types" planstypes "github.com/lavanet/lava/x/plans/types" projectstypes "github.com/lavanet/lava/x/projects/types" @@ -61,7 +61,7 @@ func TestRelayPaymentMemoryTransferAfterEpochChange(t *testing.T) { // Request payment (helper validates balances and verifies error through valid) relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -102,7 +102,7 @@ func TestRelayPaymentBlockHeight(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, tt.valid) @@ -291,7 +291,7 @@ func TestRelayPaymentDoubleSpending(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession, relaySession), + Relays: lavaslices.Slice(relaySession, relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, false, 100) @@ -391,7 +391,7 @@ func TestRelayPaymentOldEpochs(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, tt.valid) }) @@ -438,7 +438,7 @@ func TestRelayPaymentQoS(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, tt.valid) }) @@ -460,7 +460,7 @@ func TestEpochPaymentDeletion(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, true, 100) @@ -523,7 +523,7 @@ func TestCuUsageInProjectsAndSubscription(t *testing.T) { // Request payment (helper validates the balances and verifies expected errors through valid) relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -613,7 +613,7 @@ func TestBadgeValidation(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, tt.valid) @@ -720,7 +720,7 @@ func TestBadgeCuAllocationEnforcement(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, tt.valid) @@ -861,7 +861,7 @@ func TestBadgeDifferentProvidersCuAllocation(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: providers[i].Addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) diff --git a/x/pairing/keeper/pairing.go b/x/pairing/keeper/pairing.go index c94ac327b5..9c1a258c54 100644 --- a/x/pairing/keeper/pairing.go +++ b/x/pairing/keeper/pairing.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" pairingfilters "github.com/lavanet/lava/x/pairing/keeper/filters" pairingscores "github.com/lavanet/lava/x/pairing/keeper/scores" @@ -197,8 +197,8 @@ func (k Keeper) CalculateEffectiveSelectedProviders(policies []*planstypes.Polic } } - effectiveMode := slices.Max(selectedProvidersModeList) - effectiveSelectedProviders := slices.Intersection(selectedProvidersList...) + effectiveMode := lavaslices.Max(selectedProvidersModeList) + effectiveSelectedProviders := lavaslices.Intersection(selectedProvidersList...) return effectiveMode, effectiveSelectedProviders } @@ -255,13 +255,13 @@ func (k Keeper) CalculateEffectiveAllowedCuPerEpochFromPolicies(policies []*plan } } - effectiveTotalCuOfProject := slices.Min(policyTotalCuLimit) + effectiveTotalCuOfProject := lavaslices.Min(policyTotalCuLimit) cuLeftInProject := effectiveTotalCuOfProject - cuUsedInProject - effectiveEpochCuOfProject := slices.Min(policyEpochCuLimit) + effectiveEpochCuOfProject := lavaslices.Min(policyEpochCuLimit) slice := []uint64{effectiveEpochCuOfProject, cuLeftInProject, cuLeftInSubscription} - return slices.Min(slice), effectiveTotalCuOfProject + return lavaslices.Min(slice), effectiveTotalCuOfProject } func (k Keeper) ValidatePairingForClient(ctx sdk.Context, chainID string, providerAddress sdk.AccAddress, reqEpoch uint64, project projectstypes.Project) (isValidPairing bool, allowedCU uint64, pairedProviders []epochstoragetypes.StakeEntry, errorRet error) { diff --git a/x/pairing/keeper/pairing_immediately_test.go b/x/pairing/keeper/pairing_immediately_test.go index 1993268ad0..51a44fccb6 100644 --- a/x/pairing/keeper/pairing_immediately_test.go +++ b/x/pairing/keeper/pairing_immediately_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/lavanet/lava/testutil/common" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" projectTypes "github.com/lavanet/lava/x/projects/types" "github.com/stretchr/testify/require" ) @@ -50,7 +50,7 @@ func TestCreateProjectAddKey(t *testing.T) { projectData := projectTypes.ProjectData{ Name: "test", Enabled: true, - ProjectKeys: slices.Slice(projectTypes.ProjectDeveloperKey(dev1Addr)), + ProjectKeys: lavaslices.Slice(projectTypes.ProjectDeveloperKey(dev1Addr)), Policy: nil, } @@ -89,7 +89,7 @@ func TestAddKeyCreateProject(t *testing.T) { projectData := projectTypes.ProjectData{ Name: "test", Enabled: true, - ProjectKeys: slices.Slice(devkey), + ProjectKeys: lavaslices.Slice(devkey), Policy: nil, } diff --git a/x/pairing/keeper/pairing_subscription_test.go b/x/pairing/keeper/pairing_subscription_test.go index fded961ca7..45c79272b0 100644 --- a/x/pairing/keeper/pairing_subscription_test.go +++ b/x/pairing/keeper/pairing_subscription_test.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" planstypes "github.com/lavanet/lava/x/plans/types" projectstypes "github.com/lavanet/lava/x/projects/types" "github.com/stretchr/testify/require" @@ -25,7 +25,7 @@ func TestGetPairingForSubscription(t *testing.T) { Name: "project", Enabled: true, Policy: &ts.plan.PlanPolicy, - ProjectKeys: slices.Slice(projectstypes.ProjectDeveloperKey(dev1Addr)), + ProjectKeys: lavaslices.Slice(projectstypes.ProjectDeveloperKey(dev1Addr)), } err := ts.TxSubscriptionAddProject(client1Addr, projectData) require.NoError(t, err) @@ -75,7 +75,7 @@ func TestRelayPaymentSubscription(t *testing.T) { require.NoError(t, err) require.NotNil(t, sub.Sub) - policies := slices.Slice( + policies := lavaslices.Slice( proj.Project.AdminPolicy, proj.Project.SubscriptionPolicy, &ts.plan.PlanPolicy, @@ -112,7 +112,7 @@ func TestRelayPaymentSubscriptionCU(t *testing.T) { client1Acct, client1Addr := ts.GetAccount(common.CONSUMER, 0) dev1Acct, dev1Addr := ts.Account("dev1") - consumers := slices.Slice(client1Addr, dev1Addr) + consumers := lavaslices.Slice(client1Addr, dev1Addr) projectData := projectstypes.ProjectData{ Name: "proj_b", diff --git a/x/pairing/keeper/pairing_test.go b/x/pairing/keeper/pairing_test.go index 4483f9c275..426409aad7 100644 --- a/x/pairing/keeper/pairing_test.go +++ b/x/pairing/keeper/pairing_test.go @@ -10,8 +10,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" testkeeper "github.com/lavanet/lava/testutil/keeper" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" pairingscores "github.com/lavanet/lava/x/pairing/keeper/scores" "github.com/lavanet/lava/x/pairing/types" @@ -51,11 +51,11 @@ func TestPairingUniqueness(t *testing.T) { mapFunc := func(p epochstoragetypes.StakeEntry) string { return p.Address } - providerAddrs1 := slices.Map(pairing1.Providers, mapFunc) - providerAddrs2 := slices.Map(pairing2.Providers, mapFunc) + providerAddrs1 := lavaslices.Map(pairing1.Providers, mapFunc) + providerAddrs2 := lavaslices.Map(pairing2.Providers, mapFunc) require.Equal(t, len(pairing1.Providers), len(pairing2.Providers)) - require.False(t, slices.UnorderedEqual(providerAddrs1, providerAddrs2)) + require.False(t, lavaslices.UnorderedEqual(providerAddrs1, providerAddrs2)) ts.AdvanceEpoch() @@ -63,10 +63,10 @@ func TestPairingUniqueness(t *testing.T) { pairing11, err := ts.QueryPairingGetPairing(ts.spec.Index, sub1Addr) require.NoError(t, err) - providerAddrs11 := slices.Map(pairing11.Providers, mapFunc) + providerAddrs11 := lavaslices.Map(pairing11.Providers, mapFunc) require.Equal(t, len(pairing1.Providers), len(pairing11.Providers)) - require.False(t, slices.UnorderedEqual(providerAddrs1, providerAddrs11)) + require.False(t, lavaslices.UnorderedEqual(providerAddrs1, providerAddrs11)) // test that get pairing gives the same results for the whole epoch epochBlocks := ts.EpochBlocks() @@ -453,7 +453,7 @@ func TestAddonPairing(t *testing.T) { Addons: []string{mandatoryAddon.AddOn}, ApiInterfaces: []string{mandatoryAddon.ApiInterface}, }} - mandatoryAndMandatoryAddonSupportingEndpoints := slices.Concat( + mandatoryAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, mandatoryAddonSupportingEndpoints) optionalSupportingEndpoints := []epochstoragetypes.Endpoint{{ @@ -462,12 +462,12 @@ func TestAddonPairing(t *testing.T) { Addons: []string{optional.AddOn}, ApiInterfaces: []string{optional.ApiInterface}, }} - optionalAndMandatorySupportingEndpoints := slices.Concat( + optionalAndMandatorySupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalSupportingEndpoints) - optionalAndMandatoryAddonSupportingEndpoints := slices.Concat( + optionalAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryAddonSupportingEndpoints, optionalSupportingEndpoints) - allSupportingEndpoints := slices.Concat( + allSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalAndMandatoryAddonSupportingEndpoints) mandatoryAndOptionalSingleEndpoint := []epochstoragetypes.Endpoint{{ @@ -780,14 +780,14 @@ func TestSelectedProvidersPairing(t *testing.T) { count := countSelectedAddresses(providerAddresses1, expectedSelectedProviders[tt.expectedProviders]) require.GreaterOrEqual(t, count, len(providerAddresses1)/2) case "ALLOWED mode normal pairing", "DISABLED mode normal pairing": - require.False(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.False(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses1))) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses2))) case "EXCLUSIVE mode selected MaxProvidersToPair providers": - require.True(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses2))) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) case "EXCLUSIVE mode selected less than MaxProvidersToPair providers", "EXCLUSIVE mode selected less than MaxProvidersToPair different providers", @@ -795,24 +795,24 @@ func TestSelectedProvidersPairing(t *testing.T) { "EXCLUSIVE mode intersection between plan/proj policies", "EXCLUSIVE mode intersection between sub/proj policies", "EXCLUSIVE mode intersection between all policies": - require.True(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) require.Less(t, uint64(len(providerAddresses1)), maxProvidersToPair) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) case "EXCLUSIVE mode selected more than MaxProvidersToPair providers": - require.True(t, slices.IsSubset(providerAddresses1, expectedSelectedProviders[tt.expectedProviders])) - require.True(t, slices.IsSubset(providerAddresses2, expectedSelectedProviders[tt.expectedProviders])) + require.True(t, lavaslices.IsSubset(providerAddresses1, expectedSelectedProviders[tt.expectedProviders])) + require.True(t, lavaslices.IsSubset(providerAddresses2, expectedSelectedProviders[tt.expectedProviders])) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses1))) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses2))) case "EXCLUSIVE mode provider unstakes after first pairing": - require.False(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) - require.True(t, slices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses2)) + require.False(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) + require.True(t, lavaslices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses2)) case "EXCLUSIVE mode non-staked provider stakes after first pairing": - require.False(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses2)) - require.True(t, slices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses1)) + require.False(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses1)) } }) } @@ -1285,7 +1285,7 @@ func TestGeoSlotCalc(t *testing.T) { geoReqName := pairingscores.GeoReq{}.GetName() allGeos := planstypes.GetAllGeolocations() - maxGeo := slices.Max(allGeos) + maxGeo := lavaslices.Max(allGeos) // iterate over all possible geolocations, create a policy and calc slots // not checking 0 because there can never be a policy with geo=0 @@ -1786,7 +1786,7 @@ func TestExtensionAndAddonPairing(t *testing.T) { Addons: []string{mandatoryAddon.AddOn}, ApiInterfaces: []string{mandatoryAddon.ApiInterface}, }} - mandatoryAndMandatoryAddonSupportingEndpoints := slices.Concat( + mandatoryAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, mandatoryAddonSupportingEndpoints) optionalSupportingEndpoints := []epochstoragetypes.Endpoint{{ @@ -1795,12 +1795,12 @@ func TestExtensionAndAddonPairing(t *testing.T) { Addons: []string{optional.AddOn}, ApiInterfaces: []string{optional.ApiInterface}, }} - optionalAndMandatorySupportingEndpoints := slices.Concat( + optionalAndMandatorySupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalSupportingEndpoints) - optionalAndMandatoryAddonSupportingEndpoints := slices.Concat( + optionalAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryAddonSupportingEndpoints, optionalSupportingEndpoints) - allSupportingEndpoints := slices.Concat( + allSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalAndMandatoryAddonSupportingEndpoints) mandatoryAndOptionalSingleEndpoint := []epochstoragetypes.Endpoint{{ @@ -1851,7 +1851,7 @@ func TestExtensionAndAddonPairing(t *testing.T) { ApiInterfaces: []string{mandatoryAddon.ApiInterface}, Extensions: []string{"ext1"}, }} - mandatoryExtAndMandatoryAddonSupportingEndpoints := slices.Concat( + mandatoryExtAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryExtSupportingEndpoints, mandatoryExtAddonSupportingEndpoints) optionalExtSupportingEndpoints := []epochstoragetypes.Endpoint{{ @@ -1861,12 +1861,12 @@ func TestExtensionAndAddonPairing(t *testing.T) { ApiInterfaces: []string{optional.ApiInterface}, Extensions: []string{"ext1"}, }} - optionalExtAndMandatorySupportingEndpoints := slices.Concat( + optionalExtAndMandatorySupportingEndpoints := lavaslices.Concat( mandatoryExtSupportingEndpoints, optionalExtSupportingEndpoints) - optionalExtAndMandatoryAddonSupportingEndpoints := slices.Concat( + optionalExtAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryExtAddonSupportingEndpoints, optionalExtSupportingEndpoints) - allExtSupportingEndpoints := slices.Concat( + allExtSupportingEndpoints := lavaslices.Concat( mandatoryExtSupportingEndpoints, optionalExtAndMandatoryAddonSupportingEndpoints, mandatoryExt2AddonSupportingEndpoint) // mandatory err := ts.addProviderEndpoints(2, mandatoryExtSupportingEndpoints) // ext1 - 2 @@ -2215,7 +2215,7 @@ func TestPairingConsistency(t *testing.T) { currentPairingAddrs = append(currentPairingAddrs, res.Providers[i].Address) } - require.True(t, slices.UnorderedEqual(prevPairingAddrs, currentPairingAddrs)) + require.True(t, lavaslices.UnorderedEqual(prevPairingAddrs, currentPairingAddrs)) prevPairing = res.Providers } diff --git a/x/pairing/keeper/unresponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go index 9134143718..08469d8cb8 100644 --- a/x/pairing/keeper/unresponsive_provider_test.go +++ b/x/pairing/keeper/unresponsive_provider_test.go @@ -5,9 +5,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/rand" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/lavanet/lava/x/pairing/types" "github.com/stretchr/testify/require" @@ -108,7 +108,7 @@ func TestUnresponsivenessStressTest(t *testing.T) { require.NoError(t, err) relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddress, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // send relay payment and check the funds did transfer normally @@ -175,7 +175,7 @@ func TestFreezingProviderForUnresponsiveness(t *testing.T) { require.NoError(t, err) relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -233,7 +233,7 @@ func TestFreezingProviderForUnresponsivenessContinueComplainingAfterFreeze(t *te require.NoError(t, err) relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -260,7 +260,7 @@ func TestFreezingProviderForUnresponsivenessContinueComplainingAfterFreeze(t *te relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -327,7 +327,7 @@ func TestNotFreezingProviderForUnresponsivenessWithMinProviders(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(relayPaymentMessage, clients[clientIndex].Addr, provider0_addr, true, true, 100) diff --git a/x/plans/types/geolocation_test.go b/x/plans/types/geolocation_test.go index 2c4b41c9fa..5aad7095d8 100644 --- a/x/plans/types/geolocation_test.go +++ b/x/plans/types/geolocation_test.go @@ -3,7 +3,7 @@ package types_test import ( "testing" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" planstypes "github.com/lavanet/lava/x/plans/types" "github.com/stretchr/testify/require" ) @@ -19,7 +19,7 @@ func TestAllGeos(t *testing.T) { geosFromMap = append(geosFromMap, geo) } - require.True(t, slices.UnorderedEqual(geos, geosFromMap)) + require.True(t, lavaslices.UnorderedEqual(geos, geosFromMap)) } func TestGetGeoFromUint(t *testing.T) { diff --git a/x/plans/types/policy.go b/x/plans/types/policy.go index 6b108ee1c8..b562b2bc21 100644 --- a/x/plans/types/policy.go +++ b/x/plans/types/policy.go @@ -12,7 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/utils/decoder" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/mitchellh/mapstructure" ) @@ -185,7 +185,7 @@ func GetStrictestChainPolicyForSpec(chainID string, policies []*Policy) (chainPo continue } // previous policies and current policy change collection data, we need the union of both - requirements = slices.UnionByFunc(chainPolicyRequirements, requirements) + requirements = lavaslices.UnionByFunc(chainPolicyRequirements, requirements) } return ChainPolicy{ChainId: chainID, Requirements: requirements}, true diff --git a/x/rewards/client/cli/tx.go b/x/rewards/client/cli/tx.go index ff8d00261d..dc1d1f6e10 100644 --- a/x/rewards/client/cli/tx.go +++ b/x/rewards/client/cli/tx.go @@ -16,7 +16,7 @@ import ( govclient "github.com/cosmos/cosmos-sdk/x/gov/client" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/rewards/types" ) @@ -121,7 +121,7 @@ $ %s tx gov submit-legacy-proposal set-iprpc-data --min-cost 0ulava --add-subscr return err } for _, sub := range subsToRemove { - iprpcSubs, _ = slices.Remove(iprpcSubs, sub) + iprpcSubs, _ = lavaslices.Remove(iprpcSubs, sub) } deposit, err := sdk.ParseCoinsNormalized(args[0]) diff --git a/x/subscription/keeper/msg_server_auto_renewal.go b/x/subscription/keeper/msg_server_auto_renewal.go index c46091af05..ee1d82f556 100644 --- a/x/subscription/keeper/msg_server_auto_renewal.go +++ b/x/subscription/keeper/msg_server_auto_renewal.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/subscription/types" ) @@ -66,7 +66,7 @@ func (k msgServer) AutoRenewal(goCtx context.Context, msg *types.MsgAutoRenewal) } if len(plan.AllowedBuyers) != 0 { - if !slices.Contains(plan.AllowedBuyers, msg.Creator) { + if !lavaslices.Contains(plan.AllowedBuyers, msg.Creator) { allowedBuyers := strings.Join(plan.AllowedBuyers, ",") return nil, utils.LavaFormatWarning("cannot apply auto-renewal to subscription", fmt.Errorf("creator is not part of the allowed buyers list"), utils.LogAttr("creator", msg.Creator), diff --git a/x/subscription/keeper/subscription.go b/x/subscription/keeper/subscription.go index 66fba0d75f..54a052110f 100644 --- a/x/subscription/keeper/subscription.go +++ b/x/subscription/keeper/subscription.go @@ -9,7 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" planstypes "github.com/lavanet/lava/x/plans/types" projectstypes "github.com/lavanet/lava/x/projects/types" "github.com/lavanet/lava/x/subscription/types" @@ -176,7 +176,7 @@ func (k Keeper) verifySubscriptionBuyInputAndGetPlan(ctx sdk.Context, block uint } if len(plan.AllowedBuyers) != 0 { - if !slices.Contains(plan.AllowedBuyers, creator) { + if !lavaslices.Contains(plan.AllowedBuyers, creator) { allowedBuyers := strings.Join(plan.AllowedBuyers, ",") return nil, EMPTY_PLAN, utils.LavaFormatWarning("subscription buy input is invalid", fmt.Errorf("creator is not part of the allowed buyers list"), utils.LogAttr("creator", creator), @@ -311,7 +311,7 @@ func (k Keeper) renewSubscription(ctx sdk.Context, sub *types.Subscription) erro } if len(plan.AllowedBuyers) != 0 { - if !slices.Contains(plan.AllowedBuyers, sub.Creator) { + if !lavaslices.Contains(plan.AllowedBuyers, sub.Creator) { allowedBuyers := strings.Join(plan.AllowedBuyers, ",") return utils.LavaFormatWarning("cannot auto-renew subscription", fmt.Errorf("creator is not part of the allowed buyers list"), utils.LogAttr("creator", sub.Creator), From c2bb96ac653de341230e206175010ed5bd7da3ad Mon Sep 17 00:00:00 2001 From: Ran Mishael Date: Sun, 24 Mar 2024 17:17:36 +0100 Subject: [PATCH 2/3] splitting payments - fixed --- ecosystem/cache/handlers.go | 4 +- ecosystem/cache/server.go | 4 +- protocol/chaintracker/chain_tracker.go | 6 +- .../lavaprotocol/finalization_consensus.go | 4 +- protocol/lavaprotocol/response_builder.go | 4 +- .../lavasession/provider_session_manager.go | 4 +- protocol/monitoring/health_results.go | 8 +- .../provideroptimizer/provider_optimizer.go | 4 +- .../rpcprovider/rewardserver/reward_server.go | 143 +++++++++++------- protocol/rpcprovider/rpcprovider_server.go | 8 +- protocol/statetracker/tx_sender.go | 5 +- .../statetracker/updaters/payment_updater.go | 7 + .../pre_setups/init_lava_only_with_node.sh | 3 + testutil/common/tester.go | 8 +- utils/{slices => lavaslices}/slices.go | 37 ++++- utils/{slices => lavaslices}/slices_test.go | 24 ++- .../keeper/msg_server_detection_test.go | 4 +- x/dualstaking/keeper/delegate.go | 2 +- x/dualstaking/keeper/delegator_reward.go | 4 +- x/dualstaking/types/delegate.go | 8 +- x/pairing/keeper/cu_tracker_test.go | 20 +-- x/pairing/keeper/delegator_rewards_test.go | 4 +- .../msg_server_relay_payment_gov_test.go | 16 +- .../keeper/msg_server_relay_payment_test.go | 22 +-- x/pairing/keeper/pairing.go | 12 +- x/pairing/keeper/pairing_immediately_test.go | 6 +- x/pairing/keeper/pairing_subscription_test.go | 8 +- x/pairing/keeper/pairing_test.go | 66 ++++---- .../keeper/unresponsive_provider_test.go | 12 +- x/plans/types/geolocation_test.go | 4 +- x/plans/types/policy.go | 4 +- x/rewards/client/cli/tx.go | 4 +- .../keeper/msg_server_auto_renewal.go | 4 +- x/subscription/keeper/subscription.go | 6 +- 34 files changed, 289 insertions(+), 190 deletions(-) rename utils/{slices => lavaslices}/slices.go (83%) rename utils/{slices => lavaslices}/slices_test.go (95%) diff --git a/ecosystem/cache/handlers.go b/ecosystem/cache/handlers.go index a604894890..54c6e21de9 100644 --- a/ecosystem/cache/handlers.go +++ b/ecosystem/cache/handlers.go @@ -16,7 +16,7 @@ import ( "github.com/lavanet/lava/protocol/lavaprotocol" "github.com/lavanet/lava/protocol/parser" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" pairingtypes "github.com/lavanet/lava/x/pairing/types" spectypes "github.com/lavanet/lava/x/spec/types" emptypb "google.golang.org/protobuf/types/known/emptypb" @@ -128,7 +128,7 @@ func (s *RelayerCacheServer) GetRelay(ctx context.Context, relayCacheGet *pairin waitGroup.Wait() if err == nil { // in case we got a hit validate seen block of the reply. // validate that the response seen block is larger or equal to our expectations. - if cacheReply.SeenBlock < slices.Min([]int64{relayCacheGet.SeenBlock, relayCacheGet.RequestedBlock}) { // TODO unitest this. + if cacheReply.SeenBlock < lavaslices.Min([]int64{relayCacheGet.SeenBlock, relayCacheGet.RequestedBlock}) { // TODO unitest this. // Error, our reply seen block is not larger than our expectations, meaning we got an old response // this can happen only in the case relayCacheGet.SeenBlock < relayCacheGet.RequestedBlock // by setting the err variable we will get a cache miss, and the relay will continue to the node. diff --git a/ecosystem/cache/server.go b/ecosystem/cache/server.go index 4c801047ba..516bdec837 100644 --- a/ecosystem/cache/server.go +++ b/ecosystem/cache/server.go @@ -9,7 +9,7 @@ import ( "os/signal" "time" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/dgraph-io/ristretto" "github.com/improbable-eng/grpc-web/go/grpcweb" @@ -115,7 +115,7 @@ func (cs *CacheServer) Serve(ctx context.Context, func (cs *CacheServer) ExpirationForChain(averageBlockTimeForChain time.Duration) time.Duration { eighthBlock := averageBlockTimeForChain / 8 - return slices.Max([]time.Duration{eighthBlock, cs.ExpirationNonFinalized}) // return the maximum TTL between an eighth block and expiration + return lavaslices.Max([]time.Duration{eighthBlock, cs.ExpirationNonFinalized}) // return the maximum TTL between an eighth block and expiration } func Server( diff --git a/protocol/chaintracker/chain_tracker.go b/protocol/chaintracker/chain_tracker.go index 65aeae66ab..22ff149bb1 100644 --- a/protocol/chaintracker/chain_tracker.go +++ b/protocol/chaintracker/chain_tracker.go @@ -21,7 +21,7 @@ import ( "github.com/lavanet/lava/protocol/lavasession" "github.com/lavanet/lava/protocol/metrics" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" grpc "google.golang.org/grpc" @@ -467,8 +467,8 @@ func (ct *ChainTracker) updatePollingTimeBasedOnBlockGap(pollingTime time.Durati if blockGapsLen > PollingUpdateLength { // check we have enough samples // smaller times give more resolution to indentify changes, and also make block arrival predictions more optimistic // so we take a 0.33 percentile because we want to be on the safe side by have a smaller time than expected - percentileTime := slices.Percentile(ct.blockEventsGap, 0.33) - stability := slices.Stability(ct.blockEventsGap, percentileTime) + percentileTime := lavaslices.Percentile(ct.blockEventsGap, 0.33) + stability := lavaslices.Stability(ct.blockEventsGap, percentileTime) if debug { utils.LavaFormatDebug("block gaps", utils.Attribute{Key: "block gaps", Value: ct.blockEventsGap}, utils.Attribute{Key: "specID", Value: ct.endpoint.ChainID}) } diff --git a/protocol/lavaprotocol/finalization_consensus.go b/protocol/lavaprotocol/finalization_consensus.go index 3351afdf82..88107fecff 100644 --- a/protocol/lavaprotocol/finalization_consensus.go +++ b/protocol/lavaprotocol/finalization_consensus.go @@ -9,7 +9,7 @@ import ( "github.com/lavanet/lava/protocol/chainlib" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" conflicttypes "github.com/lavanet/lava/x/conflict/types" pairingtypes "github.com/lavanet/lava/x/pairing/types" ) @@ -251,7 +251,7 @@ func (fc *FinalizationConsensus) ExpectedBlockHeight(chainParser chainlib.ChainP data[i] = latestBlock i++ } - return slices.Median(data) + return lavaslices.Median(data) } medianOfExpectedBlocks := median(mapExpectedBlockHeights) providersMedianOfLatestBlock := medianOfExpectedBlocks + int64(blockDistanceForFinalizedData) diff --git a/protocol/lavaprotocol/response_builder.go b/protocol/lavaprotocol/response_builder.go index a6f472278d..cf24891477 100644 --- a/protocol/lavaprotocol/response_builder.go +++ b/protocol/lavaprotocol/response_builder.go @@ -8,8 +8,8 @@ import ( btcSecp256k1 "github.com/btcsuite/btcd/btcec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" conflicttypes "github.com/lavanet/lava/x/conflict/types" pairingtypes "github.com/lavanet/lava/x/pairing/types" spectypes "github.com/lavanet/lava/x/spec/types" @@ -87,7 +87,7 @@ func VerifyFinalizationData(reply *pairingtypes.RelayReply, relayRequest *pairin providerLatestBlock := reply.LatestBlock seenBlock := relayRequest.RelayData.SeenBlock requestBlock := relayRequest.RelayData.RequestBlock - if providerLatestBlock < slices.Min([]int64{seenBlock, requestBlock}) { + if providerLatestBlock < lavaslices.Min([]int64{seenBlock, requestBlock}) { return nil, nil, utils.LavaFormatError("provider response does not meet consistency requirements", ProviderFinzalizationDataError, utils.LogAttr("ProviderAddress", relayRequest.RelaySession.Provider), utils.LogAttr("providerLatestBlock", providerLatestBlock), utils.LogAttr("seenBlock", seenBlock), utils.LogAttr("requestBlock", requestBlock), utils.Attribute{Key: "provider address", Value: providerAddr}) } return finalizedBlocks, finalizationConflict, errRet diff --git a/protocol/lavasession/provider_session_manager.go b/protocol/lavasession/provider_session_manager.go index 72854cfe62..c7042fca09 100644 --- a/protocol/lavasession/provider_session_manager.go +++ b/protocol/lavasession/provider_session_manager.go @@ -6,7 +6,7 @@ import ( "sync/atomic" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" pairingtypes "github.com/lavanet/lava/x/pairing/types" ) @@ -109,7 +109,7 @@ func getBadgeEpochDataFromProviderSessionWithConsumer(badgeUser string, provider func registerBadgeEpochDataToProviderSessionWithConsumer(badgeUser string, badgeCuAllocation uint64, providerSessionsWithConsumer *ProviderSessionsWithConsumerProject) *ProviderSessionsEpochData { providerSessionsWithConsumer.Lock.Lock() defer providerSessionsWithConsumer.Lock.Unlock() - providerSessionsWithConsumer.badgeEpochData[badgeUser] = &ProviderSessionsEpochData{MaxComputeUnits: slices.Min([]uint64{providerSessionsWithConsumer.epochData.MaxComputeUnits, badgeCuAllocation})} + providerSessionsWithConsumer.badgeEpochData[badgeUser] = &ProviderSessionsEpochData{MaxComputeUnits: lavaslices.Min([]uint64{providerSessionsWithConsumer.epochData.MaxComputeUnits, badgeCuAllocation})} return providerSessionsWithConsumer.badgeEpochData[badgeUser] } diff --git a/protocol/monitoring/health_results.go b/protocol/monitoring/health_results.go index 9cb0632185..7f135a641b 100644 --- a/protocol/monitoring/health_results.go +++ b/protocol/monitoring/health_results.go @@ -5,7 +5,7 @@ import ( "time" "github.com/lavanet/lava/protocol/common" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" spectypes "github.com/lavanet/lava/x/spec/types" ) @@ -88,7 +88,7 @@ func (healthResults *HealthResults) updateLatestBlock(specId string, latestBlock if !ok { healthResults.LatestBlocks[specId] = latestBlock } else { - healthResults.LatestBlocks[specId] = slices.Max([]int64{existing, latestBlock}) + healthResults.LatestBlocks[specId] = lavaslices.Max([]int64{existing, latestBlock}) } } @@ -150,9 +150,9 @@ func (healthResults *HealthResults) SetProviderData(providerKey LavaEntity, late if existing.Block == 0 { existing.Block = latestData.Block } else { - latestData.Block = slices.Min([]int64{existing.Block, latestData.Block}) + latestData.Block = lavaslices.Min([]int64{existing.Block, latestData.Block}) } - latestData.Latency = slices.Max([]time.Duration{existing.Latency, latestData.Latency}) + latestData.Latency = lavaslices.Max([]time.Duration{existing.Latency, latestData.Latency}) } healthResults.ProviderData[providerKey] = latestData } diff --git a/protocol/provideroptimizer/provider_optimizer.go b/protocol/provideroptimizer/provider_optimizer.go index e78d7d1b6b..9ffd9d923c 100644 --- a/protocol/provideroptimizer/provider_optimizer.go +++ b/protocol/provideroptimizer/provider_optimizer.go @@ -10,9 +10,9 @@ import ( "github.com/dgraph-io/ristretto" "github.com/lavanet/lava/protocol/common" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/rand" "github.com/lavanet/lava/utils/score" - "github.com/lavanet/lava/utils/slices" pairingtypes "github.com/lavanet/lava/x/pairing/types" "gonum.org/v1/gonum/mathext" ) @@ -188,7 +188,7 @@ func (po *ProviderOptimizer) calculateSyncLag(latestSync uint64, timeSync time.T } // lag on first block timeLag := sampleTime.Sub(timeSync) // received the latest block at time X, this provider provided the entry at time Y, which is X-Y time after - firstBlockLag := slices.Min([]time.Duration{po.averageBlockTime, timeLag}) + firstBlockLag := lavaslices.Min([]time.Duration{po.averageBlockTime, timeLag}) blocksGap := latestSync - providerBlock - 1 // latestSync > providerBlock blocksGapTime := time.Duration(blocksGap) * po.averageBlockTime // the provider is behind by X blocks, so is expected to catch up in averageBlockTime * X timeLag = firstBlockLag + blocksGapTime diff --git a/protocol/rpcprovider/rewardserver/reward_server.go b/protocol/rpcprovider/rewardserver/reward_server.go index 7fdc0f24d1..295947492f 100644 --- a/protocol/rpcprovider/rewardserver/reward_server.go +++ b/protocol/rpcprovider/rewardserver/reward_server.go @@ -15,6 +15,7 @@ import ( "github.com/lavanet/lava/protocol/lavasession" "github.com/lavanet/lava/protocol/metrics" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/rand" "github.com/lavanet/lava/utils/sigs" pairingtypes "github.com/lavanet/lava/x/pairing/types" @@ -32,6 +33,8 @@ const ( DefaultRewardsSnapshotTimeoutSec = 30 MaxPaymentRequestsRetiresForSession = 3 RewardServerMaxRelayRetires = 3 + splitRewardsIntoChunksSize = 500 // if the reward array is larger than this it will split it into chunks and send multiple requests instead of a huge one + debug = false ) type PaymentRequest struct { @@ -58,8 +61,8 @@ type ConsumerRewards struct { } func (csrw *ConsumerRewards) PrepareRewardsForClaim() (retProofs []*pairingtypes.RelaySession, errRet error) { + utils.LavaFormatDebug("Adding reward ids for claim", utils.LogAttr("number_of_proofs", len(csrw.proofs))) for _, proof := range csrw.proofs { - utils.LavaFormatDebug("Adding reward id for claim", utils.LogAttr("Id", proof.SessionId)) retProofs = append(retProofs, proof) } return @@ -75,6 +78,11 @@ type RelaySessionsToRetryAttempts struct { paymentRequestRetryAttempts uint64 } +type PaymentConfiguration struct { + relaySessionChunks [][]*pairingtypes.RelaySession // small chunks of relay session to request payments for + shouldAddExpectedPayment bool +} + type RewardServer struct { rewardsTxSender RewardsTxSender lock sync.RWMutex @@ -223,61 +231,93 @@ func (rws *RewardServer) sendRewardsClaim(ctx context.Context, epoch uint64) err return utils.LavaFormatError("sendRewardsClaim failed to get earliest block in memory", err) } + // Handle Failed rewards claim with retry failedRewardRequestsToRetry := rws.gatherFailedRequestPaymentsToRetry(earliestSavedEpoch) if len(failedRewardRequestsToRetry) > 0 { utils.LavaFormatDebug("Found failed reward claims, retrying", utils.LogAttr("number_of_rewards", len((failedRewardRequestsToRetry)))) - specs := map[string]struct{}{} - for _, relay := range failedRewardRequestsToRetry { - utils.LavaFormatDebug("[sendRewardsClaim] retrying failed id", utils.LogAttr("id", relay.SessionId)) - specs[relay.SpecId] = struct{}{} - } - - err = rws.rewardsTxSender.TxRelayPayment(ctx, failedRewardRequestsToRetry, strconv.FormatUint(rws.serverID, 10), rws.latestBlockReports(specs)) - if err != nil { - rws.updatePaymentRequestAttempt(failedRewardRequestsToRetry, false) - utils.LavaFormatError("failed sending previously failed payment requests", err) - } else { - rws.updatePaymentRequestAttempt(failedRewardRequestsToRetry, true) - } + } + failedRewardsToClaimChunks := lavaslices.SplitGenericSliceIntoChunks(failedRewardRequestsToRetry, splitRewardsIntoChunksSize) + failedRewardsLength := len(failedRewardsToClaimChunks) + if failedRewardsLength > 1 { + utils.LavaFormatDebug("Splitting Failed Reward claims into chunks", utils.LogAttr("chunk_size", splitRewardsIntoChunksSize), utils.LogAttr("number_of_chunks", failedRewardsLength)) } - rewardsToClaim, err := rws.gatherRewardsForClaim(ctx, epoch, earliestSavedEpoch) + // Handle new claims + gatheredRewardsToClaim, err := rws.gatherRewardsForClaim(ctx, epoch, earliestSavedEpoch) if err != nil { return err } - - specs := map[string]struct{}{} - for _, relay := range rewardsToClaim { - consumerAddr, err := sigs.ExtractSignerAddress(relay) - if err != nil { - utils.LavaFormatError("invalid consumer address extraction from relay", err, utils.Attribute{Key: "relay", Value: relay}) - continue - } - expectedPay := PaymentRequest{ - ChainID: relay.SpecId, - CU: relay.CuSum, - BlockHeightDeadline: relay.Epoch, - Amount: sdk.Coin{}, - Client: consumerAddr, - UniqueIdentifier: relay.SessionId, - Description: strconv.FormatUint(rws.serverID, 10), - ConsumerRewardsKey: getKeyForConsumerRewards(relay.SpecId, consumerAddr.String()), - } - rws.addExpectedPayment(expectedPay) - rws.updateCUServiced(relay.CuSum) - specs[relay.SpecId] = struct{}{} - } - if len(rewardsToClaim) > 0 { - err = rws.rewardsTxSender.TxRelayPayment(ctx, rewardsToClaim, strconv.FormatUint(rws.serverID, 10), rws.latestBlockReports(specs)) - if err != nil { - rws.updatePaymentRequestAttempt(rewardsToClaim, false) - return utils.LavaFormatError("failed sending rewards claim", err) + rewardsToClaimChunks := lavaslices.SplitGenericSliceIntoChunks(gatheredRewardsToClaim, splitRewardsIntoChunksSize) + newRewardsLength := len(rewardsToClaimChunks) + if newRewardsLength > 1 { + utils.LavaFormatDebug("Splitting Reward claims into chunks", utils.LogAttr("chunk_size", splitRewardsIntoChunksSize), utils.LogAttr("number_of_chunks", newRewardsLength)) + } + + // payment chunk configurations + paymentConfiguration := []*PaymentConfiguration{ + { // adding the new rewards. + relaySessionChunks: rewardsToClaimChunks, + shouldAddExpectedPayment: true, + }, + { // adding the failed rewards. + relaySessionChunks: failedRewardsToClaimChunks, + shouldAddExpectedPayment: false, + }, + } + + // add expected pay and ask for rewards + for _, paymentConfig := range paymentConfiguration { + for _, rewardsToClaim := range paymentConfig.relaySessionChunks { + if len(rewardsToClaim) == 0 { + if paymentConfig.shouldAddExpectedPayment { + utils.LavaFormatDebug("no new rewards to claim") + } else { + utils.LavaFormatDebug("no failed rewards to claim") + } + continue + } + go func(rewards []*pairingtypes.RelaySession, payment *PaymentConfiguration) { // send rewards asynchronously + specs := map[string]struct{}{} + if payment.shouldAddExpectedPayment { + for _, relay := range rewards { + consumerAddr, err := sigs.ExtractSignerAddress(relay) + if err != nil { + utils.LavaFormatError("invalid consumer address extraction from relay", err, utils.Attribute{Key: "relay", Value: relay}) + continue + } + expectedPay := PaymentRequest{ + ChainID: relay.SpecId, + CU: relay.CuSum, + BlockHeightDeadline: relay.Epoch, + Amount: sdk.Coin{}, + Client: consumerAddr, + UniqueIdentifier: relay.SessionId, + Description: strconv.FormatUint(rws.serverID, 10), + ConsumerRewardsKey: getKeyForConsumerRewards(relay.SpecId, consumerAddr.String()), + } + rws.addExpectedPayment(expectedPay) + rws.updateCUServiced(relay.CuSum) + specs[relay.SpecId] = struct{}{} + if debug { + utils.LavaFormatDebug("Adding Payment for Spec", utils.LogAttr("spec", relay.SpecId), utils.LogAttr("Cu Sum", relay.CuSum), utils.LogAttr("epoch", relay.Epoch), utils.LogAttr("consumerAddr", consumerAddr), utils.LogAttr("number_of_relays_served", relay.RelayNum), utils.LogAttr("sessionId", relay.SessionId)) + } + } + } else { // just add the specs + for _, relay := range failedRewardRequestsToRetry { + utils.LavaFormatDebug("[sendRewardsClaim] retrying failed id", utils.LogAttr("id", relay.SessionId)) + specs[relay.SpecId] = struct{}{} + } + } + err = rws.rewardsTxSender.TxRelayPayment(ctx, rewards, strconv.FormatUint(rws.serverID, 10), rws.latestBlockReports(specs)) + if err != nil { + rws.updatePaymentRequestAttempt(rewards, false) + utils.LavaFormatError("failed sending rewards claim", err) + return + } + rws.updatePaymentRequestAttempt(rewards, true) + utils.LavaFormatDebug("Sent rewards claim", utils.Attribute{Key: "number_of_relay_sessions_sent", Value: len(rewards)}) + }(rewardsToClaim, paymentConfig) } - rws.updatePaymentRequestAttempt(rewardsToClaim, true) - - utils.LavaFormatDebug("Sent rewards claim", utils.Attribute{Key: "number_of_relay_sessions_sent", Value: len(rewardsToClaim)}) - } else { - utils.LavaFormatDebug("no rewards to claim") } return nil } @@ -444,14 +484,9 @@ func (rws *RewardServer) PaymentHandler(payment *PaymentRequest) { if !removedPayment { utils.LavaFormatWarning("tried removing payment that wasn't expected", nil, utils.Attribute{Key: "payment", Value: payment}) } - - utils.LavaFormatDebug("Reward Server detected successful payment request, deleting claimed rewards", utils.Attribute{Key: "payment-uid", Value: payment.UniqueIdentifier}) - err = rws.rewardDB.DeleteClaimedRewards(payment.PaymentEpoch, payment.Client.String(), payment.UniqueIdentifier, payment.ConsumerRewardsKey) if err != nil { utils.LavaFormatWarning("failed deleting claimed rewards", err) - } else { - utils.LavaFormatDebug("deleted claimed rewards successfully", utils.Attribute{Key: "payment-uid", Value: payment.UniqueIdentifier}) } } } @@ -621,13 +656,11 @@ func (rws *RewardServer) gatherFailedRequestPaymentsToRetry(earliestSavedEpoch u func (rws *RewardServer) updatePaymentRequestAttempt(paymentRequests []*pairingtypes.RelaySession, success bool) { rws.lock.Lock() defer rws.lock.Unlock() - for _, relaySession := range paymentRequests { sessionId := relaySession.SessionId sessionWithAttempts, found := rws.failedRewardsPaymentRequests[sessionId] if !found { if !success { - utils.LavaFormatDebug("Adding new session to failedRewardsPaymentRequests", utils.Attribute{Key: "sessionId", Value: sessionId}) rws.failedRewardsPaymentRequests[sessionId] = &RelaySessionsToRetryAttempts{ relaySession: relaySession, paymentRequestRetryAttempts: 1, @@ -637,7 +670,6 @@ func (rws *RewardServer) updatePaymentRequestAttempt(paymentRequests []*pairingt } if success { - utils.LavaFormatDebug("Removing session from failedRewardsPaymentRequests", utils.Attribute{Key: "sessionId", Value: sessionId}) delete(rws.failedRewardsPaymentRequests, sessionId) continue } @@ -648,7 +680,6 @@ func (rws *RewardServer) updatePaymentRequestAttempt(paymentRequests []*pairingt utils.Attribute{Key: "sessionIds", Value: sessionId}, utils.Attribute{Key: "maxRetriesAllowed", Value: MaxPaymentRequestsRetiresForSession}, ) - delete(rws.failedRewardsPaymentRequests, sessionId) rws.deleteRelaySessionFromRewardDB(relaySession) continue diff --git a/protocol/rpcprovider/rpcprovider_server.go b/protocol/rpcprovider/rpcprovider_server.go index 0a364c24a4..f4f9c396b3 100644 --- a/protocol/rpcprovider/rpcprovider_server.go +++ b/protocol/rpcprovider/rpcprovider_server.go @@ -25,9 +25,9 @@ import ( "github.com/lavanet/lava/protocol/provideroptimizer" "github.com/lavanet/lava/protocol/upgrade" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/protocopy" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" pairingtypes "github.com/lavanet/lava/x/pairing/types" spectypes "github.com/lavanet/lava/x/spec/types" grpc "google.golang.org/grpc" @@ -824,7 +824,7 @@ func (rpcps *RPCProviderServer) TryRelay(ctx context.Context, request *pairingty } // else: we updated the chain message to request the specific latestBlock we fetched earlier, so use the previously fetched latest block and hashes if proofBlock < modifiedReqBlock && proofBlock < request.RelayData.SeenBlock { // we requested with a newer block, but don't necessarily have the finaliziation proof, chaintracker might be behind - proofBlock = slices.Min([]int64{modifiedReqBlock, request.RelayData.SeenBlock}) + proofBlock = lavaslices.Min([]int64{modifiedReqBlock, request.RelayData.SeenBlock}) proofBlock, requestedHashes, err = rpcps.GetBlockDataForOptimisticFetch(ctx, relayTimeout, proofBlock, blockDistanceToFinalization, blocksInFinalizationData, averageBlockTime) if err != nil { @@ -864,7 +864,7 @@ func (rpcps *RPCProviderServer) GetBlockDataForOptimisticFetch(ctx context.Conte } timeSlept := 0 * time.Millisecond refreshTime := (averageBlockTime / chaintracker.MostFrequentPollingMultiplier) / 2 - sleepTime := slices.Min([]time.Duration{10 * refreshTime, timeCanWait, relayBaseTimeout / 2}) + sleepTime := lavaslices.Min([]time.Duration{10 * refreshTime, timeCanWait, relayBaseTimeout / 2}) sleepContext, cancel := context.WithTimeout(context.Background(), sleepTime) fetchedWithoutError := func() bool { timeSlept += refreshTime @@ -976,7 +976,7 @@ func (rpcps *RPCProviderServer) SleepUntilTimeOrConditionReached(ctx context.Con var sleeping time.Duration deadline, ok := ctx.Deadline() if ok { - sleeping = slices.Min([]time.Duration{queryTime, time.Until(deadline) / 4}) + sleeping = lavaslices.Min([]time.Duration{queryTime, time.Until(deadline) / 4}) } else { sleeping = queryTime } diff --git a/protocol/statetracker/tx_sender.go b/protocol/statetracker/tx_sender.go index be08f0ebd2..16791703bb 100644 --- a/protocol/statetracker/tx_sender.go +++ b/protocol/statetracker/tx_sender.go @@ -198,7 +198,7 @@ func (ts *TxSender) SendTxAndVerifyCommit(txfactory tx.Factory, msg sdk.Msg) (pa utils.LavaFormatDebug("transaction results", utils.Attribute{Key: "jsonParsedResult", Value: jsonParsedResult}) } resultData, err := common.ParseTransactionResult(jsonParsedResult) - utils.LavaFormatDebug("Sent Transaction", utils.LogAttr("Hash", hex.EncodeToString(resultData.Txhash))) + utils.LavaFormatInfo("Sent Transaction", utils.LogAttr("Hash", hex.EncodeToString(resultData.Txhash))) if err != nil { return common.TxResultData{}, err } @@ -218,6 +218,8 @@ func (ts *TxSender) waitForTxCommit(resultData common.TxResultData) (common.TxRe timeOutReached := false go func() { for { + // we will never catch the tx hash in the first attempt as not enough time have passed, so we sleep at the beginning of the loop + time.Sleep(5 * time.Second) if timeOutReached { utils.LavaFormatWarning("Timeout waiting for transaction", nil, utils.LogAttr("hash", resultData.Txhash)) return @@ -234,7 +236,6 @@ func (ts *TxSender) waitForTxCommit(resultData common.TxResultData) (common.TxRe if debug { utils.LavaFormatWarning("Tx query got error", err, utils.Attribute{Key: "GUID", Value: ctx}, utils.Attribute{Key: "resultData", Value: resultData}) } - time.Sleep(5 * time.Second) } }() select { diff --git a/protocol/statetracker/updaters/payment_updater.go b/protocol/statetracker/updaters/payment_updater.go index 5d25e78e70..d746d3ce55 100644 --- a/protocol/statetracker/updaters/payment_updater.go +++ b/protocol/statetracker/updaters/payment_updater.go @@ -4,6 +4,7 @@ import ( "sync" "github.com/lavanet/lava/protocol/rpcprovider/rewardserver" + "github.com/lavanet/lava/utils" "golang.org/x/net/context" ) @@ -43,12 +44,18 @@ func (pu *PaymentUpdater) updateInner() { if err != nil { return } + + relevantPayments := 0 for _, payment := range payments { updatable, foundUpdatable := pu.paymentUpdatable[payment.Description] if foundUpdatable { + relevantPayments += 1 (*updatable).PaymentHandler(payment) } } + if len(payments) > 0 { + utils.LavaFormatDebug("relevant payment events", utils.Attribute{Key: "number_of_payment_events_detected", Value: len(payments)}, utils.Attribute{Key: "number_of_relevant_payments_detected", Value: relevantPayments}) + } } func (pu *PaymentUpdater) Reset(latestBlock int64) { diff --git a/scripts/pre_setups/init_lava_only_with_node.sh b/scripts/pre_setups/init_lava_only_with_node.sh index fb1e65cc25..ee1ceb2099 100755 --- a/scripts/pre_setups/init_lava_only_with_node.sh +++ b/scripts/pre_setups/init_lava_only_with_node.sh @@ -45,6 +45,7 @@ wait_next_block lavad tx pairing stake-provider "LAV1" $PROVIDERSTAKE "$PROVIDER1_LISTENER,1" 1 $(operator_address) -y --from servicer1 --delegate-limit 1000ulava --provider-moniker "dummyMoniker" --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE sleep_until_next_epoch +wait_next_block screen -d -m -S provider1 bash -c "source ~/.bashrc; lavap rpcprovider \ $PROVIDER1_LISTENER LAV1 rest '$LAVA_REST' \ @@ -52,6 +53,8 @@ $PROVIDER1_LISTENER LAV1 tendermintrpc '$LAVA_RPC,$LAVA_RPC' \ $PROVIDER1_LISTENER LAV1 grpc '$LAVA_GRPC' \ $EXTRA_PROVIDER_FLAGS --geolocation 1 --log_level debug --from servicer1 --chain-id lava --metrics-listen-address ":7776" 2>&1 | tee $LOGS_DIR/PROVIDER1.log" && sleep 0.25 +wait_next_block + screen -d -m -S consumers bash -c "source ~/.bashrc; lavap rpcconsumer \ 127.0.0.1:3360 LAV1 rest 127.0.0.1:3361 LAV1 tendermintrpc 127.0.0.1:3362 LAV1 grpc \ $EXTRA_PORTAL_FLAGS --geolocation 1 --log_level debug --from user1 --chain-id lava --allow-insecure-provider-dialing --metrics-listen-address ":7779" 2>&1 | tee $LOGS_DIR/CONSUMERS.log" && sleep 0.25 diff --git a/testutil/common/tester.go b/testutil/common/tester.go index edc59be163..8bd0f23de6 100644 --- a/testutil/common/tester.go +++ b/testutil/common/tester.go @@ -15,8 +15,8 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" testkeeper "github.com/lavanet/lava/testutil/keeper" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" dualstakingante "github.com/lavanet/lava/x/dualstaking/ante" dualstakingtypes "github.com/lavanet/lava/x/dualstaking/types" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" @@ -297,7 +297,7 @@ func NewCoin(tokenDenom string, amount int64) sdk.Coin { } func NewCoins(tokenDenom string, amount ...int64) []sdk.Coin { - return slices.Map(amount, func(a int64) sdk.Coin { return NewCoin(tokenDenom, a) }) + return lavaslices.Map(amount, func(a int64) sdk.Coin { return NewCoin(tokenDenom, a) }) } // keeper helpers @@ -648,7 +648,7 @@ func (ts *Tester) TxPairingRelayPayment(addr string, rs ...*pairingtypes.RelaySe func (ts *Tester) TxPairingFreezeProvider(addr, chainID string) (*pairingtypes.MsgFreezeProviderResponse, error) { msg := &pairingtypes.MsgFreezeProvider{ Creator: addr, - ChainIds: slices.Slice(chainID), + ChainIds: lavaslices.Slice(chainID), Reason: "test", } return ts.Servers.PairingServer.FreezeProvider(ts.GoCtx, msg) @@ -658,7 +658,7 @@ func (ts *Tester) TxPairingFreezeProvider(addr, chainID string) (*pairingtypes.M func (ts *Tester) TxPairingUnfreezeProvider(addr, chainID string) (*pairingtypes.MsgUnfreezeProviderResponse, error) { msg := &pairingtypes.MsgUnfreezeProvider{ Creator: addr, - ChainIds: slices.Slice(chainID), + ChainIds: lavaslices.Slice(chainID), } return ts.Servers.PairingServer.UnfreezeProvider(ts.GoCtx, msg) } diff --git a/utils/slices/slices.go b/utils/lavaslices/slices.go similarity index 83% rename from utils/slices/slices.go rename to utils/lavaslices/slices.go index c7e32a17e9..d93c41ee03 100644 --- a/utils/slices/slices.go +++ b/utils/lavaslices/slices.go @@ -1,6 +1,8 @@ -package slices +package lavaslices import ( + "math" + "golang.org/x/exp/constraints" "golang.org/x/exp/slices" ) @@ -261,3 +263,36 @@ func UnorderedEqual[T comparable](slices ...[]T) bool { return true } + +// splitSliceGeneric splits a slice into smaller slices of at most chunkSize length. +// for example len(arr) == 1400 and chunk size 500 will return [500, 500, 400] +func SplitGenericSliceIntoChunks[T any](arr []T, chunkSize int) [][]T { + var result [][]T + + // Calculate the number of chunks needed + numChunks := int(math.Ceil(float64(len(arr)) / float64(chunkSize))) + + // Iterate over the original slice and slice it into chunks + for i := 0; i < numChunks; i++ { + start := i * chunkSize + end := start + chunkSize + + // Ensure end doesn't exceed the length of the slice + if end > len(arr) { + end = len(arr) + } + + // Create a chunk with preallocated capacity + chunk := make([]T, 0, chunkSize) + + // Append elements to the chunk + for j := start; j < end; j++ { + chunk = append(chunk, arr[j]) + } + + // Append the chunk to the result slice + result = append(result, chunk) + } + + return result +} diff --git a/utils/slices/slices_test.go b/utils/lavaslices/slices_test.go similarity index 95% rename from utils/slices/slices_test.go rename to utils/lavaslices/slices_test.go index 1ed4ca363a..5101457b08 100644 --- a/utils/slices/slices_test.go +++ b/utils/lavaslices/slices_test.go @@ -1,4 +1,4 @@ -package slices +package lavaslices import ( "math" @@ -419,3 +419,25 @@ func TestFilter(t *testing.T) { require.Equal(t, []int{}, Filter([]int{1}, filter)) require.Equal(t, []int{2, 4}, Filter([]int{1, 2, 3, 4}, filter)) } + +func TestSliceSplitter(t *testing.T) { + // Sample usage + originalSliceSize := 1400 + testSlice := make([]int, originalSliceSize) // Assuming this is your original array + for i := 0; i < originalSliceSize; i++ { + testSlice[i] = i + } + testSizes := []int{500, 333, 200, 20, 1} + for _, i := range testSizes { + originalSizeCopy := originalSliceSize + retSlice := SplitGenericSliceIntoChunks(testSlice, i) + for _, k := range retSlice { + if originalSizeCopy < i { + require.Len(t, k, originalSizeCopy) + } else { + require.Len(t, k, i) + } + originalSizeCopy -= i + } + } +} diff --git a/x/conflict/keeper/msg_server_detection_test.go b/x/conflict/keeper/msg_server_detection_test.go index 2e512396e8..1a61d0bf84 100644 --- a/x/conflict/keeper/msg_server_detection_test.go +++ b/x/conflict/keeper/msg_server_detection_test.go @@ -7,8 +7,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" "github.com/lavanet/lava/utils" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" conflicttypes "github.com/lavanet/lava/x/conflict/types" conflictconstruct "github.com/lavanet/lava/x/conflict/types/construct" "github.com/lavanet/lava/x/pairing/types" @@ -182,5 +182,5 @@ func TestFrozenProviderDetection(t *testing.T) { require.NotEqual(t, 0, len(votersList)) // the frozen provider should not be part of the voters list - require.False(t, slices.Contains(votersList, frozenProvider)) + require.False(t, lavaslices.Contains(votersList, frozenProvider)) } diff --git a/x/dualstaking/keeper/delegate.go b/x/dualstaking/keeper/delegate.go index bd583f9614..76051250ea 100644 --- a/x/dualstaking/keeper/delegate.go +++ b/x/dualstaking/keeper/delegate.go @@ -24,7 +24,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/utils" - lavaslices "github.com/lavanet/lava/utils/slices" + lavaslices "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/dualstaking/types" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "golang.org/x/exp/slices" diff --git a/x/dualstaking/keeper/delegator_reward.go b/x/dualstaking/keeper/delegator_reward.go index 08f317e22d..81ca598be0 100644 --- a/x/dualstaking/keeper/delegator_reward.go +++ b/x/dualstaking/keeper/delegator_reward.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/dualstaking/types" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" spectypes "github.com/lavanet/lava/x/spec/types" @@ -207,7 +207,7 @@ func (k Keeper) RewardProvidersAndDelegators(ctx sdk.Context, providerAddr sdk.A } } - relevantDelegations := slices.Filter(delegations, + relevantDelegations := lavaslices.Filter(delegations, func(d types.Delegation) bool { return d.ChainID == chainID && d.IsFirstMonthPassed(ctx.BlockTime().UTC().Unix()) && d.Delegator != d.Provider }) diff --git a/x/dualstaking/types/delegate.go b/x/dualstaking/types/delegate.go index bac2fdefc5..96b4ce6572 100644 --- a/x/dualstaking/types/delegate.go +++ b/x/dualstaking/types/delegate.go @@ -5,7 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" ) func NewDelegation(delegator, provider, chainID string, blockTime time.Time, tokenDenom string) Delegation { @@ -51,14 +51,14 @@ func NewDelegator(delegator, provider string) Delegator { } func (delegator *Delegator) AddProvider(provider string) { - if !slices.Contains(delegator.Providers, provider) { + if !lavaslices.Contains(delegator.Providers, provider) { delegator.Providers = append(delegator.Providers, provider) } } func (delegator *Delegator) DelProvider(provider string) { - if slices.Contains(delegator.Providers, provider) { - delegator.Providers, _ = slices.Remove(delegator.Providers, provider) + if lavaslices.Contains(delegator.Providers, provider) { + delegator.Providers, _ = lavaslices.Remove(delegator.Providers, provider) } } diff --git a/x/pairing/keeper/cu_tracker_test.go b/x/pairing/keeper/cu_tracker_test.go index 9cd2273574..5546197446 100644 --- a/x/pairing/keeper/cu_tracker_test.go +++ b/x/pairing/keeper/cu_tracker_test.go @@ -8,8 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" testkeeper "github.com/lavanet/lava/testutil/keeper" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" "github.com/lavanet/lava/x/pairing/types" planstypes "github.com/lavanet/lava/x/plans/types" "github.com/stretchr/testify/require" @@ -87,7 +87,7 @@ func TestAddingTrackedCuWithoutPay(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider1Addr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -242,13 +242,13 @@ func TestTrackedCuWithQos(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider1, - Relays: slices.Slice(relaySession1), + Relays: lavaslices.Slice(relaySession1), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) relayPaymentMessage2 := types.MsgRelayPayment{ Creator: provider2, - Relays: slices.Slice(relaySession2), + Relays: lavaslices.Slice(relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage2, true) @@ -314,7 +314,7 @@ func TestTrackedCuMultipleChains(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider1, - Relays: slices.Slice(relaySession, relaySession1), + Relays: lavaslices.Slice(relaySession, relaySession1), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -327,7 +327,7 @@ func TestTrackedCuMultipleChains(t *testing.T) { relayPaymentMessage2 := types.MsgRelayPayment{ Creator: provider2, - Relays: slices.Slice(relaySession2), + Relays: lavaslices.Slice(relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage2, true) @@ -428,7 +428,7 @@ func TestProviderMonthlyPayoutQuery(t *testing.T) { relaySession2.Sig = sig relayPaymentMessage := types.MsgRelayPayment{ Creator: provider, - Relays: slices.Slice(relaySession, relaySession2), + Relays: lavaslices.Slice(relaySession, relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -446,7 +446,7 @@ func TestProviderMonthlyPayoutQuery(t *testing.T) { for _, p := range res.Details { details = append(details, *p) } - require.True(t, slices.UnorderedEqual(expectedPayouts, details)) + require.True(t, lavaslices.UnorderedEqual(expectedPayouts, details)) // check the expected subscrription payout subRes, err := ts.QueryPairingSubscriptionMonthlyPayout(client) @@ -555,7 +555,7 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { relaySession2.Sig = sig relayPaymentMessage := types.MsgRelayPayment{ Creator: provider, - Relays: slices.Slice(relaySession, relaySession2), + Relays: lavaslices.Slice(relaySession, relaySession2), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -574,7 +574,7 @@ func TestProviderMonthlyPayoutQueryWithContributor(t *testing.T) { for _, p := range res.Details { details = append(details, *p) } - require.True(t, slices.UnorderedEqual(expectedPayouts, details)) + require.True(t, lavaslices.UnorderedEqual(expectedPayouts, details)) // check the expected subscrription payout subRes, err := ts.QueryPairingSubscriptionMonthlyPayout(client) diff --git a/x/pairing/keeper/delegator_rewards_test.go b/x/pairing/keeper/delegator_rewards_test.go index 489dd79365..f0a14b222e 100644 --- a/x/pairing/keeper/delegator_rewards_test.go +++ b/x/pairing/keeper/delegator_rewards_test.go @@ -6,8 +6,8 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" dualstakingtypes "github.com/lavanet/lava/x/dualstaking/types" "github.com/lavanet/lava/x/pairing/types" subscriptiontypes "github.com/lavanet/lava/x/subscription/types" @@ -281,7 +281,7 @@ func TestProviderRewardWithCommission(t *testing.T) { // the expected reward for the provider with 100% commission is the total rewards (delegators get nothing) currentTimestamp := ts.Ctx.BlockTime().UTC().Unix() - relevantDelegations := slices.Filter(res.Delegations, + relevantDelegations := lavaslices.Filter(res.Delegations, func(d dualstakingtypes.Delegation) bool { return d.ChainID == ts.spec.Index && d.IsFirstMonthPassed(currentTimestamp) }) diff --git a/x/pairing/keeper/msg_server_relay_payment_gov_test.go b/x/pairing/keeper/msg_server_relay_payment_gov_test.go index 6fb969045b..0d397b3a7d 100644 --- a/x/pairing/keeper/msg_server_relay_payment_gov_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_gov_test.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" pairingtypes "github.com/lavanet/lava/x/pairing/types" "github.com/stretchr/testify/require" @@ -169,7 +169,7 @@ func TestRelayPaymentGovEpochBlocksDecrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -242,7 +242,7 @@ func TestRelayPaymentGovEpochBlocksIncrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -320,7 +320,7 @@ func TestRelayPaymentGovEpochToSaveDecrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, tt.valid, 100) @@ -390,7 +390,7 @@ func TestRelayPaymentGovEpochToSaveIncrease(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -471,7 +471,7 @@ func TestRelayPaymentGovEpochBlocksMultipleChanges(t *testing.T) { require.NoError(t, err) payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -514,7 +514,7 @@ func TestStakePaymentUnstake(t *testing.T) { payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, true, 100) @@ -578,7 +578,7 @@ func TestRelayPaymentMemoryTransferAfterEpochChangeWithGovParamChange(t *testing payment := pairingtypes.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, true) diff --git a/x/pairing/keeper/msg_server_relay_payment_test.go b/x/pairing/keeper/msg_server_relay_payment_test.go index 47c5663a57..4d475ca14f 100644 --- a/x/pairing/keeper/msg_server_relay_payment_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_test.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" commonconsts "github.com/lavanet/lava/testutil/common/consts" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" "github.com/lavanet/lava/x/pairing/types" planstypes "github.com/lavanet/lava/x/plans/types" projectstypes "github.com/lavanet/lava/x/projects/types" @@ -61,7 +61,7 @@ func TestRelayPaymentMemoryTransferAfterEpochChange(t *testing.T) { // Request payment (helper validates balances and verifies error through valid) relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // Request payment (helper function validates the balances and verifies if we should get an error through valid) @@ -102,7 +102,7 @@ func TestRelayPaymentBlockHeight(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, tt.valid) @@ -291,7 +291,7 @@ func TestRelayPaymentDoubleSpending(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession, relaySession), + Relays: lavaslices.Slice(relaySession, relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, false, 100) @@ -391,7 +391,7 @@ func TestRelayPaymentOldEpochs(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, tt.valid) }) @@ -438,7 +438,7 @@ func TestRelayPaymentQoS(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(payment, tt.valid) }) @@ -460,7 +460,7 @@ func TestEpochPaymentDeletion(t *testing.T) { payment := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(payment, client1Acct.Addr, providerAcct.Addr, true, true, 100) @@ -523,7 +523,7 @@ func TestCuUsageInProjectsAndSubscription(t *testing.T) { // Request payment (helper validates the balances and verifies expected errors through valid) relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -613,7 +613,7 @@ func TestBadgeValidation(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, tt.valid) @@ -720,7 +720,7 @@ func TestBadgeCuAllocationEnforcement(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddr, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, tt.valid) @@ -861,7 +861,7 @@ func TestBadgeDifferentProvidersCuAllocation(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: providers[i].Addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) diff --git a/x/pairing/keeper/pairing.go b/x/pairing/keeper/pairing.go index c94ac327b5..9c1a258c54 100644 --- a/x/pairing/keeper/pairing.go +++ b/x/pairing/keeper/pairing.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" pairingfilters "github.com/lavanet/lava/x/pairing/keeper/filters" pairingscores "github.com/lavanet/lava/x/pairing/keeper/scores" @@ -197,8 +197,8 @@ func (k Keeper) CalculateEffectiveSelectedProviders(policies []*planstypes.Polic } } - effectiveMode := slices.Max(selectedProvidersModeList) - effectiveSelectedProviders := slices.Intersection(selectedProvidersList...) + effectiveMode := lavaslices.Max(selectedProvidersModeList) + effectiveSelectedProviders := lavaslices.Intersection(selectedProvidersList...) return effectiveMode, effectiveSelectedProviders } @@ -255,13 +255,13 @@ func (k Keeper) CalculateEffectiveAllowedCuPerEpochFromPolicies(policies []*plan } } - effectiveTotalCuOfProject := slices.Min(policyTotalCuLimit) + effectiveTotalCuOfProject := lavaslices.Min(policyTotalCuLimit) cuLeftInProject := effectiveTotalCuOfProject - cuUsedInProject - effectiveEpochCuOfProject := slices.Min(policyEpochCuLimit) + effectiveEpochCuOfProject := lavaslices.Min(policyEpochCuLimit) slice := []uint64{effectiveEpochCuOfProject, cuLeftInProject, cuLeftInSubscription} - return slices.Min(slice), effectiveTotalCuOfProject + return lavaslices.Min(slice), effectiveTotalCuOfProject } func (k Keeper) ValidatePairingForClient(ctx sdk.Context, chainID string, providerAddress sdk.AccAddress, reqEpoch uint64, project projectstypes.Project) (isValidPairing bool, allowedCU uint64, pairedProviders []epochstoragetypes.StakeEntry, errorRet error) { diff --git a/x/pairing/keeper/pairing_immediately_test.go b/x/pairing/keeper/pairing_immediately_test.go index 1993268ad0..51a44fccb6 100644 --- a/x/pairing/keeper/pairing_immediately_test.go +++ b/x/pairing/keeper/pairing_immediately_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/lavanet/lava/testutil/common" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" projectTypes "github.com/lavanet/lava/x/projects/types" "github.com/stretchr/testify/require" ) @@ -50,7 +50,7 @@ func TestCreateProjectAddKey(t *testing.T) { projectData := projectTypes.ProjectData{ Name: "test", Enabled: true, - ProjectKeys: slices.Slice(projectTypes.ProjectDeveloperKey(dev1Addr)), + ProjectKeys: lavaslices.Slice(projectTypes.ProjectDeveloperKey(dev1Addr)), Policy: nil, } @@ -89,7 +89,7 @@ func TestAddKeyCreateProject(t *testing.T) { projectData := projectTypes.ProjectData{ Name: "test", Enabled: true, - ProjectKeys: slices.Slice(devkey), + ProjectKeys: lavaslices.Slice(devkey), Policy: nil, } diff --git a/x/pairing/keeper/pairing_subscription_test.go b/x/pairing/keeper/pairing_subscription_test.go index fded961ca7..45c79272b0 100644 --- a/x/pairing/keeper/pairing_subscription_test.go +++ b/x/pairing/keeper/pairing_subscription_test.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" planstypes "github.com/lavanet/lava/x/plans/types" projectstypes "github.com/lavanet/lava/x/projects/types" "github.com/stretchr/testify/require" @@ -25,7 +25,7 @@ func TestGetPairingForSubscription(t *testing.T) { Name: "project", Enabled: true, Policy: &ts.plan.PlanPolicy, - ProjectKeys: slices.Slice(projectstypes.ProjectDeveloperKey(dev1Addr)), + ProjectKeys: lavaslices.Slice(projectstypes.ProjectDeveloperKey(dev1Addr)), } err := ts.TxSubscriptionAddProject(client1Addr, projectData) require.NoError(t, err) @@ -75,7 +75,7 @@ func TestRelayPaymentSubscription(t *testing.T) { require.NoError(t, err) require.NotNil(t, sub.Sub) - policies := slices.Slice( + policies := lavaslices.Slice( proj.Project.AdminPolicy, proj.Project.SubscriptionPolicy, &ts.plan.PlanPolicy, @@ -112,7 +112,7 @@ func TestRelayPaymentSubscriptionCU(t *testing.T) { client1Acct, client1Addr := ts.GetAccount(common.CONSUMER, 0) dev1Acct, dev1Addr := ts.Account("dev1") - consumers := slices.Slice(client1Addr, dev1Addr) + consumers := lavaslices.Slice(client1Addr, dev1Addr) projectData := projectstypes.ProjectData{ Name: "proj_b", diff --git a/x/pairing/keeper/pairing_test.go b/x/pairing/keeper/pairing_test.go index 4483f9c275..426409aad7 100644 --- a/x/pairing/keeper/pairing_test.go +++ b/x/pairing/keeper/pairing_test.go @@ -10,8 +10,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" testkeeper "github.com/lavanet/lava/testutil/keeper" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" pairingscores "github.com/lavanet/lava/x/pairing/keeper/scores" "github.com/lavanet/lava/x/pairing/types" @@ -51,11 +51,11 @@ func TestPairingUniqueness(t *testing.T) { mapFunc := func(p epochstoragetypes.StakeEntry) string { return p.Address } - providerAddrs1 := slices.Map(pairing1.Providers, mapFunc) - providerAddrs2 := slices.Map(pairing2.Providers, mapFunc) + providerAddrs1 := lavaslices.Map(pairing1.Providers, mapFunc) + providerAddrs2 := lavaslices.Map(pairing2.Providers, mapFunc) require.Equal(t, len(pairing1.Providers), len(pairing2.Providers)) - require.False(t, slices.UnorderedEqual(providerAddrs1, providerAddrs2)) + require.False(t, lavaslices.UnorderedEqual(providerAddrs1, providerAddrs2)) ts.AdvanceEpoch() @@ -63,10 +63,10 @@ func TestPairingUniqueness(t *testing.T) { pairing11, err := ts.QueryPairingGetPairing(ts.spec.Index, sub1Addr) require.NoError(t, err) - providerAddrs11 := slices.Map(pairing11.Providers, mapFunc) + providerAddrs11 := lavaslices.Map(pairing11.Providers, mapFunc) require.Equal(t, len(pairing1.Providers), len(pairing11.Providers)) - require.False(t, slices.UnorderedEqual(providerAddrs1, providerAddrs11)) + require.False(t, lavaslices.UnorderedEqual(providerAddrs1, providerAddrs11)) // test that get pairing gives the same results for the whole epoch epochBlocks := ts.EpochBlocks() @@ -453,7 +453,7 @@ func TestAddonPairing(t *testing.T) { Addons: []string{mandatoryAddon.AddOn}, ApiInterfaces: []string{mandatoryAddon.ApiInterface}, }} - mandatoryAndMandatoryAddonSupportingEndpoints := slices.Concat( + mandatoryAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, mandatoryAddonSupportingEndpoints) optionalSupportingEndpoints := []epochstoragetypes.Endpoint{{ @@ -462,12 +462,12 @@ func TestAddonPairing(t *testing.T) { Addons: []string{optional.AddOn}, ApiInterfaces: []string{optional.ApiInterface}, }} - optionalAndMandatorySupportingEndpoints := slices.Concat( + optionalAndMandatorySupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalSupportingEndpoints) - optionalAndMandatoryAddonSupportingEndpoints := slices.Concat( + optionalAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryAddonSupportingEndpoints, optionalSupportingEndpoints) - allSupportingEndpoints := slices.Concat( + allSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalAndMandatoryAddonSupportingEndpoints) mandatoryAndOptionalSingleEndpoint := []epochstoragetypes.Endpoint{{ @@ -780,14 +780,14 @@ func TestSelectedProvidersPairing(t *testing.T) { count := countSelectedAddresses(providerAddresses1, expectedSelectedProviders[tt.expectedProviders]) require.GreaterOrEqual(t, count, len(providerAddresses1)/2) case "ALLOWED mode normal pairing", "DISABLED mode normal pairing": - require.False(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.False(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses1))) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses2))) case "EXCLUSIVE mode selected MaxProvidersToPair providers": - require.True(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses2))) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) case "EXCLUSIVE mode selected less than MaxProvidersToPair providers", "EXCLUSIVE mode selected less than MaxProvidersToPair different providers", @@ -795,24 +795,24 @@ func TestSelectedProvidersPairing(t *testing.T) { "EXCLUSIVE mode intersection between plan/proj policies", "EXCLUSIVE mode intersection between sub/proj policies", "EXCLUSIVE mode intersection between all policies": - require.True(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) require.Less(t, uint64(len(providerAddresses1)), maxProvidersToPair) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) case "EXCLUSIVE mode selected more than MaxProvidersToPair providers": - require.True(t, slices.IsSubset(providerAddresses1, expectedSelectedProviders[tt.expectedProviders])) - require.True(t, slices.IsSubset(providerAddresses2, expectedSelectedProviders[tt.expectedProviders])) + require.True(t, lavaslices.IsSubset(providerAddresses1, expectedSelectedProviders[tt.expectedProviders])) + require.True(t, lavaslices.IsSubset(providerAddresses2, expectedSelectedProviders[tt.expectedProviders])) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses1))) require.Equal(t, maxProvidersToPair, uint64(len(providerAddresses2))) case "EXCLUSIVE mode provider unstakes after first pairing": - require.False(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) - require.True(t, slices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses2)) + require.False(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses1)) + require.True(t, lavaslices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses2)) case "EXCLUSIVE mode non-staked provider stakes after first pairing": - require.False(t, slices.UnorderedEqual(providerAddresses1, providerAddresses2)) - require.True(t, slices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses2)) - require.True(t, slices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses1)) + require.False(t, lavaslices.UnorderedEqual(providerAddresses1, providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(expectedSelectedProviders[tt.expectedProviders], providerAddresses2)) + require.True(t, lavaslices.UnorderedEqual(expectedProvidersAfterUnstake, providerAddresses1)) } }) } @@ -1285,7 +1285,7 @@ func TestGeoSlotCalc(t *testing.T) { geoReqName := pairingscores.GeoReq{}.GetName() allGeos := planstypes.GetAllGeolocations() - maxGeo := slices.Max(allGeos) + maxGeo := lavaslices.Max(allGeos) // iterate over all possible geolocations, create a policy and calc slots // not checking 0 because there can never be a policy with geo=0 @@ -1786,7 +1786,7 @@ func TestExtensionAndAddonPairing(t *testing.T) { Addons: []string{mandatoryAddon.AddOn}, ApiInterfaces: []string{mandatoryAddon.ApiInterface}, }} - mandatoryAndMandatoryAddonSupportingEndpoints := slices.Concat( + mandatoryAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, mandatoryAddonSupportingEndpoints) optionalSupportingEndpoints := []epochstoragetypes.Endpoint{{ @@ -1795,12 +1795,12 @@ func TestExtensionAndAddonPairing(t *testing.T) { Addons: []string{optional.AddOn}, ApiInterfaces: []string{optional.ApiInterface}, }} - optionalAndMandatorySupportingEndpoints := slices.Concat( + optionalAndMandatorySupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalSupportingEndpoints) - optionalAndMandatoryAddonSupportingEndpoints := slices.Concat( + optionalAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryAddonSupportingEndpoints, optionalSupportingEndpoints) - allSupportingEndpoints := slices.Concat( + allSupportingEndpoints := lavaslices.Concat( mandatorySupportingEndpoints, optionalAndMandatoryAddonSupportingEndpoints) mandatoryAndOptionalSingleEndpoint := []epochstoragetypes.Endpoint{{ @@ -1851,7 +1851,7 @@ func TestExtensionAndAddonPairing(t *testing.T) { ApiInterfaces: []string{mandatoryAddon.ApiInterface}, Extensions: []string{"ext1"}, }} - mandatoryExtAndMandatoryAddonSupportingEndpoints := slices.Concat( + mandatoryExtAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryExtSupportingEndpoints, mandatoryExtAddonSupportingEndpoints) optionalExtSupportingEndpoints := []epochstoragetypes.Endpoint{{ @@ -1861,12 +1861,12 @@ func TestExtensionAndAddonPairing(t *testing.T) { ApiInterfaces: []string{optional.ApiInterface}, Extensions: []string{"ext1"}, }} - optionalExtAndMandatorySupportingEndpoints := slices.Concat( + optionalExtAndMandatorySupportingEndpoints := lavaslices.Concat( mandatoryExtSupportingEndpoints, optionalExtSupportingEndpoints) - optionalExtAndMandatoryAddonSupportingEndpoints := slices.Concat( + optionalExtAndMandatoryAddonSupportingEndpoints := lavaslices.Concat( mandatoryExtAddonSupportingEndpoints, optionalExtSupportingEndpoints) - allExtSupportingEndpoints := slices.Concat( + allExtSupportingEndpoints := lavaslices.Concat( mandatoryExtSupportingEndpoints, optionalExtAndMandatoryAddonSupportingEndpoints, mandatoryExt2AddonSupportingEndpoint) // mandatory err := ts.addProviderEndpoints(2, mandatoryExtSupportingEndpoints) // ext1 - 2 @@ -2215,7 +2215,7 @@ func TestPairingConsistency(t *testing.T) { currentPairingAddrs = append(currentPairingAddrs, res.Providers[i].Address) } - require.True(t, slices.UnorderedEqual(prevPairingAddrs, currentPairingAddrs)) + require.True(t, lavaslices.UnorderedEqual(prevPairingAddrs, currentPairingAddrs)) prevPairing = res.Providers } diff --git a/x/pairing/keeper/unresponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go index 9134143718..08469d8cb8 100644 --- a/x/pairing/keeper/unresponsive_provider_test.go +++ b/x/pairing/keeper/unresponsive_provider_test.go @@ -5,9 +5,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/utils/rand" "github.com/lavanet/lava/utils/sigs" - "github.com/lavanet/lava/utils/slices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/lavanet/lava/x/pairing/types" "github.com/stretchr/testify/require" @@ -108,7 +108,7 @@ func TestUnresponsivenessStressTest(t *testing.T) { require.NoError(t, err) relayPaymentMessage := types.MsgRelayPayment{ Creator: providerAddress, - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } // send relay payment and check the funds did transfer normally @@ -175,7 +175,7 @@ func TestFreezingProviderForUnresponsiveness(t *testing.T) { require.NoError(t, err) relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -233,7 +233,7 @@ func TestFreezingProviderForUnresponsivenessContinueComplainingAfterFreeze(t *te require.NoError(t, err) relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -260,7 +260,7 @@ func TestFreezingProviderForUnresponsivenessContinueComplainingAfterFreeze(t *te relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.relayPaymentWithoutPay(relayPaymentMessage, true) @@ -327,7 +327,7 @@ func TestNotFreezingProviderForUnresponsivenessWithMinProviders(t *testing.T) { relayPaymentMessage := types.MsgRelayPayment{ Creator: provider0_addr.String(), - Relays: slices.Slice(relaySession), + Relays: lavaslices.Slice(relaySession), } ts.payAndVerifyBalance(relayPaymentMessage, clients[clientIndex].Addr, provider0_addr, true, true, 100) diff --git a/x/plans/types/geolocation_test.go b/x/plans/types/geolocation_test.go index 2c4b41c9fa..5aad7095d8 100644 --- a/x/plans/types/geolocation_test.go +++ b/x/plans/types/geolocation_test.go @@ -3,7 +3,7 @@ package types_test import ( "testing" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" planstypes "github.com/lavanet/lava/x/plans/types" "github.com/stretchr/testify/require" ) @@ -19,7 +19,7 @@ func TestAllGeos(t *testing.T) { geosFromMap = append(geosFromMap, geo) } - require.True(t, slices.UnorderedEqual(geos, geosFromMap)) + require.True(t, lavaslices.UnorderedEqual(geos, geosFromMap)) } func TestGetGeoFromUint(t *testing.T) { diff --git a/x/plans/types/policy.go b/x/plans/types/policy.go index 6b108ee1c8..b562b2bc21 100644 --- a/x/plans/types/policy.go +++ b/x/plans/types/policy.go @@ -12,7 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/utils/decoder" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/mitchellh/mapstructure" ) @@ -185,7 +185,7 @@ func GetStrictestChainPolicyForSpec(chainID string, policies []*Policy) (chainPo continue } // previous policies and current policy change collection data, we need the union of both - requirements = slices.UnionByFunc(chainPolicyRequirements, requirements) + requirements = lavaslices.UnionByFunc(chainPolicyRequirements, requirements) } return ChainPolicy{ChainId: chainID, Requirements: requirements}, true diff --git a/x/rewards/client/cli/tx.go b/x/rewards/client/cli/tx.go index ff8d00261d..dc1d1f6e10 100644 --- a/x/rewards/client/cli/tx.go +++ b/x/rewards/client/cli/tx.go @@ -16,7 +16,7 @@ import ( govclient "github.com/cosmos/cosmos-sdk/x/gov/client" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/rewards/types" ) @@ -121,7 +121,7 @@ $ %s tx gov submit-legacy-proposal set-iprpc-data --min-cost 0ulava --add-subscr return err } for _, sub := range subsToRemove { - iprpcSubs, _ = slices.Remove(iprpcSubs, sub) + iprpcSubs, _ = lavaslices.Remove(iprpcSubs, sub) } deposit, err := sdk.ParseCoinsNormalized(args[0]) diff --git a/x/subscription/keeper/msg_server_auto_renewal.go b/x/subscription/keeper/msg_server_auto_renewal.go index c46091af05..ee1d82f556 100644 --- a/x/subscription/keeper/msg_server_auto_renewal.go +++ b/x/subscription/keeper/msg_server_auto_renewal.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" "github.com/lavanet/lava/x/subscription/types" ) @@ -66,7 +66,7 @@ func (k msgServer) AutoRenewal(goCtx context.Context, msg *types.MsgAutoRenewal) } if len(plan.AllowedBuyers) != 0 { - if !slices.Contains(plan.AllowedBuyers, msg.Creator) { + if !lavaslices.Contains(plan.AllowedBuyers, msg.Creator) { allowedBuyers := strings.Join(plan.AllowedBuyers, ",") return nil, utils.LavaFormatWarning("cannot apply auto-renewal to subscription", fmt.Errorf("creator is not part of the allowed buyers list"), utils.LogAttr("creator", msg.Creator), diff --git a/x/subscription/keeper/subscription.go b/x/subscription/keeper/subscription.go index 66fba0d75f..54a052110f 100644 --- a/x/subscription/keeper/subscription.go +++ b/x/subscription/keeper/subscription.go @@ -9,7 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/lavanet/lava/utils" - "github.com/lavanet/lava/utils/slices" + "github.com/lavanet/lava/utils/lavaslices" planstypes "github.com/lavanet/lava/x/plans/types" projectstypes "github.com/lavanet/lava/x/projects/types" "github.com/lavanet/lava/x/subscription/types" @@ -176,7 +176,7 @@ func (k Keeper) verifySubscriptionBuyInputAndGetPlan(ctx sdk.Context, block uint } if len(plan.AllowedBuyers) != 0 { - if !slices.Contains(plan.AllowedBuyers, creator) { + if !lavaslices.Contains(plan.AllowedBuyers, creator) { allowedBuyers := strings.Join(plan.AllowedBuyers, ",") return nil, EMPTY_PLAN, utils.LavaFormatWarning("subscription buy input is invalid", fmt.Errorf("creator is not part of the allowed buyers list"), utils.LogAttr("creator", creator), @@ -311,7 +311,7 @@ func (k Keeper) renewSubscription(ctx sdk.Context, sub *types.Subscription) erro } if len(plan.AllowedBuyers) != 0 { - if !slices.Contains(plan.AllowedBuyers, sub.Creator) { + if !lavaslices.Contains(plan.AllowedBuyers, sub.Creator) { allowedBuyers := strings.Join(plan.AllowedBuyers, ",") return utils.LavaFormatWarning("cannot auto-renew subscription", fmt.Errorf("creator is not part of the allowed buyers list"), utils.LogAttr("creator", sub.Creator), From b5c502398e1a694d4798fc598aa61da60a2161be Mon Sep 17 00:00:00 2001 From: Ran Mishael Date: Sun, 24 Mar 2024 17:38:29 +0100 Subject: [PATCH 3/3] adding wait groups for reward server claims --- protocol/rpcprovider/rewardserver/reward_server.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/protocol/rpcprovider/rewardserver/reward_server.go b/protocol/rpcprovider/rewardserver/reward_server.go index 295947492f..2f56f93ac2 100644 --- a/protocol/rpcprovider/rewardserver/reward_server.go +++ b/protocol/rpcprovider/rewardserver/reward_server.go @@ -265,6 +265,9 @@ func (rws *RewardServer) sendRewardsClaim(ctx context.Context, epoch uint64) err }, } + paymentWaitGroup := sync.WaitGroup{} + paymentWaitGroup.Add(newRewardsLength + failedRewardsLength) + // add expected pay and ask for rewards for _, paymentConfig := range paymentConfiguration { for _, rewardsToClaim := range paymentConfig.relaySessionChunks { @@ -277,6 +280,7 @@ func (rws *RewardServer) sendRewardsClaim(ctx context.Context, epoch uint64) err continue } go func(rewards []*pairingtypes.RelaySession, payment *PaymentConfiguration) { // send rewards asynchronously + defer paymentWaitGroup.Done() specs := map[string]struct{}{} if payment.shouldAddExpectedPayment { for _, relay := range rewards { @@ -319,6 +323,8 @@ func (rws *RewardServer) sendRewardsClaim(ctx context.Context, epoch uint64) err }(rewardsToClaim, paymentConfig) } } + utils.LavaFormatDebug("Waiting for all Payment groups to finish", utils.LogAttr("wait_group_size", newRewardsLength+failedRewardsLength)) + paymentWaitGroup.Wait() return nil }