code.vegaprotocol.io/vega@v0.79.0/core/liquidity/v2/snapshot_v1.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package liquidity
    17  
    18  import (
    19  	"context"
    20  	"time"
    21  
    22  	"code.vegaprotocol.io/vega/core/events"
    23  	"code.vegaprotocol.io/vega/core/types"
    24  	"code.vegaprotocol.io/vega/libs/num"
    25  	"code.vegaprotocol.io/vega/libs/proto"
    26  	"code.vegaprotocol.io/vega/logging"
    27  	typespb "code.vegaprotocol.io/vega/protos/vega"
    28  	snapshotpb "code.vegaprotocol.io/vega/protos/vega/snapshot/v1"
    29  )
    30  
    31  type snapshotV1 struct {
    32  	*Engine
    33  	market  string
    34  	stopped bool
    35  	keys    []string
    36  }
    37  
    38  func (e *snapshotV1) Namespace() types.SnapshotNamespace {
    39  	return types.LiquiditySnapshot
    40  }
    41  
    42  func (e *snapshotV1) Keys() []string {
    43  	if len(e.keys) <= 0 {
    44  		e.keys = []string{
    45  			(&types.PayloadLiquidityParameters{
    46  				Parameters: &snapshotpb.LiquidityParameters{
    47  					MarketId: e.market,
    48  				},
    49  			}).Key(),
    50  			(&types.PayloadLiquidityPendingProvisions{
    51  				PendingProvisions: &snapshotpb.LiquidityPendingProvisions{
    52  					MarketId: e.market,
    53  				},
    54  			}).Key(),
    55  			(&types.PayloadLiquidityProvisions{
    56  				Provisions: &snapshotpb.LiquidityProvisions{
    57  					MarketId: e.market,
    58  				},
    59  			}).Key(),
    60  			(&types.PayloadLiquiditySupplied{
    61  				LiquiditySupplied: &snapshotpb.LiquiditySupplied{
    62  					MarketId: e.market,
    63  				},
    64  			}).Key(),
    65  			(&types.PayloadLiquidityScores{
    66  				LiquidityScores: &snapshotpb.LiquidityScores{
    67  					MarketId: e.market,
    68  				},
    69  			}).Key(),
    70  		}
    71  	}
    72  
    73  	return e.keys
    74  }
    75  
    76  func (e *snapshotV1) GetState(k string) ([]byte, []types.StateProvider, error) {
    77  	var (
    78  		keys  = e.Keys()
    79  		state = &snapshotpb.Payload{}
    80  	)
    81  
    82  	switch k {
    83  	case keys[0]:
    84  		state.Data = &snapshotpb.Payload_LiquidityParameters{
    85  			LiquidityParameters: &snapshotpb.LiquidityParameters{
    86  				MarketId: e.market,
    87  			},
    88  		}
    89  	case keys[1]:
    90  		state.Data = &snapshotpb.Payload_LiquidityPendingProvisions{
    91  			LiquidityPendingProvisions: &snapshotpb.LiquidityPendingProvisions{
    92  				MarketId: e.market,
    93  			},
    94  		}
    95  	case keys[2]:
    96  		state.Data = &snapshotpb.Payload_LiquidityProvisions{
    97  			LiquidityProvisions: &snapshotpb.LiquidityProvisions{
    98  				MarketId: e.market,
    99  			},
   100  		}
   101  	case keys[3]:
   102  		state.Data = &snapshotpb.Payload_LiquiditySupplied{
   103  			LiquiditySupplied: &snapshotpb.LiquiditySupplied{
   104  				MarketId: e.market,
   105  			},
   106  		}
   107  	case keys[4]:
   108  		state.Data = &snapshotpb.Payload_LiquidityScores{
   109  			LiquidityScores: &snapshotpb.LiquidityScores{
   110  				MarketId: e.market,
   111  			},
   112  		}
   113  	}
   114  
   115  	buf, err := proto.Marshal(state)
   116  	if err != nil {
   117  		return nil, nil, err
   118  	}
   119  
   120  	return buf, nil, nil
   121  }
   122  
   123  func (e *snapshotV1) LoadState(ctx context.Context, p *types.Payload) ([]types.StateProvider, error) {
   124  	if e.Namespace() != p.Data.Namespace() {
   125  		return nil, types.ErrInvalidSnapshotNamespace
   126  	}
   127  
   128  	switch pl := p.Data.(type) {
   129  	case *types.PayloadLiquidityProvisions:
   130  		if err := e.loadProvisions(ctx, pl.Provisions.GetLiquidityProvisions()); err != nil {
   131  			return nil, err
   132  		}
   133  
   134  		e.loadPerformances(pl.Provisions.GetLiquidityProvisions())
   135  		return nil, nil
   136  	case *types.PayloadLiquidityScores:
   137  		return nil, e.loadScores(pl.LiquidityScores)
   138  	case *types.PayloadLiquiditySupplied:
   139  		return nil, e.loadSupplied(pl.LiquiditySupplied)
   140  	case *types.PayloadLiquidityPendingProvisions:
   141  		return nil, nil
   142  	case *types.PayloadLiquidityParameters:
   143  		return nil, nil
   144  
   145  	default:
   146  		return nil, types.ErrUnknownSnapshotType
   147  	}
   148  }
   149  
   150  func (e *snapshotV1) Stopped() bool {
   151  	return e.stopped
   152  }
   153  
   154  func (e *snapshotV1) Stop() {
   155  	e.log.Debug("market has been cleared, stopping snapshot production", logging.MarketID(e.marketID))
   156  	e.stopped = true
   157  }
   158  
   159  func (e *snapshotV1) loadPerformances(provisions []*typespb.LiquidityProvision) {
   160  	e.slaPerformance = map[string]*slaPerformance{}
   161  	for _, provision := range provisions {
   162  		previousPenalties := restoreSliceRing(
   163  			[]*num.Decimal{},
   164  			e.slaParams.PerformanceHysteresisEpochs,
   165  			0,
   166  		)
   167  
   168  		var startTime time.Time
   169  
   170  		e.slaPerformance[provision.PartyId] = &slaPerformance{
   171  			s:                 0,
   172  			start:             startTime,
   173  			previousPenalties: previousPenalties,
   174  		}
   175  	}
   176  }
   177  
   178  func (e *snapshotV1) loadProvisions(ctx context.Context, provisions []*typespb.LiquidityProvision) error {
   179  	e.provisions = newSnapshotableProvisionsPerParty()
   180  
   181  	evts := make([]events.Event, 0, len(provisions))
   182  	for _, v := range provisions {
   183  		provision, err := types.LiquidityProvisionFromProto(v)
   184  		if err != nil {
   185  			return err
   186  		}
   187  		e.provisions.Set(v.PartyId, provision)
   188  		evts = append(evts, events.NewLiquidityProvisionEvent(ctx, provision))
   189  
   190  		for _, v := range v.Buys {
   191  			e.legacyOrderIDs = append(e.legacyOrderIDs, v.OrderId)
   192  		}
   193  
   194  		for _, v := range v.Sells {
   195  			e.legacyOrderIDs = append(e.legacyOrderIDs, v.OrderId)
   196  		}
   197  	}
   198  
   199  	var err error
   200  	e.broker.SendBatch(evts)
   201  	return err
   202  }
   203  
   204  func (e *snapshotV1) loadSupplied(ls *snapshotpb.LiquiditySupplied) error {
   205  	// Dirty hack so we can reuse the supplied engine from the liquidity engine v1,
   206  	// without snapshot payload namespace issue.
   207  	err := e.suppliedEngine.Reload(&snapshotpb.LiquiditySupplied{
   208  		MarketId:         ls.MarketId,
   209  		ConsensusReached: ls.ConsensusReached,
   210  		BidCache:         ls.BidCache,
   211  		AskCache:         ls.AskCache,
   212  	})
   213  	if err != nil {
   214  		return err
   215  	}
   216  
   217  	return err
   218  }
   219  
   220  func (e *snapshotV1) loadScores(ls *snapshotpb.LiquidityScores) error {
   221  	var err error
   222  
   223  	e.nAvg = int64(ls.RunningAverageCounter)
   224  	e.feeCalculationTimeStep = defaultFeeCalculationTimeStep
   225  
   226  	scores := make(map[string]num.Decimal, len(ls.Scores))
   227  	for _, p := range ls.Scores {
   228  		score, err := num.DecimalFromString(p.Score)
   229  		if err != nil {
   230  			return err
   231  		}
   232  		scores[p.PartyId] = score
   233  	}
   234  
   235  	e.avgScores = scores
   236  	return err
   237  }