code.vegaprotocol.io/vega@v0.79.0/core/protocol/l2_eth_call_engines.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 protocol
    17  
    18  // circling around import cycle here...
    19  
    20  import (
    21  	"context"
    22  
    23  	"code.vegaprotocol.io/vega/core/client/eth"
    24  	"code.vegaprotocol.io/vega/core/datasource/external/ethcall"
    25  	"code.vegaprotocol.io/vega/core/datasource/external/ethverifier"
    26  	"code.vegaprotocol.io/vega/core/datasource/spec"
    27  	"code.vegaprotocol.io/vega/core/types"
    28  	vgcontext "code.vegaprotocol.io/vega/libs/context"
    29  	"code.vegaprotocol.io/vega/logging"
    30  )
    31  
    32  type SpecActivationListener func(listener spec.SpecActivationsListener)
    33  
    34  type L2EthCallEngines struct {
    35  	log         *logging.Logger
    36  	cfg         ethcall.Config
    37  	isValidator bool
    38  	clients     *eth.L2Clients
    39  	forwarder   ethcall.Forwarder
    40  
    41  	// chain id -> engine
    42  	engines                map[string]*ethcall.Engine
    43  	specActivationListener SpecActivationListener
    44  }
    45  
    46  func NewL2EthCallEngines(log *logging.Logger, cfg ethcall.Config, isValidator bool, clients *eth.L2Clients, forwarder ethcall.Forwarder, specActivationListener SpecActivationListener) *L2EthCallEngines {
    47  	return &L2EthCallEngines{
    48  		log:                    log,
    49  		cfg:                    cfg,
    50  		isValidator:            isValidator,
    51  		clients:                clients,
    52  		forwarder:              forwarder,
    53  		engines:                map[string]*ethcall.Engine{},
    54  		specActivationListener: specActivationListener,
    55  	}
    56  }
    57  
    58  func (v *L2EthCallEngines) GetOrInstantiate(chainID string) (ethverifier.EthCallEngine, error) {
    59  	if e, ok := v.engines[chainID]; ok {
    60  		return e, nil
    61  	}
    62  
    63  	v.log.Panic("should be instantiated by now really?")
    64  	return nil, nil
    65  }
    66  
    67  func (v *L2EthCallEngines) OnEthereumL2ConfigsUpdated(
    68  	ctx context.Context, ethCfg *types.EthereumL2Configs,
    69  ) error {
    70  	// new L2 configured, instatiate the verifier for it.
    71  	for _, c := range ethCfg.Configs {
    72  		// if already exists, do nothing
    73  		if e, ok := v.engines[c.ChainID]; ok {
    74  			// the blockInterval might have changed, so let just call that.
    75  			e.EnsureChainID(ctx, c.ChainID, c.BlockInterval, v.isValidator)
    76  			continue
    77  		}
    78  
    79  		var clt *eth.L2Client
    80  		if v.isValidator {
    81  			var ok bool
    82  			clt, _, ok = v.clients.Get(c.ChainID)
    83  			if !ok {
    84  				v.log.Panic("ethereum client not configured for L2",
    85  					logging.String("chain-id", c.ChainID),
    86  					logging.String("network-id", c.NetworkID),
    87  				)
    88  			}
    89  		}
    90  
    91  		e := ethcall.NewEngine(v.log, v.cfg, v.isValidator, clt, v.forwarder)
    92  		e.EnsureChainID(ctx, c.ChainID, c.BlockInterval, v.isValidator)
    93  		v.engines[c.ChainID] = e
    94  
    95  		// if we are restoring from a snapshot we want to delay starting the engine
    96  		// until we know what block height to use. If we aren't restoring from a snapshot
    97  		// we are either loading from genesis, or the engine has been added dynamically and
    98  		// so we want to kick it off
    99  		if !vgcontext.InProgressSnapshotRestore(ctx) {
   100  			e.Start()
   101  		}
   102  
   103  		// setup activation listener
   104  		v.specActivationListener(v.engines[c.ChainID])
   105  	}
   106  
   107  	return nil
   108  }