code.vegaprotocol.io/vega@v0.79.0/core/validators/erc20multisig/topology_snapshot_state.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 erc20multisig
    17  
    18  import (
    19  	"context"
    20  	"sort"
    21  
    22  	"code.vegaprotocol.io/vega/core/types"
    23  	vgcontext "code.vegaprotocol.io/vega/libs/context"
    24  	"code.vegaprotocol.io/vega/libs/proto"
    25  	"code.vegaprotocol.io/vega/logging"
    26  	eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
    27  	snapshotpb "code.vegaprotocol.io/vega/protos/vega/snapshot/v1"
    28  )
    29  
    30  var (
    31  	verifiedStateKey = (&types.PayloadERC20MultiSigTopologyVerified{}).Key()
    32  	pendingStateKey  = (&types.PayloadERC20MultiSigTopologyPending{}).Key()
    33  
    34  	hashKeys = []string{
    35  		verifiedStateKey,
    36  		pendingStateKey,
    37  	}
    38  )
    39  
    40  func (t *Topology) Namespace() types.SnapshotNamespace {
    41  	return types.ERC20MultiSigTopologySnapshot
    42  }
    43  
    44  func (t *Topology) Keys() []string {
    45  	return hashKeys
    46  }
    47  
    48  func (t *Topology) GetState(k string) ([]byte, []types.StateProvider, error) {
    49  	data, err := t.serialise(k)
    50  	return data, nil, err
    51  }
    52  
    53  func (t *Topology) Stopped() bool {
    54  	return false
    55  }
    56  
    57  func (t *Topology) LoadState(ctx context.Context, payload *types.Payload) ([]types.StateProvider, error) {
    58  	if t.Namespace() != payload.Data.Namespace() {
    59  		return nil, types.ErrInvalidSnapshotNamespace
    60  	}
    61  
    62  	switch pl := payload.Data.(type) {
    63  	case *types.PayloadERC20MultiSigTopologyVerified:
    64  		return nil, t.restoreVerifiedState(ctx, pl.Verified)
    65  	case *types.PayloadERC20MultiSigTopologyPending:
    66  		return nil, t.restorePendingState(ctx, pl.Pending)
    67  	default:
    68  		return nil, types.ErrUnknownSnapshotType
    69  	}
    70  }
    71  
    72  func (t *Topology) restoreVerifiedState(
    73  	ctx context.Context, s *snapshotpb.ERC20MultiSigTopologyVerified,
    74  ) error {
    75  	t.log.Debug("restoring snapshot verified state")
    76  	if s.Threshold != nil {
    77  		t.log.Debug("restoring threshold")
    78  		t.threshold = types.SignerThresholdSetEventFromEventProto(s.Threshold)
    79  	}
    80  
    81  	t.log.Debug("restoring seen events", logging.Int("n", len(s.SeenEvents)))
    82  	for _, v := range s.SeenEvents {
    83  		t.seen[v] = struct{}{}
    84  	}
    85  
    86  	t.log.Debug("restoring signers", logging.Int("n", len(s.Signers)))
    87  	for _, v := range s.Signers {
    88  		t.signers[v] = struct{}{}
    89  	}
    90  
    91  	t.log.Debug("restoring events per address", logging.Int("n", len(s.EventsPerAddress)))
    92  	for _, v := range s.EventsPerAddress {
    93  		events := make([]*types.SignerEvent, 0, len(v.Events))
    94  		for _, e := range v.Events {
    95  			events = append(events, types.SignerEventFromEventProto(e))
    96  		}
    97  		t.eventsPerAddress[v.Address] = events
    98  	}
    99  
   100  	if vgcontext.InProgressUpgradeFrom(ctx, "v0.76.8") {
   101  		lastSeen := t.getLastBlockSeen()
   102  
   103  		t.log.Info("migration code updating multisig last seen",
   104  			logging.String("address", t.ocv.GetMultiSigAddress()),
   105  			logging.Uint64("last-seen", lastSeen),
   106  			logging.String("chain-id", t.chainID),
   107  		)
   108  		t.ethEventSource.UpdateContractBlock(t.ocv.GetMultiSigAddress(), t.chainID, lastSeen)
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  func (t *Topology) restorePendingState(
   115  	_ context.Context, s *snapshotpb.ERC20MultiSigTopologyPending,
   116  ) error {
   117  	t.log.Debug("restoring snapshot pending state", logging.String("chain-id", t.chainID))
   118  	t.log.Debug("restoring witness signers", logging.Int("n", len(s.WitnessedSigners)))
   119  	for _, v := range s.WitnessedSigners {
   120  		t.witnessedSigners[v] = struct{}{}
   121  	}
   122  
   123  	t.log.Debug("restoring witness threshold sets", logging.Int("n", len(s.WitnessedThresholdSets)))
   124  	for _, v := range s.WitnessedThresholdSets {
   125  		t.witnessedThresholds[v] = struct{}{}
   126  	}
   127  
   128  	t.log.Debug("restoring pending signers", logging.Int("n", len(s.PendingSigners)))
   129  	for _, v := range s.PendingSigners {
   130  		evt := types.SignerEventFromEventProto(v)
   131  		pending := &pendingSigner{
   132  			SignerEvent: evt,
   133  			check:       func() error { return t.ocv.CheckSignerEvent(evt) },
   134  		}
   135  
   136  		t.pendingSigners[evt.ID] = pending
   137  		// if we have witnessed it already,
   138  		if _, ok := t.witnessedSigners[evt.ID]; !ok {
   139  			if err := t.witness.RestoreResource(pending, t.onEventVerified); err != nil {
   140  				t.log.Panic("unable to restore pending signer resource", logging.String("id", pending.ID), logging.Error(err))
   141  			}
   142  		}
   143  	}
   144  
   145  	t.log.Debug("restoring pending threshold set", logging.Int("n", len(s.PendingThresholdSet)))
   146  	for _, v := range s.PendingThresholdSet {
   147  		evt := types.SignerThresholdSetEventFromEventProto(v)
   148  		pending := &pendingThresholdSet{
   149  			SignerThresholdSetEvent: evt,
   150  			check:                   func() error { return t.ocv.CheckThresholdSetEvent(evt) },
   151  		}
   152  
   153  		t.pendingThresholds[evt.ID] = pending
   154  		// if we have witnessed it already,
   155  		if _, ok := t.witnessedThresholds[evt.ID]; !ok {
   156  			if err := t.witness.RestoreResource(pending, t.onEventVerified); err != nil {
   157  				t.log.Panic("unable to restore pending threshold resource", logging.String("id", pending.ID), logging.Error(err))
   158  			}
   159  		}
   160  	}
   161  
   162  	return nil
   163  }
   164  
   165  func (t *Topology) constructVerifiedState() *snapshotpb.ERC20MultiSigTopologyVerified {
   166  	out := &snapshotpb.ERC20MultiSigTopologyVerified{}
   167  	t.log.Debug("serialising snapshot verified state")
   168  	// first serialise seen events
   169  	t.log.Debug("serialising seen", logging.Int("n", len(t.seen)))
   170  	out.SeenEvents = make([]string, 0, len(t.seen))
   171  	for k := range t.seen {
   172  		out.SeenEvents = append(out.SeenEvents, k)
   173  	}
   174  	sort.Strings(out.SeenEvents)
   175  
   176  	// then the current known list of signers
   177  	t.log.Debug("serialising signers", logging.Int("n", len(t.signers)))
   178  	out.Signers = make([]string, 0, len(t.signers))
   179  	for k := range t.signers {
   180  		out.Signers = append(out.Signers, k)
   181  	}
   182  	// sort it + reuse it next in the eventsPerAddress
   183  	sort.Strings(out.Signers)
   184  
   185  	evts := make([]*snapshotpb.SignerEventsPerAddress, 0, len(t.eventsPerAddress))
   186  	// now the signers events
   187  	for k, v := range t.eventsPerAddress {
   188  		events := make([]*eventspb.ERC20MultiSigSignerEvent, 0, len(v))
   189  
   190  		t.log.Debug("serialising events", logging.String("signer", k), logging.Int("n", len(v)))
   191  		for _, v := range v {
   192  			events = append(events, v.IntoProto())
   193  		}
   194  
   195  		evts = append(
   196  			evts,
   197  			&snapshotpb.SignerEventsPerAddress{
   198  				Address: k,
   199  				Events:  events,
   200  			},
   201  		)
   202  	}
   203  	sort.SliceStable(evts, func(i, j int) bool { return evts[i].Address < evts[j].Address })
   204  	out.EventsPerAddress = evts
   205  
   206  	// finally do the current threshold
   207  	if t.threshold != nil {
   208  		t.log.Debug("serialising threshold")
   209  		out.Threshold = t.threshold.IntoProto()
   210  	}
   211  
   212  	return out
   213  }
   214  
   215  func (t *Topology) serialiseVerifiedState() ([]byte, error) {
   216  	return proto.Marshal(types.Payload{
   217  		Data: &types.PayloadERC20MultiSigTopologyVerified{
   218  			Verified: t.constructVerifiedState(),
   219  		},
   220  	}.IntoProto())
   221  }
   222  
   223  func (t *Topology) constructPendingState() *snapshotpb.ERC20MultiSigTopologyPending {
   224  	t.log.Debug("serialising pending state")
   225  	out := &snapshotpb.ERC20MultiSigTopologyPending{}
   226  
   227  	t.log.Debug("serialising witness signers", logging.Int("n", len(t.witnessedSigners)))
   228  	out.WitnessedSigners = make([]string, 0, len(t.witnessedSigners))
   229  	for k := range t.witnessedSigners {
   230  		out.WitnessedSigners = append(out.WitnessedSigners, k)
   231  	}
   232  	sort.Strings(out.WitnessedSigners)
   233  
   234  	t.log.Debug("serialising witness threshold sets", logging.Int("n", len(t.witnessedThresholds)))
   235  	out.WitnessedThresholdSets = make([]string, 0, len(t.witnessedThresholds))
   236  	for k := range t.witnessedThresholds {
   237  		out.WitnessedThresholdSets = append(out.WitnessedThresholdSets, k)
   238  	}
   239  	sort.Strings(out.WitnessedThresholdSets)
   240  
   241  	t.log.Debug("serialising pending signers", logging.Int("n", len(t.pendingSigners)))
   242  	out.PendingSigners = make([]*eventspb.ERC20MultiSigSignerEvent, 0, len(t.pendingSigners))
   243  	for _, v := range t.pendingSigners {
   244  		out.PendingSigners = append(out.PendingSigners, v.IntoProto())
   245  	}
   246  	sort.SliceStable(out.PendingSigners, func(i, j int) bool {
   247  		return out.PendingSigners[i].Id < out.PendingSigners[j].Id
   248  	})
   249  
   250  	t.log.Debug("serialising pending thresholds", logging.Int("n", len(t.pendingThresholds)))
   251  	out.PendingThresholdSet = make([]*eventspb.ERC20MultiSigThresholdSetEvent, 0, len(t.pendingThresholds))
   252  	for _, v := range t.pendingThresholds {
   253  		out.PendingThresholdSet = append(out.PendingThresholdSet, v.IntoProto())
   254  	}
   255  	sort.SliceStable(out.PendingThresholdSet, func(i, j int) bool {
   256  		return out.PendingThresholdSet[i].Id < out.PendingThresholdSet[j].Id
   257  	})
   258  
   259  	return out
   260  }
   261  
   262  func (t *Topology) serialisePendingState() ([]byte, error) {
   263  	return proto.Marshal(types.Payload{
   264  		Data: &types.PayloadERC20MultiSigTopologyPending{
   265  			Pending: t.constructPendingState(),
   266  		},
   267  	}.IntoProto())
   268  }
   269  
   270  // get the serialised form of the given key.
   271  func (t *Topology) serialise(k string) ([]byte, error) {
   272  	switch k {
   273  	case verifiedStateKey:
   274  		return t.serialiseVerifiedState()
   275  	case pendingStateKey:
   276  		return t.serialisePendingState()
   277  	default:
   278  		return nil, types.ErrSnapshotKeyDoesNotExist
   279  	}
   280  }