code.vegaprotocol.io/vega@v0.79.0/core/datasource/external/ethverifier/l2_verifiers.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 ethverifier
    17  
    18  import (
    19  	"context"
    20  	"errors"
    21  	"fmt"
    22  	"sort"
    23  	"time"
    24  
    25  	"code.vegaprotocol.io/vega/core/client/eth"
    26  	"code.vegaprotocol.io/vega/core/datasource/external/ethcall"
    27  	"code.vegaprotocol.io/vega/core/types"
    28  	"code.vegaprotocol.io/vega/logging"
    29  
    30  	"golang.org/x/exp/maps"
    31  )
    32  
    33  type L2Clients interface {
    34  	Get(chainID string) (*eth.L2Client, *eth.EthereumConfirmations, bool)
    35  }
    36  
    37  type EthL2CallEngines interface {
    38  	GetOrInstantiate(chainID string) (EthCallEngine, error)
    39  }
    40  
    41  type L2Verifiers struct {
    42  	log               *logging.Logger
    43  	witness           Witness
    44  	ts                TimeService
    45  	broker            Broker
    46  	oracleBroadcaster OracleDataBroadcaster
    47  
    48  	isValidator bool
    49  
    50  	clients L2Clients
    51  
    52  	// chain id -> Verifier
    53  	verifiers map[string]*Verifier
    54  
    55  	// eth L2 call engines
    56  	ethL2CallEngine EthL2CallEngines
    57  }
    58  
    59  func NewL2Verifiers(
    60  	log *logging.Logger,
    61  	witness Witness,
    62  	ts TimeService,
    63  	broker Broker,
    64  	oracleBroadcaster OracleDataBroadcaster,
    65  	clients L2Clients,
    66  	callEngines EthL2CallEngines,
    67  	isValidator bool,
    68  ) (sv *L2Verifiers) {
    69  	return &L2Verifiers{
    70  		log:               log,
    71  		witness:           witness,
    72  		ts:                ts,
    73  		broker:            broker,
    74  		oracleBroadcaster: oracleBroadcaster,
    75  		clients:           clients,
    76  		verifiers:         map[string]*Verifier{},
    77  		ethL2CallEngine:   callEngines,
    78  		isValidator:       isValidator,
    79  	}
    80  }
    81  
    82  func (v *L2Verifiers) OnEthereumL2ConfigsUpdated(
    83  	ctx context.Context, ethCfg *types.EthereumL2Configs,
    84  ) error {
    85  	// new L2 configured, instatiate the verifier for it.
    86  	for _, c := range ethCfg.Configs {
    87  		// if already exists, do nothing
    88  		if _, ok := v.verifiers[c.ChainID]; ok {
    89  			continue
    90  		}
    91  		v.verifiers[c.ChainID] = v.instantiate(c.ChainID)
    92  	}
    93  
    94  	return nil
    95  }
    96  
    97  func (v *L2Verifiers) instantiate(chainID string) *Verifier {
    98  	var confs *eth.EthereumConfirmations
    99  	if v.isValidator {
   100  		var ok bool
   101  		_, confs, ok = v.clients.Get(chainID)
   102  		if !ok {
   103  			v.log.Panic("ethereum client not configured for L2",
   104  				logging.String("chain-id", chainID),
   105  			)
   106  		}
   107  	}
   108  
   109  	ethCallEngine, err := v.ethL2CallEngine.GetOrInstantiate(chainID)
   110  	if err != nil {
   111  		v.log.Panic("could not get call engine for L2", logging.String("chain-id", chainID))
   112  	}
   113  
   114  	return New(v.log, v.witness, v.ts, v.broker, v.oracleBroadcaster, ethCallEngine, confs, v.isValidator)
   115  }
   116  
   117  func (v *L2Verifiers) OnTick(ctx context.Context, t time.Time) {
   118  	ids := maps.Keys(v.verifiers)
   119  	sort.Strings(ids)
   120  	for _, id := range ids {
   121  		v.verifiers[id].OnTick(ctx, t)
   122  	}
   123  }
   124  
   125  func (v *L2Verifiers) ProcessEthereumContractCallResult(callEvent ethcall.ContractCallEvent) error {
   126  	if callEvent.SourceChainID == nil {
   127  		return errors.New("invalid non l2 event")
   128  	}
   129  
   130  	verifier, ok := v.verifiers[fmt.Sprintf("%v", *callEvent.SourceChainID)]
   131  	if !ok {
   132  		return errors.New("unsupported l2 chain")
   133  	}
   134  
   135  	return verifier.ProcessEthereumContractCallResult(callEvent)
   136  }
   137  
   138  func (v *L2Verifiers) FromProtoSnapshot() {}
   139  
   140  func (v *L2Verifiers) ToProtoSnapshot() []byte { return nil }