code.vegaprotocol.io/vega@v0.79.0/core/staking/stake_verifier_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 staking
    17  
    18  import (
    19  	"context"
    20  
    21  	"code.vegaprotocol.io/vega/core/events"
    22  	"code.vegaprotocol.io/vega/core/types"
    23  	"code.vegaprotocol.io/vega/libs/proto"
    24  	"code.vegaprotocol.io/vega/logging"
    25  )
    26  
    27  var (
    28  	depositedKey = (&types.PayloadStakeVerifierDeposited{}).Key()
    29  	removedKey   = (&types.PayloadStakeVerifierRemoved{}).Key()
    30  
    31  	hashKeys = []string{
    32  		depositedKey,
    33  		removedKey,
    34  	}
    35  )
    36  
    37  type stakeVerifierSnapshotState struct {
    38  	serialisedDeposited []byte
    39  	serialisedRemoved   []byte
    40  }
    41  
    42  func (s *StakeVerifier) serialisePendingSD() ([]byte, error) {
    43  	s.log.Info("serialising pending SD", logging.Int("n", len(s.pendingSDs)))
    44  	deposited := make([]*types.StakeDeposited, 0, len(s.pendingSDs))
    45  
    46  	for _, p := range s.pendingSDs {
    47  		deposited = append(deposited, p.StakeDeposited)
    48  	}
    49  
    50  	pl := types.Payload{
    51  		Data: &types.PayloadStakeVerifierDeposited{
    52  			StakeVerifierDeposited: deposited,
    53  		},
    54  	}
    55  	return proto.Marshal(pl.IntoProto())
    56  }
    57  
    58  func (s *StakeVerifier) serialisePendingSR() ([]byte, error) {
    59  	s.log.Info("serialising pending SR", logging.Int("n", len(s.pendingSRs)))
    60  	removed := make([]*types.StakeRemoved, 0, len(s.pendingSRs))
    61  
    62  	for _, p := range s.pendingSRs {
    63  		removed = append(removed, p.StakeRemoved)
    64  	}
    65  
    66  	pl := types.Payload{
    67  		Data: &types.PayloadStakeVerifierRemoved{
    68  			StakeVerifierRemoved: removed,
    69  		},
    70  	}
    71  
    72  	return proto.Marshal(pl.IntoProto())
    73  }
    74  
    75  func (s *StakeVerifier) serialiseK(serialFunc func() ([]byte, error), dataField *[]byte) ([]byte, error) {
    76  	data, err := serialFunc()
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	*dataField = data
    81  	return data, nil
    82  }
    83  
    84  // get the serialised form and hash of the given key.
    85  func (s *StakeVerifier) serialise(k string) ([]byte, error) {
    86  	switch k {
    87  	case depositedKey:
    88  		return s.serialiseK(s.serialisePendingSD, &s.svss.serialisedDeposited)
    89  	case removedKey:
    90  		return s.serialiseK(s.serialisePendingSR, &s.svss.serialisedRemoved)
    91  	default:
    92  		return nil, types.ErrSnapshotKeyDoesNotExist
    93  	}
    94  }
    95  
    96  func (s *StakeVerifier) Namespace() types.SnapshotNamespace {
    97  	return types.StakeVerifierSnapshot
    98  }
    99  
   100  func (s *StakeVerifier) Keys() []string {
   101  	return hashKeys
   102  }
   103  
   104  func (s *StakeVerifier) Stopped() bool {
   105  	return false
   106  }
   107  
   108  func (s *StakeVerifier) GetState(k string) ([]byte, []types.StateProvider, error) {
   109  	data, err := s.serialise(k)
   110  	return data, nil, err
   111  }
   112  
   113  func (s *StakeVerifier) LoadState(ctx context.Context, payload *types.Payload) ([]types.StateProvider, error) {
   114  	if s.Namespace() != payload.Data.Namespace() {
   115  		return nil, types.ErrInvalidSnapshotNamespace
   116  	}
   117  
   118  	switch pl := payload.Data.(type) {
   119  	case *types.PayloadStakeVerifierDeposited:
   120  		return nil, s.restorePendingSD(ctx, pl.StakeVerifierDeposited, payload)
   121  	case *types.PayloadStakeVerifierRemoved:
   122  		return nil, s.restorePendingSR(ctx, pl.StakeVerifierRemoved, payload)
   123  	default:
   124  		return nil, types.ErrUnknownSnapshotType
   125  	}
   126  }
   127  
   128  func (s *StakeVerifier) restorePendingSD(ctx context.Context, deposited []*types.StakeDeposited, p *types.Payload) error {
   129  	s.log.Debug("restoring pendingSDs snapshot", logging.Int("n_pending", len(deposited)))
   130  	s.pendingSDs = make([]*pendingSD, 0, len(deposited))
   131  	evts := []events.Event{}
   132  	for _, d := range deposited {
   133  		// this populates the id/hash structs
   134  		if !s.ensureNotDuplicate(d.ID, d.IntoStakeLinking().Hash()) {
   135  			s.log.Panic("pendingSD's unexpectedly pre-populated when restoring from snapshot")
   136  		}
   137  
   138  		pending := &pendingSD{
   139  			StakeDeposited: d,
   140  			chainID:        s.accs.chainID,
   141  			check:          func() error { return s.ocv.CheckStakeDeposited(d) },
   142  		}
   143  
   144  		s.pendingSDs = append(s.pendingSDs, pending)
   145  		s.log.Debug("restoring witness resource")
   146  		if err := s.witness.RestoreResource(pending, s.onEventVerified); err != nil {
   147  			s.log.Panic("unable to restore pending stake deposited resource", logging.String("id", pending.ID), logging.Error(err))
   148  		}
   149  		evts = append(evts, events.NewStakeLinking(ctx, *pending.IntoStakeLinking()))
   150  	}
   151  	var err error
   152  	s.svss.serialisedDeposited, err = proto.Marshal(p.IntoProto())
   153  	s.broker.SendBatch(evts)
   154  
   155  	// now populate "seen" map with finalised events from accounting
   156  	for _, acc := range s.accs.hashableAccounts {
   157  		for _, evt := range acc.Events {
   158  			sl := types.StakeLinkingFromProto(evt.IntoProto())
   159  			if !s.ensureNotDuplicate(sl.ID, sl.Hash()) {
   160  				s.log.Panic("finalised events unexpectedly pre-populated when restoring from snapshot")
   161  			}
   162  		}
   163  	}
   164  
   165  	return err
   166  }
   167  
   168  func (s *StakeVerifier) OnStateLoaded(ctx context.Context) error {
   169  	// tell the internal EEF where it got up to so we do not resend events we're already seen
   170  	lastBlockSeen := s.getLastBlockSeen()
   171  	if lastBlockSeen == 0 {
   172  		lastBlockSeen = s.accs.getLastBlockSeen()
   173  	}
   174  	if lastBlockSeen != 0 {
   175  		s.log.Info("restoring staking bridge starting block", logging.Uint64("block", lastBlockSeen))
   176  		// s.ethEventSource.UpdateStakingStartingBlock(lastBlockSeen)
   177  	}
   178  	return nil
   179  }
   180  
   181  func (s *StakeVerifier) restorePendingSR(ctx context.Context, removed []*types.StakeRemoved, p *types.Payload) error {
   182  	s.log.Debug("restoring pendingSRs snapshot", logging.Int("n_pending", len(removed)))
   183  	s.pendingSRs = make([]*pendingSR, 0, len(removed))
   184  	evts := []events.Event{}
   185  	for _, r := range removed {
   186  		// this populates the id/hash structs
   187  		if !s.ensureNotDuplicate(r.ID, r.IntoStakeLinking().Hash()) {
   188  			s.log.Panic("pendingSR's unexpectedly pre-populated when restoring from snapshot")
   189  		}
   190  
   191  		pending := &pendingSR{
   192  			StakeRemoved: r,
   193  			chainID:      s.accs.chainID,
   194  			check:        func() error { return s.ocv.CheckStakeRemoved(r) },
   195  		}
   196  
   197  		s.pendingSRs = append(s.pendingSRs, pending)
   198  		if err := s.witness.RestoreResource(pending, s.onEventVerified); err != nil {
   199  			s.log.Panic("unable to restore pending stake removed resource", logging.String("id", pending.ID), logging.Error(err))
   200  		}
   201  		evts = append(evts, events.NewStakeLinking(ctx, *pending.IntoStakeLinking()))
   202  	}
   203  
   204  	var err error
   205  	s.svss.serialisedRemoved, err = proto.Marshal(p.IntoProto())
   206  	s.broker.SendBatch(evts)
   207  	return err
   208  }