Commit 9309f9d4 authored by clabby's avatar clabby

Init backup sync via RPC

parent 1729edd3
......@@ -185,6 +185,12 @@ var (
EnvVar: prefixEnvVar("HEARTBEAT_URL"),
Value: "https://heartbeat.optimism.io",
}
BackupL2UnsafeSyncRPC = cli.StringFlag{
Name: "l2.backup-unsafe-sync-rpc",
Usage: "Set the backup L2 unsafe sync RPC endpoint.",
EnvVar: prefixEnvVar("L2_BACKUP_UNSAFE_SYNC_RPC"),
Required: false,
}
)
var requiredFlags = []cli.Flag{
......@@ -219,6 +225,7 @@ var optionalFlags = append([]cli.Flag{
HeartbeatEnabledFlag,
HeartbeatMonikerFlag,
HeartbeatURLFlag,
BackupL2UnsafeSyncRPC,
}, p2pFlags...)
// Flags contains the list of configuration options available to the binary.
......
......@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
......@@ -370,6 +371,54 @@ func (eq *EngineQueue) tryNextUnsafePayload(ctx context.Context) error {
eq.log.Info("skipping unsafe payload, since it does not build onto the existing unsafe chain", "safe", eq.safeHead.ID(), "unsafe", first.ID(), "payload", first.ID())
eq.unsafePayloads.Pop()
}
// Request the payload that builds upon the current unsafe head from the fallback RPC.
// This is a temporary alternative sync method- in the future, this will be done over the p2p network.
if eq.cfg.BackupL2UnsafeSyncRPC != "" {
eq.log.Info("requesting unsafe payload from backup RPC", "unsafe head", eq.unsafeHead.ID(), "first unsafe payload", first.ID(), "backup rpc", eq.cfg.BackupL2UnsafeSyncRPC)
// TODO: Create a client for the backup RPC and request the payload from the backup sync RPC via the `eth_getBlockByNumber` method.
// Once the payload has been received, verify its integrity and push it into the priority queue.
// TODO: Post Shanghai hardfork, the engine API's `PayloadBodiesByRange` method will be much more efficient, but for now,
// the `eth_getBlockByNumber` method is more widely available.
// Dial the backup unsafe sync RPC.
// TODO: Should this request block this thread (with a reasonable timeout) so that we can attempt to continue when the payload
// has been received and pushed into the priority queue? Or should it be made concurrently?
client, err := rpc.DialHTTP(eq.cfg.BackupL2UnsafeSyncRPC)
if err != nil {
return NewTemporaryError(fmt.Errorf("failed to dial backup unsafe sync RPC: %w", err))
}
// Fetch the next unsafe block from the backup unsafe sync RPC.
var block *types.Block
timeoutCtx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
if err = client.CallContext(timeoutCtx, &block, "eth_getBlockByNumber", eq.unsafeHead.Number+1); err != nil {
return NewTemporaryError(fmt.Errorf("failed to get next unsafe block from backup unsafe sync RPC: %w", err))
}
// Convert the received block to a `eth.ExecutionPayload`.
payload, err := eth.BlockAsPayload(block)
if err != nil {
return NewTemporaryError(fmt.Errorf("failed to convert block to execution payload: %w", err))
}
// TODO: Validate the integrity of the payload.
if _, ok := payload.CheckBlockHash(); !ok {
return NewTemporaryError(fmt.Errorf("received invalid payload from backup unsafe sync RPC; invalid block hash"))
}
eq.log.Info("received unsafe payload from backup RPC", "payload", payload.ID(), "backup rpc", eq.cfg.BackupL2UnsafeSyncRPC)
// Add the received execution payload to the unsafe payload priority queue.
eq.AddUnsafePayload(payload)
eq.log.Info("inserted received unsafe payload into priority queue", "payload", payload.ID(), "backup rpc", eq.cfg.BackupL2UnsafeSyncRPC)
// TODO: Should we attempt to continue here, or wait for the next iteration of the state loop and still return EOF?
}
return io.EOF // time to go to next stage if we cannot process the first unsafe payload
}
......
......@@ -36,6 +36,11 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
return nil, err
}
// If the backup sync RPC flag is set, then use it over the value present in the config file.
if backupSyncRPC := ctx.GlobalString(flags.BackupL2UnsafeSyncRPC.Name); backupSyncRPC != "" {
rollupConfig.BackupL2UnsafeSyncRPC = backupSyncRPC
}
driverConfig, err := NewDriverConfig(ctx)
if err != nil {
return nil, err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment