github.com/ethereum-optimism/optimism@v1.7.2/op-node/node/runtime_config.go (about) 1 package node 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/log" 10 "github.com/ethereum/go-ethereum/params" 11 12 "github.com/ethereum-optimism/optimism/op-node/p2p" 13 "github.com/ethereum-optimism/optimism/op-node/rollup" 14 "github.com/ethereum-optimism/optimism/op-service/eth" 15 ) 16 17 var ( 18 // UnsafeBlockSignerAddressSystemConfigStorageSlot is the storage slot identifier of the unsafeBlockSigner 19 // `address` storage value in the SystemConfig L1 contract. Computed as `keccak256("systemconfig.unsafeblocksigner")` 20 UnsafeBlockSignerAddressSystemConfigStorageSlot = common.HexToHash("0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08") 21 22 // RequiredProtocolVersionStorageSlot is the storage slot that the required protocol version is stored at. 23 // Computed as: `bytes32(uint256(keccak256("protocolversion.required")) - 1)` 24 RequiredProtocolVersionStorageSlot = common.HexToHash("0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0") 25 26 // RecommendedProtocolVersionStorageSlot is the storage slot that the recommended protocol version is stored at. 27 // Computed as: `bytes32(uint256(keccak256("protocolversion.recommended")) - 1)` 28 RecommendedProtocolVersionStorageSlot = common.HexToHash("0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a") 29 ) 30 31 type RuntimeCfgL1Source interface { 32 ReadStorageAt(ctx context.Context, address common.Address, storageSlot common.Hash, blockHash common.Hash) (common.Hash, error) 33 } 34 35 type ReadonlyRuntimeConfig interface { 36 P2PSequencerAddress() common.Address 37 RequiredProtocolVersion() params.ProtocolVersion 38 RecommendedProtocolVersion() params.ProtocolVersion 39 } 40 41 // RuntimeConfig maintains runtime-configurable options. 42 // These options are loaded based on initial loading + updates for every subsequent L1 block. 43 // Only the *latest* values are maintained however, the runtime config has no concept of chain history, 44 // does not require any archive data, and may be out of sync with the rollup derivation process. 45 type RuntimeConfig struct { 46 mu sync.RWMutex 47 48 log log.Logger 49 50 l1Client RuntimeCfgL1Source 51 rollupCfg *rollup.Config 52 53 // l1Ref is the current source of the data, 54 // if this is invalidated with a reorg the data will have to be reloaded. 55 l1Ref eth.L1BlockRef 56 57 runtimeConfigData 58 } 59 60 // runtimeConfigData is a flat bundle of configurable data, easy and light to copy around. 61 type runtimeConfigData struct { 62 p2pBlockSignerAddr common.Address 63 64 // superchain protocol version signals 65 recommended params.ProtocolVersion 66 required params.ProtocolVersion 67 } 68 69 var _ p2p.GossipRuntimeConfig = (*RuntimeConfig)(nil) 70 71 func NewRuntimeConfig(log log.Logger, l1Client RuntimeCfgL1Source, rollupCfg *rollup.Config) *RuntimeConfig { 72 return &RuntimeConfig{ 73 log: log, 74 l1Client: l1Client, 75 rollupCfg: rollupCfg, 76 } 77 } 78 79 func (r *RuntimeConfig) P2PSequencerAddress() common.Address { 80 r.mu.RLock() 81 defer r.mu.RUnlock() 82 return r.p2pBlockSignerAddr 83 } 84 85 func (r *RuntimeConfig) RequiredProtocolVersion() params.ProtocolVersion { 86 r.mu.RLock() 87 defer r.mu.RUnlock() 88 return r.required 89 } 90 91 func (r *RuntimeConfig) RecommendedProtocolVersion() params.ProtocolVersion { 92 r.mu.RLock() 93 defer r.mu.RUnlock() 94 return r.recommended 95 } 96 97 // Load resets the runtime configuration by fetching the latest config data from L1 at the given L1 block. 98 // Load is safe to call concurrently, but will lock the runtime configuration modifications only, 99 // and will thus not block other Load calls with possibly alternative L1 block views. 100 func (r *RuntimeConfig) Load(ctx context.Context, l1Ref eth.L1BlockRef) error { 101 p2pSignerVal, err := r.l1Client.ReadStorageAt(ctx, r.rollupCfg.L1SystemConfigAddress, UnsafeBlockSignerAddressSystemConfigStorageSlot, l1Ref.Hash) 102 if err != nil { 103 return fmt.Errorf("failed to fetch unsafe block signing address from system config: %w", err) 104 } 105 // The superchain protocol version data is optional; only applicable to rollup configs that specify a ProtocolVersions address. 106 var requiredProtVersion, recommendedProtoVersion params.ProtocolVersion 107 if r.rollupCfg.ProtocolVersionsAddress != (common.Address{}) { 108 requiredVal, err := r.l1Client.ReadStorageAt(ctx, r.rollupCfg.ProtocolVersionsAddress, RequiredProtocolVersionStorageSlot, l1Ref.Hash) 109 if err != nil { 110 return fmt.Errorf("required-protocol-version value failed to load from L1 contract: %w", err) 111 } 112 requiredProtVersion = params.ProtocolVersion(requiredVal) 113 recommendedVal, err := r.l1Client.ReadStorageAt(ctx, r.rollupCfg.ProtocolVersionsAddress, RecommendedProtocolVersionStorageSlot, l1Ref.Hash) 114 if err != nil { 115 return fmt.Errorf("recommended-protocol-version value failed to load from L1 contract: %w", err) 116 } 117 recommendedProtoVersion = params.ProtocolVersion(recommendedVal) 118 } 119 r.mu.Lock() 120 defer r.mu.Unlock() 121 r.l1Ref = l1Ref 122 r.p2pBlockSignerAddr = common.BytesToAddress(p2pSignerVal[:]) 123 r.required = requiredProtVersion 124 r.recommended = recommendedProtoVersion 125 r.log.Info("loaded new runtime config values!", "p2p_seq_address", r.p2pBlockSignerAddr) 126 return nil 127 }