mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
* feat: Euclid release on Scroll Sepolia (wip) * update system contract consensus params * update timestamp * improve logs * fix * adjust logs * undo some changes
142 lines
3.7 KiB
Go
142 lines
3.7 KiB
Go
package system_contract
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/scroll-tech/go-ethereum/common"
|
|
"github.com/scroll-tech/go-ethereum/log"
|
|
"github.com/scroll-tech/go-ethereum/params"
|
|
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
|
|
)
|
|
|
|
const (
|
|
defaultSyncInterval = 10 * time.Second
|
|
)
|
|
|
|
// SystemContract is the proof-of-authority consensus engine that fetches
|
|
// the authorized signer from the SystemConfig contract, starting from EuclidV2.
|
|
type SystemContract struct {
|
|
config *params.SystemContractConfig // Consensus engine configuration parameters
|
|
client sync_service.EthClient // RPC client to fetch info from L1
|
|
|
|
signerAddressL1 common.Address // Address of the signer stored in L1 System Contract
|
|
|
|
signer common.Address // Ethereum address of the signing key
|
|
signFn SignerFn // Signer function to authorize hashes with
|
|
lock sync.RWMutex // Protects the signer and proposals fields
|
|
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
}
|
|
|
|
// New creates a SystemContract consensus engine with the initial
|
|
// authorized signer fetched from L1 (if available).
|
|
func New(ctx context.Context, config *params.SystemContractConfig, client sync_service.EthClient) *SystemContract {
|
|
log.Info("Initializing system_contract consensus engine", "config", config)
|
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
|
|
s := &SystemContract{
|
|
config: config,
|
|
client: client,
|
|
|
|
ctx: ctx,
|
|
cancel: cancel,
|
|
}
|
|
|
|
if err := s.fetchAddressFromL1(); err != nil {
|
|
log.Error("Failed to fetch signer address from L1", "err", err)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// Authorize injects a private key into the consensus engine to mint new blocks
|
|
// with.
|
|
func (s *SystemContract) Authorize(signer common.Address, signFn SignerFn) {
|
|
log.Info("Authorizing system contract consensus", "signer", signer.Hex())
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
|
|
s.signer = signer
|
|
s.signFn = signFn
|
|
}
|
|
|
|
func (s *SystemContract) Start() {
|
|
go func() {
|
|
log.Info("starting SystemContract")
|
|
syncTicker := time.NewTicker(defaultSyncInterval)
|
|
defer syncTicker.Stop()
|
|
for {
|
|
select {
|
|
case <-s.ctx.Done():
|
|
return
|
|
default:
|
|
}
|
|
select {
|
|
case <-s.ctx.Done():
|
|
return
|
|
case <-syncTicker.C:
|
|
if err := s.fetchAddressFromL1(); err != nil {
|
|
log.Error("Failed to fetch signer address from L1", "err", err)
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (s *SystemContract) fetchAddressFromL1() error {
|
|
address, err := s.client.StorageAt(s.ctx, s.config.SystemContractAddress, s.config.SystemContractSlot, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get signer address from L1 System Contract: %w", err)
|
|
}
|
|
bAddress := common.BytesToAddress(address)
|
|
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
|
|
// Validate the address is not empty
|
|
if bAddress == (common.Address{}) {
|
|
log.Debug("Retrieved empty signer address from L1 System Contract", "contract", s.config.SystemContractAddress.Hex(), "slot", s.config.SystemContractSlot.Hex())
|
|
|
|
// Not initialized yet -- we don't consider this an error
|
|
if s.signerAddressL1 == (common.Address{}) {
|
|
log.Warn("System Contract signer address not initialized")
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("retrieved empty signer address from L1 System Contract")
|
|
}
|
|
|
|
log.Debug("Read address from system contract", "address", bAddress.Hex())
|
|
|
|
if s.signerAddressL1 != bAddress {
|
|
s.signerAddressL1 = bAddress
|
|
log.Info("Updated new signer from L1 system contract", "signer", bAddress.Hex())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Close implements consensus.Engine.
|
|
func (s *SystemContract) Close() error {
|
|
s.cancel()
|
|
return nil
|
|
}
|
|
|
|
func (s *SystemContract) currentSignerAddressL1() common.Address {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
|
|
return s.signerAddressL1
|
|
}
|
|
|
|
func (s *SystemContract) localSignerAddress() common.Address {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
|
|
return s.signer
|
|
}
|