diff --git a/x/pairing/keeper/msg_server_relay_payment.go b/x/pairing/keeper/msg_server_relay_payment.go index 68bda26c36..d8126eb35e 100644 --- a/x/pairing/keeper/msg_server_relay_payment.go +++ b/x/pairing/keeper/msg_server_relay_payment.go @@ -14,6 +14,7 @@ import ( "github.com/lavanet/lava/utils/sigs" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" "github.com/lavanet/lava/x/pairing/types" + subscriptiontypes "github.com/lavanet/lava/x/subscription/types" ) type BadgeData struct { @@ -70,6 +71,7 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen var rejectedCu uint64 // aggregated rejected CU (due to badge CU overuse or provider double spending) rejected_relays_num := len(msg.Relays) + validatePairingCache := map[string][]epochstoragetypes.StakeEntry{} for relayIdx, relay := range msg.Relays { rejectedCu += relay.CuSum providerAddr, err := sdk.AccAddressFromBech32(relay.Provider) @@ -169,24 +171,44 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen ) } - isValidPairing, allowedCU, providers, err := k.Keeper.ValidatePairingForClient( - ctx, - relay.SpecId, - providerAddr, - uint64(relay.Epoch), - project, - ) - if err != nil { - return nil, utils.LavaFormatWarning("invalid pairing on proof of relay", err, - utils.Attribute{Key: "client", Value: clientAddr.String()}, - utils.Attribute{Key: "provider", Value: providerAddr.String()}, - ) - } - if !isValidPairing { - return nil, utils.LavaFormatWarning("invalid pairing on proof of relay", fmt.Errorf("pairing result doesn't include provider"), - utils.Attribute{Key: "client", Value: clientAddr.String()}, - utils.Attribute{Key: "provider", Value: providerAddr.String()}, + // generate validate pairing cache key with CuTrackerKey() to reuse code (doesn't relate to CU tracking at all) + validatePairingKey := subscriptiontypes.CuTrackerKey(clientAddr.String(), relay.Provider, relay.SpecId) + var providers []epochstoragetypes.StakeEntry + allowedCU := uint64(0) + val, ok := validatePairingCache[validatePairingKey] + if ok { + providers = val + strictestPolicy, _, err := k.GetProjectStrictestPolicy(ctx, project, relay.SpecId, epochStart) + if err != nil { + return nil, utils.LavaFormatError("strictest policy calculation for pairing validation cache failed", err, + utils.LogAttr("project", project.Index), + utils.LogAttr("chainID", relay.SpecId), + utils.LogAttr("block", strconv.FormatUint(epochStart, 10)), + ) + } + allowedCU = strictestPolicy.EpochCuLimit + } else { + isValidPairing := false + isValidPairing, allowedCU, providers, err = k.Keeper.ValidatePairingForClient( + ctx, + relay.SpecId, + providerAddr, + uint64(relay.Epoch), + project, ) + if err != nil { + return nil, utils.LavaFormatWarning("invalid pairing on proof of relay", err, + utils.Attribute{Key: "client", Value: clientAddr.String()}, + utils.Attribute{Key: "provider", Value: providerAddr.String()}, + ) + } + if !isValidPairing { + return nil, utils.LavaFormatWarning("invalid pairing on proof of relay", fmt.Errorf("pairing result doesn't include provider"), + utils.Attribute{Key: "client", Value: clientAddr.String()}, + utils.Attribute{Key: "provider", Value: providerAddr.String()}, + ) + } + validatePairingCache[validatePairingKey] = providers } rewardedCU, err := k.Keeper.EnforceClientCUsUsageInEpoch(ctx, relay.CuSum, allowedCU, totalCUInEpochForUserProvider, clientAddr, relay.SpecId, uint64(relay.Epoch)) @@ -295,6 +317,10 @@ func (k msgServer) RelayPayment(goCtx context.Context, msg *types.MsgRelayPaymen } utils.LogLavaEvent(ctx, logger, types.LatestBlocksReportEventName, latestBlockReports, "New LatestBlocks Report for provider") + // consume constant gas (dependent on the number of relays) + ctx.GasMeter().RefundGas(ctx.GasMeter().GasConsumed(), "") + ctx.GasMeter().ConsumeGas(uint64(10000+100000*len(msg.Relays)), "") + return &types.MsgRelayPaymentResponse{RejectedRelays: rejected_relays}, nil }