From 4b9dfc8212b09599f7e097c6bcbc333f88786b07 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Tue, 10 Jan 2023 12:57:20 +0200 Subject: [PATCH 01/37] CNS-137: added check that consumer is paired with reported provider --- relayer/lavasession/consumer_session_manager.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/relayer/lavasession/consumer_session_manager.go b/relayer/lavasession/consumer_session_manager.go index b2671fe146..5c31eb5e7d 100644 --- a/relayer/lavasession/consumer_session_manager.go +++ b/relayer/lavasession/consumer_session_manager.go @@ -263,7 +263,15 @@ func (csm *ConsumerSessionManager) blockProvider(address string, reportProvider } } - if reportProvider { // Report provider flow + // before we report the provider, we check that we're currently paired to it + consumerPairedWithProvider := false + for _, pairingAddr := range csm.pairingAddresses { + if pairingAddr == address { + consumerPairedWithProvider = true + } + } + + if reportProvider && consumerPairedWithProvider { // Report provider flow if _, ok := csm.addedToPurgeAndReport[address]; !ok { // verify it doesn't exist already csm.addedToPurgeAndReport[address] = struct{}{} } From f30dee143c20bd0f3d0171ef40bc93e906fddac7 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Tue, 10 Jan 2023 16:55:17 +0200 Subject: [PATCH 02/37] CNS-137: changed proto of provider payment storage --- proto/pairing/provider_payment_storage.proto | 6 +- .../msg_server_unresponsive_provider.go | 185 ++++++++++++++++++ x/pairing/keeper/provider_payment_storage.go | 2 +- .../types/provider_payment_storage.pb.go | 78 +++----- 4 files changed, 219 insertions(+), 52 deletions(-) create mode 100644 x/pairing/keeper/msg_server_unresponsive_provider.go diff --git a/proto/pairing/provider_payment_storage.proto b/proto/pairing/provider_payment_storage.proto index 3627a5d1ee..cd9e03478e 100644 --- a/proto/pairing/provider_payment_storage.proto +++ b/proto/pairing/provider_payment_storage.proto @@ -5,10 +5,12 @@ option go_package = "github.com/lavanet/lava/x/pairing/types"; import "pairing/unique_payment_storage_client_provider.proto"; message ProviderPaymentStorage { + string index = 1; repeated UniquePaymentStorageClientProvider uniquePaymentStorageClientProvider = 2; - uint64 epoch = 3; - repeated string unresponsiveness_complaints = 4; + uint64 epoch = 3; + reserved 4; + uint64 complainers_total_cu = 5; // total CU that were supposed to be served by the provider but didn't because he was unavailable (so consumers complained about him) } // change Client -> consumer diff --git a/x/pairing/keeper/msg_server_unresponsive_provider.go b/x/pairing/keeper/msg_server_unresponsive_provider.go new file mode 100644 index 0000000000..f6b37ed095 --- /dev/null +++ b/x/pairing/keeper/msg_server_unresponsive_provider.go @@ -0,0 +1,185 @@ +package keeper + +import ( + "encoding/json" + "fmt" + "math" + "strconv" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/utils" + epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" + "github.com/lavanet/lava/x/pairing/types" + "github.com/tendermint/tendermint/libs/log" + "golang.org/x/exp/slices" +) + +func (k msgServer) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { + // Get current epoch + currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) + + // Get epoch payments relevant to unresponsiveness from previous blocks + unresponsiveProviders := k.getPaymentsRelatedToUnresponiveness(ctx, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers) + + // Get CU serviced by the provider + + // deal with unresponsive providers + err := k.dealWithUnresponsiveProviders(ctx, relay.UnresponsiveProviders, logger, clientAddr, epochStart, relay.ChainID) + if err != nil { + utils.LogLavaEvent(ctx, logger, types.UnresponsiveProviderUnstakeFailedEventName, map[string]string{"err:": err.Error()}, "Error Unresponsive Providers could not unstake") + } +} + +// Function that returns the payments objects relevant to the unresponsiveness punishment condition. +// The relevant payments are all the payments from the previous epoch that are determined by +// epochsNumToCheckCUForUnresponsiveProvider and epochsNumToCheckCUForComplainers. +func (k msgServer) getPaymentsRelatedToUnresponiveness(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (uint64, uint64, error) { + tempEpoch := currentEpoch + complainerUsedCU := uint64(0) + providerServicedCU := uint64(0) + + // Find which of the constants is larger to know when to stop iterating + maxEpochsBack := uint64(math.Max(float64(epochsNumToCheckCUForUnresponsiveProvider), float64(epochsNumToCheckCUForComplainers))) + + // Go over previous epoch payments + for counter := uint64(0); counter < maxEpochsBack; counter++ { + // Get previous epoch + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, tempEpoch) + if err != nil { + return 0, 0, err + } + + // Get epoch payments from block. If the epoch doesn't contain payments, continue + epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, tempEpoch) + if !found { + continue + } + + if counter < epochsNumToCheckCUForComplainers { + for _, providerPaymentStorage := range epochPayments.GetClientsPayments() { + if len(providerPaymentStorage.UnresponsivenessComplaints) == 0 { + continue + } + for _, payment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { + payment.GetUsedCU() + } + } + } + + // Update tempEpoch + tempEpoch = previousEpoch + } + // check if lists are empty (no epochs had payments in them) + + return complainerUsedCU, providerServicedCU, nil +} + +func (k msgServer) dealWithUnresponsiveProviders(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, clientAddr sdk.AccAddress, epoch uint64, chainID string) error { + var unresponsiveProviders []string + if len(unresponsiveData) == 0 { + return nil + } + err := json.Unmarshal(unresponsiveData, &unresponsiveProviders) + if err != nil { + return utils.LavaFormatError("unable to unmarshal unresponsive providers", err, &map[string]string{"UnresponsiveProviders": string(unresponsiveData), "dataLength": strconv.Itoa(len(unresponsiveData))}) + } + if len(unresponsiveProviders) == 0 { + // nothing to do. + return nil + } + for _, unresponsiveProvider := range unresponsiveProviders { + sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(unresponsiveProvider) + if err != nil { // if bad data was given, we cant parse it so we ignote it and continue this protects from spamming wrong information. + utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) + continue + } + existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) + // if !entryExists provider is alraedy unstaked + if !entryExists { + continue // if provider is not staked, nothing to do. + } + + providerStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, epoch, sdkUnresponsiveProviderAddress) + providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerStorageKey) + + if !found { + // currently this provider has not payments in this epoch and also no complaints, we need to add one complaint here + emptyProviderPaymentStorageWithComplaint := types.ProviderPaymentStorage{ + Index: providerStorageKey, + UniquePaymentStorageClientProvider: []*types.UniquePaymentStorageClientProvider{}, + Epoch: epoch, + UnresponsivenessComplaints: []string{clientAddr.String()}, + } + k.SetProviderPaymentStorage(ctx, emptyProviderPaymentStorageWithComplaint) + continue + } + // providerPaymentStorage was found for epoch, start analyzing if unstake is necessary + // check if the same consumer is trying to complain a second time for this epoch + if slices.Contains(providerPaymentStorage.UnresponsivenessComplaints, clientAddr.String()) { + continue + } + + providerPaymentStorage.UnresponsivenessComplaints = append(providerPaymentStorage.UnresponsivenessComplaints, clientAddr.String()) + + // Get the amount of CU used by the complainers (consumers that complained on the provider) + // complainersCU := + for _, complaint := range providerPaymentStorage.UnresponsivenessComplaints { + complaint + } + + // Get the amount of CU serviced by the unresponsive provider + unresponsiveProviderCU, err := k.getTotalCUServicedByProviderFromPreviousEpochs(ctx, epochsNumToCheckCUForUnresponsiveProvider, epoch, chainID, sdkUnresponsiveProviderAddress) + + // now we check if we have more UnresponsivenessComplaints than maxComplaintsPerEpoch + if len(providerPaymentStorage.UnresponsivenessComplaints) >= maxComplaintsPerEpoch { + // we check if we have double complaints than previous "collectPaymentsFromNumberOfPreviousEpochs" epochs (including this one) payment requests + totalPaymentsInPreviousEpochs, err := k.getTotalPaymentsForPreviousEpochs(ctx, collectPaymentsFromNumberOfPreviousEpochs, epoch, chainID, sdkUnresponsiveProviderAddress) + totalPaymentRequests := totalPaymentsInPreviousEpochs + len(providerPaymentStorage.UniquePaymentStorageClientProvider) // get total number of payments including this epoch + if err != nil { + utils.LavaFormatError("lava_unresponsive_providers: couldnt fetch getTotalPaymentsForPreviousEpochs", err, nil) + } else if totalPaymentRequests*providerPaymentMultiplier < len(providerPaymentStorage.UnresponsivenessComplaints) { + // unstake provider + utils.LogLavaEvent(ctx, logger, types.ProviderJailedEventName, map[string]string{"provider_address": sdkUnresponsiveProviderAddress.String(), "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") + err = k.unSafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) + if err != nil { + utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) + continue + } + } + } + // set the final provider payment storage state including the complaints + k.SetProviderPaymentStorage(ctx, providerPaymentStorage) + } + return nil +} + +func (k msgServer) getTotalCUServicedByProviderFromPreviousEpochs(ctx sdk.Context, numberOfEpochs int, currentEpoch uint64, chainID string, sdkUnresponsiveProviderAddress sdk.AccAddress) (uint64, error) { + providerServicedCU := uint64(0) + epochTemp := currentEpoch + for payment := 0; payment < numberOfEpochs; payment++ { + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + return 0, err + } + previousEpochProviderStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, previousEpoch, sdkUnresponsiveProviderAddress) + previousEpochProviderPaymentStorage, providerPaymentStorageFound := k.GetProviderPaymentStorage(ctx, previousEpochProviderStorageKey) + if !providerPaymentStorageFound { + return 0, utils.LavaError(ctx, k.Logger(ctx), "get_provider_payment_storage", map[string]string{"providerStorageKey": fmt.Sprintf("%+v", previousEpochProviderStorageKey), "epoch": fmt.Sprintf("%+v", previousEpoch)}, "couldn't get provider payment storage with given key") + } + for _, uniquePayment := range previousEpochProviderPaymentStorage.GetUniquePaymentStorageClientProvider() { + providerServicedCU += uniquePayment.GetUsedCU() + } + + epochTemp = previousEpoch + } + return providerServicedCU, nil +} + +func (k msgServer) unSafeUnstakeProviderEntry(ctx sdk.Context, providerKey string, chainID string, indexInStakeStorage uint64, existingEntry epochstoragetypes.StakeEntry) error { + err := k.epochStorageKeeper.RemoveStakeEntryCurrent(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "relay_payment_unstake", map[string]string{"existingEntry": fmt.Sprintf("%+v", existingEntry)}, "tried to unstake unsafe but didnt find entry") + } + k.epochStorageKeeper.AppendUnstakeEntry(ctx, epochstoragetypes.ProviderKey, existingEntry) + return nil +} diff --git a/x/pairing/keeper/provider_payment_storage.go b/x/pairing/keeper/provider_payment_storage.go index 02a14ec8e3..534aa23dfb 100644 --- a/x/pairing/keeper/provider_payment_storage.go +++ b/x/pairing/keeper/provider_payment_storage.go @@ -78,7 +78,7 @@ func (k Keeper) AddProviderPaymentInEpoch(ctx sdk.Context, chainID string, epoch userPaymentStorageInEpoch, found := k.GetProviderPaymentStorage(ctx, key) if !found { // is new entry - userPaymentStorageInEpoch = types.ProviderPaymentStorage{Index: key, UniquePaymentStorageClientProvider: []*types.UniquePaymentStorageClientProvider{uniquePaymentStorageClientProviderEntryAddr}, Epoch: epoch, UnresponsivenessComplaints: []string{}} + userPaymentStorageInEpoch = types.ProviderPaymentStorage{Index: key, UniquePaymentStorageClientProvider: []*types.UniquePaymentStorageClientProvider{uniquePaymentStorageClientProviderEntryAddr}, Epoch: epoch, ComplainersTotalCu: uint64(0)} usedCUConsumerTotal = usedCU } else { userPaymentStorageInEpoch.UniquePaymentStorageClientProvider = append(userPaymentStorageInEpoch.UniquePaymentStorageClientProvider, uniquePaymentStorageClientProviderEntryAddr) diff --git a/x/pairing/types/provider_payment_storage.pb.go b/x/pairing/types/provider_payment_storage.pb.go index f6b6df82eb..ee3130f489 100644 --- a/x/pairing/types/provider_payment_storage.pb.go +++ b/x/pairing/types/provider_payment_storage.pb.go @@ -26,7 +26,7 @@ type ProviderPaymentStorage struct { Index string `protobuf:"bytes,1,opt,name=index,proto3" json:"index,omitempty"` UniquePaymentStorageClientProvider []*UniquePaymentStorageClientProvider `protobuf:"bytes,2,rep,name=uniquePaymentStorageClientProvider,proto3" json:"uniquePaymentStorageClientProvider,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` - UnresponsivenessComplaints []string `protobuf:"bytes,4,rep,name=unresponsiveness_complaints,json=unresponsivenessComplaints,proto3" json:"unresponsiveness_complaints,omitempty"` + ComplainersTotalCu uint64 `protobuf:"varint,5,opt,name=complainers_total_cu,json=complainersTotalCu,proto3" json:"complainers_total_cu,omitempty"` } func (m *ProviderPaymentStorage) Reset() { *m = ProviderPaymentStorage{} } @@ -83,11 +83,11 @@ func (m *ProviderPaymentStorage) GetEpoch() uint64 { return 0 } -func (m *ProviderPaymentStorage) GetUnresponsivenessComplaints() []string { +func (m *ProviderPaymentStorage) GetComplainersTotalCu() uint64 { if m != nil { - return m.UnresponsivenessComplaints + return m.ComplainersTotalCu } - return nil + return 0 } func init() { @@ -99,25 +99,25 @@ func init() { } var fileDescriptor_4f1d2e8d774659ae = []byte{ - // 287 bytes of a gzipped FileDescriptorProto + // 284 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2b, 0x48, 0xcc, 0x2c, 0xca, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xcb, 0x4c, 0x49, 0x2d, 0x8a, 0x2f, 0x48, 0xac, 0xcc, 0x4d, 0xcd, 0x2b, 0x89, 0x2f, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc9, 0x49, 0x2c, 0x4b, 0xcc, 0x4b, 0x2d, 0xd1, 0x03, 0xd1, 0x7a, 0x50, 0x4d, 0x52, 0x26, 0x30, 0xdd, 0xa5, 0x79, 0x99, 0x85, 0xa5, 0xa9, 0xe8, 0x7a, 0xe3, 0x93, 0x73, - 0x32, 0x41, 0x5c, 0x98, 0xd9, 0x10, 0xb3, 0x94, 0x26, 0x30, 0x71, 0x89, 0x05, 0x40, 0x85, 0x02, - 0x20, 0x3a, 0x82, 0x21, 0x1a, 0x84, 0x44, 0xb8, 0x58, 0x33, 0xf3, 0x52, 0x52, 0x2b, 0x24, 0x18, - 0x15, 0x18, 0x35, 0x38, 0x83, 0x20, 0x1c, 0xa1, 0x0e, 0x46, 0x2e, 0x25, 0x88, 0x0d, 0xa8, 0xca, - 0x9d, 0xc1, 0xc6, 0xc3, 0x8c, 0x92, 0x60, 0x52, 0x60, 0xd6, 0xe0, 0x36, 0xb2, 0xd0, 0xc3, 0xe6, - 0x54, 0xbd, 0x50, 0x82, 0xfa, 0x83, 0x88, 0xb0, 0x03, 0xe4, 0xc0, 0xd4, 0x82, 0xfc, 0xe4, 0x0c, - 0x09, 0x66, 0x05, 0x46, 0x0d, 0x96, 0x20, 0x08, 0x47, 0xc8, 0x9e, 0x4b, 0xba, 0x34, 0xaf, 0x28, - 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0xb3, 0x2c, 0x35, 0x2f, 0xb5, 0xb8, 0x38, 0x3e, 0x39, 0x3f, - 0xb7, 0x20, 0x27, 0x31, 0x33, 0xaf, 0xa4, 0x58, 0x82, 0x45, 0x81, 0x59, 0x83, 0x33, 0x48, 0x0a, - 0x5d, 0x89, 0x33, 0x5c, 0x85, 0x93, 0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, - 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, - 0x44, 0xa9, 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x43, 0x3d, 0x06, - 0xa6, 0xf5, 0x2b, 0xf4, 0x61, 0x81, 0x5f, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x0e, 0x5c, - 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3e, 0x8f, 0xa8, 0xee, 0xd2, 0x01, 0x00, 0x00, + 0x32, 0x41, 0x5c, 0x98, 0xd9, 0x10, 0xb3, 0x94, 0xda, 0x99, 0xb8, 0xc4, 0x02, 0xa0, 0x42, 0x01, + 0x10, 0x1d, 0xc1, 0x10, 0x0d, 0x42, 0x22, 0x5c, 0xac, 0x99, 0x79, 0x29, 0xa9, 0x15, 0x12, 0x8c, + 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x10, 0x8e, 0x50, 0x07, 0x23, 0x97, 0x12, 0xc4, 0x06, 0x54, 0xe5, + 0xce, 0x60, 0xe3, 0x61, 0x46, 0x49, 0x30, 0x29, 0x30, 0x6b, 0x70, 0x1b, 0x59, 0xe8, 0x61, 0x73, + 0xaa, 0x5e, 0x28, 0x41, 0xfd, 0x41, 0x44, 0xd8, 0x01, 0x72, 0x60, 0x6a, 0x41, 0x7e, 0x72, 0x86, + 0x04, 0xb3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x84, 0x23, 0x64, 0xc0, 0x25, 0x92, 0x9c, 0x9f, 0x5b, + 0x90, 0x93, 0x98, 0x99, 0x97, 0x5a, 0x54, 0x1c, 0x5f, 0x92, 0x5f, 0x92, 0x98, 0x13, 0x9f, 0x5c, + 0x2a, 0xc1, 0x0a, 0x56, 0x24, 0x84, 0x24, 0x17, 0x02, 0x92, 0x72, 0x2e, 0xf5, 0x62, 0xe1, 0x60, + 0x11, 0x60, 0x75, 0x72, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, + 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xf5, + 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0xa8, 0x7f, 0xc0, 0xb4, 0x7e, + 0x85, 0x3e, 0x2c, 0xcc, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x61, 0x6a, 0x0c, 0x08, + 0x00, 0x00, 0xff, 0xff, 0xef, 0xa7, 0x63, 0x48, 0xc9, 0x01, 0x00, 0x00, } func (m *ProviderPaymentStorage) Marshal() (dAtA []byte, err error) { @@ -140,14 +140,10 @@ func (m *ProviderPaymentStorage) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l - if len(m.UnresponsivenessComplaints) > 0 { - for iNdEx := len(m.UnresponsivenessComplaints) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.UnresponsivenessComplaints[iNdEx]) - copy(dAtA[i:], m.UnresponsivenessComplaints[iNdEx]) - i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(len(m.UnresponsivenessComplaints[iNdEx]))) - i-- - dAtA[i] = 0x22 - } + if m.ComplainersTotalCu != 0 { + i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(m.ComplainersTotalCu)) + i-- + dAtA[i] = 0x28 } if m.Epoch != 0 { i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(m.Epoch)) @@ -208,11 +204,8 @@ func (m *ProviderPaymentStorage) Size() (n int) { if m.Epoch != 0 { n += 1 + sovProviderPaymentStorage(uint64(m.Epoch)) } - if len(m.UnresponsivenessComplaints) > 0 { - for _, s := range m.UnresponsivenessComplaints { - l = len(s) - n += 1 + l + sovProviderPaymentStorage(uint64(l)) - } + if m.ComplainersTotalCu != 0 { + n += 1 + sovProviderPaymentStorage(uint64(m.ComplainersTotalCu)) } return n } @@ -337,11 +330,11 @@ func (m *ProviderPaymentStorage) Unmarshal(dAtA []byte) error { break } } - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UnresponsivenessComplaints", wireType) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ComplainersTotalCu", wireType) } - var stringLen uint64 + m.ComplainersTotalCu = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowProviderPaymentStorage @@ -351,24 +344,11 @@ func (m *ProviderPaymentStorage) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.ComplainersTotalCu |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthProviderPaymentStorage - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthProviderPaymentStorage - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.UnresponsivenessComplaints = append(m.UnresponsivenessComplaints, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipProviderPaymentStorage(dAtA[iNdEx:]) From d7f055cdadcdf3c219e18b26e28ac4b8474b699c Mon Sep 17 00:00:00 2001 From: oren-lava Date: Wed, 11 Jan 2023 12:06:06 +0200 Subject: [PATCH 03/37] CNS-137: update complainer CU in provider payment storage (according to new proto) --- x/pairing/keeper/msg_server_relay_payment.go | 79 +++++--------------- 1 file changed, 17 insertions(+), 62 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 8b0be4927a..332265918c 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -12,7 +12,6 @@ import ( epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/lavanet/lava/x/pairing/types" "github.com/tendermint/tendermint/libs/log" - "golang.org/x/exp/slices" ) const ( @@ -273,9 +272,8 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen details["relayNumber"] = strconv.FormatUint(relay.RelayNum, 10) utils.LogLavaEvent(ctx, logger, types.RelayPaymentEventName, details, "New Proof Of Work Was Accepted") - // - // deal with unresponsive providers - err = k.dealWithUnresponsiveProviders(ctx, relay.UnresponsiveProviders, logger, clientAddr, epochStart, relay.ChainID) + // update provider payment storage with complainer's CU + err = k.updateProviderPaymentStorageWithComplainerCU(ctx, relay.UnresponsiveProviders, logger, clientAddr, epochStart, relay.ChainID, relay.CuSum) if err != nil { utils.LogLavaEvent(ctx, logger, types.UnresponsiveProviderUnstakeFailedEventName, map[string]string{"err:": err.Error()}, "Error Unresponsive Providers could not unstake") } @@ -283,99 +281,56 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen return &types.MsgRelayPaymentResponse{}, nil } -func (k msgServer) dealWithUnresponsiveProviders(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, clientAddr sdk.AccAddress, epoch uint64, chainID string) error { +func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, clientAddr sdk.AccAddress, epoch uint64, chainID string, cuSum uint64) error { var unresponsiveProviders []string + + // check that unresponsiveData exists if len(unresponsiveData) == 0 { return nil } + + // unmarshel the byte array unresponsiveData to get a list of unresponsive providers Bech32 addresses err := json.Unmarshal(unresponsiveData, &unresponsiveProviders) if err != nil { return utils.LavaFormatError("unable to unmarshal unresponsive providers", err, &map[string]string{"UnresponsiveProviders": string(unresponsiveData), "dataLength": strconv.Itoa(len(unresponsiveData))}) } + + // check there are unresponsive providers if len(unresponsiveProviders) == 0 { // nothing to do. return nil } + + // iterate over the unresponsive providers list and update their complainers_total_cu for _, unresponsiveProvider := range unresponsiveProviders { + // get provider address sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(unresponsiveProvider) if err != nil { // if bad data was given, we cant parse it so we ignote it and continue this protects from spamming wrong information. utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) continue } - existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) - // if !entryExists provider is alraedy unstaked - if !entryExists { - continue // if provider is not staked, nothing to do. - } + // get the providerPaymentStorage object using the providerStorageKey providerStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, epoch, sdkUnresponsiveProviderAddress) providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerStorageKey) if !found { - // currently this provider has not payments in this epoch and also no complaints, we need to add one complaint here + // providerPaymentStorage not found (this provider has no payments in this epoch and also no complaints) -> we need to add one complaint emptyProviderPaymentStorageWithComplaint := types.ProviderPaymentStorage{ Index: providerStorageKey, UniquePaymentStorageClientProvider: []*types.UniquePaymentStorageClientProvider{}, Epoch: epoch, - UnresponsivenessComplaints: []string{clientAddr.String()}, + ComplainersTotalCu: cuSum, } k.SetProviderPaymentStorage(ctx, emptyProviderPaymentStorageWithComplaint) continue } - // providerPaymentStorage was found for epoch, start analyzing if unstake is necessary - // check if the same consumer is trying to complain a second time for this epoch - if slices.Contains(providerPaymentStorage.UnresponsivenessComplaints, clientAddr.String()) { - continue - } - providerPaymentStorage.UnresponsivenessComplaints = append(providerPaymentStorage.UnresponsivenessComplaints, clientAddr.String()) + // providerPaymentStorage was found for epoch -> add complainer's used CU + providerPaymentStorage.ComplainersTotalCu += cuSum - // now we check if we have more UnresponsivenessComplaints than maxComplaintsPerEpoch - if len(providerPaymentStorage.UnresponsivenessComplaints) >= maxComplaintsPerEpoch { - // we check if we have double complaints than previous "collectPaymentsFromNumberOfPreviousEpochs" epochs (including this one) payment requests - totalPaymentsInPreviousEpochs, err := k.getTotalPaymentsForPreviousEpochs(ctx, collectPaymentsFromNumberOfPreviousEpochs, epoch, chainID, sdkUnresponsiveProviderAddress) - totalPaymentRequests := totalPaymentsInPreviousEpochs + len(providerPaymentStorage.UniquePaymentStorageClientProvider) // get total number of payments including this epoch - if err != nil { - utils.LavaFormatError("lava_unresponsive_providers: couldnt fetch getTotalPaymentsForPreviousEpochs", err, nil) - } else if totalPaymentRequests*providerPaymentMultiplier < len(providerPaymentStorage.UnresponsivenessComplaints) { - // unstake provider - utils.LogLavaEvent(ctx, logger, types.ProviderJailedEventName, map[string]string{"provider_address": sdkUnresponsiveProviderAddress.String(), "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") - err = k.unSafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) - if err != nil { - utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) - continue - } - } - } // set the final provider payment storage state including the complaints k.SetProviderPaymentStorage(ctx, providerPaymentStorage) } return nil } - -func (k msgServer) getTotalPaymentsForPreviousEpochs(ctx sdk.Context, numberOfEpochs int, currentEpoch uint64, chainID string, sdkUnresponsiveProviderAddress sdk.AccAddress) (totalPaymentsReceived int, errorsGettingEpochs error) { - var totalPaymentRequests int - epochTemp := currentEpoch - for payment := 0; payment < numberOfEpochs; payment++ { - previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) - if err != nil { - return 0, err - } - previousEpochProviderStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, previousEpoch, sdkUnresponsiveProviderAddress) - previousEpochProviderPaymentStorage, providerPaymentStorageFound := k.GetProviderPaymentStorage(ctx, previousEpochProviderStorageKey) - if providerPaymentStorageFound { - totalPaymentRequests += len(previousEpochProviderPaymentStorage.UniquePaymentStorageClientProvider) // increase by the amount of previous epoch - } - epochTemp = previousEpoch - } - return totalPaymentRequests, nil -} - -func (k msgServer) unSafeUnstakeProviderEntry(ctx sdk.Context, providerKey string, chainID string, indexInStakeStorage uint64, existingEntry epochstoragetypes.StakeEntry) error { - err := k.epochStorageKeeper.RemoveStakeEntryCurrent(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage) - if err != nil { - return utils.LavaError(ctx, k.Logger(ctx), "relay_payment_unstake", map[string]string{"existingEntry": fmt.Sprintf("%+v", existingEntry)}, "tried to unstake unsafe but didnt find entry") - } - k.epochStorageKeeper.AppendUnstakeEntry(ctx, epochstoragetypes.ProviderKey, existingEntry) - return nil -} From c3829b7accaa791accc0dca29d90b7de5a29e131 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Wed, 11 Jan 2023 19:08:06 +0200 Subject: [PATCH 04/37] CNS-137: implemented new unresponsive punishment mechanism --- x/pairing/keeper/msg_server_relay_payment.go | 7 +- .../msg_server_unresponsive_provider.go | 245 +++++++++--------- x/pairing/keeper/provider_payment_storage.go | 13 + x/pairing/module.go | 10 + 4 files changed, 146 insertions(+), 129 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 332265918c..32b78fbd01 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -301,6 +301,9 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, return nil } + // the added complainer CU takes into account the number of providers the client complained on + complainerCuToAdd := cuSum / uint64(len(unresponsiveProviders)) + // iterate over the unresponsive providers list and update their complainers_total_cu for _, unresponsiveProvider := range unresponsiveProviders { // get provider address @@ -320,14 +323,14 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, Index: providerStorageKey, UniquePaymentStorageClientProvider: []*types.UniquePaymentStorageClientProvider{}, Epoch: epoch, - ComplainersTotalCu: cuSum, + ComplainersTotalCu: complainerCuToAdd, } k.SetProviderPaymentStorage(ctx, emptyProviderPaymentStorageWithComplaint) continue } // providerPaymentStorage was found for epoch -> add complainer's used CU - providerPaymentStorage.ComplainersTotalCu += cuSum + providerPaymentStorage.ComplainersTotalCu += complainerCuToAdd // set the final provider payment storage state including the complaints k.SetProviderPaymentStorage(ctx, providerPaymentStorage) diff --git a/x/pairing/keeper/msg_server_unresponsive_provider.go b/x/pairing/keeper/msg_server_unresponsive_provider.go index f6b37ed095..ce45b5914a 100644 --- a/x/pairing/keeper/msg_server_unresponsive_provider.go +++ b/x/pairing/keeper/msg_server_unresponsive_provider.go @@ -1,185 +1,176 @@ package keeper import ( - "encoding/json" "fmt" - "math" "strconv" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/lavanet/lava/x/pairing/types" - "github.com/tendermint/tendermint/libs/log" - "golang.org/x/exp/slices" ) -func (k msgServer) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { +type punishEntry struct { + chainID string + complainersUsedCu uint64 + providerServicedCu uint64 +} + +func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { // Get current epoch currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) - // Get epoch payments relevant to unresponsiveness from previous blocks - unresponsiveProviders := k.getPaymentsRelatedToUnresponiveness(ctx, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers) - - // Get CU serviced by the provider + // Get unreponsive providers that should be punished + providersToPunishMap, err := k.getUnresponsiveProvidersToPunish(ctx, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers) + if err != nil { + return err + } - // deal with unresponsive providers - err := k.dealWithUnresponsiveProviders(ctx, relay.UnresponsiveProviders, logger, clientAddr, epochStart, relay.ChainID) + // Punish unresponsive providers (currently unstake) + err = k.punishUnresponsiveProviders(ctx, providersToPunishMap) if err != nil { - utils.LogLavaEvent(ctx, logger, types.UnresponsiveProviderUnstakeFailedEventName, map[string]string{"err:": err.Error()}, "Error Unresponsive Providers could not unstake") + return err } + + return nil } -// Function that returns the payments objects relevant to the unresponsiveness punishment condition. -// The relevant payments are all the payments from the previous epoch that are determined by -// epochsNumToCheckCUForUnresponsiveProvider and epochsNumToCheckCUForComplainers. -func (k msgServer) getPaymentsRelatedToUnresponiveness(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (uint64, uint64, error) { - tempEpoch := currentEpoch - complainerUsedCU := uint64(0) - providerServicedCU := uint64(0) - - // Find which of the constants is larger to know when to stop iterating - maxEpochsBack := uint64(math.Max(float64(epochsNumToCheckCUForUnresponsiveProvider), float64(epochsNumToCheckCUForComplainers))) - - // Go over previous epoch payments - for counter := uint64(0); counter < maxEpochsBack; counter++ { - // Get previous epoch - previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, tempEpoch) +// Function that punishes providers. Current punishment is unstake +func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish map[string]string) error { + // Go over providers + for providerAddress, chainID := range providersToPunish { + // Get provider's sdk.Account address + sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) if err != nil { - return 0, 0, err + // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. + utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": providerAddress}) + continue } - // Get epoch payments from block. If the epoch doesn't contain payments, continue - epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, tempEpoch) - if !found { + // Get provider's stake entry + existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) + if !entryExists { + // if provider is not staked, nothing to do. continue } - if counter < epochsNumToCheckCUForComplainers { - for _, providerPaymentStorage := range epochPayments.GetClientsPayments() { - if len(providerPaymentStorage.UnresponsivenessComplaints) == 0 { - continue - } - for _, payment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { - payment.GetUsedCU() - } - } + utils.LogLavaEvent(ctx, k.Logger(ctx), types.ProviderJailedEventName, map[string]string{"provider_address": providerAddress, "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") + err = k.unsafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) + if err != nil { + utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) } - - // Update tempEpoch - tempEpoch = previousEpoch } - // check if lists are empty (no epochs had payments in them) - return complainerUsedCU, providerServicedCU, nil + return nil } -func (k msgServer) dealWithUnresponsiveProviders(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, clientAddr sdk.AccAddress, epoch uint64, chainID string) error { - var unresponsiveProviders []string - if len(unresponsiveData) == 0 { - return nil - } - err := json.Unmarshal(unresponsiveData, &unresponsiveProviders) - if err != nil { - return utils.LavaFormatError("unable to unmarshal unresponsive providers", err, &map[string]string{"UnresponsiveProviders": string(unresponsiveData), "dataLength": strconv.Itoa(len(unresponsiveData))}) - } - if len(unresponsiveProviders) == 0 { - // nothing to do. - return nil +// Function that returns a map that links between a provider that should be punished and its punishEntry +func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (map[string]string, error) { + providersPunishEntryMap := make(map[string]punishEntry) + providersToPunishMap := make(map[string]string) + epochTemp := currentEpoch + + // Get servicersToPair param + servicersToPair, err := k.ServicersToPairCount(ctx, currentEpoch) + if err != nil || servicersToPair == 0 { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get servicers to pair") } - for _, unresponsiveProvider := range unresponsiveProviders { - sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(unresponsiveProvider) - if err != nil { // if bad data was given, we cant parse it so we ignote it and continue this protects from spamming wrong information. - utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) - continue - } - existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) - // if !entryExists provider is alraedy unstaked - if !entryExists { - continue // if provider is not staked, nothing to do. + + // Go over previous epochs + counter := uint64(0) + for { + // We've finished going back epochs, break the loop + if counter >= epochsNumToCheckCUForComplainers && counter >= epochsNumToCheckCUForUnresponsiveProvider { + break } - providerStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, epoch, sdkUnresponsiveProviderAddress) - providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerStorageKey) + // Get previous epoch (from epochTemp) + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + } + // Get previous epoch's payments + epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, previousEpoch) if !found { - // currently this provider has not payments in this epoch and also no complaints, we need to add one complaint here - emptyProviderPaymentStorageWithComplaint := types.ProviderPaymentStorage{ - Index: providerStorageKey, - UniquePaymentStorageClientProvider: []*types.UniquePaymentStorageClientProvider{}, - Epoch: epoch, - UnresponsivenessComplaints: []string{clientAddr.String()}, - } - k.SetProviderPaymentStorage(ctx, emptyProviderPaymentStorageWithComplaint) - continue - } - // providerPaymentStorage was found for epoch, start analyzing if unstake is necessary - // check if the same consumer is trying to complain a second time for this epoch - if slices.Contains(providerPaymentStorage.UnresponsivenessComplaints, clientAddr.String()) { + epochTemp = previousEpoch + counter++ continue } - providerPaymentStorage.UnresponsivenessComplaints = append(providerPaymentStorage.UnresponsivenessComplaints, clientAddr.String()) + // Get providerPaymentStorage list + providerPaymentStorageList := epochPayments.GetClientsPayments() - // Get the amount of CU used by the complainers (consumers that complained on the provider) - // complainersCU := - for _, complaint := range providerPaymentStorage.UnresponsivenessComplaints { - complaint - } + // Go over providerPaymentStorage + for _, providerPaymentStorage := range providerPaymentStorageList { + providerServicedCU := uint64(0) + complainersUsedCu := uint64(0) - // Get the amount of CU serviced by the unresponsive provider - unresponsiveProviderCU, err := k.getTotalCUServicedByProviderFromPreviousEpochs(ctx, epochsNumToCheckCUForUnresponsiveProvider, epoch, chainID, sdkUnresponsiveProviderAddress) - - // now we check if we have more UnresponsivenessComplaints than maxComplaintsPerEpoch - if len(providerPaymentStorage.UnresponsivenessComplaints) >= maxComplaintsPerEpoch { - // we check if we have double complaints than previous "collectPaymentsFromNumberOfPreviousEpochs" epochs (including this one) payment requests - totalPaymentsInPreviousEpochs, err := k.getTotalPaymentsForPreviousEpochs(ctx, collectPaymentsFromNumberOfPreviousEpochs, epoch, chainID, sdkUnresponsiveProviderAddress) - totalPaymentRequests := totalPaymentsInPreviousEpochs + len(providerPaymentStorage.UniquePaymentStorageClientProvider) // get total number of payments including this epoch - if err != nil { - utils.LavaFormatError("lava_unresponsive_providers: couldnt fetch getTotalPaymentsForPreviousEpochs", err, nil) - } else if totalPaymentRequests*providerPaymentMultiplier < len(providerPaymentStorage.UnresponsivenessComplaints) { - // unstake provider - utils.LogLavaEvent(ctx, logger, types.ProviderJailedEventName, map[string]string{"provider_address": sdkUnresponsiveProviderAddress.String(), "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") - err = k.unSafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) - if err != nil { - utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) - continue + // Collect serviced CU for provider + if counter < epochsNumToCheckCUForUnresponsiveProvider { + // Go over the unique payments collected by the provider. Sum the serviced CU + for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { + providerServicedCU += uniquePayment.GetUsedCU() } } + + // Collect complainers CU (divided by servicersToPair) + if counter < epochsNumToCheckCUForComplainers { + complainersUsedCu = providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) + } + + // Get provider address + providerAddress := k.getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorage.Index) + chainID := k.getChainIDFromProviderPaymentStorageKey(providerPaymentStorage.Index) + + // find the provider's punishEntry in map + providerPunishEntry, found := providersPunishEntryMap[providerAddress] + + // update provider's punish entry + if found { + providerPunishEntry.complainersUsedCu += complainersUsedCu + providerPunishEntry.providerServicedCu += providerServicedCU + } else { + providersPunishEntryMap[providerAddress] = punishEntry{complainersUsedCu: complainersUsedCu, providerServicedCu: providerServicedCU, chainID: chainID} + } } - // set the final provider payment storage state including the complaints - k.SetProviderPaymentStorage(ctx, providerPaymentStorage) + + // update epochTemp + epochTemp = previousEpoch } - return nil -} -func (k msgServer) getTotalCUServicedByProviderFromPreviousEpochs(ctx sdk.Context, numberOfEpochs int, currentEpoch uint64, chainID string, sdkUnresponsiveProviderAddress sdk.AccAddress) (uint64, error) { - providerServicedCU := uint64(0) - epochTemp := currentEpoch - for payment := 0; payment < numberOfEpochs; payment++ { - previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) - if err != nil { - return 0, err - } - previousEpochProviderStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, previousEpoch, sdkUnresponsiveProviderAddress) - previousEpochProviderPaymentStorage, providerPaymentStorageFound := k.GetProviderPaymentStorage(ctx, previousEpochProviderStorageKey) - if !providerPaymentStorageFound { - return 0, utils.LavaError(ctx, k.Logger(ctx), "get_provider_payment_storage", map[string]string{"providerStorageKey": fmt.Sprintf("%+v", previousEpochProviderStorageKey), "epoch": fmt.Sprintf("%+v", previousEpoch)}, "couldn't get provider payment storage with given key") - } - for _, uniquePayment := range previousEpochProviderPaymentStorage.GetUniquePaymentStorageClientProvider() { - providerServicedCU += uniquePayment.GetUsedCU() + // Get providers that should be punished + for providerAddress, punishEntry := range providersPunishEntryMap { + // provider doesn't have payments (serviced CU = 0) + if punishEntry.providerServicedCu == 0 { + // Try getting the provider's stake entry + _, foundStakeEntry := k.epochStorageKeeper.GetEpochStakeEntries(ctx, currentEpoch, epochstoragetypes.ProviderKey, punishEntry.chainID) + + // if stake entry is not found -> this is provider's first epoch (didn't get a chance to stake yet) -> don't punish him + if !foundStakeEntry { + continue + } } - epochTemp = previousEpoch + // provider's served less CU than the sum of the complainers CU -> should be punished + if punishEntry.complainersUsedCu > punishEntry.providerServicedCu { + providersToPunishMap[providerAddress] = punishEntry.chainID + } } - return providerServicedCU, nil + + return providersToPunishMap, nil } -func (k msgServer) unSafeUnstakeProviderEntry(ctx sdk.Context, providerKey string, chainID string, indexInStakeStorage uint64, existingEntry epochstoragetypes.StakeEntry) error { +// Function that unstakes a provider +func (k Keeper) unsafeUnstakeProviderEntry(ctx sdk.Context, providerKey string, chainID string, indexInStakeStorage uint64, existingEntry epochstoragetypes.StakeEntry) error { + // Remove the provider's stake entry err := k.epochStorageKeeper.RemoveStakeEntryCurrent(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage) if err != nil { return utils.LavaError(ctx, k.Logger(ctx), "relay_payment_unstake", map[string]string{"existingEntry": fmt.Sprintf("%+v", existingEntry)}, "tried to unstake unsafe but didnt find entry") } + + // Appened the provider's stake entry to the unstake entry list k.epochStorageKeeper.AppendUnstakeEntry(ctx, epochstoragetypes.ProviderKey, existingEntry) + return nil } diff --git a/x/pairing/keeper/provider_payment_storage.go b/x/pairing/keeper/provider_payment_storage.go index 534aa23dfb..a0950ff13d 100644 --- a/x/pairing/keeper/provider_payment_storage.go +++ b/x/pairing/keeper/provider_payment_storage.go @@ -3,6 +3,7 @@ package keeper import ( "fmt" "strconv" + "strings" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -101,3 +102,15 @@ func (k Keeper) GetTotalUsedCUForConsumerPerEpoch(ctx sdk.Context, consumerAddre } return usedCUProviderTotal, nil } + +func (k Keeper) getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorageKey string) string { + return strings.Split(providerPaymentStorageKey, "_")[2] +} + +func (k Keeper) getEpochFromProviderPaymentStorageKey(providerPaymentStorageKey string) string { + return strings.Split(providerPaymentStorageKey, "_")[1] +} + +func (k Keeper) getChainIDFromProviderPaymentStorageKey(providerPaymentStorageKey string) string { + return strings.Split(providerPaymentStorageKey, "_")[0] +} diff --git a/x/pairing/module.go b/x/pairing/module.go index c742d380fa..d55dd9d582 100644 --- a/x/pairing/module.go +++ b/x/pairing/module.go @@ -180,6 +180,7 @@ func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { // 1. remove old session payments // 2. unstake any unstaking providers // 3. unstake any unstaking users + // 4. unstake/jail unresponsive providers // 1. err := am.keeper.RemoveOldEpochPayment(ctx) @@ -188,6 +189,15 @@ func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { // 2+3. err = am.keeper.CheckUnstakingForCommit(ctx) logOnErr(err, "CheckUnstakingForCommit") + + // consts TODO: where to put it? + const ( + epochsNumToCheckCUForUnresponsiveProvider = 4 // number of epochs to sum CU that the provider serviced + epochsNumToCheckCUForComplainers = 2 // number of epochs to sum CU of complainers against the provider + ) + // 4. unstake unresponsive providers + err = am.keeper.UnstakeUnresponsiveProviders(ctx, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers) + logOnErr(err, "UnstakeUnresponsiveProviders") } } From 316f84d0f50af642a8ac5e2734a8259b53174704 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Thu, 12 Jan 2023 13:28:50 +0200 Subject: [PATCH 05/37] CNS-137: small fixes --- x/pairing/keeper/msg_server_relay_payment.go | 4 ++-- x/pairing/keeper/msg_server_unresponsive_provider.go | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 32b78fbd01..0f854cb40a 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -273,7 +273,7 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen utils.LogLavaEvent(ctx, logger, types.RelayPaymentEventName, details, "New Proof Of Work Was Accepted") // update provider payment storage with complainer's CU - err = k.updateProviderPaymentStorageWithComplainerCU(ctx, relay.UnresponsiveProviders, logger, clientAddr, epochStart, relay.ChainID, relay.CuSum) + err = k.updateProviderPaymentStorageWithComplainerCU(ctx, relay.UnresponsiveProviders, logger, epochStart, relay.ChainID, relay.CuSum) if err != nil { utils.LogLavaEvent(ctx, logger, types.UnresponsiveProviderUnstakeFailedEventName, map[string]string{"err:": err.Error()}, "Error Unresponsive Providers could not unstake") } @@ -281,7 +281,7 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen return &types.MsgRelayPaymentResponse{}, nil } -func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, clientAddr sdk.AccAddress, epoch uint64, chainID string, cuSum uint64) error { +func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, epoch uint64, chainID string, cuSum uint64) error { var unresponsiveProviders []string // check that unresponsiveData exists diff --git a/x/pairing/keeper/msg_server_unresponsive_provider.go b/x/pairing/keeper/msg_server_unresponsive_provider.go index ce45b5914a..c91314ffdf 100644 --- a/x/pairing/keeper/msg_server_unresponsive_provider.go +++ b/x/pairing/keeper/msg_server_unresponsive_provider.go @@ -37,6 +37,11 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU // Function that punishes providers. Current punishment is unstake func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish map[string]string) error { + // if providersToPunish map is empty, do nothing + if len(providersToPunish) == 0 { + return nil + } + // Go over providers for providerAddress, chainID := range providersToPunish { // Get provider's sdk.Account address @@ -66,6 +71,11 @@ func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish m // Function that returns a map that links between a provider that should be punished and its punishEntry func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (map[string]string, error) { + // check the epochsNum consts + if epochsNumToCheckCUForComplainers <= 0 || epochsNumToCheckCUForUnresponsiveProvider <= 0 { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") + } + providersPunishEntryMap := make(map[string]punishEntry) providersToPunishMap := make(map[string]string) epochTemp := currentEpoch From 8b4e2ba5a04282474dfdb05063e4f88eacd75709 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Thu, 12 Jan 2023 13:40:24 +0200 Subject: [PATCH 06/37] CNS-137: moved unresponsive unit test to seperate file + rename --- .../keeper/msg_server_relay_payment_test.go | 149 ---------------- x/pairing/keeper/unreponsive_provider_test.go | 162 ++++++++++++++++++ ...e_provider.go => unresponsive_provider.go} | 0 3 files changed, 162 insertions(+), 149 deletions(-) create mode 100644 x/pairing/keeper/unreponsive_provider_test.go rename x/pairing/keeper/{msg_server_unresponsive_provider.go => unresponsive_provider.go} (100%) diff --git a/x/pairing/keeper/msg_server_relay_payment_test.go b/x/pairing/keeper/msg_server_relay_payment_test.go index cf769dc9a1..ed001ae347 100644 --- a/x/pairing/keeper/msg_server_relay_payment_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_test.go @@ -325,155 +325,6 @@ func setupClientsAndProvidersForUnresponsiveness(t *testing.T, amountOfClients i return ts } -func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { - testClientAmount := 4 - testProviderAmount := 2 - ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) - - for i := 0; i < 2; i++ { // move to epoch 3 so we can check enough epochs in the past - ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) - } - staked_amount, _, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) - balanceProvideratBeforeStake := staked_amount.Stake.Amount.Int64() + ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), ts.providers[1].address, epochstoragetypes.TokenDenom).Amount.Int64() - - unresponsiveProvidersData, err := json.Marshal([]string{ts.providers[1].address.String()}) - require.Nil(t, err) - var Relays []*types.RelayRequest - for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints - relayRequest := &types.RelayRequest{ - Provider: ts.providers[0].address.String(), - ApiUrl: "", - Data: []byte(ts.spec.Apis[0].Name), - SessionId: uint64(1), - ChainID: ts.spec.Name, - CuSum: ts.spec.Apis[0].ComputeUnits * 10, - BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), - RelayNum: 0, - RequestBlock: -1, - DataReliability: nil, - UnresponsiveProviders: unresponsiveProvidersData, // create the complaint - } - - sig, err := sigs.SignRelay(ts.clients[clientIndex].secretKey, *relayRequest) - relayRequest.Sig = sig - require.Nil(t, err) - Relays = append(Relays, relayRequest) - } - _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) - require.Nil(t, err) - // testing that the provider was unstaked. and checking his balance after many epochs - _, unStakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) - require.True(t, unStakeStoragefound) - _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) - require.False(t, stakeStorageFound) - - OriginalBlockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) - blocksToSave, err := ts.keepers.Epochstorage.BlocksToSave(sdk.UnwrapSDKContext(ts.ctx), OriginalBlockHeight) - require.Nil(t, err) - for { // move to epoch 13 so we can check balance at the end - ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) - blockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) - if blockHeight > blocksToSave+OriginalBlockHeight { - break - } - } - // validate that the provider is no longer unstaked. and stake was returned. - _, unStakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) - require.False(t, unStakeStoragefound) - // also that the provider wasnt returned to stake pool - _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) - require.False(t, stakeStorageFound) - - balanceProviderAfterUnstakeMoneyReturned := ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), ts.providers[1].address, epochstoragetypes.TokenDenom).Amount.Int64() - require.Equal(t, balanceProvideratBeforeStake, balanceProviderAfterUnstakeMoneyReturned) -} - -func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t *testing.T) { - testClientAmount := 4 - testProviderAmount := 2 - ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) - for i := 0; i < 2; i++ { // move to epoch 3 so we can check enough epochs in the past - ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) - } - - unresponsiveProvidersData, err := json.Marshal([]string{ts.providers[1].address.String()}) - require.Nil(t, err) - var Relays []*types.RelayRequest - for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints - - relayRequest := &types.RelayRequest{ - Provider: ts.providers[0].address.String(), - ApiUrl: "", - Data: []byte(ts.spec.Apis[0].Name), - SessionId: uint64(1), - ChainID: ts.spec.Name, - CuSum: ts.spec.Apis[0].ComputeUnits * 10, - BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), - RelayNum: 0, - RequestBlock: -1, - DataReliability: nil, - UnresponsiveProviders: unresponsiveProvidersData, // create the complaint - } - - sig, err := sigs.SignRelay(ts.clients[clientIndex].secretKey, *relayRequest) - relayRequest.Sig = sig - require.Nil(t, err) - Relays = append(Relays, relayRequest) - } - _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) - require.Nil(t, err) - // testing that the provider wasnt unstaked. - _, unStakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) - require.True(t, unStakeStoragefound) - _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) - require.False(t, stakeStorageFound) - - // continue reporting provider after unstake - for i := 0; i < 2; i++ { // move to epoch 5 - ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) - } - - var RelaysAfter []*types.RelayRequest - for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints - - relayRequest := &types.RelayRequest{ - Provider: ts.providers[0].address.String(), - ApiUrl: "", - Data: []byte(ts.spec.Apis[0].Name), - SessionId: uint64(2), - ChainID: ts.spec.Name, - CuSum: ts.spec.Apis[0].ComputeUnits * 10, - BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), - RelayNum: 0, - RequestBlock: -1, - DataReliability: nil, - UnresponsiveProviders: unresponsiveProvidersData, // create the complaint - } - sig, err := sigs.SignRelay(ts.clients[clientIndex].secretKey, *relayRequest) - relayRequest.Sig = sig - require.Nil(t, err) - RelaysAfter = append(RelaysAfter, relayRequest) - } - _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: RelaysAfter}) - require.Nil(t, err) - - _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) - require.False(t, stakeStorageFound) - _, unStakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) - require.True(t, unStakeStoragefound) - - // validating number of appearances for unstaked provider in unstake storage (if more than once found, throw an error) - storage, foundStorage := ts.keepers.Epochstorage.GetStakeStorageUnstake(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey) - require.True(t, foundStorage) - var numberOfAppearances int - for _, stored := range storage.StakeEntries { - if stored.Address == ts.providers[1].address.String() { - numberOfAppearances += 1 - } - } - require.Equal(t, numberOfAppearances, 1) -} - // only one epoch is not enough for the unstaking to happen need atleast two epochs in the past func TestRelayPaymentNotUnstakingProviderForUnresponsivenessIfNoEpochInformation(t *testing.T) { testClientAmount := 4 diff --git a/x/pairing/keeper/unreponsive_provider_test.go b/x/pairing/keeper/unreponsive_provider_test.go new file mode 100644 index 0000000000..23067803c4 --- /dev/null +++ b/x/pairing/keeper/unreponsive_provider_test.go @@ -0,0 +1,162 @@ +package keeper_test + +import ( + "encoding/json" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/relayer/sigs" + testkeeper "github.com/lavanet/lava/testutil/keeper" + epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" + "github.com/lavanet/lava/x/pairing/types" + "github.com/stretchr/testify/require" +) + +func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { + testClientAmount := 4 + testProviderAmount := 2 + ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) + + for i := 0; i < 2; i++ { // move to epoch 3 so we can check enough epochs in the past + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + staked_amount, _, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) + balanceProvideratBeforeStake := staked_amount.Stake.Amount.Int64() + ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), ts.providers[1].address, epochstoragetypes.TokenDenom).Amount.Int64() + + unresponsiveProvidersData, err := json.Marshal([]string{ts.providers[1].address.String()}) + require.Nil(t, err) + var Relays []*types.RelayRequest + for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints + relayRequest := &types.RelayRequest{ + Provider: ts.providers[0].address.String(), + ApiUrl: "", + Data: []byte(ts.spec.Apis[0].Name), + SessionId: uint64(1), + ChainID: ts.spec.Name, + CuSum: ts.spec.Apis[0].ComputeUnits * 10, + BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), + RelayNum: 0, + RequestBlock: -1, + DataReliability: nil, + UnresponsiveProviders: unresponsiveProvidersData, // create the complaint + } + + sig, err := sigs.SignRelay(ts.clients[clientIndex].secretKey, *relayRequest) + relayRequest.Sig = sig + require.Nil(t, err) + Relays = append(Relays, relayRequest) + } + _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) + require.Nil(t, err) + // testing that the provider was unstaked. and checking his balance after many epochs + _, unStakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) + require.True(t, unStakeStoragefound) + _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) + require.False(t, stakeStorageFound) + + OriginalBlockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) + blocksToSave, err := ts.keepers.Epochstorage.BlocksToSave(sdk.UnwrapSDKContext(ts.ctx), OriginalBlockHeight) + require.Nil(t, err) + for { // move to epoch 13 so we can check balance at the end + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + blockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) + if blockHeight > blocksToSave+OriginalBlockHeight { + break + } + } + // validate that the provider is no longer unstaked. and stake was returned. + _, unStakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) + require.False(t, unStakeStoragefound) + // also that the provider wasnt returned to stake pool + _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) + require.False(t, stakeStorageFound) + + balanceProviderAfterUnstakeMoneyReturned := ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), ts.providers[1].address, epochstoragetypes.TokenDenom).Amount.Int64() + require.Equal(t, balanceProvideratBeforeStake, balanceProviderAfterUnstakeMoneyReturned) +} + +func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t *testing.T) { + testClientAmount := 4 + testProviderAmount := 2 + ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) + for i := 0; i < 2; i++ { // move to epoch 3 so we can check enough epochs in the past + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + + unresponsiveProvidersData, err := json.Marshal([]string{ts.providers[1].address.String()}) + require.Nil(t, err) + var Relays []*types.RelayRequest + for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints + + relayRequest := &types.RelayRequest{ + Provider: ts.providers[0].address.String(), + ApiUrl: "", + Data: []byte(ts.spec.Apis[0].Name), + SessionId: uint64(1), + ChainID: ts.spec.Name, + CuSum: ts.spec.Apis[0].ComputeUnits * 10, + BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), + RelayNum: 0, + RequestBlock: -1, + DataReliability: nil, + UnresponsiveProviders: unresponsiveProvidersData, // create the complaint + } + + sig, err := sigs.SignRelay(ts.clients[clientIndex].secretKey, *relayRequest) + relayRequest.Sig = sig + require.Nil(t, err) + Relays = append(Relays, relayRequest) + } + _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) + require.Nil(t, err) + // testing that the provider wasnt unstaked. + _, unStakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) + require.True(t, unStakeStoragefound) + _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) + require.False(t, stakeStorageFound) + + // continue reporting provider after unstake + for i := 0; i < 2; i++ { // move to epoch 5 + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + + var RelaysAfter []*types.RelayRequest + for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints + + relayRequest := &types.RelayRequest{ + Provider: ts.providers[0].address.String(), + ApiUrl: "", + Data: []byte(ts.spec.Apis[0].Name), + SessionId: uint64(2), + ChainID: ts.spec.Name, + CuSum: ts.spec.Apis[0].ComputeUnits * 10, + BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), + RelayNum: 0, + RequestBlock: -1, + DataReliability: nil, + UnresponsiveProviders: unresponsiveProvidersData, // create the complaint + } + sig, err := sigs.SignRelay(ts.clients[clientIndex].secretKey, *relayRequest) + relayRequest.Sig = sig + require.Nil(t, err) + RelaysAfter = append(RelaysAfter, relayRequest) + } + _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: RelaysAfter}) + require.Nil(t, err) + + _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) + require.False(t, stakeStorageFound) + _, unStakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) + require.True(t, unStakeStoragefound) + + // validating number of appearances for unstaked provider in unstake storage (if more than once found, throw an error) + storage, foundStorage := ts.keepers.Epochstorage.GetStakeStorageUnstake(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey) + require.True(t, foundStorage) + var numberOfAppearances int + for _, stored := range storage.StakeEntries { + if stored.Address == ts.providers[1].address.String() { + numberOfAppearances += 1 + } + } + require.Equal(t, numberOfAppearances, 1) +} diff --git a/x/pairing/keeper/msg_server_unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go similarity index 100% rename from x/pairing/keeper/msg_server_unresponsive_provider.go rename to x/pairing/keeper/unresponsive_provider.go From 481e2cdf301bffc4900000464000d2fae798f206 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 15 Jan 2023 14:02:38 +0200 Subject: [PATCH 07/37] CNS-137: finished implementing the new jailing mechanism --- x/pairing/keeper/msg_server_relay_payment.go | 16 +- x/pairing/keeper/unresponsive_provider.go | 247 ++++++++++++------- x/pairing/types/errors.go | 1 + 3 files changed, 168 insertions(+), 96 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 0f854cb40a..196fc1844b 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -289,7 +289,7 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, return nil } - // unmarshel the byte array unresponsiveData to get a list of unresponsive providers Bech32 addresses + // unmarshal the byte array unresponsiveData to get a list of unresponsive providers Bech32 addresses err := json.Unmarshal(unresponsiveData, &unresponsiveProviders) if err != nil { return utils.LavaFormatError("unable to unmarshal unresponsive providers", err, &map[string]string{"UnresponsiveProviders": string(unresponsiveData), "dataLength": strconv.Itoa(len(unresponsiveData))}) @@ -325,8 +325,18 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, Epoch: epoch, ComplainersTotalCu: complainerCuToAdd, } - k.SetProviderPaymentStorage(ctx, emptyProviderPaymentStorageWithComplaint) - continue + + // add the new empty providerPaymentStorage to epochPayments + epochPayments, found, key := k.GetEpochPaymentsFromBlock(ctx, epoch) + if !found { + epochPayments = types.EpochPayments{Index: key, ClientsPayments: []*types.ProviderPaymentStorage{&emptyProviderPaymentStorageWithComplaint}} + } else { + epochPayments.ClientsPayments = append(epochPayments.ClientsPayments, &emptyProviderPaymentStorageWithComplaint) + } + k.SetEpochPayments(ctx, epochPayments) + + // assign providerPaymentStorage with the new empty providerPaymentStorage + providerPaymentStorage = emptyProviderPaymentStorageWithComplaint } // providerPaymentStorage was found for epoch -> add complainer's used CU diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index c91314ffdf..b1270c2814 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -3,6 +3,7 @@ package keeper import ( "fmt" "strconv" + "strings" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" @@ -11,9 +12,9 @@ import ( ) type punishEntry struct { - chainID string - complainersUsedCu uint64 - providerServicedCu uint64 + providerPaymentStorageIndexList []string // index list of providerPaymentStorage objects that share providerAddress + chainID (but not epoch) + complainersUsedCu uint64 // sum of the complainers' CU over epochsNumToCheckCUForComplainers epochs back (start counting from currentEpoch-epochsNumToCheckCUForUnresponsiveProvider) + providerServicedCu uint64 // sum of the unresponsive provider's serviced CU over epochsNumToCheckCUForUnresponsiveProvider epochs back (start counting from current epoch) } func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { @@ -23,10 +24,15 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU // Get unreponsive providers that should be punished providersToPunishMap, err := k.getUnresponsiveProvidersToPunish(ctx, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers) if err != nil { + // if the epoch is too early, don't punish and log the event + if err == types.EpochTooEarlyForUnresponsiveProviderJailError { + utils.LavaFormatInfo("Epoch too early to punish unresponsive providers", &map[string]string{"epoch": fmt.Sprintf("%+v", currentEpoch)}) + return nil + } return err } - // Punish unresponsive providers (currently unstake) + // Punish unresponsive providers (the punishment is currently unstake) err = k.punishUnresponsiveProviders(ctx, providersToPunishMap) if err != nil { return err @@ -35,143 +41,198 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU return nil } -// Function that punishes providers. Current punishment is unstake -func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish map[string]string) error { - // if providersToPunish map is empty, do nothing - if len(providersToPunish) == 0 { - return nil +// Function that returns a map that links between a provider that should be punished and its punishEntry +func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (map[string][]string, error) { + // check the epochsNum consts + if epochsNumToCheckCUForComplainers <= 0 || epochsNumToCheckCUForUnresponsiveProvider <= 0 { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") } - // Go over providers - for providerAddress, chainID := range providersToPunish { - // Get provider's sdk.Account address - sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) - if err != nil { - // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. - utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": providerAddress}) - continue - } - - // Get provider's stake entry - existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) - if !entryExists { - // if provider is not staked, nothing to do. - continue - } + providersPunishEntryMap := make(map[string]punishEntry) // map of punishEntryKey keys (string) with punishEntry values (punishEntryKey = providerAddress_chainID) + providersToPunishMap := make(map[string][]string) // map of punishEntryKey keys (string) with list of providerPaymentStorage indices values (string array) (punishEntryKey = providerAddress_chainID) - utils.LogLavaEvent(ctx, k.Logger(ctx), types.ProviderJailedEventName, map[string]string{"provider_address": providerAddress, "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") - err = k.unsafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) - if err != nil { - utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) - } + // handle very early epochs (basically, don't punish) + epochBlocks, err := k.epochStorageKeeper.EpochBlocks(ctx, currentEpoch) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_epoch_blocks", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get epoch blocks param") + } + if currentEpoch < (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider)*epochBlocks { + // To check for punishment, we have to go back (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing + return nil, types.EpochTooEarlyForUnresponsiveProviderJailError } - return nil -} + // Go over previous epochs to count the CU serviced by the provider + epochAfterCountingProviderCu, err := k.countCuForUnresponsiveProviderAndComplainers(ctx, true, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, providersPunishEntryMap) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "count_cu_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't count the CU of the unresponsive provider") + } -// Function that returns a map that links between a provider that should be punished and its punishEntry -func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (map[string]string, error) { - // check the epochsNum consts - if epochsNumToCheckCUForComplainers <= 0 || epochsNumToCheckCUForUnresponsiveProvider <= 0 { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") + // Go over previous epochs (from the point the last loop finished) to count the CU of clients that complained about the provider + _, err = k.countCuForUnresponsiveProviderAndComplainers(ctx, false, epochAfterCountingProviderCu, epochsNumToCheckCUForComplainers, providersPunishEntryMap) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "count_cu_complainers", map[string]string{"err": err.Error()}, "couldn't count the CU of the complainers") } - providersPunishEntryMap := make(map[string]punishEntry) - providersToPunishMap := make(map[string]string) - epochTemp := currentEpoch + // Get providers that should be punished + for punishEntryKey, punishEntry := range providersPunishEntryMap { + // provider doesn't have payments (serviced CU = 0) + if punishEntry.providerServicedCu == 0 { + chainID := strings.Split(punishEntryKey, "_")[1] - // Get servicersToPair param - servicersToPair, err := k.ServicersToPairCount(ctx, currentEpoch) - if err != nil || servicersToPair == 0 { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get servicers to pair") - } + // Try getting the provider's stake entry + _, foundStakeEntry := k.epochStorageKeeper.GetEpochStakeEntries(ctx, currentEpoch, epochstoragetypes.ProviderKey, chainID) - // Go over previous epochs - counter := uint64(0) - for { - // We've finished going back epochs, break the loop - if counter >= epochsNumToCheckCUForComplainers && counter >= epochsNumToCheckCUForUnresponsiveProvider { - break + // if stake entry is not found -> this is the provider's first epoch (didn't get a chance to stake yet) -> don't punish him + if !foundStakeEntry { + continue + } + } + + // The provider served less CU than the sum of the complainers CU -> should be punished + if punishEntry.complainersUsedCu > punishEntry.providerServicedCu { + providersToPunishMap[punishEntryKey] = punishEntry.providerPaymentStorageIndexList } + } + + return providersToPunishMap, nil +} +// Function to count the CU serviced by the unresponsive provider or the CU of the complainers. +// The function counts CU from back. The number of epochs to go back is . The function returns the last visited epoch +func (k Keeper) countCuForUnresponsiveProviderAndComplainers(ctx sdk.Context, isProvider bool, epoch uint64, epochsNumToGoBack uint64, providersPunishEntryMap map[string]punishEntry) (uint64, error) { + epochTemp := epoch + + for counter := uint64(0); counter < epochsNumToGoBack; counter++ { // Get previous epoch (from epochTemp) previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) if err != nil { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + return 0, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") } - // Get previous epoch's payments + // Get previous epoch's epochPayments epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, previousEpoch) if !found { + // No epochPayments found -> continue to the next iteration epochTemp = previousEpoch - counter++ continue } // Get providerPaymentStorage list providerPaymentStorageList := epochPayments.GetClientsPayments() - // Go over providerPaymentStorage + // Go over providerPaymentStorage list + cuCount := uint64(0) for _, providerPaymentStorage := range providerPaymentStorageList { - providerServicedCU := uint64(0) - complainersUsedCu := uint64(0) - - // Collect serviced CU for provider - if counter < epochsNumToCheckCUForUnresponsiveProvider { - // Go over the unique payments collected by the provider. Sum the serviced CU - for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { - providerServicedCU += uniquePayment.GetUsedCU() - } - } - - // Collect complainers CU (divided by servicersToPair) - if counter < epochsNumToCheckCUForComplainers { - complainersUsedCu = providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) - } - - // Get provider address + // Get provider address and chainID providerAddress := k.getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorage.Index) chainID := k.getChainIDFromProviderPaymentStorageKey(providerPaymentStorage.Index) + // Create a punishEntryKey from the provider's address and the chain ID + punishEntryKey := providerAddress + "_" + chainID + // find the provider's punishEntry in map - providerPunishEntry, found := providersPunishEntryMap[providerAddress] + providerPunishEntry, punishEntryFound := providersPunishEntryMap[punishEntryKey] - // update provider's punish entry - if found { - providerPunishEntry.complainersUsedCu += complainersUsedCu - providerPunishEntry.providerServicedCu += providerServicedCU + if isProvider { + // if isProvider is true, we count the CU serviced by the unersponsive provider + for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { + cuCount += uniquePayment.GetUsedCU() + } + if punishEntryFound { + // punishEntry found -> add the cuCount to providerServicedCu + providerPunishEntry.providerServicedCu += cuCount + } else { + // punishEntry not found -> create a new one and add it to the map + providersPunishEntryMap[punishEntryKey] = punishEntry{complainersUsedCu: 0, providerServicedCu: cuCount, providerPaymentStorageIndexList: []string{providerPaymentStorage.Index}} + } } else { - providersPunishEntryMap[providerAddress] = punishEntry{complainersUsedCu: complainersUsedCu, providerServicedCu: providerServicedCU, chainID: chainID} + // Get servicersToPair param + servicersToPair, err := k.ServicersToPairCount(ctx, epoch) + if err != nil || servicersToPair == 0 { + return 0, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") + } + + // Collect complainers CU (divided by servicersToPair) + cuCount = providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) + + if punishEntryFound { + // punishEntry found -> add the cuCount to complainersUsedCu + providerPunishEntry.complainersUsedCu += cuCount + } else { + // punishEntry not found -> create a new one and add it to the map + providersPunishEntryMap[punishEntryKey] = punishEntry{complainersUsedCu: cuCount, providerServicedCu: 0, providerPaymentStorageIndexList: []string{providerPaymentStorage.Index}} + } } + // add the providerPaymentStorage index to the providerPaymentStorageIndexList + providerPunishEntry.providerPaymentStorageIndexList = append(providerPunishEntry.providerPaymentStorageIndexList, providerPaymentStorage.Index) } // update epochTemp epochTemp = previousEpoch } - // Get providers that should be punished - for providerAddress, punishEntry := range providersPunishEntryMap { - // provider doesn't have payments (serviced CU = 0) - if punishEntry.providerServicedCu == 0 { - // Try getting the provider's stake entry - _, foundStakeEntry := k.epochStorageKeeper.GetEpochStakeEntries(ctx, currentEpoch, epochstoragetypes.ProviderKey, punishEntry.chainID) + return epochTemp, nil +} - // if stake entry is not found -> this is provider's first epoch (didn't get a chance to stake yet) -> don't punish him - if !foundStakeEntry { - continue - } +// Function that punishes providers. Current punishment is unstake +func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish map[string][]string) error { + // if providersToPunish map is empty, do nothing + if len(providersToPunish) == 0 { + return nil + } + + // Go over providers + for punishEntryKey, providerPaymentStorageIndexList := range providersToPunish { + // extract from punishEntryKey the provider address and the chain ID + providerAddress := strings.Split(punishEntryKey, "_")[0] + chainID := strings.Split(punishEntryKey, "_")[1] + + // Get provider's sdk.Account address + sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) + if err != nil { + // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. + utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": providerAddress}) + continue } - // provider's served less CU than the sum of the complainers CU -> should be punished - if punishEntry.complainersUsedCu > punishEntry.providerServicedCu { - providersToPunishMap[providerAddress] = punishEntry.chainID + // Get provider's stake entry + existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) + if !entryExists { + // if provider is not staked, nothing to do. + continue + } + + // unstake the unresponsive provider + utils.LogLavaEvent(ctx, k.Logger(ctx), types.ProviderJailedEventName, map[string]string{"provider_address": providerAddress, "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") + err = k.unsafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) + if err != nil { + utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) } + + // reset the provider's complainer CU (so he won't get punished for the same complaints twice) + k.resetComplainersCU(ctx, providerPaymentStorageIndexList) } - return providersToPunishMap, nil + return nil +} + +// Function that reset the complainer CU of providerPaymentStorage objects that can be accessed using providerPaymentStorageIndexList +func (k Keeper) resetComplainersCU(ctx sdk.Context, providerPaymentStorageIndexList []string) { + // go over the providerPaymentStorageIndexList + for _, providerPaymentStorageIndex := range providerPaymentStorageIndexList { + // get providerPaymentStorage using its index + providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageIndex) + if !found { + continue + } + + // reset the complainer CU + providerPaymentStorage.ComplainersTotalCu = 0 + k.SetProviderPaymentStorage(ctx, providerPaymentStorage) + } } -// Function that unstakes a provider +// Function that unstakes a provider (considered unsafe because it doesn't check that the provider is staked. It's ok since we check the provider is staked before we call it) func (k Keeper) unsafeUnstakeProviderEntry(ctx sdk.Context, providerKey string, chainID string, indexInStakeStorage uint64, existingEntry epochstoragetypes.StakeEntry) error { // Remove the provider's stake entry err := k.epochStorageKeeper.RemoveStakeEntryCurrent(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage) diff --git a/x/pairing/types/errors.go b/x/pairing/types/errors.go index 3bc2851b3b..a335d4a6bd 100644 --- a/x/pairing/types/errors.go +++ b/x/pairing/types/errors.go @@ -13,4 +13,5 @@ var ( PreviousEpochStartIsBlockZeroError = sdkerrors.New("PreviousEpochStartIsBlockZeroError Error", 686, "Previous epoch start is block 0, can't be used for average block time calculation (core.Block(0) panics).") AverageBlockTimeIsLessOrEqualToZeroError = sdkerrors.New("AverageBlockTimeIsLessOrEqualToZeroError Error", 687, "The calculated average block time is less or equal to zero") NotEnoughBlocksToCalculateAverageBlockTimeError = sdkerrors.New("NotEnoughBlocksToCalculateAverageBlockTimeError Error", 688, "There isn't enough blocks in the previous epoch to calculate average block time") + EpochTooEarlyForUnresponsiveProviderJailError = sdkerrors.New("EpochTooEarlyForUnresponsiveProviderJailError Error", 689, "The epoch is too early for jailing a provider due to unersponsiveness") ) From 3b7b50870480424b115f0524df4f8df0f732b04e Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 15 Jan 2023 16:41:40 +0200 Subject: [PATCH 08/37] CNS-137: fix small bug - epoch payments saved providerPaymentStorage duplicates --- x/pairing/keeper/epoch_payments.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/x/pairing/keeper/epoch_payments.go b/x/pairing/keeper/epoch_payments.go index b2bee4f064..64ae96d15f 100644 --- a/x/pairing/keeper/epoch_payments.go +++ b/x/pairing/keeper/epoch_payments.go @@ -86,7 +86,17 @@ func (k Keeper) AddEpochPayment(ctx sdk.Context, chainID string, epoch uint64, u if !found { epochPayments = types.EpochPayments{Index: key, ClientsPayments: []*types.ProviderPaymentStorage{userPaymentProviderStorage}} } else { - epochPayments.ClientsPayments = append(epochPayments.ClientsPayments, userPaymentProviderStorage) + found = false + for _, providerEpochStorage := range epochPayments.GetClientsPayments() { + if providerEpochStorage.Index == userPaymentProviderStorage.Index { + *providerEpochStorage = *userPaymentProviderStorage + found = true + break + } + } + if !found { + epochPayments.ClientsPayments = append(epochPayments.ClientsPayments, userPaymentProviderStorage) + } } k.SetEpochPayments(ctx, epochPayments) From f9b8474f97ab53c5c0e9bf6834d40d906ce300b7 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 15 Jan 2023 17:13:38 +0200 Subject: [PATCH 09/37] CNS-137: created new pairing param RecommendedEpochNumToCollectPayment --- proto/pairing/params.proto | 1 + x/pairing/keeper/params.go | 7 ++ x/pairing/keeper/params_test.go | 1 + x/pairing/types/params.go | 51 ++++++++--- x/pairing/types/params.pb.go | 147 ++++++++++++++++++++------------ 5 files changed, 140 insertions(+), 67 deletions(-) diff --git a/proto/pairing/params.proto b/proto/pairing/params.proto index 4ebb92aff9..26a6615595 100644 --- a/proto/pairing/params.proto +++ b/proto/pairing/params.proto @@ -60,4 +60,5 @@ message Params { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + uint64 recommendedEpochNumToCollectPayment = 14 [(gogoproto.moretags) = "yaml:\"recommended_epoch_num_to_collect_payment\""]; } \ No newline at end of file diff --git a/x/pairing/keeper/params.go b/x/pairing/keeper/params.go index b0c2eadba4..878cf5ac31 100644 --- a/x/pairing/keeper/params.go +++ b/x/pairing/keeper/params.go @@ -21,6 +21,7 @@ func (k Keeper) GetParams(ctx sdk.Context) types.Params { k.SlashLimit(ctx), k.DataReliabilityReward(ctx), k.QoSWeight(ctx), + k.RecommendedEpochNumToCollectPayment(ctx), ) } @@ -110,3 +111,9 @@ func (k Keeper) QoSWeight(ctx sdk.Context) (res sdk.Dec) { k.paramstore.Get(ctx, types.KeyQoSWeight, &res) return } + +// RecommendedEpochNumToCollectPayment returns the RecommendedEpochNumToCollectPayment param +func (k Keeper) RecommendedEpochNumToCollectPayment(ctx sdk.Context) (res uint64) { + k.paramstore.Get(ctx, types.KeyRecommendedEpochNumToCollectPayment, &res) + return +} diff --git a/x/pairing/keeper/params_test.go b/x/pairing/keeper/params_test.go index 47489b73d5..a565ef973e 100644 --- a/x/pairing/keeper/params_test.go +++ b/x/pairing/keeper/params_test.go @@ -23,4 +23,5 @@ func TestGetParams(t *testing.T) { require.EqualValues(t, params.FraudSlashingAmount, k.FraudSlashingAmount(ctx)) require.EqualValues(t, params.ServicersToPairCount, k.ServicersToPairCountRaw(ctx)) require.EqualValues(t, params.EpochBlocksOverlap, k.EpochBlocksOverlap(ctx)) + require.EqualValues(t, params.RecommendedEpochNumToCollectPayment, k.RecommendedEpochNumToCollectPayment(ctx)) } diff --git a/x/pairing/types/params.go b/x/pairing/types/params.go index 84ad95426a..6934fc7f6a 100644 --- a/x/pairing/types/params.go +++ b/x/pairing/types/params.go @@ -88,6 +88,11 @@ var ( DefaultQoSWeight sdk.Dec = sdk.NewDecWithPrec(5, 1) // 0.5 ) +var ( + KeyRecommendedEpochNumToCollectPayment = []byte("RecommendedEpochNumToCollectPayment") // the recommended amount of max epochs that a provider should wait before collecting its payment (if he'll collect later, there's a higher chance to get punished) + DefaultRecommendedEpochNumToCollectPayment uint64 = 2 +) + // ParamKeyTable the param key table for launch module func ParamKeyTable() paramtypes.KeyTable { return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) @@ -108,21 +113,23 @@ func NewParams( slashLimit sdk.Dec, dataReliabilityReward sdk.Dec, qoSWeight sdk.Dec, + recommendedEpochNumToCollectPayment uint64, ) Params { return Params{ - MinStakeProvider: minStakeProvider, - MinStakeClient: minStakeClient, - MintCoinsPerCU: mintCoinsPerCU, - BurnCoinsPerCU: burnCoinsPerCU, - FraudStakeSlashingFactor: fraudStakeSlashingFactor, - FraudSlashingAmount: fraudSlashingAmount, - ServicersToPairCount: servicersToPairCount, - EpochBlocksOverlap: epochBlocksOverlap, - StakeToMaxCUList: stakeToMaxCUList, - UnpayLimit: unpayLimit, - SlashLimit: slashLimit, - DataReliabilityReward: dataReliabilityReward, - QoSWeight: qoSWeight, + MinStakeProvider: minStakeProvider, + MinStakeClient: minStakeClient, + MintCoinsPerCU: mintCoinsPerCU, + BurnCoinsPerCU: burnCoinsPerCU, + FraudStakeSlashingFactor: fraudStakeSlashingFactor, + FraudSlashingAmount: fraudSlashingAmount, + ServicersToPairCount: servicersToPairCount, + EpochBlocksOverlap: epochBlocksOverlap, + StakeToMaxCUList: stakeToMaxCUList, + UnpayLimit: unpayLimit, + SlashLimit: slashLimit, + DataReliabilityReward: dataReliabilityReward, + QoSWeight: qoSWeight, + RecommendedEpochNumToCollectPayment: recommendedEpochNumToCollectPayment, } } @@ -142,6 +149,7 @@ func DefaultParams() Params { DefaultSlashLimit, DefaultDataReliabilityReward, DefaultQoSWeight, + DefaultRecommendedEpochNumToCollectPayment, ) } @@ -161,6 +169,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(KeySlashLimit, &p.SlashLimit, validateSlashLimit), paramtypes.NewParamSetPair(KeyDataReliabilityReward, &p.DataReliabilityReward, validateDataReliabilityReward), paramtypes.NewParamSetPair(KeyQoSWeight, &p.QoSWeight, validateQoSWeight), + paramtypes.NewParamSetPair(KeyRecommendedEpochNumToCollectPayment, &p.RecommendedEpochNumToCollectPayment, validateRecommendedEpochNumToCollectPayment), } } @@ -212,6 +221,9 @@ func (p Params) Validate() error { if err := validateDataReliabilityReward(p.DataReliabilityReward); err != nil { return err } + if err := validateRecommendedEpochNumToCollectPayment(p.RecommendedEpochNumToCollectPayment); err != nil { + return err + } return nil } @@ -408,3 +420,16 @@ func validateQoSWeight(v interface{}) error { return nil } + +// validateRecommendedEpochNumToCollectPayment validates the RecommendedEpochNumToCollectPayment param +func validateRecommendedEpochNumToCollectPayment(v interface{}) error { + recommendedEpochNumToCollectPayment, ok := v.(uint64) + if !ok { + return fmt.Errorf("invalid parameter type: %T", v) + } + + // TODO implement validation + _ = recommendedEpochNumToCollectPayment + + return nil +} diff --git a/x/pairing/types/params.pb.go b/x/pairing/types/params.pb.go index 5f517fe9a3..de697e4fc9 100644 --- a/x/pairing/types/params.pb.go +++ b/x/pairing/types/params.pb.go @@ -26,19 +26,20 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for the module. type Params struct { - MinStakeProvider github_com_cosmos_cosmos_sdk_types.Coin `protobuf:"bytes,1,opt,name=minStakeProvider,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Coin" json:"minStakeProvider" yaml:"min_stake_provider"` - MinStakeClient github_com_cosmos_cosmos_sdk_types.Coin `protobuf:"bytes,2,opt,name=minStakeClient,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Coin" json:"minStakeClient" yaml:"min_stake_client"` - MintCoinsPerCU github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=mintCoinsPerCU,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"mintCoinsPerCU" yaml:"mint_coins_per_cu"` - BurnCoinsPerCU github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=burnCoinsPerCU,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"burnCoinsPerCU" yaml:"burn_coins_per_cu"` - FraudStakeSlashingFactor github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=fraudStakeSlashingFactor,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"fraudStakeSlashingFactor" yaml:"fraud_stake_slashing_factor"` - FraudSlashingAmount uint64 `protobuf:"varint,6,opt,name=fraudSlashingAmount,proto3" json:"fraudSlashingAmount,omitempty" yaml:"fraud_slashing_amount"` - ServicersToPairCount uint64 `protobuf:"varint,7,opt,name=servicersToPairCount,proto3" json:"servicersToPairCount,omitempty" yaml:"servicers_to_pair_count"` - EpochBlocksOverlap uint64 `protobuf:"varint,8,opt,name=epochBlocksOverlap,proto3" json:"epochBlocksOverlap,omitempty" yaml:"epoch_blocks_overlap"` - StakeToMaxCUList StakeToMaxCUList `protobuf:"bytes,9,opt,name=stakeToMaxCUList,proto3,customtype=StakeToMaxCUList" json:"stakeToMaxCUList" yaml:"stake_to_computeunits_list"` - UnpayLimit github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,10,opt,name=unpayLimit,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"unpayLimit" yaml:"unpay_limit"` - SlashLimit github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,11,opt,name=slashLimit,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slashLimit" yaml:"slash_limit"` - DataReliabilityReward github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,12,opt,name=dataReliabilityReward,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"dataReliabilityReward" yaml:"data_reliability_reward"` - QoSWeight github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,13,opt,name=QoSWeight,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"QoSWeight" yaml:"data_reliability_reward"` + MinStakeProvider github_com_cosmos_cosmos_sdk_types.Coin `protobuf:"bytes,1,opt,name=minStakeProvider,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Coin" json:"minStakeProvider" yaml:"min_stake_provider"` + MinStakeClient github_com_cosmos_cosmos_sdk_types.Coin `protobuf:"bytes,2,opt,name=minStakeClient,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Coin" json:"minStakeClient" yaml:"min_stake_client"` + MintCoinsPerCU github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=mintCoinsPerCU,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"mintCoinsPerCU" yaml:"mint_coins_per_cu"` + BurnCoinsPerCU github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=burnCoinsPerCU,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"burnCoinsPerCU" yaml:"burn_coins_per_cu"` + FraudStakeSlashingFactor github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=fraudStakeSlashingFactor,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"fraudStakeSlashingFactor" yaml:"fraud_stake_slashing_factor"` + FraudSlashingAmount uint64 `protobuf:"varint,6,opt,name=fraudSlashingAmount,proto3" json:"fraudSlashingAmount,omitempty" yaml:"fraud_slashing_amount"` + ServicersToPairCount uint64 `protobuf:"varint,7,opt,name=servicersToPairCount,proto3" json:"servicersToPairCount,omitempty" yaml:"servicers_to_pair_count"` + EpochBlocksOverlap uint64 `protobuf:"varint,8,opt,name=epochBlocksOverlap,proto3" json:"epochBlocksOverlap,omitempty" yaml:"epoch_blocks_overlap"` + StakeToMaxCUList StakeToMaxCUList `protobuf:"bytes,9,opt,name=stakeToMaxCUList,proto3,customtype=StakeToMaxCUList" json:"stakeToMaxCUList" yaml:"stake_to_computeunits_list"` + UnpayLimit github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,10,opt,name=unpayLimit,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"unpayLimit" yaml:"unpay_limit"` + SlashLimit github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,11,opt,name=slashLimit,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slashLimit" yaml:"slash_limit"` + DataReliabilityReward github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,12,opt,name=dataReliabilityReward,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"dataReliabilityReward" yaml:"data_reliability_reward"` + QoSWeight github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,13,opt,name=QoSWeight,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"QoSWeight" yaml:"data_reliability_reward"` + RecommendedEpochNumToCollectPayment uint64 `protobuf:"varint,14,opt,name=recommendedEpochNumToCollectPayment,proto3" json:"recommendedEpochNumToCollectPayment,omitempty" yaml:"recommended_epoch_num_to_collect_payment"` } func (m *Params) Reset() { *m = Params{} } @@ -94,6 +95,13 @@ func (m *Params) GetEpochBlocksOverlap() uint64 { return 0 } +func (m *Params) GetRecommendedEpochNumToCollectPayment() uint64 { + if m != nil { + return m.RecommendedEpochNumToCollectPayment + } + return 0 +} + func init() { proto.RegisterType((*Params)(nil), "lavanet.lava.pairing.Params") } @@ -101,47 +109,51 @@ func init() { func init() { proto.RegisterFile("pairing/params.proto", fileDescriptor_72cc734580d3bc3a) } var fileDescriptor_72cc734580d3bc3a = []byte{ - // 636 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x95, 0x4f, 0x6f, 0xd3, 0x30, - 0x18, 0x87, 0x1b, 0x18, 0x83, 0x79, 0x80, 0x26, 0x53, 0x44, 0xf8, 0xa3, 0x64, 0xe4, 0x00, 0xbb, - 0xd0, 0x1e, 0xb8, 0x4d, 0xe2, 0xb0, 0x76, 0xe2, 0x80, 0x86, 0x56, 0xd2, 0x0d, 0x24, 0x2e, 0x96, - 0xeb, 0x7a, 0xad, 0xb5, 0xc4, 0x8e, 0x6c, 0xa7, 0xac, 0x5f, 0x80, 0xf3, 0x8e, 0x1c, 0x39, 0xf0, - 0x61, 0x76, 0xdc, 0x11, 0x71, 0x88, 0xd0, 0xf6, 0x0d, 0xf2, 0x09, 0x50, 0xde, 0x64, 0x5b, 0xd7, - 0x15, 0x89, 0x6a, 0xe2, 0xe4, 0xc8, 0xfe, 0xbd, 0xcf, 0x93, 0xf8, 0x4d, 0x1c, 0x54, 0x4f, 0xa8, - 0xd0, 0x42, 0x0e, 0x9a, 0x09, 0xd5, 0x34, 0x36, 0x8d, 0x44, 0x2b, 0xab, 0x70, 0x3d, 0xa2, 0x23, - 0x2a, 0xb9, 0x6d, 0x14, 0x63, 0xa3, 0x8a, 0x3c, 0xa9, 0x0f, 0xd4, 0x40, 0x41, 0xa0, 0x59, 0x5c, - 0x95, 0xd9, 0xe0, 0xc7, 0x32, 0x5a, 0xec, 0x40, 0x31, 0x3e, 0x40, 0x2b, 0xb1, 0x90, 0x5d, 0x4b, - 0xf7, 0x79, 0x47, 0xab, 0x91, 0xe8, 0x73, 0xed, 0x3a, 0xab, 0xce, 0xda, 0x52, 0x6b, 0xeb, 0x28, - 0xf3, 0x6b, 0xbf, 0x32, 0xff, 0xe5, 0x40, 0xd8, 0x61, 0xda, 0x6b, 0x30, 0x15, 0x37, 0x99, 0x32, - 0xb1, 0x32, 0xd5, 0xf0, 0xca, 0xf4, 0xf7, 0x9b, 0x76, 0x9c, 0x70, 0xd3, 0x68, 0x2b, 0x21, 0xf3, - 0xcc, 0x7f, 0x3c, 0xa6, 0x71, 0xb4, 0x1e, 0xc4, 0x42, 0x12, 0x53, 0x10, 0x49, 0x52, 0x21, 0x83, - 0xf0, 0x8a, 0x05, 0x6b, 0x74, 0xff, 0x6c, 0xae, 0x1d, 0x09, 0x2e, 0xad, 0x7b, 0x03, 0xbc, 0xef, - 0xe6, 0xf7, 0x3e, 0x9a, 0xf6, 0x32, 0x00, 0x06, 0xe1, 0x94, 0xa1, 0x72, 0xda, 0xa2, 0xcc, 0x74, - 0xb8, 0x6e, 0xef, 0xba, 0x37, 0x2f, 0x39, 0x5f, 0xfc, 0x83, 0x73, 0x93, 0xb3, 0x3c, 0xf3, 0xdd, - 0x73, 0xa5, 0x25, 0xac, 0xc0, 0x91, 0x84, 0x6b, 0xc2, 0xd2, 0xd2, 0x39, 0x61, 0x28, 0x9c, 0xbd, - 0x54, 0xcb, 0x09, 0xe7, 0xc2, 0xf5, 0x9c, 0x05, 0x6d, 0xda, 0x79, 0xd9, 0x80, 0x0f, 0x1d, 0xe4, - 0xee, 0x69, 0x9a, 0xf6, 0xe1, 0xe1, 0xbb, 0x11, 0x35, 0x43, 0x21, 0x07, 0x6f, 0x29, 0xb3, 0x4a, - 0xbb, 0xb7, 0x40, 0xbf, 0x33, 0xb7, 0x3e, 0x28, 0xf5, 0xc0, 0xad, 0xf6, 0xd9, 0x54, 0x64, 0xb2, - 0x07, 0xe8, 0x20, 0xfc, 0xab, 0x15, 0x87, 0xe8, 0x41, 0xb9, 0x56, 0x4d, 0x6f, 0xc4, 0x2a, 0x95, - 0xd6, 0x5d, 0x5c, 0x75, 0xd6, 0x16, 0x5a, 0xab, 0x79, 0xe6, 0x3f, 0xbb, 0x84, 0x3f, 0x03, 0x53, - 0x88, 0x05, 0xe1, 0xac, 0x62, 0xfc, 0x11, 0xd5, 0x0d, 0xd7, 0x23, 0xc1, 0xb8, 0x36, 0x3b, 0xaa, - 0x43, 0x85, 0x6e, 0x03, 0xf4, 0x36, 0x40, 0x83, 0x3c, 0xf3, 0xbd, 0x12, 0x7a, 0x9e, 0x22, 0x56, - 0x91, 0xe2, 0xdb, 0x20, 0xac, 0xc4, 0xce, 0xac, 0xc7, 0xdb, 0x08, 0xf3, 0x44, 0xb1, 0x61, 0x2b, - 0x52, 0x6c, 0xdf, 0x6c, 0x8f, 0xb8, 0x8e, 0x68, 0xe2, 0xde, 0x01, 0xaa, 0x9f, 0x67, 0xfe, 0xd3, - 0x92, 0x0a, 0x19, 0xd2, 0x83, 0x10, 0x51, 0x65, 0x2a, 0x08, 0x67, 0x94, 0x62, 0x81, 0x56, 0x60, - 0xc3, 0x76, 0xd4, 0x7b, 0x7a, 0xd0, 0xde, 0xdd, 0x12, 0xc6, 0xba, 0x4b, 0xd0, 0x86, 0x37, 0x55, - 0x1b, 0x56, 0xba, 0x53, 0xeb, 0x79, 0xe6, 0x3f, 0xaf, 0x6e, 0x1e, 0xb6, 0xda, 0x2a, 0xc2, 0x54, - 0x9c, 0xa4, 0x96, 0xa7, 0x52, 0x58, 0x43, 0x22, 0x61, 0x6c, 0x10, 0x5e, 0xc1, 0xe2, 0x3e, 0x42, - 0xa9, 0x4c, 0xe8, 0x78, 0x4b, 0xc4, 0xc2, 0xba, 0x08, 0x24, 0x9b, 0x73, 0xf7, 0x1a, 0x97, 0x6a, - 0x20, 0x91, 0xa8, 0x40, 0x05, 0xe1, 0x04, 0xb7, 0xb0, 0x40, 0x8b, 0x4a, 0xcb, 0xf2, 0xf5, 0x2c, - 0x40, 0x3a, 0xb7, 0x5c, 0x70, 0xf1, 0x57, 0x07, 0x3d, 0xec, 0x53, 0x4b, 0x43, 0x1e, 0x09, 0xda, - 0x13, 0x91, 0xb0, 0xe3, 0x90, 0x7f, 0xa1, 0xba, 0xef, 0xde, 0x05, 0x63, 0x67, 0x6e, 0x63, 0xf5, - 0x3e, 0x14, 0x50, 0xa2, 0x2f, 0xa8, 0x44, 0x03, 0x36, 0x08, 0x67, 0xeb, 0xb0, 0x44, 0x4b, 0x1f, - 0x54, 0xf7, 0x13, 0x17, 0x83, 0xa1, 0x75, 0xef, 0xfd, 0x27, 0xf7, 0x85, 0x62, 0x7d, 0xe1, 0xdb, - 0x77, 0xbf, 0xd6, 0xda, 0x38, 0x3a, 0xf1, 0x9c, 0xe3, 0x13, 0xcf, 0xf9, 0x7d, 0xe2, 0x39, 0x87, - 0xa7, 0x5e, 0xed, 0xf8, 0xd4, 0xab, 0xfd, 0x3c, 0xf5, 0x6a, 0x9f, 0x27, 0xcf, 0xc6, 0xea, 0xdc, - 0x87, 0xb1, 0x79, 0xd0, 0x3c, 0xfb, 0x39, 0x80, 0xb9, 0xb7, 0x08, 0x07, 0xfe, 0xeb, 0x3f, 0x01, - 0x00, 0x00, 0xff, 0xff, 0x97, 0xce, 0x41, 0x0f, 0x34, 0x06, 0x00, 0x00, + // 698 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x95, 0x4f, 0x6f, 0xd3, 0x3e, + 0x18, 0xc7, 0x9b, 0xdf, 0x6f, 0x0c, 0x66, 0xc6, 0x34, 0x85, 0x22, 0xc2, 0x1f, 0x35, 0x23, 0x48, + 0xb0, 0x0b, 0xed, 0x61, 0xb7, 0x49, 0x1c, 0xd6, 0x0e, 0x0e, 0x68, 0xb0, 0x92, 0x76, 0x20, 0x71, + 0xb1, 0xdc, 0xc4, 0x6b, 0xad, 0x25, 0x76, 0x64, 0x3b, 0x65, 0x7d, 0x01, 0x70, 0xde, 0x91, 0x23, + 0x2f, 0x80, 0x17, 0xb2, 0xe3, 0x8e, 0x88, 0x43, 0x84, 0xb6, 0x77, 0x90, 0x57, 0x80, 0xf2, 0x38, + 0xdb, 0xba, 0xae, 0x48, 0xab, 0x26, 0x4e, 0xae, 0x92, 0xe7, 0xfb, 0xf9, 0xb4, 0x7e, 0x9e, 0xda, + 0xa8, 0x9a, 0x10, 0x26, 0x19, 0xef, 0x37, 0x12, 0x22, 0x49, 0xac, 0xea, 0x89, 0x14, 0x5a, 0xd8, + 0xd5, 0x88, 0x0c, 0x09, 0xa7, 0xba, 0x5e, 0xac, 0xf5, 0xb2, 0xe4, 0x61, 0xb5, 0x2f, 0xfa, 0x02, + 0x0a, 0x1a, 0xc5, 0x27, 0x53, 0xeb, 0xfd, 0x58, 0x44, 0xf3, 0x6d, 0x08, 0xdb, 0xfb, 0x68, 0x39, + 0x66, 0xbc, 0xa3, 0xc9, 0x1e, 0x6d, 0x4b, 0x31, 0x64, 0x21, 0x95, 0x8e, 0xb5, 0x62, 0xad, 0x2e, + 0x34, 0xb7, 0x0e, 0x33, 0xb7, 0xf2, 0x2b, 0x73, 0x9f, 0xf7, 0x99, 0x1e, 0xa4, 0xbd, 0x7a, 0x20, + 0xe2, 0x46, 0x20, 0x54, 0x2c, 0x54, 0xb9, 0xbc, 0x50, 0xe1, 0x5e, 0x43, 0x8f, 0x12, 0xaa, 0xea, + 0x2d, 0xc1, 0x78, 0x9e, 0xb9, 0x0f, 0x46, 0x24, 0x8e, 0xd6, 0xbd, 0x98, 0x71, 0xac, 0x0a, 0x22, + 0x4e, 0x4a, 0xa4, 0xe7, 0x5f, 0xb2, 0xd8, 0x12, 0x2d, 0x9d, 0x3e, 0x6b, 0x45, 0x8c, 0x72, 0xed, + 0xfc, 0x07, 0xde, 0x37, 0xb3, 0x7b, 0xef, 0x4f, 0x7a, 0x03, 0x00, 0x7a, 0xfe, 0x84, 0xa1, 0x74, + 0xea, 0x22, 0xa6, 0xda, 0x54, 0xb6, 0x76, 0x9c, 0xff, 0x2f, 0x38, 0x9f, 0x5d, 0xc1, 0xb9, 0x49, + 0x83, 0x3c, 0x73, 0x9d, 0x33, 0xa5, 0xc6, 0x41, 0x81, 0xc3, 0x09, 0x95, 0x38, 0x48, 0x8d, 0x73, + 0xcc, 0x50, 0x38, 0x7b, 0xa9, 0xe4, 0x63, 0xce, 0xb9, 0xeb, 0x39, 0x0b, 0xda, 0xa4, 0xf3, 0xa2, + 0xc1, 0x3e, 0xb0, 0x90, 0xb3, 0x2b, 0x49, 0x1a, 0xc2, 0x8f, 0xef, 0x44, 0x44, 0x0d, 0x18, 0xef, + 0xbf, 0x26, 0x81, 0x16, 0xd2, 0xb9, 0x01, 0xfa, 0xee, 0xcc, 0x7a, 0xcf, 0xe8, 0x81, 0x5b, 0xee, + 0xb3, 0x2a, 0xc9, 0x78, 0x17, 0xd0, 0x9e, 0xff, 0x57, 0xab, 0xed, 0xa3, 0xbb, 0xe6, 0x5d, 0xf9, + 0x78, 0x23, 0x16, 0x29, 0xd7, 0xce, 0xfc, 0x8a, 0xb5, 0x3a, 0xd7, 0x5c, 0xc9, 0x33, 0xf7, 0xf1, + 0x05, 0xfc, 0x29, 0x98, 0x40, 0x99, 0xe7, 0x4f, 0x0b, 0xdb, 0x1f, 0x50, 0x55, 0x51, 0x39, 0x64, + 0x01, 0x95, 0xaa, 0x2b, 0xda, 0x84, 0xc9, 0x16, 0x40, 0x6f, 0x02, 0xd4, 0xcb, 0x33, 0xb7, 0x66, + 0xa0, 0x67, 0x55, 0x58, 0x0b, 0x5c, 0xfc, 0x37, 0x70, 0x60, 0xb0, 0x53, 0xf3, 0xf6, 0x36, 0xb2, + 0x69, 0x22, 0x82, 0x41, 0x33, 0x12, 0xc1, 0x9e, 0xda, 0x1e, 0x52, 0x19, 0x91, 0xc4, 0xb9, 0x05, + 0x54, 0x37, 0xcf, 0xdc, 0x47, 0x86, 0x0a, 0x35, 0xb8, 0x07, 0x45, 0x58, 0x98, 0x2a, 0xcf, 0x9f, + 0x12, 0xb5, 0x19, 0x5a, 0x86, 0x0d, 0xeb, 0x8a, 0xb7, 0x64, 0xbf, 0xb5, 0xb3, 0xc5, 0x94, 0x76, + 0x16, 0xa0, 0x0d, 0x2f, 0xcb, 0x36, 0x2c, 0x77, 0x26, 0xde, 0xe7, 0x99, 0xfb, 0xa4, 0xfc, 0xf2, + 0xb0, 0xd5, 0x5a, 0xe0, 0x40, 0xc4, 0x49, 0xaa, 0x69, 0xca, 0x99, 0x56, 0x38, 0x62, 0x4a, 0x7b, + 0xfe, 0x25, 0xac, 0x1d, 0x22, 0x94, 0xf2, 0x84, 0x8c, 0xb6, 0x58, 0xcc, 0xb4, 0x83, 0x40, 0xb2, + 0x39, 0x73, 0xaf, 0x6d, 0xa3, 0x06, 0x12, 0x8e, 0x0a, 0x94, 0xe7, 0x8f, 0x71, 0x0b, 0x0b, 0xb4, + 0xc8, 0x58, 0x6e, 0x5f, 0xcf, 0x02, 0xa4, 0x33, 0xcb, 0x39, 0xd7, 0xfe, 0x6a, 0xa1, 0x7b, 0x21, + 0xd1, 0xc4, 0xa7, 0x11, 0x23, 0x3d, 0x16, 0x31, 0x3d, 0xf2, 0xe9, 0x67, 0x22, 0x43, 0x67, 0x11, + 0x8c, 0xed, 0x99, 0x8d, 0xe5, 0x3c, 0x14, 0x50, 0x2c, 0xcf, 0xa9, 0x58, 0x02, 0xd6, 0xf3, 0xa7, + 0xeb, 0x6c, 0x8e, 0x16, 0xde, 0x8b, 0xce, 0x47, 0xca, 0xfa, 0x03, 0xed, 0xdc, 0xf9, 0x47, 0xee, + 0x73, 0x85, 0xfd, 0xc5, 0x42, 0x4f, 0x25, 0x0d, 0x44, 0x1c, 0x53, 0x1e, 0xd2, 0xf0, 0x55, 0x31, + 0x51, 0xef, 0xd2, 0xb8, 0x2b, 0x5a, 0x22, 0x8a, 0x68, 0xa0, 0xdb, 0x64, 0x14, 0x17, 0x27, 0xe6, + 0x12, 0x8c, 0xe4, 0x5a, 0x9e, 0xb9, 0x0d, 0x03, 0x1f, 0x0b, 0x61, 0x33, 0x9e, 0x3c, 0x8d, 0xcd, + 0xec, 0x40, 0x10, 0x27, 0x26, 0xe9, 0xf9, 0x57, 0xe1, 0xaf, 0xcf, 0x7d, 0xfb, 0xee, 0x56, 0x9a, + 0x1b, 0x87, 0xc7, 0x35, 0xeb, 0xe8, 0xb8, 0x66, 0xfd, 0x3e, 0xae, 0x59, 0x07, 0x27, 0xb5, 0xca, + 0xd1, 0x49, 0xad, 0xf2, 0xf3, 0xa4, 0x56, 0xf9, 0x34, 0x7e, 0x46, 0x97, 0xf7, 0x0f, 0xac, 0x8d, + 0xfd, 0xc6, 0xe9, 0x25, 0x05, 0x3b, 0xd0, 0x9b, 0x87, 0x8b, 0x67, 0xed, 0x4f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x62, 0xf3, 0xf0, 0x83, 0xbc, 0x06, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -164,6 +176,11 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.RecommendedEpochNumToCollectPayment != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.RecommendedEpochNumToCollectPayment)) + i-- + dAtA[i] = 0x70 + } { size := m.QoSWeight.Size() i -= size @@ -328,6 +345,9 @@ func (m *Params) Size() (n int) { n += 1 + l + sovParams(uint64(l)) l = m.QoSWeight.Size() n += 1 + l + sovParams(uint64(l)) + if m.RecommendedEpochNumToCollectPayment != 0 { + n += 1 + sovParams(uint64(m.RecommendedEpochNumToCollectPayment)) + } return n } @@ -763,6 +783,25 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RecommendedEpochNumToCollectPayment", wireType) + } + m.RecommendedEpochNumToCollectPayment = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RecommendedEpochNumToCollectPayment |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) From dd435f040af6c5a82e285ef426c47afdb3c35b33 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 16 Jan 2023 10:22:11 +0200 Subject: [PATCH 10/37] CNS-137: fixed minor bugs in unresponsive code --- x/pairing/keeper/unresponsive_provider.go | 23 +++++++++++++++++++---- x/pairing/module.go | 12 ++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index b1270c2814..ca138525ba 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -51,16 +51,28 @@ func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch u providersPunishEntryMap := make(map[string]punishEntry) // map of punishEntryKey keys (string) with punishEntry values (punishEntryKey = providerAddress_chainID) providersToPunishMap := make(map[string][]string) // map of punishEntryKey keys (string) with list of providerPaymentStorage indices values (string array) (punishEntryKey = providerAddress_chainID) + // Get recommendedEpochNumToCollectPayment + recommendedEpochNumToCollectPayment := k.RecommendedEpochNumToCollectPayment(ctx) + // handle very early epochs (basically, don't punish) epochBlocks, err := k.epochStorageKeeper.EpochBlocks(ctx, currentEpoch) if err != nil { return nil, utils.LavaError(ctx, k.Logger(ctx), "get_epoch_blocks", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get epoch blocks param") } - if currentEpoch < (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider)*epochBlocks { + if currentEpoch < (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider+recommendedEpochNumToCollectPayment)*epochBlocks { // To check for punishment, we have to go back (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing return nil, types.EpochTooEarlyForUnresponsiveProviderJailError } + // Go back recommendedEpochNumToCollectPayment + for counter := uint64(0); counter < recommendedEpochNumToCollectPayment; counter++ { + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, currentEpoch) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get previous epoch") + } + currentEpoch = previousEpoch + } + // Go over previous epochs to count the CU serviced by the provider epochAfterCountingProviderCu, err := k.countCuForUnresponsiveProviderAndComplainers(ctx, true, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, providersPunishEntryMap) if err != nil { @@ -121,8 +133,9 @@ func (k Keeper) countCuForUnresponsiveProviderAndComplainers(ctx sdk.Context, is providerPaymentStorageList := epochPayments.GetClientsPayments() // Go over providerPaymentStorage list - cuCount := uint64(0) for _, providerPaymentStorage := range providerPaymentStorageList { + cuCount := uint64(0) + // Get provider address and chainID providerAddress := k.getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorage.Index) chainID := k.getChainIDFromProviderPaymentStorageKey(providerPaymentStorage.Index) @@ -139,8 +152,9 @@ func (k Keeper) countCuForUnresponsiveProviderAndComplainers(ctx sdk.Context, is cuCount += uniquePayment.GetUsedCU() } if punishEntryFound { - // punishEntry found -> add the cuCount to providerServicedCu + // punishEntry found -> add the cuCount to providerServicedCu and update the map entry providerPunishEntry.providerServicedCu += cuCount + providersPunishEntryMap[punishEntryKey] = providerPunishEntry } else { // punishEntry not found -> create a new one and add it to the map providersPunishEntryMap[punishEntryKey] = punishEntry{complainersUsedCu: 0, providerServicedCu: cuCount, providerPaymentStorageIndexList: []string{providerPaymentStorage.Index}} @@ -156,8 +170,9 @@ func (k Keeper) countCuForUnresponsiveProviderAndComplainers(ctx sdk.Context, is cuCount = providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) if punishEntryFound { - // punishEntry found -> add the cuCount to complainersUsedCu + // punishEntry found -> add the cuCount to complainersUsedCu and update the map entry providerPunishEntry.complainersUsedCu += cuCount + providersPunishEntryMap[punishEntryKey] = providerPunishEntry } else { // punishEntry not found -> create a new one and add it to the map providersPunishEntryMap[punishEntryKey] = punishEntry{complainersUsedCu: cuCount, providerServicedCu: 0, providerPaymentStorageIndexList: []string{providerPaymentStorage.Index}} diff --git a/x/pairing/module.go b/x/pairing/module.go index d55dd9d582..1f68ca827b 100644 --- a/x/pairing/module.go +++ b/x/pairing/module.go @@ -27,6 +27,11 @@ var ( _ module.AppModuleBasic = AppModuleBasic{} ) +const ( + EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER = 4 // number of epochs to sum CU that the provider serviced + EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS = 2 // number of epochs to sum CU of complainers against the provider +) + // ---------------------------------------------------------------------------- // AppModuleBasic // ---------------------------------------------------------------------------- @@ -190,13 +195,8 @@ func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { err = am.keeper.CheckUnstakingForCommit(ctx) logOnErr(err, "CheckUnstakingForCommit") - // consts TODO: where to put it? - const ( - epochsNumToCheckCUForUnresponsiveProvider = 4 // number of epochs to sum CU that the provider serviced - epochsNumToCheckCUForComplainers = 2 // number of epochs to sum CU of complainers against the provider - ) // 4. unstake unresponsive providers - err = am.keeper.UnstakeUnresponsiveProviders(ctx, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers) + err = am.keeper.UnstakeUnresponsiveProviders(ctx, EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) logOnErr(err, "UnstakeUnresponsiveProviders") } } From 5087d0e9970d96935233f158f99391ab3ab6d7ad Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 16 Jan 2023 10:24:46 +0200 Subject: [PATCH 11/37] CNS-137: fixed unresponsive unit tests --- testutil/keeper/keepers_init.go | 12 ++- x/pairing/keeper/unreponsive_provider_test.go | 74 ++++++++++++++----- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 683a903d10..79b7c3b1c9 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "fmt" "testing" "time" @@ -30,7 +31,11 @@ import ( tmdb "github.com/tendermint/tm-db" ) -const BLOCK_TIME = 30 * time.Second +const ( + BLOCK_TIME = 30 * time.Second + EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER = 4 // number of epochs to sum CU that the provider serviced + EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS = 2 // number of epochs to sum CU of complainers against the provider +) type Keepers struct { Epochstorage epochstoragekeeper.Keeper @@ -221,6 +226,11 @@ func NewBlock(ctx context.Context, ks *Keepers, customTime ...time.Duration) { ks.Pairing.RemoveOldEpochPayment(unwrapedCtx) ks.Pairing.CheckUnstakingForCommit(unwrapedCtx) + + start := time.Now() + ks.Pairing.UnstakeUnresponsiveProviders(unwrapedCtx, EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) + elapsed_time := time.Since(start) + fmt.Printf("elapsed_time: %v\n", elapsed_time) } ks.Conflict.CheckAndHandleAllVotes(unwrapedCtx) diff --git a/x/pairing/keeper/unreponsive_provider_test.go b/x/pairing/keeper/unreponsive_provider_test.go index 23067803c4..703702de13 100644 --- a/x/pairing/keeper/unreponsive_provider_test.go +++ b/x/pairing/keeper/unreponsive_provider_test.go @@ -12,28 +12,36 @@ import ( "github.com/stretchr/testify/require" ) +// Test to measure the time the check for unresponsiveness every epoch start takes func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { + // setup test for unresponsiveness testClientAmount := 4 testProviderAmount := 2 ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) - for i := 0; i < 2; i++ { // move to epoch 3 so we can check enough epochs in the past + // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) + for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+testkeeper.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } + + // get provider1's balance before the stake staked_amount, _, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) balanceProvideratBeforeStake := staked_amount.Stake.Amount.Int64() + ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), ts.providers[1].address, epochstoragetypes.TokenDenom).Amount.Int64() + // create unresponsive data that includes provider1 being unresponsive unresponsiveProvidersData, err := json.Marshal([]string{ts.providers[1].address.String()}) require.Nil(t, err) + + // create relay requests for provider0 that contain complaints about provider1 var Relays []*types.RelayRequest for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints relayRequest := &types.RelayRequest{ Provider: ts.providers[0].address.String(), ApiUrl: "", Data: []byte(ts.spec.Apis[0].Name), - SessionId: uint64(1), + SessionId: uint64(0), ChainID: ts.spec.Name, - CuSum: ts.spec.Apis[0].ComputeUnits * 10, + CuSum: ts.spec.Apis[0].ComputeUnits*10 + uint64(clientIndex), BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), RelayNum: 0, RequestBlock: -1, @@ -46,45 +54,63 @@ func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { require.Nil(t, err) Relays = append(Relays, relayRequest) } + + // send the relay requests (provider gets payment) _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) require.Nil(t, err) - // testing that the provider was unstaked. and checking his balance after many epochs - _, unStakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) - require.True(t, unStakeStoragefound) + + // advance enough epochs so the unresponsive provider will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) + for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + + // test the provider has been unstaked + _, unstakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) + require.True(t, unstakeStoragefound) _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) require.False(t, stakeStorageFound) + // advance enough epochs so the current block will be deleted (advance more than the chain's memory - blocksToSave) OriginalBlockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) blocksToSave, err := ts.keepers.Epochstorage.BlocksToSave(sdk.UnwrapSDKContext(ts.ctx), OriginalBlockHeight) require.Nil(t, err) - for { // move to epoch 13 so we can check balance at the end + for { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) blockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) if blockHeight > blocksToSave+OriginalBlockHeight { break } } - // validate that the provider is no longer unstaked. and stake was returned. - _, unStakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) - require.False(t, unStakeStoragefound) - // also that the provider wasnt returned to stake pool + + // validate that the provider is no longer unstaked + _, unstakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) + require.False(t, unstakeStoragefound) + + // also validate that the provider hasn't returned to the stake pool _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) require.False(t, stakeStorageFound) + // validate that the provider's balance after the unstake is the same as before he staked balanceProviderAfterUnstakeMoneyReturned := ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), ts.providers[1].address, epochstoragetypes.TokenDenom).Amount.Int64() require.Equal(t, balanceProvideratBeforeStake, balanceProviderAfterUnstakeMoneyReturned) } func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t *testing.T) { + // setup test for unresponsiveness testClientAmount := 4 testProviderAmount := 2 ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) - for i := 0; i < 2; i++ { // move to epoch 3 so we can check enough epochs in the past + + // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) + for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+testkeeper.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } + // create unresponsive data that includes provider1 being unresponsive unresponsiveProvidersData, err := json.Marshal([]string{ts.providers[1].address.String()}) require.Nil(t, err) + + // create relay requests for provider0 that contain complaints about provider1 var Relays []*types.RelayRequest for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints @@ -92,7 +118,7 @@ func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfte Provider: ts.providers[0].address.String(), ApiUrl: "", Data: []byte(ts.spec.Apis[0].Name), - SessionId: uint64(1), + SessionId: uint64(0), ChainID: ts.spec.Name, CuSum: ts.spec.Apis[0].ComputeUnits * 10, BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), @@ -107,19 +133,28 @@ func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfte require.Nil(t, err) Relays = append(Relays, relayRequest) } + + // send the relay requests (provider gets payment) _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) require.Nil(t, err) - // testing that the provider wasnt unstaked. + + // advance enough epochs so the unresponsive provider will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) + for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + + // test the provider has been unstaked _, unStakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) require.True(t, unStakeStoragefound) _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) require.False(t, stakeStorageFound) - // continue reporting provider after unstake - for i := 0; i < 2; i++ { // move to epoch 5 + // advance some more epochs + for i := 0; i < 2; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } + // create more relay requests for provider0 that contain complaints about provider1 (note, sessionID changed) var RelaysAfter []*types.RelayRequest for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints @@ -141,17 +176,22 @@ func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfte require.Nil(t, err) RelaysAfter = append(RelaysAfter, relayRequest) } + + // send the relay requests (provider gets payment) _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: RelaysAfter}) require.Nil(t, err) + // test the provider is still unstaked _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) require.False(t, stakeStorageFound) _, unStakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) require.True(t, unStakeStoragefound) - // validating number of appearances for unstaked provider in unstake storage (if more than once found, throw an error) + // get the current unstake storage storage, foundStorage := ts.keepers.Epochstorage.GetStakeStorageUnstake(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey) require.True(t, foundStorage) + + // validate the punished provider is not shown twice (or more) in the unstake storage var numberOfAppearances int for _, stored := range storage.StakeEntries { if stored.Address == ts.providers[1].address.String() { From ecd0c94e9c2a6fbb360a24ce0e3c1838c98eda4e Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 16 Jan 2023 14:34:24 +0200 Subject: [PATCH 12/37] CNS-137: checking only payments of staked providers (instead of all payments) --- x/pairing/keeper/unresponsive_provider.go | 68 ++++++++++++++++++++--- x/pairing/types/expected_keepers.go | 1 + 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index ca138525ba..02f8755d95 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -121,16 +121,18 @@ func (k Keeper) countCuForUnresponsiveProviderAndComplainers(ctx sdk.Context, is return 0, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") } - // Get previous epoch's epochPayments - epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, previousEpoch) - if !found { - // No epochPayments found -> continue to the next iteration - epochTemp = previousEpoch - continue + // Get the current stake storages (from all chains) + stakeStorageList := k.getCurrentProviderStakeStorageList(ctx) + if len(stakeStorageList) == 0 { + // no provider is staked -> CU = 0 + return 0, nil } - // Get providerPaymentStorage list - providerPaymentStorageList := epochPayments.GetClientsPayments() + // Get a providerPaymentStorage of all staked providers + providerPaymentStorageList, err := k.getProviderPaymentStorageFromStakeStorageList(ctx, previousEpoch, stakeStorageList) + if err != nil { + return 0, utils.LavaError(ctx, k.Logger(ctx), "get_provider_payment_storage_from_stake_storage_list", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", previousEpoch)}, "couldn't get providerPaymentStorageList from stakeStorageList") + } // Go over providerPaymentStorage list for _, providerPaymentStorage := range providerPaymentStorageList { @@ -189,6 +191,56 @@ func (k Keeper) countCuForUnresponsiveProviderAndComplainers(ctx sdk.Context, is return epochTemp, nil } +// Function that return the current stake storage for all chains +func (k Keeper) getCurrentProviderStakeStorageList(ctx sdk.Context) []epochstoragetypes.StakeStorage { + var stakeStorageList []epochstoragetypes.StakeStorage + + // get all chain IDs + chainIdList := k.specKeeper.GetAllChainIDs(ctx) + + // go over all chain IDs and keep their stake storage. If there is no stake storage for a specific chain, continue to the next one + for _, chainID := range chainIdList { + stakeStorage, found := k.epochStorageKeeper.GetStakeStorageCurrent(ctx, epochstoragetypes.ProviderKey, chainID) + if !found { + continue + } + stakeStorageList = append(stakeStorageList, stakeStorage) + } + + return stakeStorageList +} + +// Function that returns a list of pointers to ProviderPaymentStorage objects by iterating on all the staked providers +func (k Keeper) getProviderPaymentStorageFromStakeStorageList(ctx sdk.Context, epoch uint64, stakeStorageList []epochstoragetypes.StakeStorage) ([]*types.ProviderPaymentStorage, error) { + var providerPaymentStorageList []*types.ProviderPaymentStorage + + // Go over the provider list + for _, stakeStorage := range stakeStorageList { + for _, stakeEntry := range stakeStorage.GetStakeEntries() { + sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(stakeEntry.Address) + if err != nil { + // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. + utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": stakeEntry.Address}) + continue + } + + // get providerPaymentStorageKey from the stake entry details + providerPaymentStorageKey := k.GetProviderPaymentStorageKey(ctx, stakeEntry.GetChain(), epoch, sdkStakeEntryProviderAddress) + + // get providerPaymentStorage with providerPaymentStorageKey + providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageKey) + if !found { + continue + } + + // add a pointer to the providerPaymentStorage to the providerPaymentStorageList + providerPaymentStorageList = append(providerPaymentStorageList, &providerPaymentStorage) + } + } + + return providerPaymentStorageList, nil +} + // Function that punishes providers. Current punishment is unstake func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish map[string][]string) error { // if providersToPunish map is empty, do nothing diff --git a/x/pairing/types/expected_keepers.go b/x/pairing/types/expected_keepers.go index f3b465ea5e..289b344c99 100644 --- a/x/pairing/types/expected_keepers.go +++ b/x/pairing/types/expected_keepers.go @@ -13,6 +13,7 @@ type SpecKeeper interface { GetSpec(ctx sdk.Context, index string) (val spectypes.Spec, found bool) GeolocationCount(ctx sdk.Context) uint64 GetExpectedInterfacesForSpec(ctx sdk.Context, chainID string) map[string]bool + GetAllChainIDs(ctx sdk.Context) (chainIDs []string) } type EpochstorageKeeper interface { From 400de418129b99d6ad632f5f117b4f7f65dee400 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 16 Jan 2023 16:14:49 +0200 Subject: [PATCH 13/37] CNS-137: added stress test --- testutil/keeper/keepers_init.go | 2 +- x/pairing/keeper/unreponsive_provider_test.go | 94 ++++++++++++++++++- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 79b7c3b1c9..525f5be926 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -230,7 +230,7 @@ func NewBlock(ctx context.Context, ks *Keepers, customTime ...time.Duration) { start := time.Now() ks.Pairing.UnstakeUnresponsiveProviders(unwrapedCtx, EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) elapsed_time := time.Since(start) - fmt.Printf("elapsed_time: %v\n", elapsed_time) + fmt.Printf("%v, ", elapsed_time) } ks.Conflict.CheckAndHandleAllVotes(unwrapedCtx) diff --git a/x/pairing/keeper/unreponsive_provider_test.go b/x/pairing/keeper/unreponsive_provider_test.go index 703702de13..022b850e5e 100644 --- a/x/pairing/keeper/unreponsive_provider_test.go +++ b/x/pairing/keeper/unreponsive_provider_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "encoding/json" + "math/rand" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,8 +13,79 @@ import ( "github.com/stretchr/testify/require" ) +func TestUnresponsivenessStressTest(t *testing.T) { + // setup test for unresponsiveness + testClientAmount := 10000 + testProviderAmount := 1000 + ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) + + // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) + for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+testkeeper.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + + // create unresponsive data list of the first 100 providers being unresponsive + var unresponsiveDataList [][]byte + unresponsiveProviderAmount := 100 + for i := 0; i < unresponsiveProviderAmount; i++ { + unresponsiveData, err := json.Marshal([]string{ts.providers[i].address.String()}) + require.Nil(t, err) + unresponsiveDataList = append(unresponsiveDataList, unresponsiveData) + } + + // create relay requests for that contain complaints about providers with indices 0-100 + relayEpoch := sdk.UnwrapSDKContext(ts.ctx).BlockHeight() + for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints + var Relays []*types.RelayRequest + + // Get pairing for the client to pick a valid provider + providersStakeEntries, err := ts.keepers.Pairing.GetPairingForClient(sdk.UnwrapSDKContext(ts.ctx), ts.spec.Name, ts.clients[clientIndex].address) + providerIndex := rand.Intn(len(providersStakeEntries)) + providerAddress := providersStakeEntries[providerIndex].Address + + // create relay request + relayRequest := &types.RelayRequest{ + Provider: providerAddress, + ApiUrl: "", + Data: []byte(ts.spec.Apis[0].Name), + SessionId: uint64(0), + ChainID: ts.spec.Name, + CuSum: ts.spec.Apis[0].ComputeUnits*10 + uint64(clientIndex), + BlockHeight: relayEpoch, + RelayNum: 0, + RequestBlock: -1, + DataReliability: nil, + UnresponsiveProviders: unresponsiveDataList[clientIndex%unresponsiveProviderAmount], // create the complaint + } + + sig, err := sigs.SignRelay(ts.clients[clientIndex].secretKey, *relayRequest) + relayRequest.Sig = sig + require.Nil(t, err) + Relays = append(Relays, relayRequest) + + // send the relay requests (provider gets payment) + _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: providerAddress, Relays: Relays}) + require.Nil(t, err) + + } + + // advance enough epochs so the unresponsive providers will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) + for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + + // test the providers has been unstaked + for i := 0; i < unresponsiveProviderAmount; i++ { + _, unstakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[i].address) + require.True(t, unstakeStoragefound) + _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[i].address) + require.False(t, stakeStorageFound) + } +} + // Test to measure the time the check for unresponsiveness every epoch start takes -func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { +func TestUnstakingProviderForUnresponsiveness(t *testing.T) { // setup test for unresponsiveness testClientAmount := 4 testProviderAmount := 2 @@ -34,6 +106,7 @@ func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { // create relay requests for provider0 that contain complaints about provider1 var Relays []*types.RelayRequest + relayEpoch := sdk.UnwrapSDKContext(ts.ctx).BlockHeight() for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints relayRequest := &types.RelayRequest{ Provider: ts.providers[0].address.String(), @@ -42,7 +115,7 @@ func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { SessionId: uint64(0), ChainID: ts.spec.Name, CuSum: ts.spec.Apis[0].ComputeUnits*10 + uint64(clientIndex), - BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), + BlockHeight: relayEpoch, RelayNum: 0, RequestBlock: -1, DataReliability: nil, @@ -70,6 +143,12 @@ func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) require.False(t, stakeStorageFound) + // validate the complainers CU field in provider1's providerPaymentStorage has been reset after being punished (note we use the epoch from the relay because that is when it got reported) + providerPaymentStorageKey := ts.keepers.Pairing.GetProviderPaymentStorageKey(sdk.UnwrapSDKContext(ts.ctx), ts.spec.Name, uint64(relayEpoch), ts.providers[1].address) + providerPaymentStorage, found := ts.keepers.Pairing.GetProviderPaymentStorage(sdk.UnwrapSDKContext(ts.ctx), providerPaymentStorageKey) + require.Equal(t, true, found) + require.Equal(t, uint64(0), providerPaymentStorage.GetComplainersTotalCu()) + // advance enough epochs so the current block will be deleted (advance more than the chain's memory - blocksToSave) OriginalBlockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) blocksToSave, err := ts.keepers.Epochstorage.BlocksToSave(sdk.UnwrapSDKContext(ts.ctx), OriginalBlockHeight) @@ -95,7 +174,7 @@ func TestRelayPaymentUnstakingProviderForUnresponsiveness(t *testing.T) { require.Equal(t, balanceProvideratBeforeStake, balanceProviderAfterUnstakeMoneyReturned) } -func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t *testing.T) { +func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t *testing.T) { // setup test for unresponsiveness testClientAmount := 4 testProviderAmount := 2 @@ -112,6 +191,7 @@ func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfte // create relay requests for provider0 that contain complaints about provider1 var Relays []*types.RelayRequest + relayEpoch := sdk.UnwrapSDKContext(ts.ctx).BlockHeight() for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints relayRequest := &types.RelayRequest{ @@ -121,7 +201,7 @@ func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfte SessionId: uint64(0), ChainID: ts.spec.Name, CuSum: ts.spec.Apis[0].ComputeUnits * 10, - BlockHeight: sdk.UnwrapSDKContext(ts.ctx).BlockHeight(), + BlockHeight: relayEpoch, RelayNum: 0, RequestBlock: -1, DataReliability: nil, @@ -149,6 +229,12 @@ func TestRelayPaymentUnstakingProviderForUnresponsivenessContinueComplainingAfte _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) require.False(t, stakeStorageFound) + // validate the complainers CU field in provider1's providerPaymentStorage has been reset after being punished (note we use the epoch from the relay because that is when it got reported) + providerPaymentStorageKey := ts.keepers.Pairing.GetProviderPaymentStorageKey(sdk.UnwrapSDKContext(ts.ctx), ts.spec.Name, uint64(relayEpoch), ts.providers[1].address) + providerPaymentStorage, found := ts.keepers.Pairing.GetProviderPaymentStorage(sdk.UnwrapSDKContext(ts.ctx), providerPaymentStorageKey) + require.Equal(t, true, found) + require.Equal(t, uint64(0), providerPaymentStorage.GetComplainersTotalCu()) + // advance some more epochs for i := 0; i < 2; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) From b0c5dc00b6c96beda2dfe7b3c3575e442059f51b Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 16 Jan 2023 16:20:41 +0200 Subject: [PATCH 14/37] CNS-137: rename test file (typo) --- ...unreponsive_provider_test.go => unresponsive_provider_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename x/pairing/keeper/{unreponsive_provider_test.go => unresponsive_provider_test.go} (100%) diff --git a/x/pairing/keeper/unreponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go similarity index 100% rename from x/pairing/keeper/unreponsive_provider_test.go rename to x/pairing/keeper/unresponsive_provider_test.go From fd177c0bc5b0dcec789e7bf706df78122d16fd6b Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 16 Jan 2023 18:51:36 +0200 Subject: [PATCH 15/37] CNS-137: lowered the providers/clients amount in the stress test (so it won't be too slow) --- x/pairing/keeper/unresponsive_provider_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/pairing/keeper/unresponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go index 022b850e5e..f80c7ec0e0 100644 --- a/x/pairing/keeper/unresponsive_provider_test.go +++ b/x/pairing/keeper/unresponsive_provider_test.go @@ -15,8 +15,8 @@ import ( func TestUnresponsivenessStressTest(t *testing.T) { // setup test for unresponsiveness - testClientAmount := 10000 - testProviderAmount := 1000 + testClientAmount := 50 + testProviderAmount := 5 ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) @@ -26,7 +26,7 @@ func TestUnresponsivenessStressTest(t *testing.T) { // create unresponsive data list of the first 100 providers being unresponsive var unresponsiveDataList [][]byte - unresponsiveProviderAmount := 100 + unresponsiveProviderAmount := 1 for i := 0; i < unresponsiveProviderAmount; i++ { unresponsiveData, err := json.Marshal([]string{ts.providers[i].address.String()}) require.Nil(t, err) From 3f31066728dd479a984183abdaab73de76dfc3ab Mon Sep 17 00:00:00 2001 From: oren-lava Date: Wed, 18 Jan 2023 17:31:46 +0200 Subject: [PATCH 16/37] CNS-137: fix PR issues --- .../lavasession/consumer_session_manager.go | 10 +- testutil/keeper/keepers_init.go | 12 +- x/pairing/keeper/msg_server_relay_payment.go | 13 + x/pairing/keeper/unresponsive_provider.go | 248 ++++++++++-------- .../keeper/unresponsive_provider_test.go | 22 +- 5 files changed, 172 insertions(+), 133 deletions(-) diff --git a/relayer/lavasession/consumer_session_manager.go b/relayer/lavasession/consumer_session_manager.go index 5c31eb5e7d..b2671fe146 100644 --- a/relayer/lavasession/consumer_session_manager.go +++ b/relayer/lavasession/consumer_session_manager.go @@ -263,15 +263,7 @@ func (csm *ConsumerSessionManager) blockProvider(address string, reportProvider } } - // before we report the provider, we check that we're currently paired to it - consumerPairedWithProvider := false - for _, pairingAddr := range csm.pairingAddresses { - if pairingAddr == address { - consumerPairedWithProvider = true - } - } - - if reportProvider && consumerPairedWithProvider { // Report provider flow + if reportProvider { // Report provider flow if _, ok := csm.addedToPurgeAndReport[address]; !ok { // verify it doesn't exist already csm.addedToPurgeAndReport[address] = struct{}{} } diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 525f5be926..0cf082c4f0 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -2,7 +2,6 @@ package keeper import ( "context" - "fmt" "testing" "time" @@ -18,6 +17,7 @@ import ( conflicttypes "github.com/lavanet/lava/x/conflict/types" epochstoragekeeper "github.com/lavanet/lava/x/epochstorage/keeper" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" + "github.com/lavanet/lava/x/pairing" pairingkeeper "github.com/lavanet/lava/x/pairing/keeper" pairingtypes "github.com/lavanet/lava/x/pairing/types" "github.com/lavanet/lava/x/spec" @@ -32,9 +32,7 @@ import ( ) const ( - BLOCK_TIME = 30 * time.Second - EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER = 4 // number of epochs to sum CU that the provider serviced - EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS = 2 // number of epochs to sum CU of complainers against the provider + BLOCK_TIME = 30 * time.Second ) type Keepers struct { @@ -226,11 +224,7 @@ func NewBlock(ctx context.Context, ks *Keepers, customTime ...time.Duration) { ks.Pairing.RemoveOldEpochPayment(unwrapedCtx) ks.Pairing.CheckUnstakingForCommit(unwrapedCtx) - - start := time.Now() - ks.Pairing.UnstakeUnresponsiveProviders(unwrapedCtx, EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) - elapsed_time := time.Since(start) - fmt.Printf("%v, ", elapsed_time) + ks.Pairing.UnstakeUnresponsiveProviders(unwrapedCtx, pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) } ks.Conflict.CheckAndHandleAllVotes(unwrapedCtx) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 196fc1844b..7cf29151de 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -344,6 +344,19 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, // set the final provider payment storage state including the complaints k.SetProviderPaymentStorage(ctx, providerPaymentStorage) + + // update the complainer CU also in epochPayments (providerPaymentStorage objects are saved in a list inside epochPayments and also seperately - need to update both) + epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, providerPaymentStorage.GetEpoch()) + if !found { + utils.LavaFormatError("unable to find epochPayments entry of unresponsive provider", nil, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) + continue + } + providerPaymentStorageList := epochPayments.GetClientsPayments() + for _, providerPaymentStorageElem := range providerPaymentStorageList { + if providerPaymentStorage.GetIndex() == providerPaymentStorageElem.GetIndex() { + providerPaymentStorageElem.ComplainersTotalCu += complainerCuToAdd + } + } } return nil } diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index 02f8755d95..49039438fa 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -11,7 +11,8 @@ import ( "github.com/lavanet/lava/x/pairing/types" ) -type punishEntry struct { +// This struct's goal is to keep track of the CU required for unresponsiveness for a specific provider and a specific chain ID (the CUs are counted over several epochs) +type providerCuCounterForUnreponsiveness struct { providerPaymentStorageIndexList []string // index list of providerPaymentStorage objects that share providerAddress + chainID (but not epoch) complainersUsedCu uint64 // sum of the complainers' CU over epochsNumToCheckCUForComplainers epochs back (start counting from currentEpoch-epochsNumToCheckCUForUnresponsiveProvider) providerServicedCu uint64 // sum of the unresponsive provider's serviced CU over epochsNumToCheckCUForUnresponsiveProvider epochs back (start counting from current epoch) @@ -41,68 +42,65 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU return nil } -// Function that returns a map that links between a provider that should be punished and its punishEntry +// Function that returns a map that links between a provider that should be punished and its providerCuCounterForUnreponsiveness func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (map[string][]string, error) { // check the epochsNum consts if epochsNumToCheckCUForComplainers <= 0 || epochsNumToCheckCUForUnresponsiveProvider <= 0 { return nil, utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") } - providersPunishEntryMap := make(map[string]punishEntry) // map of punishEntryKey keys (string) with punishEntry values (punishEntryKey = providerAddress_chainID) - providersToPunishMap := make(map[string][]string) // map of punishEntryKey keys (string) with list of providerPaymentStorage indices values (string array) (punishEntryKey = providerAddress_chainID) - // Get recommendedEpochNumToCollectPayment recommendedEpochNumToCollectPayment := k.RecommendedEpochNumToCollectPayment(ctx) - // handle very early epochs (basically, don't punish) - epochBlocks, err := k.epochStorageKeeper.EpochBlocks(ctx, currentEpoch) - if err != nil { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_epoch_blocks", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get epoch blocks param") + // To check for punishment, we have to go back (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing + epochTemp := currentEpoch + for counter := uint64(0); counter < epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider+recommendedEpochNumToCollectPayment; counter++ { + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + return nil, types.EpochTooEarlyForUnresponsiveProviderJailError + } + epochTemp = previousEpoch } - if currentEpoch < (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider+recommendedEpochNumToCollectPayment)*epochBlocks { - // To check for punishment, we have to go back (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing - return nil, types.EpochTooEarlyForUnresponsiveProviderJailError + + providerCuCounterForUnreponsivenessMap := make(map[string]providerCuCounterForUnreponsiveness) // map of providerCuCounterForUnreponsiveness keys (string) with providerCuCounterForUnreponsiveness values (providerCuCounterForUnreponsiveness = providerAddress_chainID) + providersToPunishMap := make(map[string][]string) // map of providerCuCounterForUnreponsiveness keys (string) with list of providerPaymentStorage indices values (string array) (providerCuCounterForUnreponsiveness = providerAddress_chainID) + + // Get the current stake storages (from all chains). stake storages contain a list of stake entries. Each stake storage is for a different chain + providerStakeStorageList := k.getCurrentProviderStakeStorageList(ctx) + if len(providerStakeStorageList) == 0 { + // no provider is staked -> no one to punish + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_current_provider_stake_storage_list", nil, "no provider is staked, no one to punish") } // Go back recommendedEpochNumToCollectPayment + epochTemp = currentEpoch for counter := uint64(0); counter < recommendedEpochNumToCollectPayment; counter++ { - previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, currentEpoch) + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) if err != nil { return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get previous epoch") } - currentEpoch = previousEpoch - } - - // Go over previous epochs to count the CU serviced by the provider - epochAfterCountingProviderCu, err := k.countCuForUnresponsiveProviderAndComplainers(ctx, true, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, providersPunishEntryMap) - if err != nil { - return nil, utils.LavaError(ctx, k.Logger(ctx), "count_cu_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't count the CU of the unresponsive provider") - } - - // Go over previous epochs (from the point the last loop finished) to count the CU of clients that complained about the provider - _, err = k.countCuForUnresponsiveProviderAndComplainers(ctx, false, epochAfterCountingProviderCu, epochsNumToCheckCUForComplainers, providersPunishEntryMap) - if err != nil { - return nil, utils.LavaError(ctx, k.Logger(ctx), "count_cu_complainers", map[string]string{"err": err.Error()}, "couldn't count the CU of the complainers") + epochTemp = previousEpoch } - // Get providers that should be punished - for punishEntryKey, punishEntry := range providersPunishEntryMap { - // provider doesn't have payments (serviced CU = 0) - if punishEntry.providerServicedCu == 0 { - chainID := strings.Split(punishEntryKey, "_")[1] - - // Try getting the provider's stake entry - _, foundStakeEntry := k.epochStorageKeeper.GetEpochStakeEntries(ctx, currentEpoch, epochstoragetypes.ProviderKey, chainID) - - // if stake entry is not found -> this is the provider's first epoch (didn't get a chance to stake yet) -> don't punish him - if !foundStakeEntry { - continue + // Go over the staked provider entries (on all chains) + for _, providerStakeStorage := range providerStakeStorageList { + for _, providerStakeEntry := range providerStakeStorage.GetStakeEntries() { + // update the CU count for this provider in providerCuCounterForUnreponsivenessMap + err := k.updateCuForProviderInProviderCuCounterForUnreponsivenessMap(ctx, epochTemp, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers, providerStakeEntry, providerCuCounterForUnreponsivenessMap) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "update_cu_for_provider_in_provider_cu_counter_for_unreponsiveness_map", map[string]string{"err": err.Error()}, "couldn't update the CU count in the providerCuCounterForUnreponsivenessMap") } - } - // The provider served less CU than the sum of the complainers CU -> should be punished - if punishEntry.complainersUsedCu > punishEntry.providerServicedCu { - providersToPunishMap[punishEntryKey] = punishEntry.providerPaymentStorageIndexList + // get the provider's providerCuCounterForUnreponsiveness from the providerCuCounterForUnreponsivenessMap + providerCuCounterForUnreponsiveness, found, providerCuCounterForUnreponsivenessKey := k.getProviderCuCounterForUnreponsivenessEntryFromMap(providerStakeEntry, providerCuCounterForUnreponsivenessMap) + if !found { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_providerCuCounterForUnreponsiveness_entry_from_map", nil, "couldn't get providerCuCounterForUnreponsiveness entry from map") + } + // check whether this provider should be punished + shouldBePunished := k.checkIfProviderShouldBePunishedDueToUnresponsiveness(providerCuCounterForUnreponsiveness) + if shouldBePunished { + providersToPunishMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsiveness.providerPaymentStorageIndexList + } } } @@ -111,84 +109,118 @@ func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch u // Function to count the CU serviced by the unresponsive provider or the CU of the complainers. // The function counts CU from back. The number of epochs to go back is . The function returns the last visited epoch -func (k Keeper) countCuForUnresponsiveProviderAndComplainers(ctx sdk.Context, isProvider bool, epoch uint64, epochsNumToGoBack uint64, providersPunishEntryMap map[string]punishEntry) (uint64, error) { +func (k Keeper) updateCuForProviderInProviderCuCounterForUnreponsivenessMap(ctx sdk.Context, epoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64, providerStakeEntry epochstoragetypes.StakeEntry, providerCuCounterForUnreponsivenessMap map[string]providerCuCounterForUnreponsiveness) error { epochTemp := epoch + createNewproviderCuCounterForUnreponsivenessEntryFlag := false + // get the provider's SDK account address + sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(providerStakeEntry.GetAddress()) + if err != nil { + return utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) + } - for counter := uint64(0); counter < epochsNumToGoBack; counter++ { - // Get previous epoch (from epochTemp) - previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) - if err != nil { - return 0, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") - } + // get the provider's providerCuCounterForUnreponsiveness + providerCuCounterForUnreponsivenessEntry, found, providerCuCounterForUnreponsivenessKey := k.getProviderCuCounterForUnreponsivenessEntryFromMap(providerStakeEntry, providerCuCounterForUnreponsivenessMap) + if !found { + // if providerCuCounterForUnreponsivenessEntry is not found, raise a flag to create new entry in providerCuCounterForUnreponsivenessMap + createNewproviderCuCounterForUnreponsivenessEntryFlag = true + } - // Get the current stake storages (from all chains) - stakeStorageList := k.getCurrentProviderStakeStorageList(ctx) - if len(stakeStorageList) == 0 { - // no provider is staked -> CU = 0 - return 0, nil - } + // count the CU serviced by the unersponsive provider and used CU of the complainers + for counter := uint64(0); counter < epochsNumToCheckCUForUnresponsiveProvider+epochsNumToCheckCUForComplainers; counter++ { + // get providerPaymentStorageKey for epochTemp (other traits from the stake entry) + providerPaymentStorageKey := k.GetProviderPaymentStorageKey(ctx, providerStakeEntry.GetChain(), epochTemp, sdkStakeEntryProviderAddress) - // Get a providerPaymentStorage of all staked providers - providerPaymentStorageList, err := k.getProviderPaymentStorageFromStakeStorageList(ctx, previousEpoch, stakeStorageList) - if err != nil { - return 0, utils.LavaError(ctx, k.Logger(ctx), "get_provider_payment_storage_from_stake_storage_list", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", previousEpoch)}, "couldn't get providerPaymentStorageList from stakeStorageList") + // try getting providerPaymentStorage using the providerPaymentStorageKey + providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageKey) + if !found { + // Get previous epoch (from epochTemp) + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + } + // update epochTemp + epochTemp = previousEpoch + + // there is no providerPaymentStorage for this provider in this epoch -> continue searching + continue } - // Go over providerPaymentStorage list - for _, providerPaymentStorage := range providerPaymentStorageList { + // counter is smaller than epochsNumToCheckCUForUnresponsiveProvider -> only count CU serviced by the provider in the epoch + if counter < epochsNumToCheckCUForUnresponsiveProvider { + // count the CU by iterating through the uniquePaymentStorageClientProvider objects cuCount := uint64(0) + for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { + cuCount += uniquePayment.GetUsedCU() + } - // Get provider address and chainID - providerAddress := k.getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorage.Index) - chainID := k.getChainIDFromProviderPaymentStorageKey(providerPaymentStorage.Index) - - // Create a punishEntryKey from the provider's address and the chain ID - punishEntryKey := providerAddress + "_" + chainID - - // find the provider's punishEntry in map - providerPunishEntry, punishEntryFound := providersPunishEntryMap[punishEntryKey] - - if isProvider { - // if isProvider is true, we count the CU serviced by the unersponsive provider - for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { - cuCount += uniquePayment.GetUsedCU() - } - if punishEntryFound { - // punishEntry found -> add the cuCount to providerServicedCu and update the map entry - providerPunishEntry.providerServicedCu += cuCount - providersPunishEntryMap[punishEntryKey] = providerPunishEntry - } else { - // punishEntry not found -> create a new one and add it to the map - providersPunishEntryMap[punishEntryKey] = punishEntry{complainersUsedCu: 0, providerServicedCu: cuCount, providerPaymentStorageIndexList: []string{providerPaymentStorage.Index}} - } + // update the CU in the providerCuCounterForUnreponsivenessMap + if createNewproviderCuCounterForUnreponsivenessEntryFlag { + // providerCuCounterForUnreponsiveness not found -> create a new one and add it to the map + providerCuCounterForUnreponsivenessMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsiveness{complainersUsedCu: 0, providerServicedCu: cuCount, providerPaymentStorageIndexList: []string{providerPaymentStorage.GetIndex()}} + + // set the createNewproviderCuCounterForUnreponsivenessEntryFlag to false + createNewproviderCuCounterForUnreponsivenessEntryFlag = false } else { - // Get servicersToPair param - servicersToPair, err := k.ServicersToPairCount(ctx, epoch) - if err != nil || servicersToPair == 0 { - return 0, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") - } - - // Collect complainers CU (divided by servicersToPair) - cuCount = providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) - - if punishEntryFound { - // punishEntry found -> add the cuCount to complainersUsedCu and update the map entry - providerPunishEntry.complainersUsedCu += cuCount - providersPunishEntryMap[punishEntryKey] = providerPunishEntry - } else { - // punishEntry not found -> create a new one and add it to the map - providersPunishEntryMap[punishEntryKey] = punishEntry{complainersUsedCu: cuCount, providerServicedCu: 0, providerPaymentStorageIndexList: []string{providerPaymentStorage.Index}} - } + // providerCuCounterForUnreponsiveness found -> add the cuCount to providerServicedCu and update the map entry + providerCuCounterForUnreponsivenessEntry.providerServicedCu += cuCount + providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList = append(providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList, providerPaymentStorage.GetIndex()) + providerCuCounterForUnreponsivenessMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsivenessEntry + } + } else { + // counter is larger than epochsNumToCheckCUForUnresponsiveProvider -> only count complainer CU + // Get servicersToPair param + servicersToPair, err := k.ServicersToPairCount(ctx, epoch) + if err != nil || servicersToPair == 0 { + return utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") } - // add the providerPaymentStorage index to the providerPaymentStorageIndexList - providerPunishEntry.providerPaymentStorageIndexList = append(providerPunishEntry.providerPaymentStorageIndexList, providerPaymentStorage.Index) + + // Collect complainers CU (divided by servicersToPair) + complainersCuCount := providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) + + // add the complainersCuCount to complainersUsedCu and update the map entry + providerCuCounterForUnreponsivenessEntry.complainersUsedCu += complainersCuCount + providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList = append(providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList, providerPaymentStorage.GetIndex()) + providerCuCounterForUnreponsivenessMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsivenessEntry } + // Get previous epoch (from epochTemp) + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + } // update epochTemp epochTemp = previousEpoch } + return nil +} + +func (k Keeper) getProviderCuCounterForUnreponsivenessEntryFromMap(providerStakeEntry epochstoragetypes.StakeEntry, providerCuCounterForUnreponsivenessMap map[string]providerCuCounterForUnreponsiveness) (providerCuCounterForUnreponsiveness, bool, string) { + // get ProviderCuCounterForUnreponsivenessKey + ProviderCuCounterForUnreponsivenessKey := k.getProviderCuCounterForUnreponsivenessKey(providerStakeEntry.GetAddress(), providerStakeEntry.GetChain()) + + // get ProviderCuCounterForUnreponsiveness + providerCuCounterForUnreponsiveness, found := providerCuCounterForUnreponsivenessMap[ProviderCuCounterForUnreponsivenessKey] + return providerCuCounterForUnreponsiveness, found, ProviderCuCounterForUnreponsivenessKey +} + +func (k Keeper) checkIfProviderShouldBePunishedDueToUnresponsiveness(providerCuCounterForUnreponsiveness providerCuCounterForUnreponsiveness) bool { + // if the provider served less CU than the sum of the complainers CU -> should be punished + return providerCuCounterForUnreponsiveness.complainersUsedCu > providerCuCounterForUnreponsiveness.providerServicedCu +} + +// Function to create a providerCuCounterForUnreponsivenessKey +func (k Keeper) getProviderCuCounterForUnreponsivenessKey(providerAddress string, chainID string) string { + return providerAddress + "_" + chainID +} + +// Function to extract the chain ID from providerCuCounterForUnreponsivenessKey +func (k Keeper) getChainIDFromProviderCuCounterForUnreponsivenessKey(providerCuCounterForUnreponsivenessKey string) string { + return strings.Split(providerCuCounterForUnreponsivenessKey, "_")[1] +} - return epochTemp, nil +// Function to extract the provider address from providerCuCounterForUnreponsivenessKey +func (k Keeper) getProviderAddressFromProviderCuCounterForUnreponsivenessKey(providerCuCounterForUnreponsivenessKey string) string { + return strings.Split(providerCuCounterForUnreponsivenessKey, "_")[0] } // Function that return the current stake storage for all chains @@ -249,10 +281,10 @@ func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish m } // Go over providers - for punishEntryKey, providerPaymentStorageIndexList := range providersToPunish { - // extract from punishEntryKey the provider address and the chain ID - providerAddress := strings.Split(punishEntryKey, "_")[0] - chainID := strings.Split(punishEntryKey, "_")[1] + for providerCuCounterForUnreponsivenessKey, providerPaymentStorageIndexList := range providersToPunish { + // extract from providerCuCounterForUnreponsivenessKey the provider address and the chain ID + providerAddress := strings.Split(providerCuCounterForUnreponsivenessKey, "_")[0] + chainID := strings.Split(providerCuCounterForUnreponsivenessKey, "_")[1] // Get provider's sdk.Account address sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) diff --git a/x/pairing/keeper/unresponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go index f80c7ec0e0..af3bda5686 100644 --- a/x/pairing/keeper/unresponsive_provider_test.go +++ b/x/pairing/keeper/unresponsive_provider_test.go @@ -9,6 +9,7 @@ import ( "github.com/lavanet/lava/relayer/sigs" testkeeper "github.com/lavanet/lava/testutil/keeper" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" + "github.com/lavanet/lava/x/pairing" "github.com/lavanet/lava/x/pairing/types" "github.com/stretchr/testify/require" ) @@ -20,7 +21,7 @@ func TestUnresponsivenessStressTest(t *testing.T) { ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) - for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+testkeeper.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -70,17 +71,24 @@ func TestUnresponsivenessStressTest(t *testing.T) { } // advance enough epochs so the unresponsive providers will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) - for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) - // test the providers has been unstaked + // go over unresponsive providers for i := 0; i < unresponsiveProviderAmount; i++ { + // test the providers has been unstaked _, unstakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[i].address) require.True(t, unstakeStoragefound) _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[i].address) require.False(t, stakeStorageFound) + + // validate the complainers CU field in the unresponsive provider's providerPaymentStorage has been reset after being punished (note we use the epoch from the relay because that is when it got reported) + providerPaymentStorageKey := ts.keepers.Pairing.GetProviderPaymentStorageKey(sdk.UnwrapSDKContext(ts.ctx), ts.spec.Name, uint64(relayEpoch), ts.providers[1].address) + providerPaymentStorage, found := ts.keepers.Pairing.GetProviderPaymentStorage(sdk.UnwrapSDKContext(ts.ctx), providerPaymentStorageKey) + require.Equal(t, true, found) + require.Equal(t, uint64(0), providerPaymentStorage.GetComplainersTotalCu()) } } @@ -92,7 +100,7 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) - for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+testkeeper.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -133,7 +141,7 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { require.Nil(t, err) // advance enough epochs so the unresponsive provider will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) - for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { + for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -181,7 +189,7 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) - for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+testkeeper.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -219,7 +227,7 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * require.Nil(t, err) // advance enough epochs so the unresponsive provider will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) - for i := uint64(0); i < testkeeper.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { + for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } From 382ad0849a3824c3623f2f265b2778ede662cc26 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Wed, 18 Jan 2023 17:42:49 +0200 Subject: [PATCH 17/37] CNS-137: fix typo --- x/pairing/keeper/msg_server_relay_payment.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 7cf29151de..7454a80418 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -345,7 +345,7 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, // set the final provider payment storage state including the complaints k.SetProviderPaymentStorage(ctx, providerPaymentStorage) - // update the complainer CU also in epochPayments (providerPaymentStorage objects are saved in a list inside epochPayments and also seperately - need to update both) + // update the complainer CU also in epochPayments (providerPaymentStorage objects are saved in a list inside epochPayments and also separately - need to update both) epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, providerPaymentStorage.GetEpoch()) if !found { utils.LavaFormatError("unable to find epochPayments entry of unresponsive provider", nil, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) From 84e1a6341eb6d96995129ecb5dd70317369d0c86 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Thu, 19 Jan 2023 13:31:33 +0200 Subject: [PATCH 18/37] CNS-137: in sentry replaced StaleEpochDistance with recommendedEpochNumToCollectPayment --- relayer/sentry/sentry.go | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/relayer/sentry/sentry.go b/relayer/sentry/sentry.go index c9b8257f3b..442c418294 100755 --- a/relayer/sentry/sentry.go +++ b/relayer/sentry/sentry.go @@ -131,12 +131,13 @@ type Sentry struct { // server Blocks To Save (atomic) earliestSavedBlock uint64 // Block storage (atomic) - blockHeight int64 - currentEpoch uint64 - prevEpoch uint64 - EpochSize uint64 - EpochBlocksOverlap uint64 - providersCount uint64 + blockHeight int64 + currentEpoch uint64 + prevEpoch uint64 + EpochSize uint64 + EpochBlocksOverlap uint64 + providersCount uint64 + recommendedEpochNumToCollectPayment uint64 // // Spec storage (rw mutex) specMu sync.RWMutex @@ -207,6 +208,15 @@ func (s *Sentry) FetchOverlapSize(ctx context.Context) error { return nil } +func (s *Sentry) FetchRecommendedEpochNumToCollectPayment(ctx context.Context) error { + res, err := s.pairingQueryClient.Params(ctx, &pairingtypes.QueryParamsRequest{}) + if err != nil { + return err + } + atomic.StoreUint64(&s.recommendedEpochNumToCollectPayment, res.GetParams().RecommendedEpochNumToCollectPayment) + return nil +} + func (s *Sentry) FetchEpochParams(ctx context.Context) error { res, err := s.epochStorageQueryClient.EpochDetails(ctx, &epochstoragetypes.QueryGetEpochDetailsRequest{}) if err != nil { @@ -620,7 +630,7 @@ func (s *Sentry) Start(ctx context.Context) { } if s.newEpochCb != nil { - go s.newEpochCb(data.Block.Height - StaleEpochDistance*int64(s.GetEpochSize())) // Currently this is only askForRewards + go s.newEpochCb(data.Block.Height - int64(s.recommendedEpochNumToCollectPayment)*int64(s.GetEpochSize())) // Currently this is only askForRewards } // From 645be2b35a6c255310804eda9339b8438608e342 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Thu, 19 Jan 2023 15:15:00 +0200 Subject: [PATCH 19/37] CNS-137: fix additional PR issues --- x/pairing/keeper/msg_server_relay_payment.go | 1 + x/pairing/keeper/unresponsive_provider.go | 284 ++++++------------ .../keeper/unresponsive_provider_test.go | 55 +++- x/pairing/module.go | 4 +- x/pairing/types/errors.go | 1 - 5 files changed, 132 insertions(+), 213 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 7454a80418..0ac925f565 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -357,6 +357,7 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, providerPaymentStorageElem.ComplainersTotalCu += complainerCuToAdd } } + k.SetEpochPayments(ctx, epochPayments) } return nil } diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index 49039438fa..c7e5747f3d 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -3,7 +3,6 @@ package keeper import ( "fmt" "strconv" - "strings" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" @@ -11,65 +10,41 @@ import ( "github.com/lavanet/lava/x/pairing/types" ) -// This struct's goal is to keep track of the CU required for unresponsiveness for a specific provider and a specific chain ID (the CUs are counted over several epochs) -type providerCuCounterForUnreponsiveness struct { - providerPaymentStorageIndexList []string // index list of providerPaymentStorage objects that share providerAddress + chainID (but not epoch) - complainersUsedCu uint64 // sum of the complainers' CU over epochsNumToCheckCUForComplainers epochs back (start counting from currentEpoch-epochsNumToCheckCUForUnresponsiveProvider) - providerServicedCu uint64 // sum of the unresponsive provider's serviced CU over epochsNumToCheckCUForUnresponsiveProvider epochs back (start counting from current epoch) -} - -func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { - // Get current epoch - currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) - - // Get unreponsive providers that should be punished - providersToPunishMap, err := k.getUnresponsiveProvidersToPunish(ctx, currentEpoch, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers) - if err != nil { - // if the epoch is too early, don't punish and log the event - if err == types.EpochTooEarlyForUnresponsiveProviderJailError { - utils.LavaFormatInfo("Epoch too early to punish unresponsive providers", &map[string]string{"epoch": fmt.Sprintf("%+v", currentEpoch)}) - return nil - } - return err - } - - // Punish unresponsive providers (the punishment is currently unstake) - err = k.punishUnresponsiveProviders(ctx, providersToPunishMap) - if err != nil { - return err - } - - return nil -} - // Function that returns a map that links between a provider that should be punished and its providerCuCounterForUnreponsiveness -func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) (map[string][]string, error) { +func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { // check the epochsNum consts if epochsNumToCheckCUForComplainers <= 0 || epochsNumToCheckCUForUnresponsiveProvider <= 0 { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") + return utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") } + // Get current epoch + currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) + // Get recommendedEpochNumToCollectPayment recommendedEpochNumToCollectPayment := k.RecommendedEpochNumToCollectPayment(ctx) - // To check for punishment, we have to go back (epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing + // check which of the consts is larger + largerEpochsNumConst := epochsNumToCheckCUForComplainers + if epochsNumToCheckCUForUnresponsiveProvider > epochsNumToCheckCUForComplainers { + largerEpochsNumConst = epochsNumToCheckCUForUnresponsiveProvider + } + + // To check for punishment, we have to go back recommendedEpochNumToCollectPayment+max(epochsNumToCheckCUForComplainers,epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing epochTemp := currentEpoch - for counter := uint64(0); counter < epochsNumToCheckCUForComplainers+epochsNumToCheckCUForUnresponsiveProvider+recommendedEpochNumToCollectPayment; counter++ { + for counter := uint64(0); counter < largerEpochsNumConst+recommendedEpochNumToCollectPayment; counter++ { previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) if err != nil { - return nil, types.EpochTooEarlyForUnresponsiveProviderJailError + utils.LavaFormatInfo("Epoch too early to punish unresponsive providers", &map[string]string{"epoch": fmt.Sprintf("%+v", currentEpoch)}) + return nil } epochTemp = previousEpoch } - providerCuCounterForUnreponsivenessMap := make(map[string]providerCuCounterForUnreponsiveness) // map of providerCuCounterForUnreponsiveness keys (string) with providerCuCounterForUnreponsiveness values (providerCuCounterForUnreponsiveness = providerAddress_chainID) - providersToPunishMap := make(map[string][]string) // map of providerCuCounterForUnreponsiveness keys (string) with list of providerPaymentStorage indices values (string array) (providerCuCounterForUnreponsiveness = providerAddress_chainID) - // Get the current stake storages (from all chains). stake storages contain a list of stake entries. Each stake storage is for a different chain providerStakeStorageList := k.getCurrentProviderStakeStorageList(ctx) if len(providerStakeStorageList) == 0 { // no provider is staked -> no one to punish - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_current_provider_stake_storage_list", nil, "no provider is staked, no one to punish") + return utils.LavaError(ctx, k.Logger(ctx), "get_current_provider_stake_storage_list", nil, "no provider is staked, no one to punish") } // Go back recommendedEpochNumToCollectPayment @@ -77,7 +52,7 @@ func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch u for counter := uint64(0); counter < recommendedEpochNumToCollectPayment; counter++ { previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) if err != nil { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get previous epoch") + return utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get previous epoch") } epochTemp = previousEpoch } @@ -86,141 +61,90 @@ func (k Keeper) getUnresponsiveProvidersToPunish(ctx sdk.Context, currentEpoch u for _, providerStakeStorage := range providerStakeStorageList { for _, providerStakeEntry := range providerStakeStorage.GetStakeEntries() { // update the CU count for this provider in providerCuCounterForUnreponsivenessMap - err := k.updateCuForProviderInProviderCuCounterForUnreponsivenessMap(ctx, epochTemp, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers, providerStakeEntry, providerCuCounterForUnreponsivenessMap) + providerPaymentStorageKeyList, err := k.countCuForUnresponsiveness(ctx, epochTemp, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers, providerStakeEntry) if err != nil { - return nil, utils.LavaError(ctx, k.Logger(ctx), "update_cu_for_provider_in_provider_cu_counter_for_unreponsiveness_map", map[string]string{"err": err.Error()}, "couldn't update the CU count in the providerCuCounterForUnreponsivenessMap") + return utils.LavaError(ctx, k.Logger(ctx), "update_cu_for_provider_in_provider_cu_counter_for_unreponsiveness_map", map[string]string{"err": err.Error()}, "couldn't update the CU count in the providerCuCounterForUnreponsivenessMap") } - // get the provider's providerCuCounterForUnreponsiveness from the providerCuCounterForUnreponsivenessMap - providerCuCounterForUnreponsiveness, found, providerCuCounterForUnreponsivenessKey := k.getProviderCuCounterForUnreponsivenessEntryFromMap(providerStakeEntry, providerCuCounterForUnreponsivenessMap) - if !found { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_providerCuCounterForUnreponsiveness_entry_from_map", nil, "couldn't get providerCuCounterForUnreponsiveness entry from map") - } - // check whether this provider should be punished - shouldBePunished := k.checkIfProviderShouldBePunishedDueToUnresponsiveness(providerCuCounterForUnreponsiveness) - if shouldBePunished { - providersToPunishMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsiveness.providerPaymentStorageIndexList + // providerPaymentStorageKeyList is not nil -> provider should be punished + if providerPaymentStorageKeyList != nil { + err = k.punishUnresponsiveProvider(ctx, providerPaymentStorageKeyList) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "punish_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't punish unresponsive provider") + } } } } - return providersToPunishMap, nil + return nil } -// Function to count the CU serviced by the unresponsive provider or the CU of the complainers. -// The function counts CU from back. The number of epochs to go back is . The function returns the last visited epoch -func (k Keeper) updateCuForProviderInProviderCuCounterForUnreponsivenessMap(ctx sdk.Context, epoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64, providerStakeEntry epochstoragetypes.StakeEntry, providerCuCounterForUnreponsivenessMap map[string]providerCuCounterForUnreponsiveness) error { +// Function to count the CU serviced by the unresponsive provider and the CU of the complainers. The function returns a list of the found providerPaymentStorageKey +func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64, providerStakeEntry epochstoragetypes.StakeEntry) ([]string, error) { epochTemp := epoch - createNewproviderCuCounterForUnreponsivenessEntryFlag := false + providerServicedCu := uint64(0) + complainersCu := uint64(0) + providerPaymentStorageKeyList := []string{} + // get the provider's SDK account address sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(providerStakeEntry.GetAddress()) if err != nil { - return utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) + return nil, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) } - // get the provider's providerCuCounterForUnreponsiveness - providerCuCounterForUnreponsivenessEntry, found, providerCuCounterForUnreponsivenessKey := k.getProviderCuCounterForUnreponsivenessEntryFromMap(providerStakeEntry, providerCuCounterForUnreponsivenessMap) - if !found { - // if providerCuCounterForUnreponsivenessEntry is not found, raise a flag to create new entry in providerCuCounterForUnreponsivenessMap - createNewproviderCuCounterForUnreponsivenessEntryFlag = true + // check which of the consts is larger + largerEpochsNumConst := epochsNumToCheckCUForComplainers + if epochsNumToCheckCUForUnresponsiveProvider > epochsNumToCheckCUForComplainers { + largerEpochsNumConst = epochsNumToCheckCUForUnresponsiveProvider } // count the CU serviced by the unersponsive provider and used CU of the complainers - for counter := uint64(0); counter < epochsNumToCheckCUForUnresponsiveProvider+epochsNumToCheckCUForComplainers; counter++ { + for counter := uint64(0); counter < largerEpochsNumConst; counter++ { // get providerPaymentStorageKey for epochTemp (other traits from the stake entry) providerPaymentStorageKey := k.GetProviderPaymentStorageKey(ctx, providerStakeEntry.GetChain(), epochTemp, sdkStakeEntryProviderAddress) // try getting providerPaymentStorage using the providerPaymentStorageKey providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageKey) - if !found { - // Get previous epoch (from epochTemp) - previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) - if err != nil { - return utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + if found { + // counter is smaller than epochsNumToCheckCUForUnresponsiveProvider -> count CU serviced by the provider in the epoch + if counter < epochsNumToCheckCUForUnresponsiveProvider { + // count the CU by iterating through the uniquePaymentStorageClientProvider objects + for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { + providerServicedCu += uniquePayment.GetUsedCU() + } } - // update epochTemp - epochTemp = previousEpoch - // there is no providerPaymentStorage for this provider in this epoch -> continue searching - continue - } - - // counter is smaller than epochsNumToCheckCUForUnresponsiveProvider -> only count CU serviced by the provider in the epoch - if counter < epochsNumToCheckCUForUnresponsiveProvider { - // count the CU by iterating through the uniquePaymentStorageClientProvider objects - cuCount := uint64(0) - for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { - cuCount += uniquePayment.GetUsedCU() - } + // counter is smaller than epochsNumToCheckCUForComplainers -> count complainer CU + if counter < epochsNumToCheckCUForComplainers { + // Get servicersToPair param + servicersToPair, err := k.ServicersToPairCount(ctx, epoch) + if err != nil || servicersToPair == 0 { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") + } - // update the CU in the providerCuCounterForUnreponsivenessMap - if createNewproviderCuCounterForUnreponsivenessEntryFlag { - // providerCuCounterForUnreponsiveness not found -> create a new one and add it to the map - providerCuCounterForUnreponsivenessMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsiveness{complainersUsedCu: 0, providerServicedCu: cuCount, providerPaymentStorageIndexList: []string{providerPaymentStorage.GetIndex()}} - - // set the createNewproviderCuCounterForUnreponsivenessEntryFlag to false - createNewproviderCuCounterForUnreponsivenessEntryFlag = false - } else { - // providerCuCounterForUnreponsiveness found -> add the cuCount to providerServicedCu and update the map entry - providerCuCounterForUnreponsivenessEntry.providerServicedCu += cuCount - providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList = append(providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList, providerPaymentStorage.GetIndex()) - providerCuCounterForUnreponsivenessMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsivenessEntry - } - } else { - // counter is larger than epochsNumToCheckCUForUnresponsiveProvider -> only count complainer CU - // Get servicersToPair param - servicersToPair, err := k.ServicersToPairCount(ctx, epoch) - if err != nil || servicersToPair == 0 { - return utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") + // update complainersCu + complainersCu += providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) } - // Collect complainers CU (divided by servicersToPair) - complainersCuCount := providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) - - // add the complainersCuCount to complainersUsedCu and update the map entry - providerCuCounterForUnreponsivenessEntry.complainersUsedCu += complainersCuCount - providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList = append(providerCuCounterForUnreponsivenessEntry.providerPaymentStorageIndexList, providerPaymentStorage.GetIndex()) - providerCuCounterForUnreponsivenessMap[providerCuCounterForUnreponsivenessKey] = providerCuCounterForUnreponsivenessEntry + // save the providerPaymentStorageKey in the providerPaymentStorageKeyList + providerPaymentStorageKeyList = append(providerPaymentStorageKeyList, providerPaymentStorageKey) } // Get previous epoch (from epochTemp) previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) if err != nil { - return utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") } // update epochTemp epochTemp = previousEpoch } - return nil -} - -func (k Keeper) getProviderCuCounterForUnreponsivenessEntryFromMap(providerStakeEntry epochstoragetypes.StakeEntry, providerCuCounterForUnreponsivenessMap map[string]providerCuCounterForUnreponsiveness) (providerCuCounterForUnreponsiveness, bool, string) { - // get ProviderCuCounterForUnreponsivenessKey - ProviderCuCounterForUnreponsivenessKey := k.getProviderCuCounterForUnreponsivenessKey(providerStakeEntry.GetAddress(), providerStakeEntry.GetChain()) - - // get ProviderCuCounterForUnreponsiveness - providerCuCounterForUnreponsiveness, found := providerCuCounterForUnreponsivenessMap[ProviderCuCounterForUnreponsivenessKey] - return providerCuCounterForUnreponsiveness, found, ProviderCuCounterForUnreponsivenessKey -} - -func (k Keeper) checkIfProviderShouldBePunishedDueToUnresponsiveness(providerCuCounterForUnreponsiveness providerCuCounterForUnreponsiveness) bool { - // if the provider served less CU than the sum of the complainers CU -> should be punished - return providerCuCounterForUnreponsiveness.complainersUsedCu > providerCuCounterForUnreponsiveness.providerServicedCu -} - -// Function to create a providerCuCounterForUnreponsivenessKey -func (k Keeper) getProviderCuCounterForUnreponsivenessKey(providerAddress string, chainID string) string { - return providerAddress + "_" + chainID -} -// Function to extract the chain ID from providerCuCounterForUnreponsivenessKey -func (k Keeper) getChainIDFromProviderCuCounterForUnreponsivenessKey(providerCuCounterForUnreponsivenessKey string) string { - return strings.Split(providerCuCounterForUnreponsivenessKey, "_")[1] -} + // the complainers' CU is larger than the provider serviced CU -> should be punished (return providerPaymentStorageKeyList so the complainers' CU can be reset after the punishment) + if complainersCu > providerServicedCu { + return providerPaymentStorageKeyList, nil + } -// Function to extract the provider address from providerCuCounterForUnreponsivenessKey -func (k Keeper) getProviderAddressFromProviderCuCounterForUnreponsivenessKey(providerCuCounterForUnreponsivenessKey string) string { - return strings.Split(providerCuCounterForUnreponsivenessKey, "_")[0] + return nil, nil } // Function that return the current stake storage for all chains @@ -242,76 +166,36 @@ func (k Keeper) getCurrentProviderStakeStorageList(ctx sdk.Context) []epochstora return stakeStorageList } -// Function that returns a list of pointers to ProviderPaymentStorage objects by iterating on all the staked providers -func (k Keeper) getProviderPaymentStorageFromStakeStorageList(ctx sdk.Context, epoch uint64, stakeStorageList []epochstoragetypes.StakeStorage) ([]*types.ProviderPaymentStorage, error) { - var providerPaymentStorageList []*types.ProviderPaymentStorage - - // Go over the provider list - for _, stakeStorage := range stakeStorageList { - for _, stakeEntry := range stakeStorage.GetStakeEntries() { - sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(stakeEntry.Address) - if err != nil { - // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. - utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": stakeEntry.Address}) - continue - } - - // get providerPaymentStorageKey from the stake entry details - providerPaymentStorageKey := k.GetProviderPaymentStorageKey(ctx, stakeEntry.GetChain(), epoch, sdkStakeEntryProviderAddress) - - // get providerPaymentStorage with providerPaymentStorageKey - providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageKey) - if !found { - continue - } +// Function that punishes providers. Current punishment is unstake +func (k Keeper) punishUnresponsiveProvider(ctx sdk.Context, providerPaymentStorageKeyList []string) error { + // extract from a providerPaymentStorageKey the provider address and the chain ID + providerAddress := k.getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorageKeyList[0]) + chainID := k.getChainIDFromProviderPaymentStorageKey(providerPaymentStorageKeyList[0]) - // add a pointer to the providerPaymentStorage to the providerPaymentStorageList - providerPaymentStorageList = append(providerPaymentStorageList, &providerPaymentStorage) - } + // Get provider's sdk.Account address + sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) + if err != nil { + // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. + return utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": providerAddress}) } - return providerPaymentStorageList, nil -} - -// Function that punishes providers. Current punishment is unstake -func (k Keeper) punishUnresponsiveProviders(ctx sdk.Context, providersToPunish map[string][]string) error { - // if providersToPunish map is empty, do nothing - if len(providersToPunish) == 0 { + // Get provider's stake entry + existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) + if !entryExists { + // if provider is not staked, nothing to do. return nil } - // Go over providers - for providerCuCounterForUnreponsivenessKey, providerPaymentStorageIndexList := range providersToPunish { - // extract from providerCuCounterForUnreponsivenessKey the provider address and the chain ID - providerAddress := strings.Split(providerCuCounterForUnreponsivenessKey, "_")[0] - chainID := strings.Split(providerCuCounterForUnreponsivenessKey, "_")[1] - - // Get provider's sdk.Account address - sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) - if err != nil { - // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. - utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": providerAddress}) - continue - } - - // Get provider's stake entry - existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) - if !entryExists { - // if provider is not staked, nothing to do. - continue - } - - // unstake the unresponsive provider - utils.LogLavaEvent(ctx, k.Logger(ctx), types.ProviderJailedEventName, map[string]string{"provider_address": providerAddress, "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") - err = k.unsafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) - if err != nil { - utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) - } - - // reset the provider's complainer CU (so he won't get punished for the same complaints twice) - k.resetComplainersCU(ctx, providerPaymentStorageIndexList) + // unstake the unresponsive provider + utils.LogLavaEvent(ctx, k.Logger(ctx), types.ProviderJailedEventName, map[string]string{"provider_address": providerAddress, "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") + err = k.unsafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) + if err != nil { + utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) } + // reset the provider's complainer CU (so he won't get punished for the same complaints twice) + k.resetComplainersCU(ctx, providerPaymentStorageKeyList) + return nil } diff --git a/x/pairing/keeper/unresponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go index af3bda5686..f0534eafe6 100644 --- a/x/pairing/keeper/unresponsive_provider_test.go +++ b/x/pairing/keeper/unresponsive_provider_test.go @@ -20,8 +20,17 @@ func TestUnresponsivenessStressTest(t *testing.T) { testProviderAmount := 5 ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) + // get recommendedEpochNumToCollectPayment + recommendedEpochNumToCollectPayment := ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)) + + // check which const is larger + largerConst := pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER + if largerConst < pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS { + largerConst = pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS + } + // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) - for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + for i := uint64(0); i < uint64(largerConst)+recommendedEpochNumToCollectPayment; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -70,11 +79,13 @@ func TestUnresponsivenessStressTest(t *testing.T) { } - // advance enough epochs so the unresponsive providers will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) - for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + // advance enough epochs so the unresponsive providers will be punished + if largerConst < recommendedEpochNumToCollectPayment { + largerConst = recommendedEpochNumToCollectPayment + } + for i := uint64(0); i < largerConst; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } - ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) // go over unresponsive providers for i := 0; i < unresponsiveProviderAmount; i++ { @@ -99,8 +110,17 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { testProviderAmount := 2 ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) + // get recommendedEpochNumToCollectPayment + recommendedEpochNumToCollectPayment := ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)) + + // check which const is larger + largerConst := pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER + if largerConst < pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS { + largerConst = pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS + } + // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) - for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + for i := uint64(0); i < uint64(largerConst)+recommendedEpochNumToCollectPayment; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -140,8 +160,11 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) require.Nil(t, err) - // advance enough epochs so the unresponsive provider will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) - for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { + // advance enough epochs so the unresponsive provider will be punished + if largerConst < recommendedEpochNumToCollectPayment { + largerConst = recommendedEpochNumToCollectPayment + } + for i := uint64(0); i < largerConst; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -188,8 +211,17 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * testProviderAmount := 2 ts := setupClientsAndProvidersForUnresponsiveness(t, testClientAmount, testProviderAmount) + // get recommendedEpochNumToCollectPayment + recommendedEpochNumToCollectPayment := ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)) + + // check which const is larger + largerConst := pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER + if largerConst < pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS { + largerConst = pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS + } + // advance enough epochs so we can check punishment due to unresponsiveness (if the epoch is too early, there's no punishment) - for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { + for i := uint64(0); i < uint64(largerConst)+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx)); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -226,8 +258,11 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) require.Nil(t, err) - // advance enough epochs so the unresponsive provider will be punished (the check happens every epoch start, the complaints will be accounted for after EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+RecommendedEpochNumToCollectPayment+1 epochs from the payment epoch) - for i := uint64(0); i < pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER+ts.keepers.Pairing.RecommendedEpochNumToCollectPayment(sdk.UnwrapSDKContext(ts.ctx))+1; i++ { + // advance enough epochs so the unresponsive provider will be punished + if largerConst < recommendedEpochNumToCollectPayment { + largerConst = recommendedEpochNumToCollectPayment + } + for i := uint64(0); i < largerConst; i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } diff --git a/x/pairing/module.go b/x/pairing/module.go index 1f68ca827b..7d74c00159 100644 --- a/x/pairing/module.go +++ b/x/pairing/module.go @@ -28,8 +28,8 @@ var ( ) const ( - EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER = 4 // number of epochs to sum CU that the provider serviced - EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS = 2 // number of epochs to sum CU of complainers against the provider + EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER uint64 = 4 // number of epochs to sum CU that the provider serviced + EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS uint64 = 2 // number of epochs to sum CU of complainers against the provider ) // ---------------------------------------------------------------------------- diff --git a/x/pairing/types/errors.go b/x/pairing/types/errors.go index a335d4a6bd..3bc2851b3b 100644 --- a/x/pairing/types/errors.go +++ b/x/pairing/types/errors.go @@ -13,5 +13,4 @@ var ( PreviousEpochStartIsBlockZeroError = sdkerrors.New("PreviousEpochStartIsBlockZeroError Error", 686, "Previous epoch start is block 0, can't be used for average block time calculation (core.Block(0) panics).") AverageBlockTimeIsLessOrEqualToZeroError = sdkerrors.New("AverageBlockTimeIsLessOrEqualToZeroError Error", 687, "The calculated average block time is less or equal to zero") NotEnoughBlocksToCalculateAverageBlockTimeError = sdkerrors.New("NotEnoughBlocksToCalculateAverageBlockTimeError Error", 688, "There isn't enough blocks in the previous epoch to calculate average block time") - EpochTooEarlyForUnresponsiveProviderJailError = sdkerrors.New("EpochTooEarlyForUnresponsiveProviderJailError Error", 689, "The epoch is too early for jailing a provider due to unersponsiveness") ) From bae645c7adca730880b22721dd6192f9d36d2480 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Thu, 19 Jan 2023 16:23:21 +0200 Subject: [PATCH 20/37] CNS-137: fix more PR issues --- x/pairing/keeper/unresponsive_provider.go | 27 ++++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index c7e5747f3d..105f26b876 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -44,7 +44,7 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU providerStakeStorageList := k.getCurrentProviderStakeStorageList(ctx) if len(providerStakeStorageList) == 0 { // no provider is staked -> no one to punish - return utils.LavaError(ctx, k.Logger(ctx), "get_current_provider_stake_storage_list", nil, "no provider is staked, no one to punish") + return nil } // Go back recommendedEpochNumToCollectPayment @@ -63,11 +63,11 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU // update the CU count for this provider in providerCuCounterForUnreponsivenessMap providerPaymentStorageKeyList, err := k.countCuForUnresponsiveness(ctx, epochTemp, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers, providerStakeEntry) if err != nil { - return utils.LavaError(ctx, k.Logger(ctx), "update_cu_for_provider_in_provider_cu_counter_for_unreponsiveness_map", map[string]string{"err": err.Error()}, "couldn't update the CU count in the providerCuCounterForUnreponsivenessMap") + return utils.LavaError(ctx, k.Logger(ctx), "count_cu_for_unresponsiveness", map[string]string{"err": err.Error()}, "couldn't count CU for unreponsiveness") } - // providerPaymentStorageKeyList is not nil -> provider should be punished - if providerPaymentStorageKeyList != nil { + // providerPaymentStorageKeyList is not empty -> provider should be punished + if len(providerPaymentStorageKeyList) != 0 { err = k.punishUnresponsiveProvider(ctx, providerPaymentStorageKeyList) if err != nil { return utils.LavaError(ctx, k.Logger(ctx), "punish_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't punish unresponsive provider") @@ -85,11 +85,18 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs providerServicedCu := uint64(0) complainersCu := uint64(0) providerPaymentStorageKeyList := []string{} + emptyList := []string{} // get the provider's SDK account address sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(providerStakeEntry.GetAddress()) if err != nil { - return nil, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) + return emptyList, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) + } + + // Get servicersToPair param + servicersToPair, err := k.ServicersToPairCount(ctx, epochTemp) + if err != nil || servicersToPair == 0 { + return emptyList, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") } // check which of the consts is larger @@ -116,12 +123,6 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs // counter is smaller than epochsNumToCheckCUForComplainers -> count complainer CU if counter < epochsNumToCheckCUForComplainers { - // Get servicersToPair param - servicersToPair, err := k.ServicersToPairCount(ctx, epoch) - if err != nil || servicersToPair == 0 { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") - } - // update complainersCu complainersCu += providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) } @@ -133,7 +134,7 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs // Get previous epoch (from epochTemp) previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) if err != nil { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + return emptyList, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") } // update epochTemp epochTemp = previousEpoch @@ -144,7 +145,7 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs return providerPaymentStorageKeyList, nil } - return nil, nil + return emptyList, nil } // Function that return the current stake storage for all chains From 3bc9cb11fc77b547952f09f068e83adc49071bcc Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 22 Jan 2023 17:59:19 +0200 Subject: [PATCH 21/37] CNS-137: revert sentry.go change for testing --- relayer/sentry/sentry.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/relayer/sentry/sentry.go b/relayer/sentry/sentry.go index 442c418294..d86cf280e8 100755 --- a/relayer/sentry/sentry.go +++ b/relayer/sentry/sentry.go @@ -630,7 +630,9 @@ func (s *Sentry) Start(ctx context.Context) { } if s.newEpochCb != nil { - go s.newEpochCb(data.Block.Height - int64(s.recommendedEpochNumToCollectPayment)*int64(s.GetEpochSize())) // Currently this is only askForRewards + go s.newEpochCb(data.Block.Height - StaleEpochDistance*int64(s.GetEpochSize())) + // fmt.Printf("s.recommendedEpochNumToCollectPayment: %v\n", s.FetchRecommendedEpochNumToCollectPayment(ctx)) + // go s.newEpochCb(data.Block.Height - int64(s.recommendedEpochNumToCollectPayment)*int64(s.GetEpochSize())) // Currently this is only askForRewards } // From b6e4b93782f9a1212f457bb19194995875beb8cf Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 22 Jan 2023 18:16:22 +0200 Subject: [PATCH 22/37] CNS-137: fix small PR issue (unresponsive list check) --- x/pairing/keeper/unresponsive_provider.go | 11 +++++------ x/pairing/module_simulation.go | 3 +++ x/pairing/types/params.go | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index 105f26b876..74920d4f56 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -67,7 +67,7 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU } // providerPaymentStorageKeyList is not empty -> provider should be punished - if len(providerPaymentStorageKeyList) != 0 { + if len(providerPaymentStorageKeyList) != 0 && providerPaymentStorageKeyList != nil { err = k.punishUnresponsiveProvider(ctx, providerPaymentStorageKeyList) if err != nil { return utils.LavaError(ctx, k.Logger(ctx), "punish_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't punish unresponsive provider") @@ -85,18 +85,17 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs providerServicedCu := uint64(0) complainersCu := uint64(0) providerPaymentStorageKeyList := []string{} - emptyList := []string{} // get the provider's SDK account address sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(providerStakeEntry.GetAddress()) if err != nil { - return emptyList, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) + return nil, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) } // Get servicersToPair param servicersToPair, err := k.ServicersToPairCount(ctx, epochTemp) if err != nil || servicersToPair == 0 { - return emptyList, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") } // check which of the consts is larger @@ -134,7 +133,7 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs // Get previous epoch (from epochTemp) previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) if err != nil { - return emptyList, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") } // update epochTemp epochTemp = previousEpoch @@ -145,7 +144,7 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs return providerPaymentStorageKeyList, nil } - return emptyList, nil + return nil, nil } // Function that return the current stake storage for all chains diff --git a/x/pairing/module_simulation.go b/x/pairing/module_simulation.go index 56bc304903..091d58d154 100644 --- a/x/pairing/module_simulation.go +++ b/x/pairing/module_simulation.go @@ -93,6 +93,9 @@ func (am AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { simulation.NewSimParamChange(types.ModuleName, string(types.KeyEpochBlocksOverlap), func(r *rand.Rand) string { return string(types.Amino.MustMarshalJSON(pairingParams.EpochBlocksOverlap)) }), + simulation.NewSimParamChange(types.ModuleName, string(types.KeyRecommendedEpochNumToCollectPayment), func(r *rand.Rand) string { + return string(types.Amino.MustMarshalJSON(pairingParams.RecommendedEpochNumToCollectPayment)) + }), } } diff --git a/x/pairing/types/params.go b/x/pairing/types/params.go index 6934fc7f6a..dce8e8bf36 100644 --- a/x/pairing/types/params.go +++ b/x/pairing/types/params.go @@ -90,7 +90,7 @@ var ( var ( KeyRecommendedEpochNumToCollectPayment = []byte("RecommendedEpochNumToCollectPayment") // the recommended amount of max epochs that a provider should wait before collecting its payment (if he'll collect later, there's a higher chance to get punished) - DefaultRecommendedEpochNumToCollectPayment uint64 = 2 + DefaultRecommendedEpochNumToCollectPayment uint64 = 3 ) // ParamKeyTable the param key table for launch module From ebc575b3f49f27c478c35a79fdc830c97ce64154 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 29 Jan 2023 14:56:44 +0200 Subject: [PATCH 23/37] CNS-137: revert sentry.go changes --- relayer/sentry/sentry.go | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/relayer/sentry/sentry.go b/relayer/sentry/sentry.go index d86cf280e8..4410ffec36 100755 --- a/relayer/sentry/sentry.go +++ b/relayer/sentry/sentry.go @@ -131,13 +131,12 @@ type Sentry struct { // server Blocks To Save (atomic) earliestSavedBlock uint64 // Block storage (atomic) - blockHeight int64 - currentEpoch uint64 - prevEpoch uint64 - EpochSize uint64 - EpochBlocksOverlap uint64 - providersCount uint64 - recommendedEpochNumToCollectPayment uint64 + blockHeight int64 + currentEpoch uint64 + prevEpoch uint64 + EpochSize uint64 + EpochBlocksOverlap uint64 + providersCount uint64 // // Spec storage (rw mutex) specMu sync.RWMutex @@ -208,15 +207,6 @@ func (s *Sentry) FetchOverlapSize(ctx context.Context) error { return nil } -func (s *Sentry) FetchRecommendedEpochNumToCollectPayment(ctx context.Context) error { - res, err := s.pairingQueryClient.Params(ctx, &pairingtypes.QueryParamsRequest{}) - if err != nil { - return err - } - atomic.StoreUint64(&s.recommendedEpochNumToCollectPayment, res.GetParams().RecommendedEpochNumToCollectPayment) - return nil -} - func (s *Sentry) FetchEpochParams(ctx context.Context) error { res, err := s.epochStorageQueryClient.EpochDetails(ctx, &epochstoragetypes.QueryGetEpochDetailsRequest{}) if err != nil { @@ -631,8 +621,6 @@ func (s *Sentry) Start(ctx context.Context) { if s.newEpochCb != nil { go s.newEpochCb(data.Block.Height - StaleEpochDistance*int64(s.GetEpochSize())) - // fmt.Printf("s.recommendedEpochNumToCollectPayment: %v\n", s.FetchRecommendedEpochNumToCollectPayment(ctx)) - // go s.newEpochCb(data.Block.Height - int64(s.recommendedEpochNumToCollectPayment)*int64(s.GetEpochSize())) // Currently this is only askForRewards } // From de591e3e050c2c4d28a892add1e199eae2ecca39 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 29 Jan 2023 16:28:25 +0200 Subject: [PATCH 24/37] CNS-137: moved servicersToPair CU division to relay payment --- x/pairing/keeper/msg_server_relay_payment.go | 19 +++++++++++++++---- x/pairing/keeper/unresponsive_provider.go | 8 +------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 0ac925f565..5568480b0d 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -272,8 +272,14 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen details["relayNumber"] = strconv.FormatUint(relay.RelayNum, 10) utils.LogLavaEvent(ctx, logger, types.RelayPaymentEventName, details, "New Proof Of Work Was Accepted") + // Get servicersToPair param + servicersToPair, err := k.ServicersToPairCount(ctx, epochStart) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochStart)}, "couldn't get servicers to pair") + } + // update provider payment storage with complainer's CU - err = k.updateProviderPaymentStorageWithComplainerCU(ctx, relay.UnresponsiveProviders, logger, epochStart, relay.ChainID, relay.CuSum) + err = k.updateProviderPaymentStorageWithComplainerCU(ctx, relay.UnresponsiveProviders, logger, epochStart, relay.ChainID, relay.CuSum, servicersToPair) if err != nil { utils.LogLavaEvent(ctx, logger, types.UnresponsiveProviderUnstakeFailedEventName, map[string]string{"err:": err.Error()}, "Error Unresponsive Providers could not unstake") } @@ -281,7 +287,7 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen return &types.MsgRelayPaymentResponse{}, nil } -func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, epoch uint64, chainID string, cuSum uint64) error { +func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, epoch uint64, chainID string, cuSum uint64, servicersToPair uint64) error { var unresponsiveProviders []string // check that unresponsiveData exists @@ -289,6 +295,11 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, return nil } + // check that servicersToPair is bigger than 1 + if servicersToPair <= 1 { + return utils.LavaFormatError("servicersToPair is less than or equal to one. The value is invalid", nil, &map[string]string{"servicersToPair": strconv.FormatUint(servicersToPair, 10)}) + } + // unmarshal the byte array unresponsiveData to get a list of unresponsive providers Bech32 addresses err := json.Unmarshal(unresponsiveData, &unresponsiveProviders) if err != nil { @@ -301,8 +312,8 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, return nil } - // the added complainer CU takes into account the number of providers the client complained on - complainerCuToAdd := cuSum / uint64(len(unresponsiveProviders)) + // the added complainer CU takes into account the number of providers the client complained on and the number + complainerCuToAdd := cuSum / (uint64(len(unresponsiveProviders)) * (servicersToPair - 1)) // iterate over the unresponsive providers list and update their complainers_total_cu for _, unresponsiveProvider := range unresponsiveProviders { diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index 74920d4f56..dca4f7c7f1 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -92,12 +92,6 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs return nil, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) } - // Get servicersToPair param - servicersToPair, err := k.ServicersToPairCount(ctx, epochTemp) - if err != nil || servicersToPair == 0 { - return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epoch)}, "couldn't get servicers to pair") - } - // check which of the consts is larger largerEpochsNumConst := epochsNumToCheckCUForComplainers if epochsNumToCheckCUForUnresponsiveProvider > epochsNumToCheckCUForComplainers { @@ -123,7 +117,7 @@ func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochs // counter is smaller than epochsNumToCheckCUForComplainers -> count complainer CU if counter < epochsNumToCheckCUForComplainers { // update complainersCu - complainersCu += providerPaymentStorage.ComplainersTotalCu / (servicersToPair - 1) + complainersCu += providerPaymentStorage.ComplainersTotalCu } // save the providerPaymentStorageKey in the providerPaymentStorageKeyList From 16eb24b81df0084d9569bb62114af4fbc1d069bd Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 29 Jan 2023 17:07:14 +0200 Subject: [PATCH 25/37] CNS-137: changed proto to camelCase --- proto/pairing/provider_payment_storage.proto | 2 +- .../types/provider_payment_storage.pb.go | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/proto/pairing/provider_payment_storage.proto b/proto/pairing/provider_payment_storage.proto index cd9e03478e..6b18a18014 100644 --- a/proto/pairing/provider_payment_storage.proto +++ b/proto/pairing/provider_payment_storage.proto @@ -10,7 +10,7 @@ message ProviderPaymentStorage { repeated UniquePaymentStorageClientProvider uniquePaymentStorageClientProvider = 2; uint64 epoch = 3; reserved 4; - uint64 complainers_total_cu = 5; // total CU that were supposed to be served by the provider but didn't because he was unavailable (so consumers complained about him) + uint64 complainersTotalCu = 5; // total CU that were supposed to be served by the provider but didn't because he was unavailable (so consumers complained about him) } // change Client -> consumer diff --git a/x/pairing/types/provider_payment_storage.pb.go b/x/pairing/types/provider_payment_storage.pb.go index ee3130f489..c74d80091e 100644 --- a/x/pairing/types/provider_payment_storage.pb.go +++ b/x/pairing/types/provider_payment_storage.pb.go @@ -26,7 +26,7 @@ type ProviderPaymentStorage struct { Index string `protobuf:"bytes,1,opt,name=index,proto3" json:"index,omitempty"` UniquePaymentStorageClientProvider []*UniquePaymentStorageClientProvider `protobuf:"bytes,2,rep,name=uniquePaymentStorageClientProvider,proto3" json:"uniquePaymentStorageClientProvider,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` - ComplainersTotalCu uint64 `protobuf:"varint,5,opt,name=complainers_total_cu,json=complainersTotalCu,proto3" json:"complainers_total_cu,omitempty"` + ComplainersTotalCu uint64 `protobuf:"varint,5,opt,name=complainersTotalCu,proto3" json:"complainersTotalCu,omitempty"` } func (m *ProviderPaymentStorage) Reset() { *m = ProviderPaymentStorage{} } @@ -99,25 +99,25 @@ func init() { } var fileDescriptor_4f1d2e8d774659ae = []byte{ - // 284 bytes of a gzipped FileDescriptorProto + // 276 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2b, 0x48, 0xcc, 0x2c, 0xca, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xcb, 0x4c, 0x49, 0x2d, 0x8a, 0x2f, 0x48, 0xac, 0xcc, 0x4d, 0xcd, 0x2b, 0x89, 0x2f, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc9, 0x49, 0x2c, 0x4b, 0xcc, 0x4b, 0x2d, 0xd1, 0x03, 0xd1, 0x7a, 0x50, 0x4d, 0x52, 0x26, 0x30, 0xdd, 0xa5, 0x79, 0x99, 0x85, 0xa5, 0xa9, 0xe8, 0x7a, 0xe3, 0x93, 0x73, - 0x32, 0x41, 0x5c, 0x98, 0xd9, 0x10, 0xb3, 0x94, 0xda, 0x99, 0xb8, 0xc4, 0x02, 0xa0, 0x42, 0x01, + 0x32, 0x41, 0x5c, 0x98, 0xd9, 0x10, 0xb3, 0x94, 0x5a, 0x99, 0xb8, 0xc4, 0x02, 0xa0, 0x42, 0x01, 0x10, 0x1d, 0xc1, 0x10, 0x0d, 0x42, 0x22, 0x5c, 0xac, 0x99, 0x79, 0x29, 0xa9, 0x15, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x10, 0x8e, 0x50, 0x07, 0x23, 0x97, 0x12, 0xc4, 0x06, 0x54, 0xe5, 0xce, 0x60, 0xe3, 0x61, 0x46, 0x49, 0x30, 0x29, 0x30, 0x6b, 0x70, 0x1b, 0x59, 0xe8, 0x61, 0x73, 0xaa, 0x5e, 0x28, 0x41, 0xfd, 0x41, 0x44, 0xd8, 0x01, 0x72, 0x60, 0x6a, 0x41, 0x7e, 0x72, 0x86, - 0x04, 0xb3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x84, 0x23, 0x64, 0xc0, 0x25, 0x92, 0x9c, 0x9f, 0x5b, - 0x90, 0x93, 0x98, 0x99, 0x97, 0x5a, 0x54, 0x1c, 0x5f, 0x92, 0x5f, 0x92, 0x98, 0x13, 0x9f, 0x5c, - 0x2a, 0xc1, 0x0a, 0x56, 0x24, 0x84, 0x24, 0x17, 0x02, 0x92, 0x72, 0x2e, 0xf5, 0x62, 0xe1, 0x60, - 0x11, 0x60, 0x75, 0x72, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, - 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xf5, - 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0xa8, 0x7f, 0xc0, 0xb4, 0x7e, - 0x85, 0x3e, 0x2c, 0xcc, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x61, 0x6a, 0x0c, 0x08, - 0x00, 0x00, 0xff, 0xff, 0xef, 0xa7, 0x63, 0x48, 0xc9, 0x01, 0x00, 0x00, + 0x04, 0xb3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x84, 0x23, 0xa4, 0xc7, 0x25, 0x94, 0x9c, 0x9f, 0x5b, + 0x90, 0x93, 0x98, 0x99, 0x97, 0x5a, 0x54, 0x1c, 0x92, 0x5f, 0x92, 0x98, 0xe3, 0x5c, 0x2a, 0xc1, + 0x0a, 0x56, 0x82, 0x45, 0xc6, 0x8b, 0x85, 0x83, 0x45, 0x80, 0xd5, 0xc9, 0xf1, 0xc4, 0x23, 0x39, + 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, + 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xd4, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, + 0xf3, 0x73, 0xf5, 0xa1, 0xbe, 0x01, 0xd3, 0xfa, 0x15, 0xfa, 0xb0, 0x10, 0x2f, 0xa9, 0x2c, 0x48, + 0x2d, 0x4e, 0x62, 0x03, 0x87, 0xa8, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x9b, 0x82, 0x45, + 0xc7, 0x01, 0x00, 0x00, } func (m *ProviderPaymentStorage) Marshal() (dAtA []byte, err error) { From c814dd7ea7b1a4703c2e90cd5d0594d0edc6e53d Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 29 Jan 2023 17:51:27 +0200 Subject: [PATCH 26/37] CNS-137: moved epoch start funcs in each module to a designated func --- testutil/keeper/keepers_init.go | 16 ++----------- x/epochstorage/keeper/epoch_start.go | 32 ++++++++++++++++++++++++++ x/epochstorage/module.go | 24 ++------------------ x/pairing/keeper/epoch_start.go | 34 ++++++++++++++++++++++++++++ x/pairing/module.go | 27 ++-------------------- 5 files changed, 72 insertions(+), 61 deletions(-) create mode 100644 x/epochstorage/keeper/epoch_start.go create mode 100644 x/pairing/keeper/epoch_start.go diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 0cf082c4f0..a0cd4eb4a1 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -210,21 +210,9 @@ func AdvanceEpoch(ctx context.Context, ks *Keepers, customBlockTime ...time.Dura // Make sure you save the new context func NewBlock(ctx context.Context, ks *Keepers, customTime ...time.Duration) { unwrapedCtx := sdk.UnwrapSDKContext(ctx) - block := uint64(unwrapedCtx.BlockHeight()) if ks.Epochstorage.IsEpochStart(sdk.UnwrapSDKContext(ctx)) { - ks.Epochstorage.FixateParams(unwrapedCtx, block) - // begin block - ks.Epochstorage.SetEpochDetailsStart(unwrapedCtx, block) - ks.Epochstorage.StoreCurrentEpochStakeStorage(unwrapedCtx, block, epochstoragetypes.ProviderKey) - ks.Epochstorage.StoreCurrentEpochStakeStorage(unwrapedCtx, block, epochstoragetypes.ClientKey) - - ks.Epochstorage.UpdateEarliestEpochstart(unwrapedCtx) - ks.Epochstorage.RemoveOldEpochData(unwrapedCtx, epochstoragetypes.ProviderKey) - ks.Epochstorage.RemoveOldEpochData(unwrapedCtx, epochstoragetypes.ClientKey) - - ks.Pairing.RemoveOldEpochPayment(unwrapedCtx) - ks.Pairing.CheckUnstakingForCommit(unwrapedCtx) - ks.Pairing.UnstakeUnresponsiveProviders(unwrapedCtx, pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) + ks.Epochstorage.EpochStart(unwrapedCtx) + ks.Pairing.EpochStart(unwrapedCtx, pairing.EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, pairing.EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) } ks.Conflict.CheckAndHandleAllVotes(unwrapedCtx) diff --git a/x/epochstorage/keeper/epoch_start.go b/x/epochstorage/keeper/epoch_start.go new file mode 100644 index 0000000000..9e433a6cf9 --- /dev/null +++ b/x/epochstorage/keeper/epoch_start.go @@ -0,0 +1,32 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/x/epochstorage/types" +) + +// Function that calls all the functions that are supposed to run in epoch start +func (k Keeper) EpochStart(ctx sdk.Context) { + block := uint64(ctx.BlockHeight()) + + // save params for this epoch + k.FixateParams(ctx, block) + + // on Epoch start we need to do: + // 1. update Epoch start + // 2. update the StakeStorage + // on epoch start block end: (because other modules need this info) to clear their storages + // 3. remove old StakeStorage + // 4. update earliest epoch start + + k.SetEpochDetailsStart(ctx, block) + + k.StoreCurrentEpochStakeStorage(ctx, block, types.ProviderKey) + + k.StoreCurrentEpochStakeStorage(ctx, block, types.ClientKey) + + k.UpdateEarliestEpochstart(ctx) + + k.RemoveOldEpochData(ctx, types.ProviderKey) + k.RemoveOldEpochData(ctx, types.ClientKey) +} diff --git a/x/epochstorage/module.go b/x/epochstorage/module.go index 8e4f73e336..e7e3c8fb50 100644 --- a/x/epochstorage/module.go +++ b/x/epochstorage/module.go @@ -169,28 +169,8 @@ func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { if am.keeper.IsEpochStart(ctx) { - block := uint64(ctx.BlockHeight()) - - // save params for this epoch - am.keeper.FixateParams(ctx, block) - - // on Epoch start we need to do: - // 1. update Epoch start - // 2. update the StakeStorage - // on epoch start block end: (because other modules need this info) to clear their storages - // 3. remove old StakeStorage - // 4. update earliest epoch start - - am.keeper.SetEpochDetailsStart(ctx, block) - - am.keeper.StoreCurrentEpochStakeStorage(ctx, block, types.ProviderKey) - - am.keeper.StoreCurrentEpochStakeStorage(ctx, block, types.ClientKey) - - am.keeper.UpdateEarliestEpochstart(ctx) - - am.keeper.RemoveOldEpochData(ctx, types.ProviderKey) - am.keeper.RemoveOldEpochData(ctx, types.ClientKey) + // run functions that are supposed to run in epoch start + am.keeper.EpochStart(ctx) // Notify world we have a new session diff --git a/x/pairing/keeper/epoch_start.go b/x/pairing/keeper/epoch_start.go new file mode 100644 index 0000000000..86b18b5ff7 --- /dev/null +++ b/x/pairing/keeper/epoch_start.go @@ -0,0 +1,34 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/utils" +) + +// Function that calls all the functions that are supposed to run in epoch start +func (k Keeper) EpochStart(ctx sdk.Context, epochsNumToCheckCuForUnresponsiveProvider uint64, epochsNumToCheckForComplainers uint64) { + logger := k.Logger(ctx) + logOnErr := func(err error, failingFunc string) { + if err != nil { + attrs := map[string]string{"error": err.Error()} + utils.LavaError(ctx, logger, "new_epoch", attrs, failingFunc) + } + } + // on session start we need to do: + // 1. remove old session payments + // 2. unstake any unstaking providers + // 3. unstake any unstaking users + // 4. unstake/jail unresponsive providers + + // 1. + err := k.RemoveOldEpochPayment(ctx) + logOnErr(err, "RemoveOldEpochPayment") + + // 2+3. + err = k.CheckUnstakingForCommit(ctx) + logOnErr(err, "CheckUnstakingForCommit") + + // 4. unstake unresponsive providers + err = k.UnstakeUnresponsiveProviders(ctx, epochsNumToCheckCuForUnresponsiveProvider, epochsNumToCheckForComplainers) + logOnErr(err, "UnstakeUnresponsiveProviders") +} diff --git a/x/pairing/module.go b/x/pairing/module.go index 7d74c00159..821c6e0ed7 100644 --- a/x/pairing/module.go +++ b/x/pairing/module.go @@ -16,7 +16,6 @@ import ( cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/lavanet/lava/utils" "github.com/lavanet/lava/x/pairing/client/cli" "github.com/lavanet/lava/x/pairing/keeper" "github.com/lavanet/lava/x/pairing/types" @@ -173,31 +172,9 @@ func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { - logger := am.keeper.Logger(ctx) - logOnErr := func(err error, failingFunc string) { - if err != nil { - attrs := map[string]string{"error": err.Error()} - utils.LavaError(ctx, logger, "new_epoch", attrs, failingFunc) - } - } if am.keeper.IsEpochStart(ctx) { - // on session start we need to do: - // 1. remove old session payments - // 2. unstake any unstaking providers - // 3. unstake any unstaking users - // 4. unstake/jail unresponsive providers - - // 1. - err := am.keeper.RemoveOldEpochPayment(ctx) - logOnErr(err, "RemoveOldEpochPayment") - - // 2+3. - err = am.keeper.CheckUnstakingForCommit(ctx) - logOnErr(err, "CheckUnstakingForCommit") - - // 4. unstake unresponsive providers - err = am.keeper.UnstakeUnresponsiveProviders(ctx, EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) - logOnErr(err, "UnstakeUnresponsiveProviders") + // run functions that are supposed to run in epoch start + am.keeper.EpochStart(ctx, EPOCHS_NUM_TO_CHECK_CU_FOR_UNRESPONSIVE_PROVIDER, EPOCHS_NUM_TO_CHECK_FOR_COMPLAINERS) } } From 2d5cb6e9cbb93c5959617b220b6b9280a8657798 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 29 Jan 2023 17:58:24 +0200 Subject: [PATCH 27/37] CNS-137: rename ClientPayments to ProviderPaymentStorages in epochPayments object --- proto/pairing/epoch_payments.proto | 2 +- testutil/e2e/e2e.go | 2 +- x/pairing/keeper/epoch_payments.go | 8 ++-- x/pairing/keeper/msg_server_relay_payment.go | 6 +-- .../msg_server_relay_payment_gov_test.go | 2 +- x/pairing/types/epoch_payments.pb.go | 44 +++++++++---------- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/proto/pairing/epoch_payments.proto b/proto/pairing/epoch_payments.proto index a2fe06120b..90c04436b2 100644 --- a/proto/pairing/epoch_payments.proto +++ b/proto/pairing/epoch_payments.proto @@ -6,6 +6,6 @@ import "pairing/provider_payment_storage.proto"; message EpochPayments { string index = 1; - repeated ProviderPaymentStorage clientsPayments = 2; + repeated ProviderPaymentStorage providerPaymentStorages = 2; } diff --git a/testutil/e2e/e2e.go b/testutil/e2e/e2e.go index 88f6014563..27f92d8dc8 100644 --- a/testutil/e2e/e2e.go +++ b/testutil/e2e/e2e.go @@ -632,7 +632,7 @@ func (lt *lavaTest) checkPayments(testDuration time.Duration) { continue } for _, epochPayment := range pairingRes.EpochPayments { - for _, clientsPayment := range epochPayment.ClientsPayments { + for _, clientsPayment := range epochPayment.GetProviderPaymentStorages() { if strings.Contains(clientsPayment.Index, "ETH") { ethPaid = true } else if strings.Contains(clientsPayment.Index, "LAV") { diff --git a/x/pairing/keeper/epoch_payments.go b/x/pairing/keeper/epoch_payments.go index 64ae96d15f..3a877d8178 100644 --- a/x/pairing/keeper/epoch_payments.go +++ b/x/pairing/keeper/epoch_payments.go @@ -84,10 +84,10 @@ func (k Keeper) AddEpochPayment(ctx sdk.Context, chainID string, epoch uint64, u epochPayments, found, key := k.GetEpochPaymentsFromBlock(ctx, epoch) if !found { - epochPayments = types.EpochPayments{Index: key, ClientsPayments: []*types.ProviderPaymentStorage{userPaymentProviderStorage}} + epochPayments = types.EpochPayments{Index: key, ProviderPaymentStorages: []*types.ProviderPaymentStorage{userPaymentProviderStorage}} } else { found = false - for _, providerEpochStorage := range epochPayments.GetClientsPayments() { + for _, providerEpochStorage := range epochPayments.GetProviderPaymentStorages() { if providerEpochStorage.Index == userPaymentProviderStorage.Index { *providerEpochStorage = *userPaymentProviderStorage found = true @@ -95,7 +95,7 @@ func (k Keeper) AddEpochPayment(ctx sdk.Context, chainID string, epoch uint64, u } } if !found { - epochPayments.ClientsPayments = append(epochPayments.ClientsPayments, userPaymentProviderStorage) + epochPayments.ProviderPaymentStorages = append(epochPayments.GetProviderPaymentStorages(), userPaymentProviderStorage) } } @@ -110,7 +110,7 @@ func (k Keeper) RemoveAllEpochPaymentsForBlock(ctx sdk.Context, blockForDelete u // return fmt.Errorf("did not find any epochPayments for block %d", blockForDelete.Num) return nil } - userPaymentsStorages := epochPayments.ClientsPayments + userPaymentsStorages := epochPayments.GetProviderPaymentStorages() for _, userPaymentStorage := range userPaymentsStorages { uniquePaymentStoragesCliPro := userPaymentStorage.UniquePaymentStorageClientProvider for _, uniquePaymentStorageCliPro := range uniquePaymentStoragesCliPro { diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 5568480b0d..69b7df5296 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -340,9 +340,9 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, // add the new empty providerPaymentStorage to epochPayments epochPayments, found, key := k.GetEpochPaymentsFromBlock(ctx, epoch) if !found { - epochPayments = types.EpochPayments{Index: key, ClientsPayments: []*types.ProviderPaymentStorage{&emptyProviderPaymentStorageWithComplaint}} + epochPayments = types.EpochPayments{Index: key, ProviderPaymentStorages: []*types.ProviderPaymentStorage{&emptyProviderPaymentStorageWithComplaint}} } else { - epochPayments.ClientsPayments = append(epochPayments.ClientsPayments, &emptyProviderPaymentStorageWithComplaint) + epochPayments.ProviderPaymentStorages = append(epochPayments.GetProviderPaymentStorages(), &emptyProviderPaymentStorageWithComplaint) } k.SetEpochPayments(ctx, epochPayments) @@ -362,7 +362,7 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, utils.LavaFormatError("unable to find epochPayments entry of unresponsive provider", nil, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) continue } - providerPaymentStorageList := epochPayments.GetClientsPayments() + providerPaymentStorageList := epochPayments.GetProviderPaymentStorages() for _, providerPaymentStorageElem := range providerPaymentStorageList { if providerPaymentStorage.GetIndex() == providerPaymentStorageElem.GetIndex() { providerPaymentStorageElem.ComplainersTotalCu += complainerCuToAdd 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 f69c594262..8e109b04cf 100644 --- a/x/pairing/keeper/msg_server_relay_payment_gov_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_gov_test.go @@ -991,7 +991,7 @@ func verifyRelayPaymentObjects(t *testing.T, ts *testStruct, relayRequest *pairi // Get the providerPaymentStorage struct from epochPayments providerPaymentStorageFromEpochPayments := pairingtypes.ProviderPaymentStorage{} - for _, providerPaymentStorageFromEpochPaymentsElem := range epochPayments.GetClientsPayments() { + for _, providerPaymentStorageFromEpochPaymentsElem := range epochPayments.GetProviderPaymentStorages() { if providerPaymentStorageFromEpochPaymentsElem.GetIndex() == providerPaymentStorageKey { providerPaymentStorageFromEpochPayments = *providerPaymentStorageFromEpochPaymentsElem } diff --git a/x/pairing/types/epoch_payments.pb.go b/x/pairing/types/epoch_payments.pb.go index a9f76c8305..73b8cbb3b7 100644 --- a/x/pairing/types/epoch_payments.pb.go +++ b/x/pairing/types/epoch_payments.pb.go @@ -23,8 +23,8 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type EpochPayments struct { - Index string `protobuf:"bytes,1,opt,name=index,proto3" json:"index,omitempty"` - ClientsPayments []*ProviderPaymentStorage `protobuf:"bytes,2,rep,name=clientsPayments,proto3" json:"clientsPayments,omitempty"` + Index string `protobuf:"bytes,1,opt,name=index,proto3" json:"index,omitempty"` + ProviderPaymentStorages []*ProviderPaymentStorage `protobuf:"bytes,2,rep,name=providerPaymentStorages,proto3" json:"providerPaymentStorages,omitempty"` } func (m *EpochPayments) Reset() { *m = EpochPayments{} } @@ -67,9 +67,9 @@ func (m *EpochPayments) GetIndex() string { return "" } -func (m *EpochPayments) GetClientsPayments() []*ProviderPaymentStorage { +func (m *EpochPayments) GetProviderPaymentStorages() []*ProviderPaymentStorage { if m != nil { - return m.ClientsPayments + return m.ProviderPaymentStorages } return nil } @@ -81,21 +81,21 @@ func init() { func init() { proto.RegisterFile("pairing/epoch_payments.proto", fileDescriptor_747a4457843f82da) } var fileDescriptor_747a4457843f82da = []byte{ - // 215 bytes of a gzipped FileDescriptorProto + // 213 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x48, 0xcc, 0x2c, 0xca, 0xcc, 0x4b, 0xd7, 0x4f, 0x2d, 0xc8, 0x4f, 0xce, 0x88, 0x2f, 0x48, 0xac, 0xcc, 0x4d, 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc9, 0x49, 0x2c, 0x4b, 0xcc, 0x4b, 0x2d, 0xd1, 0x03, 0xd1, 0x7a, 0x50, 0xa5, 0x52, 0x6a, 0x30, 0x3d, 0x05, 0x45, 0xf9, 0x65, 0x99, 0x29, 0xa9, 0x45, 0x30, 0x6d, 0xf1, 0xc5, 0x25, 0xf9, 0x45, 0x89, 0xe9, 0xa9, 0x10, 0xdd, 0x4a, - 0xb5, 0x5c, 0xbc, 0xae, 0x20, 0x53, 0x03, 0xa0, 0x86, 0x0a, 0x89, 0x70, 0xb1, 0x66, 0xe6, 0xa5, - 0xa4, 0x56, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x38, 0x42, 0x61, 0x5c, 0xfc, 0xc9, - 0x39, 0x99, 0x20, 0x05, 0x30, 0x85, 0x12, 0x4c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x3a, 0x7a, 0xd8, - 0xac, 0xd7, 0x0b, 0x80, 0xda, 0x0a, 0x55, 0x1d, 0x0c, 0xb1, 0x33, 0x08, 0xdd, 0x10, 0x27, 0xc7, - 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, - 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x52, 0x4f, 0xcf, 0x2c, 0xc9, 0x28, - 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x87, 0x5a, 0x01, 0xa6, 0xf5, 0x2b, 0xf4, 0x61, 0x5e, 0x2b, - 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x7b, 0xc4, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xfe, - 0x1d, 0x32, 0x4e, 0x26, 0x01, 0x00, 0x00, + 0xbd, 0x8c, 0x5c, 0xbc, 0xae, 0x20, 0x63, 0x03, 0xa0, 0xa6, 0x0a, 0x89, 0x70, 0xb1, 0x66, 0xe6, + 0xa5, 0xa4, 0x56, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x38, 0x42, 0x69, 0x5c, 0xe2, + 0x30, 0x93, 0xa0, 0x2a, 0x83, 0x21, 0xe6, 0x14, 0x4b, 0x30, 0x29, 0x30, 0x6b, 0x70, 0x1b, 0xe9, + 0xe8, 0x61, 0x73, 0x87, 0x5e, 0x00, 0x56, 0x4d, 0x41, 0xb8, 0x0c, 0x73, 0x72, 0x3c, 0xf1, 0x48, + 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, + 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xf5, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, + 0xe4, 0xfc, 0x5c, 0x7d, 0xa8, 0x55, 0x60, 0x5a, 0xbf, 0x42, 0x1f, 0xe6, 0xd7, 0x92, 0xca, 0x82, + 0xd4, 0xe2, 0x24, 0x36, 0xb0, 0xcf, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xad, 0xc8, 0x70, + 0xee, 0x37, 0x01, 0x00, 0x00, } func (m *EpochPayments) Marshal() (dAtA []byte, err error) { @@ -118,10 +118,10 @@ func (m *EpochPayments) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.ClientsPayments) > 0 { - for iNdEx := len(m.ClientsPayments) - 1; iNdEx >= 0; iNdEx-- { + if len(m.ProviderPaymentStorages) > 0 { + for iNdEx := len(m.ProviderPaymentStorages) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.ClientsPayments[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ProviderPaymentStorages[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -163,8 +163,8 @@ func (m *EpochPayments) Size() (n int) { if l > 0 { n += 1 + l + sovEpochPayments(uint64(l)) } - if len(m.ClientsPayments) > 0 { - for _, e := range m.ClientsPayments { + if len(m.ProviderPaymentStorages) > 0 { + for _, e := range m.ProviderPaymentStorages { l = e.Size() n += 1 + l + sovEpochPayments(uint64(l)) } @@ -241,7 +241,7 @@ func (m *EpochPayments) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientsPayments", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProviderPaymentStorages", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -268,8 +268,8 @@ func (m *EpochPayments) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ClientsPayments = append(m.ClientsPayments, &ProviderPaymentStorage{}) - if err := m.ClientsPayments[len(m.ClientsPayments)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ProviderPaymentStorages = append(m.ProviderPaymentStorages, &ProviderPaymentStorage{}) + if err := m.ProviderPaymentStorages[len(m.ProviderPaymentStorages)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex From bf93de574b406793fcdd61264b3d860eed67883d Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 30 Jan 2023 16:51:23 +0200 Subject: [PATCH 28/37] CNS-137: fix PR issues --- x/pairing/keeper/msg_server_relay_payment.go | 26 +++++++++----------- x/pairing/keeper/provider_payment_storage.go | 13 ---------- x/pairing/keeper/unresponsive_provider.go | 12 ++++----- 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 69b7df5296..38a8459adb 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -324,6 +324,14 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, continue } + // get this epoch's epochPayments object + epochPayments, found, key := k.GetEpochPaymentsFromBlock(ctx, epoch) + if !found { + // the epochPayments object should exist since we already paid. if not found, print an error and continue + utils.LavaFormatError("did not find epochPayments object", err, &map[string]string{"epochPaymentskey": key}) + continue + } + // get the providerPaymentStorage object using the providerStorageKey providerStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, epoch, sdkUnresponsiveProviderAddress) providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerStorageKey) @@ -334,34 +342,24 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, Index: providerStorageKey, UniquePaymentStorageClientProvider: []*types.UniquePaymentStorageClientProvider{}, Epoch: epoch, - ComplainersTotalCu: complainerCuToAdd, + ComplainersTotalCu: 0, } - // add the new empty providerPaymentStorage to epochPayments - epochPayments, found, key := k.GetEpochPaymentsFromBlock(ctx, epoch) - if !found { - epochPayments = types.EpochPayments{Index: key, ProviderPaymentStorages: []*types.ProviderPaymentStorage{&emptyProviderPaymentStorageWithComplaint}} - } else { - epochPayments.ProviderPaymentStorages = append(epochPayments.GetProviderPaymentStorages(), &emptyProviderPaymentStorageWithComplaint) - } + // append the emptyProviderPaymentStorageWithComplaint to the epochPayments object's providerPaymentStorages + epochPayments.ProviderPaymentStorages = append(epochPayments.GetProviderPaymentStorages(), &emptyProviderPaymentStorageWithComplaint) k.SetEpochPayments(ctx, epochPayments) // assign providerPaymentStorage with the new empty providerPaymentStorage providerPaymentStorage = emptyProviderPaymentStorageWithComplaint } - // providerPaymentStorage was found for epoch -> add complainer's used CU + // add complainer's used CU to providerPaymentStorage providerPaymentStorage.ComplainersTotalCu += complainerCuToAdd // set the final provider payment storage state including the complaints k.SetProviderPaymentStorage(ctx, providerPaymentStorage) // update the complainer CU also in epochPayments (providerPaymentStorage objects are saved in a list inside epochPayments and also separately - need to update both) - epochPayments, found, _ := k.GetEpochPaymentsFromBlock(ctx, providerPaymentStorage.GetEpoch()) - if !found { - utils.LavaFormatError("unable to find epochPayments entry of unresponsive provider", nil, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) - continue - } providerPaymentStorageList := epochPayments.GetProviderPaymentStorages() for _, providerPaymentStorageElem := range providerPaymentStorageList { if providerPaymentStorage.GetIndex() == providerPaymentStorageElem.GetIndex() { diff --git a/x/pairing/keeper/provider_payment_storage.go b/x/pairing/keeper/provider_payment_storage.go index a0950ff13d..534aa23dfb 100644 --- a/x/pairing/keeper/provider_payment_storage.go +++ b/x/pairing/keeper/provider_payment_storage.go @@ -3,7 +3,6 @@ package keeper import ( "fmt" "strconv" - "strings" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -102,15 +101,3 @@ func (k Keeper) GetTotalUsedCUForConsumerPerEpoch(ctx sdk.Context, consumerAddre } return usedCUProviderTotal, nil } - -func (k Keeper) getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorageKey string) string { - return strings.Split(providerPaymentStorageKey, "_")[2] -} - -func (k Keeper) getEpochFromProviderPaymentStorageKey(providerPaymentStorageKey string) string { - return strings.Split(providerPaymentStorageKey, "_")[1] -} - -func (k Keeper) getChainIDFromProviderPaymentStorageKey(providerPaymentStorageKey string) string { - return strings.Split(providerPaymentStorageKey, "_")[0] -} diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index dca4f7c7f1..e13c451b4f 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -66,9 +66,13 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU return utils.LavaError(ctx, k.Logger(ctx), "count_cu_for_unresponsiveness", map[string]string{"err": err.Error()}, "couldn't count CU for unreponsiveness") } + // get the provider address and chain ID of the stake entry + providerAddress := providerStakeEntry.Address + chainID := providerStakeEntry.Chain + // providerPaymentStorageKeyList is not empty -> provider should be punished if len(providerPaymentStorageKeyList) != 0 && providerPaymentStorageKeyList != nil { - err = k.punishUnresponsiveProvider(ctx, providerPaymentStorageKeyList) + err = k.punishUnresponsiveProvider(ctx, providerAddress, chainID, providerPaymentStorageKeyList) if err != nil { return utils.LavaError(ctx, k.Logger(ctx), "punish_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't punish unresponsive provider") } @@ -161,11 +165,7 @@ func (k Keeper) getCurrentProviderStakeStorageList(ctx sdk.Context) []epochstora } // Function that punishes providers. Current punishment is unstake -func (k Keeper) punishUnresponsiveProvider(ctx sdk.Context, providerPaymentStorageKeyList []string) error { - // extract from a providerPaymentStorageKey the provider address and the chain ID - providerAddress := k.getProviderAddressFromProviderPaymentStorageKey(providerPaymentStorageKeyList[0]) - chainID := k.getChainIDFromProviderPaymentStorageKey(providerPaymentStorageKeyList[0]) - +func (k Keeper) punishUnresponsiveProvider(ctx sdk.Context, providerAddress string, chainID string, providerPaymentStorageKeyList []string) error { // Get provider's sdk.Account address sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) if err != nil { From 787e9abfc5c9055925c1b665fa12ebe5b0f3c814 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Wed, 1 Feb 2023 18:19:33 +0200 Subject: [PATCH 29/37] CNS-137: added RecommendedEpochNumToCollectPayment param --- x/pairing/keeper/params_test.go | 2 +- x/pairing/module_simulation.go | 6 +++--- x/pairing/types/params.go | 31 ++++++++++++++++--------------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/x/pairing/keeper/params_test.go b/x/pairing/keeper/params_test.go index e3c1716dc0..230d9367de 100644 --- a/x/pairing/keeper/params_test.go +++ b/x/pairing/keeper/params_test.go @@ -21,5 +21,5 @@ func TestGetParams(t *testing.T) { require.EqualValues(t, params.FraudSlashingAmount, k.FraudSlashingAmount(ctx)) require.EqualValues(t, params.ServicersToPairCount, k.ServicersToPairCountRaw(ctx)) require.EqualValues(t, params.EpochBlocksOverlap, k.EpochBlocksOverlap(ctx)) - // require.EqualValues(t, params., k.RecommendedEpochNumToCollectPayment(ctx)) + require.EqualValues(t, params.RecommendedEpochNumToCollectPayment, k.RecommendedEpochNumToCollectPayment(ctx)) } diff --git a/x/pairing/module_simulation.go b/x/pairing/module_simulation.go index da383f6fbf..73da491fd1 100644 --- a/x/pairing/module_simulation.go +++ b/x/pairing/module_simulation.go @@ -87,9 +87,9 @@ func (am AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { simulation.NewSimParamChange(types.ModuleName, string(types.KeyEpochBlocksOverlap), func(r *rand.Rand) string { return string(types.Amino.MustMarshalJSON(pairingParams.EpochBlocksOverlap)) }), - // simulation.NewSimParamChange(types.ModuleName, string(types.KeyRecommendedEpochNumToCollectPayment), func(r *rand.Rand) string { - // return string(types.Amino.MustMarshalJSON(pairingParams.RecommendedEpochNumToCollectPayment)) - // }), + simulation.NewSimParamChange(types.ModuleName, string(types.KeyRecommendedEpochNumToCollectPayment), func(r *rand.Rand) string { + return string(types.Amino.MustMarshalJSON(pairingParams.RecommendedEpochNumToCollectPayment)) + }), } } diff --git a/x/pairing/types/params.go b/x/pairing/types/params.go index 05867295ff..f3c85e7ca8 100644 --- a/x/pairing/types/params.go +++ b/x/pairing/types/params.go @@ -104,17 +104,18 @@ func NewParams( recommendedEpochNumToCollectPayment uint64, ) Params { return Params{ - MintCoinsPerCU: mintCoinsPerCU, - BurnCoinsPerCU: burnCoinsPerCU, - FraudStakeSlashingFactor: fraudStakeSlashingFactor, - FraudSlashingAmount: fraudSlashingAmount, - ServicersToPairCount: servicersToPairCount, - EpochBlocksOverlap: epochBlocksOverlap, - StakeToMaxCUList: stakeToMaxCUList, - UnpayLimit: unpayLimit, - SlashLimit: slashLimit, - DataReliabilityReward: dataReliabilityReward, - QoSWeight: qoSWeight, + MintCoinsPerCU: mintCoinsPerCU, + BurnCoinsPerCU: burnCoinsPerCU, + FraudStakeSlashingFactor: fraudStakeSlashingFactor, + FraudSlashingAmount: fraudSlashingAmount, + ServicersToPairCount: servicersToPairCount, + EpochBlocksOverlap: epochBlocksOverlap, + StakeToMaxCUList: stakeToMaxCUList, + UnpayLimit: unpayLimit, + SlashLimit: slashLimit, + DataReliabilityReward: dataReliabilityReward, + QoSWeight: qoSWeight, + RecommendedEpochNumToCollectPayment: recommendedEpochNumToCollectPayment, } } @@ -150,7 +151,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(KeySlashLimit, &p.SlashLimit, validateSlashLimit), paramtypes.NewParamSetPair(KeyDataReliabilityReward, &p.DataReliabilityReward, validateDataReliabilityReward), paramtypes.NewParamSetPair(KeyQoSWeight, &p.QoSWeight, validateQoSWeight), - // paramtypes.NewParamSetPair(KeyRecommendedEpochNumToCollectPayment, &p.RecommendedEpochNumToCollectPayment, validateRecommendedEpochNumToCollectPayment), + paramtypes.NewParamSetPair(KeyRecommendedEpochNumToCollectPayment, &p.RecommendedEpochNumToCollectPayment, validateRecommendedEpochNumToCollectPayment), } } @@ -194,9 +195,9 @@ func (p Params) Validate() error { if err := validateDataReliabilityReward(p.DataReliabilityReward); err != nil { return err } - // if err := validateRecommendedEpochNumToCollectPayment(p.RecommendedEpochNumToCollectPayment); err != nil { - // return err - // } + if err := validateRecommendedEpochNumToCollectPayment(p.RecommendedEpochNumToCollectPayment); err != nil { + return err + } return nil } From 49cebea0d98167266393be3cb6d5be08987348f5 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Wed, 1 Feb 2023 18:20:21 +0200 Subject: [PATCH 30/37] CNS-137: fixed unresponsive provider to work with new payment objects (that are using keys) --- proto/pairing/provider_payment_storage.proto | 6 +- x/pairing/keeper/epoch_start.go | 6 +- x/pairing/keeper/msg_server_relay_payment.go | 216 ++++----- x/pairing/keeper/unresponsive_provider.go | 444 +++++++++--------- .../types/provider_payment_storage.pb.go | 104 ++-- 5 files changed, 359 insertions(+), 417 deletions(-) diff --git a/proto/pairing/provider_payment_storage.proto b/proto/pairing/provider_payment_storage.proto index 2acba5fde2..644a6e9c76 100644 --- a/proto/pairing/provider_payment_storage.proto +++ b/proto/pairing/provider_payment_storage.proto @@ -9,8 +9,10 @@ message ProviderPaymentStorage { string index = 1; reserved 2; uint64 epoch = 3; - repeated string unresponsiveness_complaints = 4; - repeated string uniquePaymentStorageClientProviderKeys = 5; + reserved 4; + reserved 5; + repeated string uniquePaymentStorageClientProviderKeys = 6; + uint64 complainersTotalCu = 7; // total CU that were supposed to be served by the provider but didn't because he was unavailable (so consumers complained about him) } // change Client -> consumer diff --git a/x/pairing/keeper/epoch_start.go b/x/pairing/keeper/epoch_start.go index e81542861f..86b18b5ff7 100644 --- a/x/pairing/keeper/epoch_start.go +++ b/x/pairing/keeper/epoch_start.go @@ -28,7 +28,7 @@ func (k Keeper) EpochStart(ctx sdk.Context, epochsNumToCheckCuForUnresponsivePro err = k.CheckUnstakingForCommit(ctx) logOnErr(err, "CheckUnstakingForCommit") - // // 4. unstake unresponsive providers - // err = k.UnstakeUnresponsiveProviders(ctx, epochsNumToCheckCuForUnresponsiveProvider, epochsNumToCheckForComplainers) - // logOnErr(err, "UnstakeUnresponsiveProviders") + // 4. unstake unresponsive providers + err = k.UnstakeUnresponsiveProviders(ctx, epochsNumToCheckCuForUnresponsiveProvider, epochsNumToCheckForComplainers) + logOnErr(err, "UnstakeUnresponsiveProviders") } diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 8fc98f1165..9a9225cc2c 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "encoding/json" "fmt" "strconv" @@ -10,6 +11,7 @@ import ( "github.com/lavanet/lava/utils" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/lavanet/lava/x/pairing/types" + "github.com/tendermint/tendermint/libs/log" ) const ( @@ -259,135 +261,93 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen details["relayNumber"] = strconv.FormatUint(relay.RelayNum, 10) utils.LogLavaEvent(ctx, logger, types.RelayPaymentEventName, details, "New Proof Of Work Was Accepted") - // // Get servicersToPair param - // servicersToPair, err := k.ServicersToPairCount(ctx, epochStart) - // if err != nil { - // return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochStart)}, "couldn't get servicers to pair") - // } - - // // update provider payment storage with complainer's CU - // err = k.updateProviderPaymentStorageWithComplainerCU(ctx, relay.UnresponsiveProviders, logger, epochStart, relay.ChainID, relay.CuSum, servicersToPair) - // if err != nil { - // utils.LogLavaEvent(ctx, logger, types.UnresponsiveProviderUnstakeFailedEventName, map[string]string{"err:": err.Error()}, "Error Unresponsive Providers could not unstake") - // } + // Get servicersToPair param + servicersToPair, err := k.ServicersToPairCount(ctx, epochStart) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_servicers_to_pair", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochStart)}, "couldn't get servicers to pair") + } + + // update provider payment storage with complainer's CU + err = k.updateProviderPaymentStorageWithComplainerCU(ctx, relay.UnresponsiveProviders, logger, epochStart, relay.ChainID, relay.CuSum, servicersToPair, clientAddr) + if err != nil { + utils.LogLavaEvent(ctx, logger, types.UnresponsiveProviderUnstakeFailedEventName, map[string]string{"err:": err.Error()}, "Error Unresponsive Providers could not unstake") + } } return &types.MsgRelayPaymentResponse{}, nil } -// func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, epoch uint64, chainID string, cuSum uint64, servicersToPair uint64) error { -// var unresponsiveProviders []string - -// // check that unresponsiveData exists -// if len(unresponsiveData) == 0 { -// return nil -// } - -// // check that servicersToPair is bigger than 1 -// if servicersToPair <= 1 { -// return utils.LavaFormatError("servicersToPair is less than or equal to one. The value is invalid", nil, &map[string]string{"servicersToPair": strconv.FormatUint(servicersToPair, 10)}) -// } - -// // unmarshal the byte array unresponsiveData to get a list of unresponsive providers Bech32 addresses -// err := json.Unmarshal(unresponsiveData, &unresponsiveProviders) -// if err != nil { -// return utils.LavaFormatError("unable to unmarshal unresponsive providers", err, &map[string]string{"UnresponsiveProviders": string(unresponsiveData), "dataLength": strconv.Itoa(len(unresponsiveData))}) -// } - -// // check there are unresponsive providers -// if len(unresponsiveProviders) == 0 { -// // nothing to do. -// return nil -// } - -// // the added complainer CU takes into account the number of providers the client complained on and the number -// complainerCuToAdd := cuSum / (uint64(len(unresponsiveProviders)) * (servicersToPair - 1)) - -// // iterate over the unresponsive providers list and update their complainers_total_cu -// for _, unresponsiveProvider := range unresponsiveProviders { -// // get provider address -// sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(unresponsiveProvider) -// if err != nil { // if bad data was given, we cant parse it so we ignote it and continue this protects from spamming wrong information. -// utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) -// continue -// } - -// // get this epoch's epochPayments object -// epochPayments, found, key := k.GetEpochPaymentsFromBlock(ctx, epoch) -// if !found { -// // the epochPayments object should exist since we already paid. if not found, print an error and continue -// utils.LavaFormatError("did not find epochPayments object", err, &map[string]string{"epochPaymentskey": key}) -// continue -// } - -// // get the providerPaymentStorage object using the providerStorageKey -// providerStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, epoch, sdkUnresponsiveProviderAddress) -// providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerStorageKey) - -// if !found { -// // providerPaymentStorage not found (this provider has no payments in this epoch and also no complaints) -> we need to add one complaint -// emptyProviderPaymentStorageWithComplaint := types.ProviderPaymentStorage{ -// Index: providerStorageKey, -// UniquePaymentStorageClientProviderKeys: []string{}, -// Epoch: epoch, -// UnresponsivenessComplaints: []string{clientAddr.String()}, -// } - -// // append the emptyProviderPaymentStorageWithComplaint to the epochPayments object's providerPaymentStorages -// epochPayments.ProviderPaymentStorages = append(epochPayments.GetProviderPaymentStorages(), &emptyProviderPaymentStorageWithComplaint) -// k.SetEpochPayments(ctx, epochPayments) - -// // assign providerPaymentStorage with the new empty providerPaymentStorage -// providerPaymentStorage = emptyProviderPaymentStorageWithComplaint -// } - -// // add complainer's used CU to providerPaymentStorage -// providerPaymentStorage.ComplainersTotalCu += complainerCuToAdd - -// // now we check if we have more UnresponsivenessComplaints than maxComplaintsPerEpoch -// if len(providerPaymentStorage.UnresponsivenessComplaints) >= maxComplaintsPerEpoch { -// // we check if we have double complaints than previous "collectPaymentsFromNumberOfPreviousEpochs" epochs (including this one) payment requests -// totalPaymentsInPreviousEpochs, err := k.getTotalPaymentsForPreviousEpochs(ctx, collectPaymentsFromNumberOfPreviousEpochs, epoch, chainID, sdkUnresponsiveProviderAddress) -// totalPaymentRequests := totalPaymentsInPreviousEpochs + len(providerPaymentStorage.UniquePaymentStorageClientProviderKeys) // get total number of payments including this epoch -// if err != nil { -// utils.LavaFormatError("lava_unresponsive_providers: couldnt fetch getTotalPaymentsForPreviousEpochs", err, nil) -// } else if totalPaymentRequests*providerPaymentMultiplier < len(providerPaymentStorage.UnresponsivenessComplaints) { -// // unstake provider -// utils.LogLavaEvent(ctx, logger, types.ProviderJailedEventName, map[string]string{"provider_address": sdkUnresponsiveProviderAddress.String(), "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") -// err = k.unSafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) -// if err != nil { -// utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) -// continue -// } -// } -// } -// // set the final provider payment storage state including the complaints -// k.SetProviderPaymentStorage(ctx, providerPaymentStorage) -// } - -// return nil -// } - -// func (k msgServer) getTotalPaymentsForPreviousEpochs(ctx sdk.Context, numberOfEpochs int, currentEpoch uint64, chainID string, sdkUnresponsiveProviderAddress sdk.AccAddress) (totalPaymentsReceived int, errorsGettingEpochs error) { -// var totalPaymentRequests int -// epochTemp := currentEpoch -// for payment := 0; payment < numberOfEpochs; payment++ { -// previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) -// if err != nil { -// return 0, err -// } -// previousEpochProviderStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, previousEpoch, sdkUnresponsiveProviderAddress) -// previousEpochProviderPaymentStorage, providerPaymentStorageFound := k.GetProviderPaymentStorage(ctx, previousEpochProviderStorageKey) -// if providerPaymentStorageFound { -// totalPaymentRequests += len(previousEpochProviderPaymentStorage.UniquePaymentStorageClientProviderKeys) // increase by the amount of previous epoch -// } -// k.SetEpochPayments(ctx, epochPayments) -// } - -// unstakeHoldBlocks, err := k.unstakeHoldBlocks(ctx, existingEntry.Chain, true) -// if err != nil { -// return err -// } - -// k.epochStorageKeeper.AppendUnstakeEntry(ctx, epochstoragetypes.ProviderKey, existingEntry, unstakeHoldBlocks) -// return nil -// } +func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, unresponsiveData []byte, logger log.Logger, epoch uint64, chainID string, cuSum uint64, servicersToPair uint64, clientAddr sdk.AccAddress) error { + var unresponsiveProviders []string + + // check that unresponsiveData exists + if len(unresponsiveData) == 0 { + return nil + } + + // check that servicersToPair is bigger than 1 + if servicersToPair <= 1 { + return utils.LavaFormatError("servicersToPair is less than or equal to one. The value is invalid", nil, &map[string]string{"servicersToPair": strconv.FormatUint(servicersToPair, 10)}) + } + + // unmarshal the byte array unresponsiveData to get a list of unresponsive providers Bech32 addresses + err := json.Unmarshal(unresponsiveData, &unresponsiveProviders) + if err != nil { + return utils.LavaFormatError("unable to unmarshal unresponsive providers", err, &map[string]string{"UnresponsiveProviders": string(unresponsiveData), "dataLength": strconv.Itoa(len(unresponsiveData))}) + } + + // check there are unresponsive providers + if len(unresponsiveProviders) == 0 { + // nothing to do. + return nil + } + + // the added complainer CU takes into account the number of providers the client complained on and the number + complainerCuToAdd := cuSum / (uint64(len(unresponsiveProviders)) * (servicersToPair - 1)) + + // iterate over the unresponsive providers list and update their complainers_total_cu + for _, unresponsiveProvider := range unresponsiveProviders { + // get provider address + sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(unresponsiveProvider) + if err != nil { // if bad data was given, we cant parse it so we ignote it and continue this protects from spamming wrong information. + utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": unresponsiveProvider}) + continue + } + + // get this epoch's epochPayments object + epochPayments, found, key := k.GetEpochPaymentsFromBlock(ctx, epoch) + if !found { + // the epochPayments object should exist since we already paid. if not found, print an error and continue + utils.LavaFormatError("did not find epochPayments object", err, &map[string]string{"epochPaymentskey": key}) + continue + } + + // get the providerPaymentStorage object using the providerStorageKey + providerStorageKey := k.GetProviderPaymentStorageKey(ctx, chainID, epoch, sdkUnresponsiveProviderAddress) + providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerStorageKey) + + if !found { + // providerPaymentStorage not found (this provider has no payments in this epoch and also no complaints) -> we need to add one complaint + emptyProviderPaymentStorageWithComplaint := types.ProviderPaymentStorage{ + Index: providerStorageKey, + UniquePaymentStorageClientProviderKeys: []string{}, + Epoch: epoch, + ComplainersTotalCu: uint64(0), + } + + // append the emptyProviderPaymentStorageWithComplaint to the epochPayments object's providerPaymentStorages + epochPayments.ProviderPaymentStorageKeys = append(epochPayments.GetProviderPaymentStorageKeys(), emptyProviderPaymentStorageWithComplaint.GetIndex()) + k.SetEpochPayments(ctx, epochPayments) + + // assign providerPaymentStorage with the new empty providerPaymentStorage + providerPaymentStorage = emptyProviderPaymentStorageWithComplaint + } + + // add complainer's used CU to providerPaymentStorage + providerPaymentStorage.ComplainersTotalCu += complainerCuToAdd + + // set the final provider payment storage state including the complaints + k.SetProviderPaymentStorage(ctx, providerPaymentStorage) + } + + return nil +} diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index 49dd758e9a..97c356f18f 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -1,224 +1,224 @@ package keeper -// import ( -// "fmt" -// "strconv" - -// sdk "github.com/cosmos/cosmos-sdk/types" -// "github.com/lavanet/lava/utils" -// epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" -// "github.com/lavanet/lava/x/pairing/types" -// ) - -// // Function that returns a map that links between a provider that should be punished and its providerCuCounterForUnreponsiveness -// func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { -// // check the epochsNum consts -// if epochsNumToCheckCUForComplainers <= 0 || epochsNumToCheckCUForUnresponsiveProvider <= 0 { -// return utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") -// } - -// // Get current epoch -// currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) - -// // Get recommendedEpochNumToCollectPayment -// recommendedEpochNumToCollectPayment := k.RecommendedEpochNumToCollectPayment(ctx) - -// // check which of the consts is larger -// largerEpochsNumConst := epochsNumToCheckCUForComplainers -// if epochsNumToCheckCUForUnresponsiveProvider > epochsNumToCheckCUForComplainers { -// largerEpochsNumConst = epochsNumToCheckCUForUnresponsiveProvider -// } - -// // To check for punishment, we have to go back recommendedEpochNumToCollectPayment+max(epochsNumToCheckCUForComplainers,epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing -// epochTemp := currentEpoch -// for counter := uint64(0); counter < largerEpochsNumConst+recommendedEpochNumToCollectPayment; counter++ { -// previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) -// if err != nil { -// utils.LavaFormatInfo("Epoch too early to punish unresponsive providers", &map[string]string{"epoch": fmt.Sprintf("%+v", currentEpoch)}) -// return nil -// } -// epochTemp = previousEpoch -// } - -// // Get the current stake storages (from all chains). stake storages contain a list of stake entries. Each stake storage is for a different chain -// providerStakeStorageList := k.getCurrentProviderStakeStorageList(ctx) -// if len(providerStakeStorageList) == 0 { -// // no provider is staked -> no one to punish -// return nil -// } - -// // Go back recommendedEpochNumToCollectPayment -// epochTemp = currentEpoch -// for counter := uint64(0); counter < recommendedEpochNumToCollectPayment; counter++ { -// previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) -// if err != nil { -// return utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get previous epoch") -// } -// epochTemp = previousEpoch -// } - -// // Go over the staked provider entries (on all chains) -// for _, providerStakeStorage := range providerStakeStorageList { -// for _, providerStakeEntry := range providerStakeStorage.GetStakeEntries() { -// // update the CU count for this provider in providerCuCounterForUnreponsivenessMap -// providerPaymentStorageKeyList, err := k.countCuForUnresponsiveness(ctx, epochTemp, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers, providerStakeEntry) -// if err != nil { -// return utils.LavaError(ctx, k.Logger(ctx), "count_cu_for_unresponsiveness", map[string]string{"err": err.Error()}, "couldn't count CU for unreponsiveness") -// } - -// // get the provider address and chain ID of the stake entry -// providerAddress := providerStakeEntry.Address -// chainID := providerStakeEntry.Chain - -// // providerPaymentStorageKeyList is not empty -> provider should be punished -// if len(providerPaymentStorageKeyList) != 0 && providerPaymentStorageKeyList != nil { -// err = k.punishUnresponsiveProvider(ctx, providerAddress, chainID, providerPaymentStorageKeyList) -// if err != nil { -// return utils.LavaError(ctx, k.Logger(ctx), "punish_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't punish unresponsive provider") -// } -// } -// } -// } - -// return nil -// } - -// // Function to count the CU serviced by the unresponsive provider and the CU of the complainers. The function returns a list of the found providerPaymentStorageKey -// func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64, providerStakeEntry epochstoragetypes.StakeEntry) ([]string, error) { -// epochTemp := epoch -// providerServicedCu := uint64(0) -// complainersCu := uint64(0) -// providerPaymentStorageKeyList := []string{} - -// // get the provider's SDK account address -// sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(providerStakeEntry.GetAddress()) -// if err != nil { -// return nil, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) -// } - -// // check which of the consts is larger -// largerEpochsNumConst := epochsNumToCheckCUForComplainers -// if epochsNumToCheckCUForUnresponsiveProvider > epochsNumToCheckCUForComplainers { -// largerEpochsNumConst = epochsNumToCheckCUForUnresponsiveProvider -// } - -// // count the CU serviced by the unersponsive provider and used CU of the complainers -// for counter := uint64(0); counter < largerEpochsNumConst; counter++ { -// // get providerPaymentStorageKey for epochTemp (other traits from the stake entry) -// providerPaymentStorageKey := k.GetProviderPaymentStorageKey(ctx, providerStakeEntry.GetChain(), epochTemp, sdkStakeEntryProviderAddress) - -// // try getting providerPaymentStorage using the providerPaymentStorageKey -// providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageKey) -// if found { -// // counter is smaller than epochsNumToCheckCUForUnresponsiveProvider -> count CU serviced by the provider in the epoch -// if counter < epochsNumToCheckCUForUnresponsiveProvider { -// // count the CU by iterating through the uniquePaymentStorageClientProvider objects -// for _, uniquePayment := range providerPaymentStorage.GetUniquePaymentStorageClientProvider() { -// providerServicedCu += uniquePayment.GetUsedCU() -// } -// } - -// // counter is smaller than epochsNumToCheckCUForComplainers -> count complainer CU -// if counter < epochsNumToCheckCUForComplainers { -// // update complainersCu -// complainersCu += providerPaymentStorage.ComplainersTotalCu -// } - -// // save the providerPaymentStorageKey in the providerPaymentStorageKeyList -// providerPaymentStorageKeyList = append(providerPaymentStorageKeyList, providerPaymentStorageKey) -// } - -// // Get previous epoch (from epochTemp) -// previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) -// if err != nil { -// return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") -// } -// // update epochTemp -// epochTemp = previousEpoch -// } - -// // the complainers' CU is larger than the provider serviced CU -> should be punished (return providerPaymentStorageKeyList so the complainers' CU can be reset after the punishment) -// if complainersCu > providerServicedCu { -// return providerPaymentStorageKeyList, nil -// } - -// return nil, nil -// } - -// // Function that return the current stake storage for all chains -// func (k Keeper) getCurrentProviderStakeStorageList(ctx sdk.Context) []epochstoragetypes.StakeStorage { -// var stakeStorageList []epochstoragetypes.StakeStorage - -// // get all chain IDs -// chainIdList := k.specKeeper.GetAllChainIDs(ctx) - -// // go over all chain IDs and keep their stake storage. If there is no stake storage for a specific chain, continue to the next one -// for _, chainID := range chainIdList { -// stakeStorage, found := k.epochStorageKeeper.GetStakeStorageCurrent(ctx, epochstoragetypes.ProviderKey, chainID) -// if !found { -// continue -// } -// stakeStorageList = append(stakeStorageList, stakeStorage) -// } - -// return stakeStorageList -// } - -// // Function that punishes providers. Current punishment is unstake -// func (k Keeper) punishUnresponsiveProvider(ctx sdk.Context, providerAddress string, chainID string, providerPaymentStorageKeyList []string) error { -// // Get provider's sdk.Account address -// sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) -// if err != nil { -// // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. -// return utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": providerAddress}) -// } - -// // Get provider's stake entry -// existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) -// if !entryExists { -// // if provider is not staked, nothing to do. -// return nil -// } - -// // unstake the unresponsive provider -// utils.LogLavaEvent(ctx, k.Logger(ctx), types.ProviderJailedEventName, map[string]string{"provider_address": providerAddress, "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") -// err = k.unsafeUnstakeProviderEntry(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) -// if err != nil { -// utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) -// } - -// // reset the provider's complainer CU (so he won't get punished for the same complaints twice) -// k.resetComplainersCU(ctx, providerPaymentStorageKeyList) - -// return nil -// } - -// // Function that reset the complainer CU of providerPaymentStorage objects that can be accessed using providerPaymentStorageIndexList -// func (k Keeper) resetComplainersCU(ctx sdk.Context, providerPaymentStorageIndexList []string) { -// // go over the providerPaymentStorageIndexList -// for _, providerPaymentStorageIndex := range providerPaymentStorageIndexList { -// // get providerPaymentStorage using its index -// providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageIndex) -// if !found { -// continue -// } - -// // reset the complainer CU -// providerPaymentStorage.ComplainersTotalCu = 0 -// k.SetProviderPaymentStorage(ctx, providerPaymentStorage) -// } -// } - -// // Function that unstakes a provider (considered unsafe because it doesn't check that the provider is staked. It's ok since we check the provider is staked before we call it) -// func (k Keeper) unsafeUnstakeProviderEntry(ctx sdk.Context, providerKey string, chainID string, indexInStakeStorage uint64, existingEntry epochstoragetypes.StakeEntry) error { -// // Remove the provider's stake entry -// err := k.epochStorageKeeper.RemoveStakeEntryCurrent(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage) -// if err != nil { -// return utils.LavaError(ctx, k.Logger(ctx), "relay_payment_unstake", map[string]string{"existingEntry": fmt.Sprintf("%+v", existingEntry)}, "tried to unstake unsafe but didnt find entry") -// } - -// // Appened the provider's stake entry to the unstake entry list -// k.epochStorageKeeper.AppendUnstakeEntry(ctx, epochstoragetypes.ProviderKey, existingEntry) - -// return nil -// } +import ( + "fmt" + "strconv" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/utils" + epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" + "github.com/lavanet/lava/x/pairing/types" +) + +// Function that returns a map that links between a provider that should be punished and its providerCuCounterForUnreponsiveness +func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64) error { + // check the epochsNum consts + if epochsNumToCheckCUForComplainers <= 0 || epochsNumToCheckCUForUnresponsiveProvider <= 0 { + return utils.LavaError(ctx, k.Logger(ctx), "get_unresponsive_providers_to_punish", nil, "epochsNumToCheckCUForUnresponsiveProvider or epochsNumToCheckCUForComplainers are smaller or equal than zero") + } + + // Get current epoch + currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) + + // Get recommendedEpochNumToCollectPayment + recommendedEpochNumToCollectPayment := k.RecommendedEpochNumToCollectPayment(ctx) + + // check which of the consts is larger + largerEpochsNumConst := epochsNumToCheckCUForComplainers + if epochsNumToCheckCUForUnresponsiveProvider > epochsNumToCheckCUForComplainers { + largerEpochsNumConst = epochsNumToCheckCUForUnresponsiveProvider + } + + // To check for punishment, we have to go back recommendedEpochNumToCollectPayment+max(epochsNumToCheckCUForComplainers,epochsNumToCheckCUForUnresponsiveProvider) epochs from the current epoch. If there isn't enough memory, do nothing + epochTemp := currentEpoch + for counter := uint64(0); counter < largerEpochsNumConst+recommendedEpochNumToCollectPayment; counter++ { + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + utils.LavaFormatInfo("Epoch too early to punish unresponsive providers", &map[string]string{"epoch": fmt.Sprintf("%+v", currentEpoch)}) + return nil + } + epochTemp = previousEpoch + } + + // Get the current stake storages (from all chains). stake storages contain a list of stake entries. Each stake storage is for a different chain + providerStakeStorageList := k.getCurrentProviderStakeStorageList(ctx) + if len(providerStakeStorageList) == 0 { + // no provider is staked -> no one to punish + return nil + } + + // Go back recommendedEpochNumToCollectPayment + epochTemp = currentEpoch + for counter := uint64(0); counter < recommendedEpochNumToCollectPayment; counter++ { + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", currentEpoch)}, "couldn't get previous epoch") + } + epochTemp = previousEpoch + } + + // Go over the staked provider entries (on all chains) + for _, providerStakeStorage := range providerStakeStorageList { + for _, providerStakeEntry := range providerStakeStorage.GetStakeEntries() { + // update the CU count for this provider in providerCuCounterForUnreponsivenessMap + providerPaymentStorageKeyList, err := k.countCuForUnresponsiveness(ctx, epochTemp, epochsNumToCheckCUForUnresponsiveProvider, epochsNumToCheckCUForComplainers, providerStakeEntry) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "count_cu_for_unresponsiveness", map[string]string{"err": err.Error()}, "couldn't count CU for unreponsiveness") + } + + // providerPaymentStorageKeyList is not empty -> provider should be punished + if len(providerPaymentStorageKeyList) != 0 && providerPaymentStorageKeyList != nil { + err = k.punishUnresponsiveProvider(ctx, epochTemp, providerPaymentStorageKeyList, providerStakeEntry.GetAddress(), providerStakeEntry.GetChain()) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "punish_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't punish unresponsive provider") + } + } + } + } + + return nil +} + +// Function to count the CU serviced by the unresponsive provider and the CU of the complainers. The function returns a list of the found providerPaymentStorageKey +func (k Keeper) countCuForUnresponsiveness(ctx sdk.Context, epoch uint64, epochsNumToCheckCUForUnresponsiveProvider uint64, epochsNumToCheckCUForComplainers uint64, providerStakeEntry epochstoragetypes.StakeEntry) ([]string, error) { + epochTemp := epoch + providerServicedCu := uint64(0) + complainersCu := uint64(0) + providerPaymentStorageKeyList := []string{} + + // get the provider's SDK account address + sdkStakeEntryProviderAddress, err := sdk.AccAddressFromBech32(providerStakeEntry.GetAddress()) + if err != nil { + return nil, utils.LavaFormatError("unable to sdk.AccAddressFromBech32(provider)", err, &map[string]string{"provider_address": providerStakeEntry.Address}) + } + + // check which of the consts is larger + largerEpochsNumConst := epochsNumToCheckCUForComplainers + if epochsNumToCheckCUForUnresponsiveProvider > epochsNumToCheckCUForComplainers { + largerEpochsNumConst = epochsNumToCheckCUForUnresponsiveProvider + } + + // count the CU serviced by the unersponsive provider and used CU of the complainers + for counter := uint64(0); counter < largerEpochsNumConst; counter++ { + // get providerPaymentStorageKey for epochTemp (other traits from the stake entry) + providerPaymentStorageKey := k.GetProviderPaymentStorageKey(ctx, providerStakeEntry.GetChain(), epochTemp, sdkStakeEntryProviderAddress) + + // try getting providerPaymentStorage using the providerPaymentStorageKey + providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageKey) + if found { + // counter is smaller than epochsNumToCheckCUForUnresponsiveProvider -> count CU serviced by the provider in the epoch + if counter < epochsNumToCheckCUForUnresponsiveProvider { + // count the CU by iterating through the uniquePaymentStorageClientProvider objects + for _, uniquePaymentKey := range providerPaymentStorage.GetUniquePaymentStorageClientProviderKeys() { + uniquePayment, _ := k.GetUniquePaymentStorageClientProvider(ctx, uniquePaymentKey) + providerServicedCu += uniquePayment.GetUsedCU() + } + } + + // counter is smaller than epochsNumToCheckCUForComplainers -> count complainer CU + if counter < epochsNumToCheckCUForComplainers { + // update complainersCu + complainersCu += providerPaymentStorage.ComplainersTotalCu + } + + // save the providerPaymentStorageKey in the providerPaymentStorageKeyList + providerPaymentStorageKeyList = append(providerPaymentStorageKeyList, providerPaymentStorageKey) + } + + // Get previous epoch (from epochTemp) + previousEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epochTemp) + if err != nil { + return nil, utils.LavaError(ctx, k.Logger(ctx), "get_previous_epoch", map[string]string{"err": err.Error(), "epoch": fmt.Sprintf("%+v", epochTemp)}, "couldn't get previous epoch") + } + // update epochTemp + epochTemp = previousEpoch + } + + // the complainers' CU is larger than the provider serviced CU -> should be punished (return providerPaymentStorageKeyList so the complainers' CU can be reset after the punishment) + if complainersCu > providerServicedCu { + return providerPaymentStorageKeyList, nil + } + + return nil, nil +} + +// Function that return the current stake storage for all chains +func (k Keeper) getCurrentProviderStakeStorageList(ctx sdk.Context) []epochstoragetypes.StakeStorage { + var stakeStorageList []epochstoragetypes.StakeStorage + + // get all chain IDs + chainIdList := k.specKeeper.GetAllChainIDs(ctx) + + // go over all chain IDs and keep their stake storage. If there is no stake storage for a specific chain, continue to the next one + for _, chainID := range chainIdList { + stakeStorage, found := k.epochStorageKeeper.GetStakeStorageCurrent(ctx, epochstoragetypes.ProviderKey, chainID) + if !found { + continue + } + stakeStorageList = append(stakeStorageList, stakeStorage) + } + + return stakeStorageList +} + +// Function that punishes providers. Current punishment is unstake +func (k Keeper) punishUnresponsiveProvider(ctx sdk.Context, epoch uint64, providerPaymentStorageKeyList []string, providerAddress string, chainID string) error { + // Get provider's sdk.Account address + sdkUnresponsiveProviderAddress, err := sdk.AccAddressFromBech32(providerAddress) + if err != nil { + // if bad data was given, we cant parse it so we ignore it and continue this protects from spamming wrong information. + return utils.LavaFormatError("unable to sdk.AccAddressFromBech32(unresponsive_provider)", err, &map[string]string{"unresponsive_provider_address": providerAddress}) + } + + // Get provider's stake entry + existingEntry, entryExists, indexInStakeStorage := k.epochStorageKeeper.GetStakeEntryByAddressCurrent(ctx, epochstoragetypes.ProviderKey, chainID, sdkUnresponsiveProviderAddress) + if !entryExists { + // if provider is not staked, nothing to do. + return nil + } + + // unstake the unresponsive provider + utils.LogLavaEvent(ctx, k.Logger(ctx), types.ProviderJailedEventName, map[string]string{"provider_address": providerAddress, "chain_id": chainID}, "Unresponsive provider was unstaked from the chain due to unresponsiveness") + err = k.unsafeUnstakeProviderEntry(ctx, epoch, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage, existingEntry) + if err != nil { + utils.LavaFormatError("unable to unstake provider entry (unsafe method)", err, &map[string]string{"chainID": chainID, "indexInStakeStorage": strconv.FormatUint(indexInStakeStorage, 10), "existingEntry": existingEntry.GetStake().String()}) + } + + // reset the provider's complainer CU (so he won't get punished for the same complaints twice) + k.resetComplainersCU(ctx, providerPaymentStorageKeyList) + + return nil +} + +// Function that reset the complainer CU of providerPaymentStorage objects that can be accessed using providerPaymentStorageIndexList +func (k Keeper) resetComplainersCU(ctx sdk.Context, providerPaymentStorageIndexList []string) { + // go over the providerPaymentStorageIndexList + for _, providerPaymentStorageIndex := range providerPaymentStorageIndexList { + // get providerPaymentStorage using its index + providerPaymentStorage, found := k.GetProviderPaymentStorage(ctx, providerPaymentStorageIndex) + if !found { + continue + } + + // reset the complainer CU + providerPaymentStorage.ComplainersTotalCu = 0 + k.SetProviderPaymentStorage(ctx, providerPaymentStorage) + } +} + +// Function that unstakes a provider (considered unsafe because it doesn't check that the provider is staked. It's ok since we check the provider is staked before we call it) +func (k Keeper) unsafeUnstakeProviderEntry(ctx sdk.Context, epoch uint64, providerKey string, chainID string, indexInStakeStorage uint64, existingEntry epochstoragetypes.StakeEntry) error { + // Remove the provider's stake entry + err := k.epochStorageKeeper.RemoveStakeEntryCurrent(ctx, epochstoragetypes.ProviderKey, chainID, indexInStakeStorage) + if err != nil { + return utils.LavaError(ctx, k.Logger(ctx), "relay_payment_unstake", map[string]string{"existingEntry": fmt.Sprintf("%+v", existingEntry)}, "tried to unstake unsafe but didnt find entry") + } + + // get unstakeHoldBlocks + unstakeHoldBlocks := k.epochStorageKeeper.UnstakeHoldBlocks(ctx, epoch) + + // Appened the provider's stake entry to the unstake entry list + k.epochStorageKeeper.AppendUnstakeEntry(ctx, epochstoragetypes.ProviderKey, existingEntry, unstakeHoldBlocks) + + return nil +} diff --git a/x/pairing/types/provider_payment_storage.pb.go b/x/pairing/types/provider_payment_storage.pb.go index 302601fe9f..a5e6a1680e 100644 --- a/x/pairing/types/provider_payment_storage.pb.go +++ b/x/pairing/types/provider_payment_storage.pb.go @@ -25,8 +25,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type ProviderPaymentStorage struct { Index string `protobuf:"bytes,1,opt,name=index,proto3" json:"index,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` - UnresponsivenessComplaints []string `protobuf:"bytes,4,rep,name=unresponsiveness_complaints,json=unresponsivenessComplaints,proto3" json:"unresponsiveness_complaints,omitempty"` - UniquePaymentStorageClientProviderKeys []string `protobuf:"bytes,5,rep,name=uniquePaymentStorageClientProviderKeys,proto3" json:"uniquePaymentStorageClientProviderKeys,omitempty"` + UniquePaymentStorageClientProviderKeys []string `protobuf:"bytes,6,rep,name=uniquePaymentStorageClientProviderKeys,proto3" json:"uniquePaymentStorageClientProviderKeys,omitempty"` + ComplainersTotalCu uint64 `protobuf:"varint,7,opt,name=complainersTotalCu,proto3" json:"complainersTotalCu,omitempty"` } func (m *ProviderPaymentStorage) Reset() { *m = ProviderPaymentStorage{} } @@ -76,18 +76,18 @@ func (m *ProviderPaymentStorage) GetEpoch() uint64 { return 0 } -func (m *ProviderPaymentStorage) GetUnresponsivenessComplaints() []string { +func (m *ProviderPaymentStorage) GetUniquePaymentStorageClientProviderKeys() []string { if m != nil { - return m.UnresponsivenessComplaints + return m.UniquePaymentStorageClientProviderKeys } return nil } -func (m *ProviderPaymentStorage) GetUniquePaymentStorageClientProviderKeys() []string { +func (m *ProviderPaymentStorage) GetComplainersTotalCu() uint64 { if m != nil { - return m.UniquePaymentStorageClientProviderKeys + return m.ComplainersTotalCu } - return nil + return 0 } func init() { @@ -100,24 +100,24 @@ func init() { var fileDescriptor_4f1d2e8d774659ae = []byte{ // 282 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xb1, 0x4a, 0xf4, 0x40, - 0x14, 0x85, 0x33, 0x7f, 0xb2, 0x3f, 0x6e, 0x2a, 0x09, 0x8b, 0x84, 0x15, 0x86, 0x60, 0xb1, 0xa6, - 0x4a, 0x0a, 0xed, 0x45, 0xb7, 0xd3, 0x66, 0x89, 0x60, 0x61, 0x13, 0x66, 0xb3, 0x97, 0xec, 0x40, - 0x32, 0x33, 0xce, 0x4c, 0xc2, 0xe6, 0x2d, 0x7c, 0x2c, 0xcb, 0x2d, 0x2d, 0x25, 0x79, 0x11, 0x49, - 0x26, 0x11, 0xdc, 0xca, 0xea, 0x72, 0x2e, 0xe7, 0x3b, 0x1c, 0x8e, 0xbb, 0x12, 0x84, 0x4a, 0xca, - 0xf2, 0x58, 0x48, 0x5e, 0xd3, 0x1d, 0xc8, 0x54, 0x90, 0xa6, 0x04, 0xa6, 0x53, 0xa5, 0xb9, 0x24, - 0x39, 0x44, 0x42, 0x72, 0xcd, 0xbd, 0x45, 0x41, 0x6a, 0xc2, 0x40, 0x47, 0xfd, 0x8d, 0x46, 0x68, - 0x79, 0x3b, 0xd1, 0x15, 0xa3, 0x6f, 0x15, 0x9c, 0xb2, 0x69, 0x56, 0xd0, 0x5e, 0x4e, 0xd9, 0x26, - 0xeb, 0xaa, 0x43, 0xee, 0xc5, 0x66, 0x7c, 0x6d, 0x0c, 0xf1, 0x6c, 0x00, 0x6f, 0xe1, 0xce, 0x28, - 0xdb, 0xc1, 0xc1, 0x47, 0x01, 0x0a, 0xe7, 0x89, 0x11, 0xfd, 0x17, 0x04, 0xcf, 0xf6, 0xbe, 0x1d, - 0xa0, 0xd0, 0x49, 0x8c, 0xf0, 0xee, 0xdc, 0xcb, 0x8a, 0x49, 0x50, 0x82, 0x33, 0x45, 0x6b, 0x60, - 0xa0, 0x54, 0x9a, 0xf1, 0x52, 0x14, 0x84, 0x32, 0xad, 0x7c, 0x27, 0xb0, 0xc3, 0x79, 0xb2, 0x3c, - 0xb5, 0xac, 0x7f, 0x1c, 0xde, 0x8b, 0xbb, 0x32, 0xbd, 0x7f, 0x97, 0x58, 0x0f, 0xa5, 0xa7, 0x82, - 0x4f, 0xd0, 0x28, 0x7f, 0x36, 0x64, 0xfd, 0xd1, 0xfd, 0xe8, 0x9c, 0xfd, 0x3b, 0xb7, 0x1f, 0xee, - 0x3f, 0x5a, 0x8c, 0x8e, 0x2d, 0x46, 0x5f, 0x2d, 0x46, 0xef, 0x1d, 0xb6, 0x8e, 0x1d, 0xb6, 0x3e, - 0x3b, 0x6c, 0xbd, 0x5e, 0xe7, 0x54, 0xef, 0xab, 0x6d, 0x94, 0xf1, 0x32, 0x1e, 0x67, 0x1d, 0x6e, - 0x7c, 0x88, 0xa7, 0x3d, 0x75, 0x23, 0x40, 0x6d, 0xff, 0x0f, 0x7b, 0xdd, 0x7c, 0x07, 0x00, 0x00, - 0xff, 0xff, 0xb5, 0x8b, 0x82, 0xb1, 0xa5, 0x01, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2b, 0x48, 0xcc, 0x2c, + 0xca, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xcb, 0x4c, 0x49, 0x2d, 0x8a, 0x2f, 0x48, 0xac, + 0xcc, 0x4d, 0xcd, 0x2b, 0x89, 0x2f, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, + 0x2f, 0xc9, 0x17, 0x12, 0xc9, 0x49, 0x2c, 0x4b, 0xcc, 0x4b, 0x2d, 0xd1, 0x03, 0xd1, 0x7a, 0x50, + 0x4d, 0x52, 0x26, 0x30, 0xdd, 0xa5, 0x79, 0x99, 0x85, 0xa5, 0xa9, 0xe8, 0x7a, 0xe3, 0x93, 0x73, + 0x32, 0x41, 0x5c, 0x98, 0xd9, 0x10, 0xb3, 0x94, 0xee, 0x31, 0x72, 0x89, 0x05, 0x40, 0x85, 0x02, + 0x20, 0x3a, 0x82, 0x21, 0x1a, 0x84, 0x44, 0xb8, 0x58, 0x33, 0xf3, 0x52, 0x52, 0x2b, 0x24, 0x18, + 0x15, 0x18, 0x35, 0x38, 0x83, 0x20, 0x1c, 0x90, 0x68, 0x6a, 0x41, 0x7e, 0x72, 0x86, 0x04, 0xb3, + 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x84, 0x23, 0x14, 0xc6, 0xa5, 0x06, 0xb1, 0x16, 0xd5, 0x0c, 0x67, + 0xb0, 0x9d, 0x30, 0xf3, 0xbd, 0x53, 0x2b, 0x8b, 0x25, 0xd8, 0x14, 0x98, 0x35, 0x38, 0x83, 0x88, + 0x54, 0x2d, 0xa4, 0xc7, 0x25, 0x94, 0x9c, 0x9f, 0x5b, 0x90, 0x93, 0x98, 0x99, 0x97, 0x5a, 0x54, + 0x1c, 0x92, 0x5f, 0x92, 0x98, 0xe3, 0x5c, 0x2a, 0xc1, 0x0e, 0xb6, 0x1a, 0x8b, 0x8c, 0x17, 0x0b, + 0x07, 0x93, 0x00, 0xb3, 0x17, 0x0b, 0x07, 0x8b, 0x00, 0xab, 0x17, 0x0b, 0x07, 0xab, 0x00, 0x9b, + 0x93, 0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, + 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xa9, 0xa7, 0x67, 0x96, + 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x43, 0x43, 0x14, 0x4c, 0xeb, 0x57, 0xe8, 0xc3, + 0x82, 0xb2, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, 0x54, 0xc6, 0x80, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xe4, 0x32, 0xb0, 0x09, 0xa0, 0x01, 0x00, 0x00, } func (m *ProviderPaymentStorage) Marshal() (dAtA []byte, err error) { @@ -140,22 +140,18 @@ func (m *ProviderPaymentStorage) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l + if m.ComplainersTotalCu != 0 { + i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(m.ComplainersTotalCu)) + i-- + dAtA[i] = 0x38 + } if len(m.UniquePaymentStorageClientProviderKeys) > 0 { for iNdEx := len(m.UniquePaymentStorageClientProviderKeys) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.UniquePaymentStorageClientProviderKeys[iNdEx]) copy(dAtA[i:], m.UniquePaymentStorageClientProviderKeys[iNdEx]) i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(len(m.UniquePaymentStorageClientProviderKeys[iNdEx]))) i-- - dAtA[i] = 0x2a - } - } - if len(m.UnresponsivenessComplaints) > 0 { - for iNdEx := len(m.UnresponsivenessComplaints) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.UnresponsivenessComplaints[iNdEx]) - copy(dAtA[i:], m.UnresponsivenessComplaints[iNdEx]) - i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(len(m.UnresponsivenessComplaints[iNdEx]))) - i-- - dAtA[i] = 0x22 + dAtA[i] = 0x32 } } if m.Epoch != 0 { @@ -197,18 +193,15 @@ func (m *ProviderPaymentStorage) Size() (n int) { if m.Epoch != 0 { n += 1 + sovProviderPaymentStorage(uint64(m.Epoch)) } - if len(m.UnresponsivenessComplaints) > 0 { - for _, s := range m.UnresponsivenessComplaints { - l = len(s) - n += 1 + l + sovProviderPaymentStorage(uint64(l)) - } - } if len(m.UniquePaymentStorageClientProviderKeys) > 0 { for _, s := range m.UniquePaymentStorageClientProviderKeys { l = len(s) n += 1 + l + sovProviderPaymentStorage(uint64(l)) } } + if m.ComplainersTotalCu != 0 { + n += 1 + sovProviderPaymentStorage(uint64(m.ComplainersTotalCu)) + } return n } @@ -298,9 +291,9 @@ func (m *ProviderPaymentStorage) Unmarshal(dAtA []byte) error { break } } - case 4: + case 6: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UnresponsivenessComplaints", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field UniquePaymentStorageClientProviderKeys", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -328,13 +321,13 @@ func (m *ProviderPaymentStorage) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.UnresponsivenessComplaints = append(m.UnresponsivenessComplaints, string(dAtA[iNdEx:postIndex])) + m.UniquePaymentStorageClientProviderKeys = append(m.UniquePaymentStorageClientProviderKeys, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UniquePaymentStorageClientProviderKeys", wireType) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ComplainersTotalCu", wireType) } - var stringLen uint64 + m.ComplainersTotalCu = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowProviderPaymentStorage @@ -344,24 +337,11 @@ func (m *ProviderPaymentStorage) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.ComplainersTotalCu |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthProviderPaymentStorage - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthProviderPaymentStorage - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.UniquePaymentStorageClientProviderKeys = append(m.UniquePaymentStorageClientProviderKeys, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipProviderPaymentStorage(dAtA[iNdEx:]) From e4085b775cf01e7a905a6007067a2fa06a24a0c6 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Thu, 2 Feb 2023 15:28:21 +0200 Subject: [PATCH 31/37] CNS-137: fix minor PR issues --- x/pairing/keeper/msg_server_relay_payment.go | 2 +- x/pairing/keeper/unresponsive_provider.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 9a9225cc2c..c45cc02460 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -286,7 +286,7 @@ func (k msgServer) updateProviderPaymentStorageWithComplainerCU(ctx sdk.Context, // check that servicersToPair is bigger than 1 if servicersToPair <= 1 { - return utils.LavaFormatError("servicersToPair is less than or equal to one. The value is invalid", nil, &map[string]string{"servicersToPair": strconv.FormatUint(servicersToPair, 10)}) + servicersToPair = 2 } // unmarshal the byte array unresponsiveData to get a list of unresponsive providers Bech32 addresses diff --git a/x/pairing/keeper/unresponsive_provider.go b/x/pairing/keeper/unresponsive_provider.go index 97c356f18f..ec1ab17bc4 100644 --- a/x/pairing/keeper/unresponsive_provider.go +++ b/x/pairing/keeper/unresponsive_provider.go @@ -67,7 +67,7 @@ func (k Keeper) UnstakeUnresponsiveProviders(ctx sdk.Context, epochsNumToCheckCU } // providerPaymentStorageKeyList is not empty -> provider should be punished - if len(providerPaymentStorageKeyList) != 0 && providerPaymentStorageKeyList != nil { + if len(providerPaymentStorageKeyList) != 0 { err = k.punishUnresponsiveProvider(ctx, epochTemp, providerPaymentStorageKeyList, providerStakeEntry.GetAddress(), providerStakeEntry.GetChain()) if err != nil { return utils.LavaError(ctx, k.Logger(ctx), "punish_unresponsive_provider", map[string]string{"err": err.Error()}, "couldn't punish unresponsive provider") From 8cc05aada75601d96f40e7c871210c8e06181e1d Mon Sep 17 00:00:00 2001 From: oren-lava Date: Thu, 2 Feb 2023 16:40:00 +0200 Subject: [PATCH 32/37] CNS-137: changed providerPaymentStorage proto field nums --- proto/pairing/provider_payment_storage.proto | 5 ++- .../types/provider_payment_storage.pb.go | 32 +++++++++---------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/proto/pairing/provider_payment_storage.proto b/proto/pairing/provider_payment_storage.proto index 644a6e9c76..1cbed1db3f 100644 --- a/proto/pairing/provider_payment_storage.proto +++ b/proto/pairing/provider_payment_storage.proto @@ -10,9 +10,8 @@ message ProviderPaymentStorage { reserved 2; uint64 epoch = 3; reserved 4; - reserved 5; - repeated string uniquePaymentStorageClientProviderKeys = 6; - uint64 complainersTotalCu = 7; // total CU that were supposed to be served by the provider but didn't because he was unavailable (so consumers complained about him) + repeated string uniquePaymentStorageClientProviderKeys = 5; + uint64 complainersTotalCu = 6; // total CU that were supposed to be served by the provider but didn't because he was unavailable (so consumers complained about him) } // change Client -> consumer diff --git a/x/pairing/types/provider_payment_storage.pb.go b/x/pairing/types/provider_payment_storage.pb.go index a5e6a1680e..40a774a086 100644 --- a/x/pairing/types/provider_payment_storage.pb.go +++ b/x/pairing/types/provider_payment_storage.pb.go @@ -25,8 +25,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type ProviderPaymentStorage struct { Index string `protobuf:"bytes,1,opt,name=index,proto3" json:"index,omitempty"` Epoch uint64 `protobuf:"varint,3,opt,name=epoch,proto3" json:"epoch,omitempty"` - UniquePaymentStorageClientProviderKeys []string `protobuf:"bytes,6,rep,name=uniquePaymentStorageClientProviderKeys,proto3" json:"uniquePaymentStorageClientProviderKeys,omitempty"` - ComplainersTotalCu uint64 `protobuf:"varint,7,opt,name=complainersTotalCu,proto3" json:"complainersTotalCu,omitempty"` + UniquePaymentStorageClientProviderKeys []string `protobuf:"bytes,5,rep,name=uniquePaymentStorageClientProviderKeys,proto3" json:"uniquePaymentStorageClientProviderKeys,omitempty"` + ComplainersTotalCu uint64 `protobuf:"varint,6,opt,name=complainersTotalCu,proto3" json:"complainersTotalCu,omitempty"` } func (m *ProviderPaymentStorage) Reset() { *m = ProviderPaymentStorage{} } @@ -99,25 +99,25 @@ func init() { } var fileDescriptor_4f1d2e8d774659ae = []byte{ - // 282 bytes of a gzipped FileDescriptorProto + // 276 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2b, 0x48, 0xcc, 0x2c, 0xca, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xcb, 0x4c, 0x49, 0x2d, 0x8a, 0x2f, 0x48, 0xac, 0xcc, 0x4d, 0xcd, 0x2b, 0x89, 0x2f, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc9, 0x49, 0x2c, 0x4b, 0xcc, 0x4b, 0x2d, 0xd1, 0x03, 0xd1, 0x7a, 0x50, 0x4d, 0x52, 0x26, 0x30, 0xdd, 0xa5, 0x79, 0x99, 0x85, 0xa5, 0xa9, 0xe8, 0x7a, 0xe3, 0x93, 0x73, - 0x32, 0x41, 0x5c, 0x98, 0xd9, 0x10, 0xb3, 0x94, 0xee, 0x31, 0x72, 0x89, 0x05, 0x40, 0x85, 0x02, + 0x32, 0x41, 0x5c, 0x98, 0xd9, 0x10, 0xb3, 0x94, 0x6e, 0x30, 0x72, 0x89, 0x05, 0x40, 0x85, 0x02, 0x20, 0x3a, 0x82, 0x21, 0x1a, 0x84, 0x44, 0xb8, 0x58, 0x33, 0xf3, 0x52, 0x52, 0x2b, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x20, 0x1c, 0x90, 0x68, 0x6a, 0x41, 0x7e, 0x72, 0x86, 0x04, 0xb3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x84, 0x23, 0x14, 0xc6, 0xa5, 0x06, 0xb1, 0x16, 0xd5, 0x0c, 0x67, - 0xb0, 0x9d, 0x30, 0xf3, 0xbd, 0x53, 0x2b, 0x8b, 0x25, 0xd8, 0x14, 0x98, 0x35, 0x38, 0x83, 0x88, + 0xb0, 0x9d, 0x30, 0xf3, 0xbd, 0x53, 0x2b, 0x8b, 0x25, 0x58, 0x15, 0x98, 0x35, 0x38, 0x83, 0x88, 0x54, 0x2d, 0xa4, 0xc7, 0x25, 0x94, 0x9c, 0x9f, 0x5b, 0x90, 0x93, 0x98, 0x99, 0x97, 0x5a, 0x54, - 0x1c, 0x92, 0x5f, 0x92, 0x98, 0xe3, 0x5c, 0x2a, 0xc1, 0x0e, 0xb6, 0x1a, 0x8b, 0x8c, 0x17, 0x0b, - 0x07, 0x93, 0x00, 0xb3, 0x17, 0x0b, 0x07, 0x8b, 0x00, 0xab, 0x17, 0x0b, 0x07, 0xab, 0x00, 0x9b, - 0x93, 0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, - 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xa9, 0xa7, 0x67, 0x96, - 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x43, 0x43, 0x14, 0x4c, 0xeb, 0x57, 0xe8, 0xc3, - 0x82, 0xb2, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, 0x54, 0xc6, 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xe4, 0x32, 0xb0, 0x09, 0xa0, 0x01, 0x00, 0x00, + 0x1c, 0x92, 0x5f, 0x92, 0x98, 0xe3, 0x5c, 0x2a, 0xc1, 0x06, 0xb6, 0x1a, 0x8b, 0x8c, 0x17, 0x0b, + 0x07, 0x93, 0x00, 0xb3, 0x17, 0x0b, 0x07, 0x8b, 0x00, 0xab, 0x93, 0xe3, 0x89, 0x47, 0x72, 0x8c, + 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, + 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xa9, 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, + 0xe7, 0xea, 0x43, 0xc3, 0x12, 0x4c, 0xeb, 0x57, 0xe8, 0xc3, 0x02, 0xb1, 0xa4, 0xb2, 0x20, 0xb5, + 0x38, 0x89, 0x0d, 0x1c, 0x48, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xa4, 0x36, 0x92, + 0x9a, 0x01, 0x00, 0x00, } func (m *ProviderPaymentStorage) Marshal() (dAtA []byte, err error) { @@ -143,7 +143,7 @@ func (m *ProviderPaymentStorage) MarshalToSizedBuffer(dAtA []byte) (int, error) if m.ComplainersTotalCu != 0 { i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(m.ComplainersTotalCu)) i-- - dAtA[i] = 0x38 + dAtA[i] = 0x30 } if len(m.UniquePaymentStorageClientProviderKeys) > 0 { for iNdEx := len(m.UniquePaymentStorageClientProviderKeys) - 1; iNdEx >= 0; iNdEx-- { @@ -151,7 +151,7 @@ func (m *ProviderPaymentStorage) MarshalToSizedBuffer(dAtA []byte) (int, error) copy(dAtA[i:], m.UniquePaymentStorageClientProviderKeys[iNdEx]) i = encodeVarintProviderPaymentStorage(dAtA, i, uint64(len(m.UniquePaymentStorageClientProviderKeys[iNdEx]))) i-- - dAtA[i] = 0x32 + dAtA[i] = 0x2a } } if m.Epoch != 0 { @@ -291,7 +291,7 @@ func (m *ProviderPaymentStorage) Unmarshal(dAtA []byte) error { break } } - case 6: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field UniquePaymentStorageClientProviderKeys", wireType) } @@ -323,7 +323,7 @@ func (m *ProviderPaymentStorage) Unmarshal(dAtA []byte) error { } m.UniquePaymentStorageClientProviderKeys = append(m.UniquePaymentStorageClientProviderKeys, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 7: + case 6: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field ComplainersTotalCu", wireType) } From 27690c0ebd4a1384b00d4fcf30001e024f3730ef Mon Sep 17 00:00:00 2001 From: oren-lava Date: Sun, 5 Feb 2023 16:55:25 +0200 Subject: [PATCH 33/37] CNS-137: added upgrade v0.5.1 which inits the RecommendedEpochNumToCollectPayment param --- app/app.go | 3 ++- app/upgrades/v0_5_1/upgrade.go | 39 ++++++++++++++++++++++++++++++++++ x/pairing/keeper/params.go | 4 ++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 app/upgrades/v0_5_1/upgrade.go diff --git a/app/app.go b/app/app.go index 926bfaefa2..4245a728e4 100644 --- a/app/app.go +++ b/app/app.go @@ -87,6 +87,7 @@ import ( "github.com/lavanet/lava/app/keepers" "github.com/lavanet/lava/app/upgrades" "github.com/lavanet/lava/app/upgrades/v0_5_0" + "github.com/lavanet/lava/app/upgrades/v0_5_1" "github.com/lavanet/lava/docs" conflictmodule "github.com/lavanet/lava/x/conflict" conflictmodulekeeper "github.com/lavanet/lava/x/conflict/keeper" @@ -116,7 +117,7 @@ const ( ) // Upgrades add here future upgrades (upgrades.Upgrade) -var Upgrades = []upgrades.Upgrade{upgrades.Upgrade_0_4_0, upgrades.Upgrade_0_4_3, upgrades.Upgrade_0_4_4, upgrades.Upgrade_0_4_5, v0_5_0.Upgrade} +var Upgrades = []upgrades.Upgrade{upgrades.Upgrade_0_4_0, upgrades.Upgrade_0_4_3, upgrades.Upgrade_0_4_4, upgrades.Upgrade_0_4_5, v0_5_0.Upgrade, v0_5_1.Upgrade} // this line is used by starport scaffolding # stargate/wasm/app/enabledProposals diff --git a/app/upgrades/v0_5_1/upgrade.go b/app/upgrades/v0_5_1/upgrade.go new file mode 100644 index 0000000000..8eb6a998bb --- /dev/null +++ b/app/upgrades/v0_5_1/upgrade.go @@ -0,0 +1,39 @@ +package v0_5_1 + +import ( + "log" + + store "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/lavanet/lava/app/keepers" + "github.com/lavanet/lava/app/upgrades" + pairingtypes "github.com/lavanet/lava/x/pairing/types" +) + +const UpgradeName = "v0.5.1" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, // upgrade name defined few lines above + CreateUpgradeHandler: CreateUpgradeHandler, // create CreateUpgradeHandler in upgrades.go below + StoreUpgrades: store.StoreUpgrades{}, // StoreUpgrades has 3 fields: Added/Renamed/Deleted any module that fits these description should be added in the way below +} + +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + bpm upgrades.BaseAppParamManager, + keepers *keepers.LavaKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + log.Println("########################") + log.Println("# STARTING UPGRADE #") + log.Println("########################") + + // we use a dedicated SET since the upgrade package doesn't have access to the paramstore, thus can't set a parameter directly + keepers.PairingKeeper.SetRecommendedEpochNumToCollectPayment(ctx, pairingtypes.DefaultRecommendedEpochNumToCollectPayment) + + return mm.RunMigrations(ctx, configurator, vm) + } +} diff --git a/x/pairing/keeper/params.go b/x/pairing/keeper/params.go index 64c34a2611..d6bb58364a 100644 --- a/x/pairing/keeper/params.go +++ b/x/pairing/keeper/params.go @@ -103,3 +103,7 @@ func (k Keeper) RecommendedEpochNumToCollectPayment(ctx sdk.Context) (res uint64 k.paramstore.Get(ctx, types.KeyRecommendedEpochNumToCollectPayment, &res) return } + +func (k Keeper) SetRecommendedEpochNumToCollectPayment(ctx sdk.Context, val uint64) { + k.paramstore.Set(ctx, types.KeyRecommendedEpochNumToCollectPayment, val) +} From 2a556f479a66de54403b5b815cf82abbf7179409 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 6 Feb 2023 11:21:20 +0200 Subject: [PATCH 34/37] CNS-137: fix unit tests PR issues --- .../keeper/msg_server_relay_payment_test.go | 1 + .../keeper/unresponsive_provider_test.go | 56 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/x/pairing/keeper/msg_server_relay_payment_test.go b/x/pairing/keeper/msg_server_relay_payment_test.go index ed001ae347..e3c40b671d 100644 --- a/x/pairing/keeper/msg_server_relay_payment_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_test.go @@ -1409,6 +1409,7 @@ func payAndVerifyBalance(t *testing.T, ts *testStruct, relayPaymentMessage types // perform payment _, err := ts.servers.PairingServer.RelayPayment(ts.ctx, &relayPaymentMessage) if valid { + require.Nil(t, err) // payment is valid, provider's balance should increase mint := ts.keepers.Pairing.MintCoinsPerCU(sdk.UnwrapSDKContext(ts.ctx)) want := mint.MulInt64(int64(relayPaymentMessage.GetRelays()[0].CuSum)) // The compensation for a single query diff --git a/x/pairing/keeper/unresponsive_provider_test.go b/x/pairing/keeper/unresponsive_provider_test.go index f0534eafe6..7db4dbeaac 100644 --- a/x/pairing/keeper/unresponsive_provider_test.go +++ b/x/pairing/keeper/unresponsive_provider_test.go @@ -52,6 +52,8 @@ func TestUnresponsivenessStressTest(t *testing.T) { providersStakeEntries, err := ts.keepers.Pairing.GetPairingForClient(sdk.UnwrapSDKContext(ts.ctx), ts.spec.Name, ts.clients[clientIndex].address) providerIndex := rand.Intn(len(providersStakeEntries)) providerAddress := providersStakeEntries[providerIndex].Address + providerSdkAddress, err := sdk.AccAddressFromBech32(providerAddress) + require.Nil(t, err) // create relay request relayRequest := &types.RelayRequest{ @@ -73,10 +75,8 @@ func TestUnresponsivenessStressTest(t *testing.T) { require.Nil(t, err) Relays = append(Relays, relayRequest) - // send the relay requests (provider gets payment) - _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: providerAddress, Relays: Relays}) - require.Nil(t, err) - + // send relay payment and check the funds did transfer normally + payAndVerifyBalance(t, ts, types.MsgRelayPayment{Creator: providerAddress, Relays: Relays}, true, ts.clients[clientIndex].address, providerSdkAddress) } // advance enough epochs so the unresponsive providers will be punished @@ -96,11 +96,20 @@ func TestUnresponsivenessStressTest(t *testing.T) { require.False(t, stakeStorageFound) // validate the complainers CU field in the unresponsive provider's providerPaymentStorage has been reset after being punished (note we use the epoch from the relay because that is when it got reported) - providerPaymentStorageKey := ts.keepers.Pairing.GetProviderPaymentStorageKey(sdk.UnwrapSDKContext(ts.ctx), ts.spec.Name, uint64(relayEpoch), ts.providers[1].address) + providerPaymentStorageKey := ts.keepers.Pairing.GetProviderPaymentStorageKey(sdk.UnwrapSDKContext(ts.ctx), ts.spec.Name, uint64(relayEpoch), ts.providers[i].address) providerPaymentStorage, found := ts.keepers.Pairing.GetProviderPaymentStorage(sdk.UnwrapSDKContext(ts.ctx), providerPaymentStorageKey) require.Equal(t, true, found) require.Equal(t, uint64(0), providerPaymentStorage.GetComplainersTotalCu()) } + + // go over responsive providers - make sure they are still staked + for i := unresponsiveProviderAmount; i < testProviderAmount; i++ { + // test the providers hasn't been unstaked + _, unstakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[i].address) + require.False(t, unstakeStoragefound) + _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[i].address) + require.True(t, stakeStorageFound) + } } // Test to measure the time the check for unresponsiveness every epoch start takes @@ -133,9 +142,9 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { require.Nil(t, err) // create relay requests for provider0 that contain complaints about provider1 - var Relays []*types.RelayRequest relayEpoch := sdk.UnwrapSDKContext(ts.ctx).BlockHeight() for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints + var Relays []*types.RelayRequest relayRequest := &types.RelayRequest{ Provider: ts.providers[0].address.String(), ApiUrl: "", @@ -154,11 +163,10 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { relayRequest.Sig = sig require.Nil(t, err) Relays = append(Relays, relayRequest) - } - // send the relay requests (provider gets payment) - _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) - require.Nil(t, err) + // send relay payment and check the funds did transfer normally + payAndVerifyBalance(t, ts, types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}, true, ts.clients[clientIndex].address, ts.providers[0].address) + } // advance enough epochs so the unresponsive provider will be punished if largerConst < recommendedEpochNumToCollectPayment { @@ -168,7 +176,7 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } - // test the provider has been unstaked + // test the unresponsive provider1 has been unstaked _, unstakeStoragefound, _ := ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[1].address) require.True(t, unstakeStoragefound) _, stakeStorageFound, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) @@ -180,6 +188,12 @@ func TestUnstakingProviderForUnresponsiveness(t *testing.T) { require.Equal(t, true, found) require.Equal(t, uint64(0), providerPaymentStorage.GetComplainersTotalCu()) + // test the responsive provider0 hasn't been unstaked + _, unstakeStoragefound, _ = ts.keepers.Epochstorage.UnstakeEntryByAddress(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.providers[0].address) + require.False(t, unstakeStoragefound) + _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[0].address) + require.True(t, stakeStorageFound) + // advance enough epochs so the current block will be deleted (advance more than the chain's memory - blocksToSave) OriginalBlockHeight := uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) blocksToSave, err := ts.keepers.Epochstorage.BlocksToSave(sdk.UnwrapSDKContext(ts.ctx), OriginalBlockHeight) @@ -230,10 +244,9 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * require.Nil(t, err) // create relay requests for provider0 that contain complaints about provider1 - var Relays []*types.RelayRequest relayEpoch := sdk.UnwrapSDKContext(ts.ctx).BlockHeight() for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints - + var Relays []*types.RelayRequest relayRequest := &types.RelayRequest{ Provider: ts.providers[0].address.String(), ApiUrl: "", @@ -252,11 +265,10 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * relayRequest.Sig = sig require.Nil(t, err) Relays = append(Relays, relayRequest) - } - // send the relay requests (provider gets payment) - _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) - require.Nil(t, err) + // send relay payment and check the funds did transfer normally + payAndVerifyBalance(t, ts, types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}, true, ts.clients[clientIndex].address, ts.providers[0].address) + } // advance enough epochs so the unresponsive provider will be punished if largerConst < recommendedEpochNumToCollectPayment { @@ -284,9 +296,8 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * } // create more relay requests for provider0 that contain complaints about provider1 (note, sessionID changed) - var RelaysAfter []*types.RelayRequest for clientIndex := 0; clientIndex < testClientAmount; clientIndex++ { // testing testClientAmount of complaints - + var RelaysAfter []*types.RelayRequest relayRequest := &types.RelayRequest{ Provider: ts.providers[0].address.String(), ApiUrl: "", @@ -304,11 +315,10 @@ func TestUnstakingProviderForUnresponsivenessContinueComplainingAfterUnstake(t * relayRequest.Sig = sig require.Nil(t, err) RelaysAfter = append(RelaysAfter, relayRequest) - } - // send the relay requests (provider gets payment) - _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: RelaysAfter}) - require.Nil(t, err) + // send relay payment and check the funds did transfer normally + payAndVerifyBalance(t, ts, types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: RelaysAfter}, true, ts.clients[clientIndex].address, ts.providers[0].address) + } // test the provider is still unstaked _, stakeStorageFound, _ = ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ProviderKey, ts.spec.Name, ts.providers[1].address) From eae380f594d2ff1a8cb3054337aa7862721ad301 Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 6 Feb 2023 11:24:34 +0200 Subject: [PATCH 35/37] CNS-137: changed upgrade tag to v0.5.2 to avoid conflicts --- app/app.go | 4 ++-- app/upgrades/{v0_5_1 => v0_5_2}/upgrade.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename app/upgrades/{v0_5_1 => v0_5_2}/upgrade.go (97%) diff --git a/app/app.go b/app/app.go index 4245a728e4..d32e9d704b 100644 --- a/app/app.go +++ b/app/app.go @@ -87,7 +87,7 @@ import ( "github.com/lavanet/lava/app/keepers" "github.com/lavanet/lava/app/upgrades" "github.com/lavanet/lava/app/upgrades/v0_5_0" - "github.com/lavanet/lava/app/upgrades/v0_5_1" + "github.com/lavanet/lava/app/upgrades/v0_5_2" "github.com/lavanet/lava/docs" conflictmodule "github.com/lavanet/lava/x/conflict" conflictmodulekeeper "github.com/lavanet/lava/x/conflict/keeper" @@ -117,7 +117,7 @@ const ( ) // Upgrades add here future upgrades (upgrades.Upgrade) -var Upgrades = []upgrades.Upgrade{upgrades.Upgrade_0_4_0, upgrades.Upgrade_0_4_3, upgrades.Upgrade_0_4_4, upgrades.Upgrade_0_4_5, v0_5_0.Upgrade, v0_5_1.Upgrade} +var Upgrades = []upgrades.Upgrade{upgrades.Upgrade_0_4_0, upgrades.Upgrade_0_4_3, upgrades.Upgrade_0_4_4, upgrades.Upgrade_0_4_5, v0_5_0.Upgrade, v0_5_2.Upgrade} // this line is used by starport scaffolding # stargate/wasm/app/enabledProposals diff --git a/app/upgrades/v0_5_1/upgrade.go b/app/upgrades/v0_5_2/upgrade.go similarity index 97% rename from app/upgrades/v0_5_1/upgrade.go rename to app/upgrades/v0_5_2/upgrade.go index 8eb6a998bb..4906d1d8e7 100644 --- a/app/upgrades/v0_5_1/upgrade.go +++ b/app/upgrades/v0_5_2/upgrade.go @@ -1,4 +1,4 @@ -package v0_5_1 +package v0_5_2 import ( "log" @@ -12,7 +12,7 @@ import ( pairingtypes "github.com/lavanet/lava/x/pairing/types" ) -const UpgradeName = "v0.5.1" +const UpgradeName = "v0.5.2" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, // upgrade name defined few lines above From 42d71b14d8e43b3a2b18c82976cb34bf1700609d Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 6 Feb 2023 11:35:47 +0200 Subject: [PATCH 36/37] CNS-137: fix lint issues --- x/pairing/keeper/epoch_payments_test.go | 1 + x/pairing/keeper/fixation_test.go | 23 +++++----- .../msg_server_relay_payment_gov_test.go | 24 ----------- .../keeper/msg_server_relay_payment_test.go | 42 ++++++------------- .../keeper/msg_server_stake_client_test.go | 15 +++---- .../keeper/msg_server_stake_provider_test.go | 5 +-- .../msg_server_stake_unstake_gov_test.go | 10 ----- x/pairing/keeper/msg_server_test.go | 2 +- .../keeper/msg_server_unstake_client_test.go | 7 ++-- x/pairing/keeper/pairing_test.go | 11 ++--- .../keeper/provider_payment_storage_test.go | 1 + ...ue_payment_storage_client_provider_test.go | 1 + x/pairing/types/relay_test.go | 3 +- 13 files changed, 43 insertions(+), 102 deletions(-) diff --git a/x/pairing/keeper/epoch_payments_test.go b/x/pairing/keeper/epoch_payments_test.go index 1d4b4854fc..a20b5f29e6 100644 --- a/x/pairing/keeper/epoch_payments_test.go +++ b/x/pairing/keeper/epoch_payments_test.go @@ -39,6 +39,7 @@ func TestEpochPaymentsGet(t *testing.T) { ) } } + func TestEpochPaymentsRemove(t *testing.T) { keeper, ctx := keepertest.PairingKeeper(t) items := createNEpochPayments(keeper, ctx, 10) diff --git a/x/pairing/keeper/fixation_test.go b/x/pairing/keeper/fixation_test.go index 5cf52a264d..9ce379773f 100644 --- a/x/pairing/keeper/fixation_test.go +++ b/x/pairing/keeper/fixation_test.go @@ -26,10 +26,10 @@ func TestServicersToPair(t *testing.T) { tests := []struct { name string - Block uint64 //advance test to this block - ServicersToPair uint64 //set this if not zero at the start of the test + Block uint64 // advance test to this block + ServicersToPair uint64 // set this if not zero at the start of the test ExpectedServicersToPair uint64 - NumOfFixation int //expected number of fixations in the memory + NumOfFixation int // expected number of fixations in the memory }{ {"FillHalfMemory", blocksInMemory / 2, 0, servicersToParCount, 1}, {"ParamChange", blocksInMemory / 2, 2 * servicersToParCount, servicersToParCount, 1}, @@ -84,14 +84,12 @@ func TestServicersToPair(t *testing.T) { Block uint64 ExpectedServicersToPair uint64 }{Block: tt.Block, ExpectedServicersToPair: tt.ExpectedServicersToPair}) - }) } } func TestEpochPaymentDeletionWithMemoryShortening(t *testing.T) { - - ts := setupForPaymentTest(t) //reset the keepers state before each state + ts := setupForPaymentTest(t) // reset the keepers state before each state ts.spec = common.CreateMockSpec() ts.keepers.Spec.SetSpec(sdk.UnwrapSDKContext(ts.ctx), ts.spec) err := ts.addClient(1) @@ -120,18 +118,18 @@ func TestEpochPaymentDeletionWithMemoryShortening(t *testing.T) { relayRequest.Sig = sig require.Nil(t, err) - //make payment request + // make payment request _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &pairingtypes.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: []*pairingtypes.RelayRequest{relayRequest}}) require.Nil(t, err) - //shorten memory + // shorten memory err = testkeeper.SimulateParamChange(sdk.UnwrapSDKContext(ts.ctx), ts.keepers.ParamsKeeper, epochstoragetypes.ModuleName, string(epochstoragetypes.KeyEpochsToSave), "\""+strconv.FormatUint(epochsToSave/2, 10)+"\"") require.NoError(t, err) - //advance epoch + // advance epoch ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) - //make another request + // make another request relayRequest.SessionId++ sig, err = sigs.SignRelay(ts.clients[0].secretKey, *relayRequest) @@ -141,14 +139,13 @@ func TestEpochPaymentDeletionWithMemoryShortening(t *testing.T) { _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &pairingtypes.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: []*pairingtypes.RelayRequest{relayRequest}}) require.Nil(t, err) - //check that both payments were deleted + // check that both payments were deleted for i := 0; i < int(epochsToSave); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } - //check second payment was deleted + // check second payment was deleted ans, err := ts.keepers.Pairing.EpochPaymentsAll(ts.ctx, &pairingtypes.QueryAllEpochPaymentsRequest{}) require.Nil(t, err) require.Equal(t, 0, len(ans.EpochPayments)) - } 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 d8af13596c..16be3cecb0 100644 --- a/x/pairing/keeper/msg_server_relay_payment_gov_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_gov_test.go @@ -15,7 +15,6 @@ import ( // Test that if the QosWeight param changes before the provider collected its reward, the provider's payment is according to the last QosWeight value (QosWeight is not fixated) // Provider reward formula: reward = reward*(QOSScore*QOSWeight + (1-QOSWeight)) func TestRelayPaymentGovQosWeightChange(t *testing.T) { - // setup testnet with mock spec, a staked client and a staked provider ts := setupForPaymentTest(t) @@ -64,7 +63,6 @@ func TestRelayPaymentGovQosWeightChange(t *testing.T) { for ti, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create relay request that was done in the test's epoch. Change session ID each iteration to avoid double spending error (provider asks reward for the same transaction twice) relayRequest := &pairingtypes.RelayRequest{ Provider: ts.providers[0].address.String(), @@ -123,7 +121,6 @@ func TestRelayPaymentGovQosWeightChange(t *testing.T) { // Test that if the EpochBlocks param decreases make sure the provider can claim reward after the new EpochBlocks*EpochsToSave, and not the original EpochBlocks (EpochBlocks = number of blocks in an epoch) func TestRelayPaymentGovEpochBlocksDecrease(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -171,7 +168,6 @@ func TestRelayPaymentGovEpochBlocksDecrease(t *testing.T) { for ti, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create relay request that was done in the test's epoch. Change session ID each iteration to avoid double spending error (provider asks reward for the same transaction twice) relayRequest := &pairingtypes.RelayRequest{ Provider: ts.providers[0].address.String(), @@ -198,13 +194,11 @@ func TestRelayPaymentGovEpochBlocksDecrease(t *testing.T) { payAndVerifyBalance(t, ts, relayPaymentMessage, tt.valid, ts.clients[0].address, ts.providers[0].address) }) } - } // TODO: Currently the test passes since PaymentBeforeEpochBlocksChangesToFifty's value is false. It should be true. After bug CNS-83 is fixed, change this test // Test that if the EpochBlocks param increases make sure the provider can claim reward after the new EpochBlocks*EpochsToSave, and not the original EpochBlocks (EpochBlocks = number of blocks in an epoch) func TestRelayPaymentGovEpochBlocksIncrease(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -256,7 +250,6 @@ func TestRelayPaymentGovEpochBlocksIncrease(t *testing.T) { for ti, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create relay request that was done in the test's epoch+block. Change session ID each iteration to avoid double spending error (provider asks reward for the same transaction twice) relayRequest := &pairingtypes.RelayRequest{ Provider: ts.providers[0].address.String(), @@ -283,12 +276,10 @@ func TestRelayPaymentGovEpochBlocksIncrease(t *testing.T) { payAndVerifyBalance(t, ts, relayPaymentMessage, tt.valid, ts.clients[0].address, ts.providers[0].address) }) } - } // Test that if the EpochToSave param decreases make sure the provider can claim reward after the new EpochBlocks*EpochsToSave, and not the original EpochBlocks (EpochsToSave = number of epochs the chain remembers (accessible memory)) func TestRelayPaymentGovEpochToSaveDecrease(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -341,7 +332,6 @@ func TestRelayPaymentGovEpochToSaveDecrease(t *testing.T) { for ti, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // advance to one block to reach the start of the newDecreasedEpochsToSave+1 epoch -> the provider from epochAfterChange shouldn't be able to get its payments (epoch out of memory) if ti == 2 { ts.ctx = testkeeper.AdvanceBlock(ts.ctx, ts.keepers) @@ -373,13 +363,11 @@ func TestRelayPaymentGovEpochToSaveDecrease(t *testing.T) { payAndVerifyBalance(t, ts, relayPaymentMessage, tt.valid, ts.clients[0].address, ts.providers[0].address) }) } - } // TODO: Currently the test passes since PaymentBeforeEpochsToSaveChangesToTwenty's value is false. It should be true. After bug CNS-83 is fixed, change this test // Test that if the EpochToSave param increases make sure the provider can claim reward after the new EpochBlocks*EpochsToSave, and not the original EpochBlocks (EpochsToSave = number of epochs the chain remembers (accessible memory)) func TestRelayPaymentGovEpochToSaveIncrease(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -425,7 +413,6 @@ func TestRelayPaymentGovEpochToSaveIncrease(t *testing.T) { for ti, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create relay request that was done in the test's epoch+block. Change session ID each iteration to avoid double spending error (provider asks reward for the same transaction twice) relayRequest := &pairingtypes.RelayRequest{ Provider: ts.providers[0].address.String(), @@ -452,12 +439,10 @@ func TestRelayPaymentGovEpochToSaveIncrease(t *testing.T) { payAndVerifyBalance(t, ts, relayPaymentMessage, tt.valid, ts.clients[0].address, ts.providers[0].address) }) } - } // Test that if the StakeToMaxCU.MaxCU param decreases make sure the client can send queries according to the original StakeToMaxCUList in the current epoch (This parameter is fixated) func TestRelayPaymentGovStakeToMaxCUListMaxCUDecrease(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -548,12 +533,10 @@ func TestRelayPaymentGovStakeToMaxCUListMaxCUDecrease(t *testing.T) { payAndVerifyBalance(t, ts, relayPaymentMessage, tt.valid, ts.clients[0].address, ts.providers[0].address) }) } - } // Test that if the StakeToMaxCU.StakeThreshold param increases make sure the client can send queries according to the original StakeToMaxCUList in the current epoch (This parameter is fixated) func TestRelayPaymentGovStakeToMaxCUListStakeThresholdIncrease(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -644,7 +627,6 @@ func TestRelayPaymentGovStakeToMaxCUListStakeThresholdIncrease(t *testing.T) { payAndVerifyBalance(t, ts, relayPaymentMessage, tt.valid, ts.clients[0].address, ts.providers[0].address) }) } - } func TestRelayPaymentGovEpochBlocksMultipleChanges(t *testing.T) { @@ -699,7 +681,6 @@ func TestRelayPaymentGovEpochBlocksMultipleChanges(t *testing.T) { for ti, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // change the EpochBlocks parameter according to the epoch test values epochBlocksNew := uint64(epochTests[ti].epochBlocksNewValues) err = testkeeper.SimulateParamChange(sdk.UnwrapSDKContext(ts.ctx), ts.keepers.ParamsKeeper, epochstoragetypes.ModuleName, string(epochstoragetypes.KeyEpochBlocks), "\""+strconv.FormatUint(epochBlocksNew, 10)+"\"") @@ -741,11 +722,9 @@ func TestRelayPaymentGovEpochBlocksMultipleChanges(t *testing.T) { payAndVerifyBalance(t, ts, relayPaymentMessage, tt.valid, ts.clients[0].address, ts.providers[0].address) }) } - } func TestRelayPaymentGovStakeToMaxCUListStakeThresholdMultipleChanges(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -827,7 +806,6 @@ func TestRelayPaymentGovStakeToMaxCUListStakeThresholdMultipleChanges(t *testing // this test checks what happens if a single provider stake, get payment, and then unstake and gets its money. func TestStakePaymentUnstake(t *testing.T) { - // setup testnet with mock spec, stake a client and a provider ts := setupForPaymentTest(t) @@ -888,7 +866,6 @@ func TestStakePaymentUnstake(t *testing.T) { // TODO: Currently the test passes since second call to verifyRelayPaymentObjects is called with true (see TODO comment right next to it). It should be false. After bug CNS-83 is fixed, change this test // Test that the payment object is deleted in the end of the memory and can't be used to double spend all while making gov changes func TestRelayPaymentMemoryTransferAfterEpochChangeWithGovParamChange(t *testing.T) { - tests := []struct { name string // Test name decreaseEpochBlocks bool // flag to indicate if EpochBlocks is decreased or not @@ -975,7 +952,6 @@ func TestRelayPaymentMemoryTransferAfterEpochChangeWithGovParamChange(t *testing // Helper function to verify the relay payment objects that are saved on-chain after getting payment from a relay request func verifyRelayPaymentObjects(t *testing.T, ts *testStruct, relayRequest *pairingtypes.RelayRequest, objectExists bool) { - // Get EpochPayment struct from current epoch and perform basic verifications epochPayments, found, epochPaymentKey := ts.keepers.Pairing.GetEpochPaymentsFromBlock(sdk.UnwrapSDKContext(ts.ctx), uint64(relayRequest.GetBlockHeight())) if objectExists { diff --git a/x/pairing/keeper/msg_server_relay_payment_test.go b/x/pairing/keeper/msg_server_relay_payment_test.go index e3c40b671d..e18a85c192 100644 --- a/x/pairing/keeper/msg_server_relay_payment_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_test.go @@ -87,7 +87,6 @@ func (ts *testStruct) getProvider(addr string) *account { // Test that a provider payment is valid if he asked it within the chain's memory, and check the relay payment object (RPO) func TestRelayPaymentMemoryTransferAfterEpochChange(t *testing.T) { - // setup testnet with mock spec, a staked client and a staked provider ts := setupForPaymentTest(t) @@ -122,7 +121,6 @@ func TestRelayPaymentMemoryTransferAfterEpochChange(t *testing.T) { for _, tt := range tests { sessionCounter += 1 t.Run(tt.name, func(t *testing.T) { - // Advance epochs according to the epochsToAdvance if tt.epochsToAdvance != 0 { for i := 0; i < int(tt.epochsToAdvance); i++ { @@ -164,10 +162,8 @@ func TestRelayPaymentMemoryTransferAfterEpochChange(t *testing.T) { // Check the RPO exists (shouldn't exist after epochsToSave+1 passes) verifyRelayPaymentObjects(t, ts, relayRequest, tt.valid) - }) } - } func setupForPaymentTest(t *testing.T) *testStruct { @@ -189,7 +185,6 @@ func setupForPaymentTest(t *testing.T) *testStruct { } func TestRelayPaymentBlockHeight(t *testing.T) { - tests := []struct { name string blockTime int64 @@ -202,8 +197,7 @@ func TestRelayPaymentBlockHeight(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - ts := setupForPaymentTest(t) //reset the keepers state before each state + ts := setupForPaymentTest(t) // reset the keepers state before each state ts.spec = common.CreateMockSpec() ts.keepers.Spec.SetSpec(sdk.UnwrapSDKContext(ts.ctx), ts.spec) err := ts.addClient(1) @@ -255,7 +249,6 @@ func TestRelayPaymentBlockHeight(t *testing.T) { } else { require.NotNil(t, err) } - }) } } @@ -534,7 +527,6 @@ func TestRelayPaymentDoubleSpending(t *testing.T) { burn := ts.keepers.Pairing.BurnCoinsPerCU(sdk.UnwrapSDKContext(ts.ctx)).MulInt64(int64(cuSum)) newStakeClient, _, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ClientKey, ts.spec.Index, ts.clients[0].address) require.Equal(t, stakeClient.Stake.Amount.Int64()-burn.TruncateInt64(), newStakeClient.Stake.Amount.Int64()) - } func TestRelayPaymentDataModification(t *testing.T) { @@ -578,7 +570,6 @@ func TestRelayPaymentDataModification(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - relayRequest.Provider = tt.provider relayRequest.CuSum = tt.cu relayRequest.SessionId = uint64(tt.id) @@ -637,13 +628,12 @@ func TestRelayPaymentDelayedDoubleSpending(t *testing.T) { }{ {"Epoch", 1}, {"Memory-Epoch", epochToSave - 1}, - {"Memory", 1}, //epochToSave - {"Memory+Epoch", 1}, //epochToSave + 1 + {"Memory", 1}, // epochToSave + {"Memory+Epoch", 1}, // epochToSave + 1 } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - for i := 0; i < int(tt.advance); i++ { ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) } @@ -654,7 +644,6 @@ func TestRelayPaymentDelayedDoubleSpending(t *testing.T) { _, err = ts.servers.PairingServer.RelayPayment(ts.ctx, &types.MsgRelayPayment{Creator: ts.providers[0].address.String(), Relays: Relays}) require.NotNil(t, err) - }) } } @@ -685,10 +674,10 @@ func TestRelayPaymentOldEpochs(t *testing.T) { epoch int64 valid bool }{ - {"Epoch", 1, 1, true}, //current -1*epoch - {"Memory-Epoch", 2, int64(epochsToSave - 1), true}, //current -epoch to save + 1 - {"Memory", 3, int64(epochsToSave), true}, //current - epochToSave - {"Memory+Epoch", 4, int64(epochsToSave + 1), false}, //current - epochToSave - 1 + {"Epoch", 1, 1, true}, // current -1*epoch + {"Memory-Epoch", 2, int64(epochsToSave - 1), true}, // current -epoch to save + 1 + {"Memory", 3, int64(epochsToSave), true}, // current - epochToSave + {"Memory+Epoch", 4, int64(epochsToSave + 1), false}, // current - epochToSave - 1 } for _, tt := range tests { @@ -731,7 +720,6 @@ func TestRelayPaymentOldEpochs(t *testing.T) { } else { require.NotNil(t, err) } - }) } } @@ -812,7 +800,6 @@ func TestRelayPaymentQoS(t *testing.T) { } else { require.NotNil(t, err) } - }) } } @@ -846,7 +833,7 @@ func TestRelayPaymentDataReliability(t *testing.T) { params := ts.keepers.Pairing.GetParams(sdk.UnwrapSDKContext(ts.ctx)) params.ServicersToPairCount = 100 ts.keepers.Pairing.SetParams(sdk.UnwrapSDKContext(ts.ctx), params) - ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) //we need that in order for the param set to take effect + ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) // we need that in order for the param set to take effect err := ts.addClient(1) require.Nil(t, err) err = ts.addProvider(100) @@ -990,7 +977,7 @@ func TestRelayPaymentDataReliabilityWrongProvider(t *testing.T) { params := ts.keepers.Pairing.GetParams(sdk.UnwrapSDKContext(ts.ctx)) params.ServicersToPairCount = 100 ts.keepers.Pairing.SetParams(sdk.UnwrapSDKContext(ts.ctx), params) - ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) //we need that in order for the param set to take effect + ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) // we need that in order for the param set to take effect err := ts.addClient(1) require.Nil(t, err) err = ts.addProvider(100) @@ -1108,7 +1095,7 @@ func TestRelayPaymentDataReliabilityBelowReliabilityThreshold(t *testing.T) { params := ts.keepers.Pairing.GetParams(sdk.UnwrapSDKContext(ts.ctx)) params.ServicersToPairCount = 5 ts.keepers.Pairing.SetParams(sdk.UnwrapSDKContext(ts.ctx), params) - ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) //we need that in order for the param set to take effect + ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) // we need that in order for the param set to take effect err := ts.addClient(1) require.Nil(t, err) err = ts.addProvider(5) @@ -1199,7 +1186,7 @@ func TestRelayPaymentDataReliabilityDifferentClientSign(t *testing.T) { params := ts.keepers.Pairing.GetParams(sdk.UnwrapSDKContext(ts.ctx)) params.ServicersToPairCount = 100 ts.keepers.Pairing.SetParams(sdk.UnwrapSDKContext(ts.ctx), params) - ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) //we need that in order for the param set to take effect + ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) // we need that in order for the param set to take effect err := ts.addClient(2) require.Nil(t, err) err = ts.addProvider(100) @@ -1297,7 +1284,7 @@ func TestRelayPaymentDataReliabilityDoubleSpendDifferentEpoch(t *testing.T) { params := ts.keepers.Pairing.GetParams(sdk.UnwrapSDKContext(ts.ctx)) params.ServicersToPairCount = 100 ts.keepers.Pairing.SetParams(sdk.UnwrapSDKContext(ts.ctx), params) - ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) //we need that in order for the param set to take effect + ts.keepers.Epochstorage.PushFixatedParams(sdk.UnwrapSDKContext(ts.ctx), 0, 0) // we need that in order for the param set to take effect err := ts.addClient(1) require.Nil(t, err) err = ts.addProvider(100) @@ -1401,7 +1388,6 @@ func TestRelayPaymentDataReliabilityDoubleSpendDifferentEpoch(t *testing.T) { // Helper function to perform payment and verify the balances (if valid, provider's balance should increase and consumer should decrease) func payAndVerifyBalance(t *testing.T, ts *testStruct, relayPaymentMessage types.MsgRelayPayment, valid bool, clientAddress sdk.AccAddress, providerAddress sdk.AccAddress) { - // Get provider's and consumer's before payment balance := ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), providerAddress, epochstoragetypes.TokenDenom).Amount.Int64() stakeClient, _, _ := ts.keepers.Epochstorage.GetStakeEntryByAddressCurrent(sdk.UnwrapSDKContext(ts.ctx), epochstoragetypes.ClientKey, ts.spec.Index, clientAddress) @@ -1428,8 +1414,7 @@ func payAndVerifyBalance(t *testing.T, ts *testStruct, relayPaymentMessage types } func TestEpochPaymentDeletion(t *testing.T) { - - ts := setupForPaymentTest(t) //reset the keepers state before each state + ts := setupForPaymentTest(t) // reset the keepers state before each state ts.spec = common.CreateMockSpec() ts.keepers.Spec.SetSpec(sdk.UnwrapSDKContext(ts.ctx), ts.spec) err := ts.addClient(1) @@ -1488,5 +1473,4 @@ func TestEpochPaymentDeletion(t *testing.T) { ans, err := ts.keepers.Pairing.EpochPaymentsAll(ts.ctx, &types.QueryAllEpochPaymentsRequest{}) require.Nil(t, err) require.Equal(t, 0, len(ans.EpochPayments)) - } diff --git a/x/pairing/keeper/msg_server_stake_client_test.go b/x/pairing/keeper/msg_server_stake_client_test.go index 4b7d37d853..b69285bc66 100644 --- a/x/pairing/keeper/msg_server_stake_client_test.go +++ b/x/pairing/keeper/msg_server_stake_client_test.go @@ -16,7 +16,7 @@ import ( func TestNewStakeClient(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state _, clientAddr := sigs.GenerateFloatingKey() var amount int64 = 1000 keepers.BankKeeper.SetBalance(sdk.UnwrapSDKContext(ctx), clientAddr, sdk.NewCoins(sdk.NewCoin(epochstoragetypes.TokenDenom, sdk.NewInt(amount)))) @@ -39,7 +39,6 @@ func TestNewStakeClient(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err := servers.PairingServer.StakeClient(ctx, &types.MsgStakeClient{Creator: clientAddr.String(), ChainID: spec.Name, Amount: tt.stake, Geolocation: 1, Vrfpk: vrfPk.String()}) ctx = testkeeper.AdvanceEpoch(ctx, keepers) @@ -60,7 +59,7 @@ func TestNewStakeClient(t *testing.T) { func TestAddStakeClient(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state _, clientAddr := sigs.GenerateFloatingKey() var amount int64 = 1000 keepers.BankKeeper.SetBalance(sdk.UnwrapSDKContext(ctx), clientAddr, sdk.NewCoins(sdk.NewCoin(epochstoragetypes.TokenDenom, sdk.NewInt(amount)))) @@ -103,13 +102,12 @@ func TestAddStakeClient(t *testing.T) { } }) } - } func TestStakeClientPairingimmediately(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state var balance int64 = 10000 consumer := common.CreateNewAccount(ctx, *keepers, balance) provider1 := common.CreateNewAccount(ctx, *keepers, balance) @@ -128,7 +126,7 @@ func TestStakeClientPairingimmediately(t *testing.T) { ctx = testkeeper.AdvanceBlock(ctx, keepers) - //check pairing in the same epoch + // check pairing in the same epoch clientStakeEntry, err := keepers.Pairing.VerifyPairingData(sdk.UnwrapSDKContext(ctx), spec.Index, consumer.Addr, uint64(sdk.UnwrapSDKContext(ctx).BlockHeight())) require.Nil(t, err) require.Equal(t, clientStakeEntry.Stake.Amount, sdk.NewInt(stake)) @@ -136,17 +134,16 @@ func TestStakeClientPairingimmediately(t *testing.T) { _, err = keepers.Pairing.GetPairingForClient(sdk.UnwrapSDKContext(ctx), spec.Index, consumer.Addr) require.Nil(t, err) - //try to change stake + // try to change stake common.StakeAccount(t, ctx, *keepers, *servers, consumer, spec, 2*stake, false) clientStakeEntry, err = keepers.Pairing.VerifyPairingData(sdk.UnwrapSDKContext(ctx), spec.Index, consumer.Addr, uint64(sdk.UnwrapSDKContext(ctx).BlockHeight())) require.Nil(t, err) require.Equal(t, clientStakeEntry.Stake.Amount, sdk.NewInt(stake)) - //new stake takes effect + // new stake takes effect ctx = testkeeper.AdvanceEpoch(ctx, keepers) clientStakeEntry, err = keepers.Pairing.VerifyPairingData(sdk.UnwrapSDKContext(ctx), spec.Index, consumer.Addr, uint64(sdk.UnwrapSDKContext(ctx).BlockHeight())) require.Nil(t, err) require.Equal(t, clientStakeEntry.Stake.Amount, sdk.NewInt(2*stake)) - } diff --git a/x/pairing/keeper/msg_server_stake_provider_test.go b/x/pairing/keeper/msg_server_stake_provider_test.go index c2161b9ea4..f10d139f8d 100644 --- a/x/pairing/keeper/msg_server_stake_provider_test.go +++ b/x/pairing/keeper/msg_server_stake_provider_test.go @@ -39,7 +39,6 @@ func TestStakeProviderWithMoniker(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Advance epoch ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) @@ -66,10 +65,8 @@ func TestStakeProviderWithMoniker(t *testing.T) { } else { require.NotEqual(t, tt.moniker, stakeEntry.Moniker) } - }) } - } func TestModifyStakeProviderWithMoniker(t *testing.T) { @@ -107,7 +104,7 @@ func TestModifyStakeProviderWithMoniker(t *testing.T) { require.True(t, foundProvider) require.Equal(t, moniker, stakeEntry.Moniker) - //modify moniker + // modify moniker moniker = "anotherExampleMoniker" _, err = ts.servers.PairingServer.StakeProvider(ts.ctx, &types.MsgStakeProvider{Creator: address.String(), ChainID: ts.spec.Name, Amount: sdk.NewCoin(epochstoragetypes.TokenDenom, sdk.NewInt(stake)), Geolocation: 1, Endpoints: endpoints, Moniker: moniker}) require.Nil(t, err) diff --git a/x/pairing/keeper/msg_server_stake_unstake_gov_test.go b/x/pairing/keeper/msg_server_stake_unstake_gov_test.go index 292189bffb..31643cb302 100644 --- a/x/pairing/keeper/msg_server_stake_unstake_gov_test.go +++ b/x/pairing/keeper/msg_server_stake_unstake_gov_test.go @@ -14,7 +14,6 @@ import ( // Test that if the EpochBlocks param decreases make sure the provider/client is staked only after the original EpochBlocks value (EpochBlocks = number of blocks in an epoch. This parameter is fixated) func TestStakeGovEpochBlocksDecrease(t *testing.T) { - // Create teststruct ts ts := &testStruct{ providers: make([]*account, 0), @@ -84,7 +83,6 @@ func TestStakeGovEpochBlocksDecrease(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // check if the provider/client are staked _, foundProvider, _ := ts.keepers.Epochstorage.GetEpochStakeEntries(sdk.UnwrapSDKContext(ts.ctx), tt.epoch, epochstoragetypes.ProviderKey, ts.spec.GetIndex()) require.Equal(t, tt.shouldBeStaked, foundProvider) @@ -92,12 +90,10 @@ func TestStakeGovEpochBlocksDecrease(t *testing.T) { require.Equal(t, tt.shouldBeStaked, foundClient) }) } - } // Test that if the EpochBlocks param increases make sure the provider/client is staked after the original EpochBlocks value, and not the new enlarged one (EpochBlocks = number of blocks in an epoch. This parameter is fixated) func TestStakeGovEpochBlocksIncrease(t *testing.T) { - // Create teststruct ts ts := &testStruct{ providers: make([]*account, 0), @@ -171,7 +167,6 @@ func TestStakeGovEpochBlocksIncrease(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // check if the provider/client are staked _, found, _ := ts.keepers.Epochstorage.GetEpochStakeEntries(sdk.UnwrapSDKContext(ts.ctx), tt.epoch, epochstoragetypes.ProviderKey, ts.spec.GetIndex()) require.Equal(t, tt.shouldBeStaked, found) @@ -179,12 +174,10 @@ func TestStakeGovEpochBlocksIncrease(t *testing.T) { require.Equal(t, tt.shouldBeStaked, found) }) } - } // Test that if the UnstakeHoldBlocks param decreases make sure the provider/client is getting their funds back only by the original UnstakeHoldBlocks value (return_funds_block = next_epoch(current_block + max(UnstakeHoldBlocks, BlocksToSave))) func TestUnstakeGovUnstakeHoldBlocksDecrease(t *testing.T) { - // Create teststruct ts ts := &testStruct{ providers: make([]*account, 0), @@ -263,12 +256,10 @@ func TestUnstakeGovUnstakeHoldBlocksDecrease(t *testing.T) { require.Equal(t, balance, clientCurrentFunds.Amount.Int64()) providerCurrentFunds = ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), providerAddress, epochstoragetypes.TokenDenom) require.Equal(t, balance, providerCurrentFunds.Amount.Int64()) - } // Test that if the UnstakeHoldBlocks param increases make sure the provider/client is getting their funds back only by the original UnstakeHoldBlocks value (return_funds_block = next_epoch(current_block + max(UnstakeHoldBlocks, BlocksToSave))) func TestUnstakeGovUnstakeHoldBlocksIncrease(t *testing.T) { - // Create teststruct ts ts := &testStruct{ providers: make([]*account, 0), @@ -349,5 +340,4 @@ func TestUnstakeGovUnstakeHoldBlocksIncrease(t *testing.T) { require.Equal(t, balance, clientCurrentFunds.Amount.Int64()) providerCurrentFunds = ts.keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ts.ctx), providerAddress, epochstoragetypes.TokenDenom) require.Equal(t, balance, providerCurrentFunds.Amount.Int64()) - } diff --git a/x/pairing/keeper/msg_server_test.go b/x/pairing/keeper/msg_server_test.go index ef473f2be9..29a517d670 100644 --- a/x/pairing/keeper/msg_server_test.go +++ b/x/pairing/keeper/msg_server_test.go @@ -10,7 +10,7 @@ import ( "github.com/lavanet/lava/x/pairing/types" ) -//TODO: use or delete this function +// TODO: use or delete this function func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) { k, ctx := keepertest.PairingKeeper(t) return keeper.NewMsgServerImpl(*k), sdk.WrapSDKContext(ctx) diff --git a/x/pairing/keeper/msg_server_unstake_client_test.go b/x/pairing/keeper/msg_server_unstake_client_test.go index 3237d728b0..ff5542eb19 100644 --- a/x/pairing/keeper/msg_server_unstake_client_test.go +++ b/x/pairing/keeper/msg_server_unstake_client_test.go @@ -16,7 +16,7 @@ import ( func TestUnstakeClient(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state _, clientAddr := sigs.GenerateFloatingKey() var amount int64 = 1000 keepers.BankKeeper.SetBalance(sdk.UnwrapSDKContext(ctx), clientAddr, sdk.NewCoins(sdk.NewCoin(epochstoragetypes.TokenDenom, sdk.NewInt(amount)))) @@ -67,7 +67,7 @@ func TestUnstakeClient(t *testing.T) { func TestUnstakeNotStakedClient(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state _, clientAddr := sigs.GenerateFloatingKey() var amount int64 = 1000 keepers.BankKeeper.SetBalance(sdk.UnwrapSDKContext(ctx), clientAddr, sdk.NewCoins(sdk.NewCoin(epochstoragetypes.TokenDenom, sdk.NewInt(amount)))) @@ -96,7 +96,6 @@ func TestUnstakeNotStakedClient(t *testing.T) { balance := keepers.BankKeeper.GetBalance(sdk.UnwrapSDKContext(ctx), clientAddr, epochstoragetypes.TokenDenom).Amount.Int64() require.Equal(t, amount, balance) - }) } } @@ -104,7 +103,7 @@ func TestUnstakeNotStakedClient(t *testing.T) { func TestDoubleUnstakeClient(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state _, clientAddr := sigs.GenerateFloatingKey() var amount int64 = 1000 keepers.BankKeeper.SetBalance(sdk.UnwrapSDKContext(ctx), clientAddr, sdk.NewCoins(sdk.NewCoin(epochstoragetypes.TokenDenom, sdk.NewInt(amount)))) diff --git a/x/pairing/keeper/pairing_test.go b/x/pairing/keeper/pairing_test.go index b037c5d5a0..80089b3315 100644 --- a/x/pairing/keeper/pairing_test.go +++ b/x/pairing/keeper/pairing_test.go @@ -15,7 +15,7 @@ import ( func TestPairingUniqueness(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state spec := common.CreateMockSpec() keepers.Spec.SetSpec(sdk.UnwrapSDKContext(ctx), spec) @@ -79,7 +79,7 @@ func TestPairingUniqueness(t *testing.T) { } require.True(t, different) - //test that get pairing gives the same results for the whole epoch + // test that get pairing gives the same results for the whole epoch epochBlocks := keepers.Epochstorage.EpochBlocksRaw(sdk.UnwrapSDKContext(ctx)) foundIndexMap := map[string]int{} for i := uint64(0); i < epochBlocks-1; i++ { @@ -129,7 +129,6 @@ func TestGetPairing(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Advance an epoch according to the test switch tt.name { case "zeroEpoch": @@ -221,7 +220,6 @@ func TestGetPairing(t *testing.T) { // verify nextPairingBlock require.Equal(t, nextPairingBlock, pairing.BlockOfNextPairing) } - }) } } @@ -229,7 +227,7 @@ func TestGetPairing(t *testing.T) { func TestPairingStatic(t *testing.T) { servers, keepers, ctx := testkeeper.InitAllKeepers(t) - //init keepers state + // init keepers state spec := common.CreateMockSpec() spec.ProvidersTypes = spectypes.Spec_static keepers.Spec.SetSpec(sdk.UnwrapSDKContext(ctx), spec) @@ -246,7 +244,7 @@ func TestPairingStatic(t *testing.T) { common.StakeAccount(t, ctx, *keepers, *servers, provider, spec, stake+int64(i), true) } - //we expect to get all the providers in static spec + // we expect to get all the providers in static spec ctx = testkeeper.AdvanceEpoch(ctx, keepers) @@ -256,5 +254,4 @@ func TestPairingStatic(t *testing.T) { for i, provider := range providers { require.Equal(t, provider.Stake.Amount.Int64(), stake+int64(i)) } - } diff --git a/x/pairing/keeper/provider_payment_storage_test.go b/x/pairing/keeper/provider_payment_storage_test.go index b3c903f864..d8bb531410 100644 --- a/x/pairing/keeper/provider_payment_storage_test.go +++ b/x/pairing/keeper/provider_payment_storage_test.go @@ -39,6 +39,7 @@ func TestProviderPaymentStorageGet(t *testing.T) { ) } } + func TestProviderPaymentStorageRemove(t *testing.T) { keeper, ctx := keepertest.PairingKeeper(t) items := createNProviderPaymentStorage(keeper, ctx, 10) diff --git a/x/pairing/keeper/unique_payment_storage_client_provider_test.go b/x/pairing/keeper/unique_payment_storage_client_provider_test.go index a990b7eb44..7f0edbe276 100644 --- a/x/pairing/keeper/unique_payment_storage_client_provider_test.go +++ b/x/pairing/keeper/unique_payment_storage_client_provider_test.go @@ -39,6 +39,7 @@ func TestUniquePaymentStorageClientProviderGet(t *testing.T) { ) } } + func TestUniquePaymentStorageClientProviderRemove(t *testing.T) { keeper, ctx := keepertest.PairingKeeper(t) items := createNUniquePaymentStorageClientProvider(keeper, ctx, 10) diff --git a/x/pairing/types/relay_test.go b/x/pairing/types/relay_test.go index 31aa1edea2..5edc50873f 100644 --- a/x/pairing/types/relay_test.go +++ b/x/pairing/types/relay_test.go @@ -1,8 +1,9 @@ package types import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) // getDummyRequest creates dummy request used in tests From 24a3def263580e08b3c21af2f7eeb99755cd8e0e Mon Sep 17 00:00:00 2001 From: oren-lava Date: Mon, 6 Feb 2023 11:40:53 +0200 Subject: [PATCH 37/37] CNS-137: fix more lint issues --- app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index 3f122720b6..5f02207dde 100644 --- a/app/app.go +++ b/app/app.go @@ -87,8 +87,8 @@ import ( "github.com/lavanet/lava/app/keepers" "github.com/lavanet/lava/app/upgrades" "github.com/lavanet/lava/app/upgrades/v0_5_0" - "github.com/lavanet/lava/app/upgrades/v0_5_2" "github.com/lavanet/lava/app/upgrades/v0_5_1" + "github.com/lavanet/lava/app/upgrades/v0_5_2" "github.com/lavanet/lava/docs" conflictmodule "github.com/lavanet/lava/x/conflict" conflictmodulekeeper "github.com/lavanet/lava/x/conflict/keeper"