code.vegaprotocol.io/vega@v0.79.0/core/coreapi/services/validators.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 services
    17  
    18  import (
    19  	"context"
    20  	"sync"
    21  
    22  	"code.vegaprotocol.io/vega/core/events"
    23  	"code.vegaprotocol.io/vega/core/subscribers"
    24  	eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
    25  )
    26  
    27  type validatorUpdateE interface {
    28  	events.Event
    29  	ValidatorUpdate() eventspb.ValidatorUpdate
    30  }
    31  
    32  type ethereumKeyRotationE interface {
    33  	events.Event
    34  	EthereumKeyRotation() eventspb.EthereumKeyRotation
    35  }
    36  type keyRotationE interface {
    37  	events.Event
    38  	KeyRotation() eventspb.KeyRotation
    39  }
    40  
    41  type Validators struct {
    42  	*subscribers.Base
    43  	ctx context.Context
    44  
    45  	mu         sync.RWMutex
    46  	validators map[string]eventspb.ValidatorUpdate
    47  	ch         chan events.Event
    48  }
    49  
    50  func NewValidators(ctx context.Context) (assets *Validators) {
    51  	defer func() { go assets.consume() }()
    52  	return &Validators{
    53  		Base:       subscribers.NewBase(ctx, 1000, true),
    54  		ctx:        ctx,
    55  		validators: map[string]eventspb.ValidatorUpdate{},
    56  		ch:         make(chan events.Event, 100),
    57  	}
    58  }
    59  
    60  func (a *Validators) consume() {
    61  	defer func() { close(a.ch) }()
    62  	for {
    63  		select {
    64  		case <-a.Closed():
    65  			return
    66  		case e, ok := <-a.ch:
    67  			if !ok {
    68  				// cleanup base
    69  				a.Halt()
    70  				// channel is closed
    71  				return
    72  			}
    73  			a.mu.Lock()
    74  			switch te := e.(type) {
    75  			case keyRotationE:
    76  				kr := te.KeyRotation()
    77  				vu, ok := a.validators[kr.NodeId]
    78  				if !ok {
    79  					break
    80  				}
    81  
    82  				vu.VegaPubKey = kr.NewPubKey
    83  				a.validators[kr.NodeId] = vu
    84  			case ethereumKeyRotationE:
    85  				kr := te.EthereumKeyRotation()
    86  				vu, ok := a.validators[kr.NodeId]
    87  				if !ok {
    88  					break
    89  				}
    90  
    91  				vu.EthereumAddress = kr.NewAddress
    92  				a.validators[kr.NodeId] = vu
    93  			case validatorUpdateE:
    94  				a.validators[te.ValidatorUpdate().NodeId] = te.ValidatorUpdate()
    95  			}
    96  			a.mu.Unlock()
    97  		}
    98  	}
    99  }
   100  
   101  func (a *Validators) Push(evts ...events.Event) {
   102  	for _, e := range evts {
   103  		switch te := e.(type) {
   104  		case keyRotationE,
   105  			ethereumKeyRotationE,
   106  			validatorUpdateE:
   107  			a.ch <- te
   108  		}
   109  	}
   110  }
   111  
   112  func (a *Validators) List() []*eventspb.ValidatorUpdate {
   113  	a.mu.RLock()
   114  	defer a.mu.RUnlock()
   115  	out := make([]*eventspb.ValidatorUpdate, 0, len(a.validators))
   116  	for _, v := range a.validators {
   117  		v := v
   118  		out = append(out, &v)
   119  	}
   120  	return out
   121  }
   122  
   123  func (a *Validators) Types() []events.Type {
   124  	return []events.Type{
   125  		events.ValidatorUpdateEvent,
   126  		events.EthereumKeyRotationEvent,
   127  		events.KeyRotationEvent,
   128  	}
   129  }