code.vegaprotocol.io/vega@v0.79.0/core/evtforward/engine.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 evtforward 17 18 import ( 19 "context" 20 "fmt" 21 22 "code.vegaprotocol.io/vega/core/evtforward/ethereum" 23 "code.vegaprotocol.io/vega/core/types" 24 "code.vegaprotocol.io/vega/logging" 25 ) 26 27 const ( 28 topEngineLogger = "event-forwarder" 29 ethereumLogger = "ethereum" 30 ) 31 32 type Engine struct { 33 cfg ethereum.Config 34 log *logging.Logger 35 36 ethEngine *ethereum.Engine 37 38 stakingStartingBlock uint64 39 multisigControlStartingBlock uint64 40 } 41 42 func NewEngine(log *logging.Logger, config ethereum.Config) *Engine { 43 topEngineLogger := log.Named(topEngineLogger) 44 topEngineLogger.SetLevel(config.Level.Get()) 45 46 return &Engine{ 47 cfg: config, 48 log: topEngineLogger, 49 } 50 } 51 52 // ReloadConf updates the internal configuration of the Event Forwarder engine. 53 func (e *Engine) ReloadConf(config ethereum.Config) { 54 e.log.Info("Reloading configuration") 55 56 if e.log.GetLevel() != config.Level.Get() { 57 e.log.Debug("Updating log level", 58 logging.String("old", e.log.GetLevel().String()), 59 logging.String("new", config.Level.String()), 60 ) 61 e.log.SetLevel(config.Level.Get()) 62 } 63 if e.ethEngine != nil { 64 e.ethEngine.ReloadConf(config) 65 } 66 } 67 68 func (e *Engine) UpdateCollateralStartingBlock(b uint64) { 69 e.ethEngine.UpdateCollateralStartingBlock(b) 70 } 71 72 func (e *Engine) UpdateStakingStartingBlock(b uint64) { 73 e.stakingStartingBlock = b 74 e.ethEngine.UpdateStakingStartingBlock(b) 75 } 76 77 func (e *Engine) UpdateMultisigControlStartingBlock(b uint64) { 78 e.multisigControlStartingBlock = b 79 e.ethEngine.UpdateMultiSigControlStartingBlock(b) 80 } 81 82 func (e *Engine) VerifyHeartbeat(ctx context.Context, height uint64, chainID string, contract string, blockTime uint64) error { 83 return e.ethEngine.VerifyHeartbeat(ctx, height, chainID, contract, blockTime) 84 } 85 86 func (e *Engine) UpdateStartingBlock(address string, block uint64) { 87 e.ethEngine.UpdateStartingBlock(address, block) 88 } 89 90 func (e *Engine) SetupEthereumEngine( 91 client ethereum.Client, 92 forwarder ethereum.Forwarder, 93 config ethereum.Config, 94 ethCfg *types.EthereumConfig, 95 assets ethereum.Assets, 96 ) error { 97 if e.log.IsDebug() { 98 e.log.Debug("Ethereum configuration has been loaded") 99 } 100 101 if e.ethEngine != nil { 102 if e.log.IsDebug() { 103 e.log.Debug("Stopping previous Ethereum Event Forwarder") 104 } 105 e.Stop() 106 } 107 108 if e.log.IsDebug() { 109 e.log.Debug("Setting up the Ethereum Event Forwarder") 110 } 111 112 ethLogger := e.log.Named(ethereumLogger) 113 ethLogger.SetLevel(config.Level.Get()) 114 115 filterer, err := ethereum.NewLogFilterer( 116 e.cfg, 117 ethLogger, 118 client, 119 ethCfg.CollateralBridge(), 120 ethCfg.StakingBridge(), 121 ethCfg.VestingBridge(), 122 ethCfg.MultiSigControl(), 123 assets, 124 ethCfg.ChainID(), 125 ) 126 if err != nil { 127 return fmt.Errorf("couldn't create the log filterer: %w", err) 128 } 129 130 e.ethEngine = ethereum.NewEngine( 131 e.cfg, 132 ethLogger, 133 filterer, 134 forwarder, 135 ethCfg.StakingBridge(), 136 ethCfg.VestingBridge(), 137 ethCfg.MultiSigControl(), 138 ethCfg.CollateralBridge(), 139 ethCfg.ChainID(), 140 ethCfg.BlockTime(), 141 ) 142 143 e.UpdateCollateralStartingBlock(filterer.CurrentHeight(context.Background())) 144 145 if e.multisigControlStartingBlock != 0 { 146 e.ethEngine.UpdateMultiSigControlStartingBlock(e.multisigControlStartingBlock) 147 } 148 if e.stakingStartingBlock != 0 { 149 e.ethEngine.UpdateStakingStartingBlock(e.stakingStartingBlock) 150 } 151 152 if err := filterer.VerifyClient(context.Background()); err != nil { 153 return err 154 } 155 156 e.Start() 157 158 return nil 159 } 160 161 func (e *Engine) SetupSecondaryEthereumEngine( 162 client ethereum.Client, 163 forwarder ethereum.Forwarder, 164 config ethereum.Config, 165 ethCfg *types.EVMChainConfig, 166 assets ethereum.Assets, 167 ) error { 168 if e.log.IsDebug() { 169 e.log.Debug("Secondary Ethereum configuration has been loaded") 170 } 171 172 if e.ethEngine != nil { 173 if e.log.IsDebug() { 174 e.log.Debug("Stopping previous secondary Ethereum Event Forwarder") 175 } 176 e.Stop() 177 } 178 179 if e.log.IsDebug() { 180 e.log.Debug("Setting up EVM Event Forwarder") 181 } 182 183 ethLogger := e.log.Named(ethereumLogger) 184 ethLogger.SetLevel(config.Level.Get()) 185 186 filterer, err := ethereum.NewLogFilterer( 187 e.cfg, 188 ethLogger, 189 client, 190 ethCfg.CollateralBridge(), 191 types.EthereumContract{}, 192 types.EthereumContract{}, 193 ethCfg.MultiSigControl(), 194 assets, 195 ethCfg.ChainID(), 196 ) 197 if err != nil { 198 return fmt.Errorf("couldn't create the log filterer: %w", err) 199 } 200 201 e.ethEngine = ethereum.NewEngine( 202 e.cfg, 203 ethLogger, 204 filterer, 205 forwarder, 206 types.EthereumContract{}, 207 types.EthereumContract{}, 208 ethCfg.MultiSigControl(), 209 ethCfg.CollateralBridge(), 210 ethCfg.ChainID(), 211 ethCfg.BlockTime(), 212 ) 213 214 e.UpdateCollateralStartingBlock(filterer.CurrentHeight(context.Background())) 215 216 if e.multisigControlStartingBlock != 0 { 217 e.ethEngine.UpdateMultiSigControlStartingBlock(e.multisigControlStartingBlock) 218 } 219 if e.stakingStartingBlock != 0 { 220 e.ethEngine.UpdateStakingStartingBlock(e.stakingStartingBlock) 221 } 222 223 if err := filterer.VerifyClient(context.Background()); err != nil { 224 return err 225 } 226 227 e.Start() 228 229 return nil 230 } 231 232 func (e *Engine) Start() { 233 if e.ethEngine != nil { 234 go func() { 235 e.log.Info("Starting the Ethereum Event Forwarder") 236 e.ethEngine.Start() 237 }() 238 } 239 } 240 241 func (e *Engine) Stop() { 242 if e.ethEngine != nil { 243 e.log.Info("Stopping the Ethereum Event Forwarder") 244 e.ethEngine.Stop() 245 } 246 e.log.Info("The Event Forwarder engine stopped") 247 } 248 249 // NoopEngine can be use as a stub for the Engine. It does nothing. 250 type NoopEngine struct { 251 log *logging.Logger 252 } 253 254 func NewNoopEngine(log *logging.Logger, config ethereum.Config) *NoopEngine { 255 topEngineLogger := log.Named(topEngineLogger) 256 topEngineLogger.SetLevel(config.Level.Get()) 257 258 return &NoopEngine{ 259 log: topEngineLogger, 260 } 261 } 262 263 func (e *NoopEngine) ReloadConf(_ ethereum.Config) { 264 if e.log.IsDebug() { 265 e.log.Debug("Reloading Ethereum configuration is a no-op") 266 } 267 } 268 269 func (e *NoopEngine) UpdateCollateralStartingBlock(b uint64) {} 270 271 func (e *NoopEngine) UpdateStakingStartingBlock(b uint64) {} 272 273 func (e *NoopEngine) UpdateMultisigControlStartingBlock(b uint64) {} 274 275 func (e *NoopEngine) VerifyHeartbeat(_ context.Context, _ uint64, _ string, _ string, _ uint64) error { 276 return nil 277 } 278 279 func (e *NoopEngine) UpdateStartingBlock(_ string, _ uint64) {} 280 281 func (e *NoopEngine) SetupEthereumEngine( 282 _ ethereum.Client, 283 _ ethereum.Forwarder, 284 _ ethereum.Config, 285 _ *types.EthereumConfig, 286 _ ethereum.Assets, 287 ) error { 288 if e.log.IsDebug() { 289 e.log.Debug("Starting Ethereum configuration is a no-op") 290 } 291 292 return nil 293 } 294 295 func (e *NoopEngine) SetupSecondaryEthereumEngine( 296 _ ethereum.Client, 297 _ ethereum.Forwarder, 298 _ ethereum.Config, 299 _ *types.EVMChainConfig, 300 _ ethereum.Assets, 301 ) error { 302 if e.log.IsDebug() { 303 e.log.Debug("Starting secondary Ethereum configuration is a no-op") 304 } 305 306 return nil 307 } 308 309 func (e *NoopEngine) Start() { 310 if e.log.IsDebug() { 311 e.log.Debug("Starting Ethereum configuration is a no-op") 312 } 313 } 314 315 func (e *NoopEngine) Stop() { 316 if e.log.IsDebug() { 317 e.log.Debug("Stopping Ethereum configuration is a no-op") 318 } 319 }