code.vegaprotocol.io/vega@v0.79.0/core/matching/snapshot.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 matching 17 18 import ( 19 "context" 20 "log" 21 22 "code.vegaprotocol.io/vega/core/types" 23 "code.vegaprotocol.io/vega/libs/num" 24 "code.vegaprotocol.io/vega/libs/proto" 25 "code.vegaprotocol.io/vega/logging" 26 ) 27 28 func (b *OrderBook) StopSnapshots() { 29 b.log.Debug("market has been cleared, stopping snapshot production", logging.String("marketid", b.marketID)) 30 b.stopped = true 31 } 32 33 func (b *OrderBook) Keys() []string { 34 return []string{b.snapshot.Key()} 35 } 36 37 func (b *OrderBook) Stopped() bool { 38 return b.stopped 39 } 40 41 func (b OrderBook) Namespace() types.SnapshotNamespace { 42 return types.MatchingSnapshot 43 } 44 45 func (b *OrderBook) GetState(key string) ([]byte, []types.StateProvider, error) { 46 if key != b.snapshot.Key() { 47 return nil, nil, types.ErrSnapshotKeyDoesNotExist 48 } 49 50 if b.stopped { 51 return nil, nil, nil 52 } 53 54 // Copy all the state into a domain object 55 payload := b.buildPayload() 56 57 s, err := proto.Marshal(payload.IntoProto()) 58 return s, nil, err 59 } 60 61 func (b *OrderBook) buildPayload() *types.Payload { 62 return &types.Payload{ 63 Data: &types.PayloadMatchingBook{ 64 MatchingBook: &types.MatchingBook{ 65 MarketID: b.marketID, 66 Buy: b.copyOrders(b.buy), 67 Sell: b.copyOrders(b.sell), 68 LastTradedPrice: b.lastTradedPrice, 69 Auction: b.auction, 70 BatchID: b.batchID, 71 PeggedOrderIDs: b.GetActivePeggedOrderIDs(), 72 }, 73 }, 74 } 75 } 76 77 func (b *OrderBook) copyOrders(obs *OrderBookSide) []*types.Order { 78 orders := make([]*types.Order, 0) 79 pricelevels := obs.getLevels() 80 for _, pl := range pricelevels { 81 for _, order := range pl.orders { 82 orders = append(orders, order.Clone()) 83 } 84 } 85 return orders 86 } 87 88 func (b *OrderBook) LoadState(_ context.Context, payload *types.Payload) ([]types.StateProvider, error) { 89 if b.Namespace() != payload.Namespace() { 90 return nil, types.ErrInvalidSnapshotNamespace 91 } 92 93 var mb *types.MatchingBook 94 95 switch pl := payload.Data.(type) { 96 case *types.PayloadMatchingBook: 97 mb = pl.MatchingBook 98 default: 99 return nil, types.ErrUnknownSnapshotType 100 } 101 102 // Check we have an empty book here or else we should panic 103 if len(b.buy.levels) > 0 || len(b.sell.levels) > 0 { 104 log.Panic("orderbook is not empty so we should not be loading snapshot state") 105 } 106 107 b.marketID = mb.MarketID 108 b.batchID = mb.BatchID 109 b.auction = mb.Auction 110 b.lastTradedPrice = mb.LastTradedPrice 111 112 for _, o := range mb.Buy { 113 b.buy.addOrder(o) 114 b.add(o) 115 } 116 117 for _, o := range mb.Sell { 118 b.sell.addOrder(o) 119 b.add(o) 120 } 121 122 if len(mb.PeggedOrderIDs) != 0 { 123 // the pegged orders will be added in an arbitrary order during b.add() above 124 // which is all we can do if we've upgraded from older versions. If we have peggedOrder IDs 125 // in the snapshot then we clear them and re-add in the snapshot order 126 // (which will be the order they were added to the book) 127 b.peggedOrders.Clear() 128 for _, pid := range mb.PeggedOrderIDs { 129 b.peggedOrders.Add(pid) 130 } 131 } 132 133 if b.auction { 134 b.indicativePriceAndVolume = NewIndicativePriceAndVolume(b.log, b.buy, b.sell) 135 } 136 137 return nil, nil 138 } 139 140 // RestoreWithMarketPriceFactor takes the given market price factor and updates all the OriginalPrices 141 // in the orders accordingly. 142 func (b *OrderBook) RestoreWithMarketPriceFactor(priceFactor num.Decimal) { 143 for _, o := range b.ordersByID { 144 if o.Price.IsZero() { 145 continue 146 } 147 o.OriginalPrice, _ = num.UintFromDecimal(o.Price.ToDecimal().Div(priceFactor)) 148 } 149 }