Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
feat(prover): additional startup info for guardian prover (#552)
Browse files Browse the repository at this point in the history
Co-authored-by: David <[email protected]>
  • Loading branch information
cyberhorsey and davidtaikocha committed Feb 16, 2024
1 parent b93cfcf commit 6fefa6e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 14 deletions.
12 changes: 12 additions & 0 deletions cmd/flags/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,16 @@ var (
Value: false,
Category: proverCategory,
}
L1NodeVersion = &cli.StringFlag{
Name: "prover.l1NodeVersion",
Usage: "Version or tag or the L1 Node Version used as an L1 RPC Url by this guardian prover",
Category: proverCategory,
}
L2NodeVersion = &cli.StringFlag{
Name: "prover.l2NodeVersion",
Usage: "Version or tag or the L2 Node Version used as an L2 RPC Url by this guardian prover",
Category: proverCategory,
}
)

// ProverFlags All prover flags.
Expand Down Expand Up @@ -227,4 +237,6 @@ var ProverFlags = MergeFlags(CommonFlags, []cli.Flag{
DatabaseCacheSize,
ProverAssignmentHookAddress,
Allowance,
L1NodeVersion,
L2NodeVersion,
})
15 changes: 15 additions & 0 deletions prover/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package prover

import (
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"net/url"
Expand Down Expand Up @@ -57,6 +58,8 @@ type Config struct {
Allowance *big.Int
GuardianProverHealthCheckServerEndpoint *url.URL
RaikoHostEndpoint string
L1NodeVersion string
L2NodeVersion string
}

// NewConfigFromCliContext creates a new config instance from command line flags.
Expand Down Expand Up @@ -114,9 +117,19 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) {
if err := c.Set(flags.ProveUnassignedBlocks.Name, "true"); err != nil {
return nil, err
}

if err := c.Set(flags.ContesterMode.Name, "true"); err != nil {
return nil, err
}

// l1 and l2 node version flags are required only if guardian prover
if !c.IsSet(flags.L1NodeVersion.Name) {
return nil, errors.New("L1NodeVersion is required if guardian prover is set")
}

if !c.IsSet(flags.L2NodeVersion.Name) {
return nil, errors.New("L2NodeVersion is required if guardian prover is set")
}
}

if !c.IsSet(flags.GuardianProver.Name) && !c.IsSet(flags.RaikoHostEndpoint.Name) {
Expand Down Expand Up @@ -165,5 +178,7 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) {
DatabasePath: c.String(flags.DatabasePath.Name),
DatabaseCacheSize: c.Uint64(flags.DatabaseCacheSize.Name),
Allowance: allowance,
L1NodeVersion: c.String(flags.L1NodeVersion.Name),
L2NodeVersion: c.String(flags.L2NodeVersion.Name),
}, nil
}
8 changes: 8 additions & 0 deletions prover/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import (
var (
l1WsEndpoint = os.Getenv("L1_NODE_WS_ENDPOINT")
l1HttpEndpoint = os.Getenv("L1_NODE_HTTP_ENDPOINT")
l1NodeVersion = "1.0.0"
l2WsEndpoint = os.Getenv("L2_EXECUTION_ENGINE_WS_ENDPOINT")
l2HttpEndpoint = os.Getenv("L2_EXECUTION_ENGINE_HTTP_ENDPOINT")
l2NodeVersion = "0.1.0"
taikoL1 = os.Getenv("TAIKO_L1_ADDRESS")
taikoL2 = os.Getenv("TAIKO_L2_ADDRESS")
allowance = "10000000000000000000000000000000000000000000000000"
Expand Down Expand Up @@ -50,6 +52,8 @@ func (s *ProverTestSuite) TestNewConfigFromCliContextGuardianProver() {
s.Equal(uint64(minTierFee), c.MinPseZkevmTierFee.Uint64())
s.Equal(uint64(3), c.ProveBlockTxReplacementMultiplier)
s.Equal(uint64(256), c.ProveBlockMaxTxGasTipCap.Uint64())
s.Equal(c.L1NodeVersion, l1NodeVersion)
s.Equal(c.L2NodeVersion, l2NodeVersion)
s.Nil(new(Prover).InitFromCli(context.Background(), ctx))
s.True(c.ProveUnassignedBlocks)
s.Equal("dbPath", c.DatabasePath)
Expand Down Expand Up @@ -88,6 +92,8 @@ func (s *ProverTestSuite) TestNewConfigFromCliContextGuardianProver() {
"--" + flags.DatabaseCacheSize.Name, "128",
"--" + flags.MaxProposedIn.Name, "100",
"--" + flags.Allowance.Name, allowance,
"--" + flags.L1NodeVersion.Name, l1NodeVersion,
"--" + flags.L2NodeVersion.Name, l2NodeVersion,
}))
}

Expand Down Expand Up @@ -129,6 +135,8 @@ func (s *ProverTestSuite) SetupApp() *cli.App {
&cli.StringFlag{Name: flags.ProverAssignmentHookAddress.Name},
&cli.StringFlag{Name: flags.Allowance.Name},
&cli.StringFlag{Name: flags.ContesterMode.Name},
&cli.StringFlag{Name: flags.L1NodeVersion.Name},
&cli.StringFlag{Name: flags.L2NodeVersion.Name},
}
app.Action = func(ctx *cli.Context) error {
_, err := NewConfigFromCliContext(ctx)
Expand Down
43 changes: 32 additions & 11 deletions prover/guardian_prover_sender/guardian_prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
type healthCheckReq struct {
ProverAddress string `json:"prover"`
HeartBeatSignature []byte `json:"heartBeatSignature"`
LatestL1Block uint64 `json:"latestL1Block"`
LatestL2Block uint64 `json:"latestL2Block"`
}

// signedBlockReq is the request body sent to the health check server when a block is signed.
Expand All @@ -36,10 +38,12 @@ type signedBlockReq struct {

// startupReq is the request body send to the health check server when the guardian prover starts up.
type startupReq struct {
ProverAddress string `json:"prover"`
Version string `json:"version"`
Revision string `json:"revision"`
Signature []byte `json:"signature"`
ProverAddress string `json:"prover"`
GuardianVersion string `json:"guardianVersion"`
L1NodeVersion string `json:"l1NodeVersion"`
L2NodeVersion string `json:"l2NodeVersion"`
Revision string `json:"revision"`
Signature []byte `json:"signature"`
}

// GuardianProverBlockSender is responsible for signing and sending known blocks to the health check server.
Expand Down Expand Up @@ -118,7 +122,13 @@ func (s *GuardianProverBlockSender) SignAndSendBlock(ctx context.Context, blockI
)
}

func (s *GuardianProverBlockSender) SendStartup(ctx context.Context, revision string, version string) error {
func (s *GuardianProverBlockSender) SendStartup(
ctx context.Context,
revision string,
version string,
l1NodeVersion string,
l2NodeVersion string,
) error {
if s.healthCheckServerEndpoint == nil {
log.Info("No health check server endpoint set, returning early")
return nil
Expand All @@ -128,17 +138,22 @@ func (s *GuardianProverBlockSender) SendStartup(ctx context.Context, revision st
crypto.Keccak256Hash(
s.proverAddress.Bytes(),
[]byte(revision),
[]byte(version)).Bytes(),
[]byte(version),
[]byte(l1NodeVersion),
[]byte(l2NodeVersion),
).Bytes(),
s.privateKey)
if err != nil {
return err
}

req := &startupReq{
Revision: revision,
Version: version,
ProverAddress: s.proverAddress.Hex(),
Signature: sig,
Revision: revision,
GuardianVersion: version,
L1NodeVersion: l1NodeVersion,
L2NodeVersion: l2NodeVersion,
ProverAddress: s.proverAddress.Hex(),
Signature: sig,
}

if err := s.post(ctx, "startup", req); err != nil {
Expand Down Expand Up @@ -242,7 +257,11 @@ func (s *GuardianProverBlockSender) Close() error {
}

// SendHeartbeat sends a heartbeat to the health check server.
func (s *GuardianProverBlockSender) SendHeartbeat(ctx context.Context) error {
func (s *GuardianProverBlockSender) SendHeartbeat(
ctx context.Context,
latestL1Block uint64,
latestL2Block uint64,
) error {
sig, err := crypto.Sign(crypto.Keccak256Hash([]byte("HEART_BEAT")).Bytes(), s.privateKey)
if err != nil {
return err
Expand All @@ -251,6 +270,8 @@ func (s *GuardianProverBlockSender) SendHeartbeat(ctx context.Context) error {
req := &healthCheckReq{
HeartBeatSignature: sig,
ProverAddress: s.proverAddress.Hex(),
LatestL1Block: latestL1Block,
LatestL2Block: latestL2Block,
}

if err := s.post(ctx, "healthCheck", req); err != nil {
Expand Down
10 changes: 8 additions & 2 deletions prover/guardian_prover_sender/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ import (

type BlockSigner interface {
SignAndSendBlock(ctx context.Context, blockID *big.Int) error
SendStartup(ctx context.Context, revision string, version string) error
SendStartup(
ctx context.Context,
revision string,
version string,
l1NodeVersion string,
l2NodeVersion string,
) error
}

type Heartbeater interface {
SendHeartbeat(ctx context.Context) error
SendHeartbeat(ctx context.Context, latestL1Block uint64, latestL2Block uint64) error
}

// BlockSenderHeartbeater defines an interface that communicates with a central Guardian Prover server,
Expand Down
20 changes: 19 additions & 1 deletion prover/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ func (p *Prover) Start() error {
p.ctx,
version.CommitVersion(),
version.CommitVersion(),
p.cfg.L1NodeVersion,
p.cfg.L2NodeVersion,
); err != nil {
log.Crit("Failed to send guardian prover startup", "error", err)
}
Expand Down Expand Up @@ -1321,7 +1323,23 @@ func (p *Prover) heartbeatInterval(ctx context.Context) {
case <-p.ctx.Done():
return
case <-t.C:
if err := p.guardianProverSender.SendHeartbeat(ctx); err != nil {
latestL1Block, err := p.rpc.L1.BlockNumber(ctx)
if err != nil {
log.Error("guardian prover error getting latestL1Block", err)
continue
}

latestL2Block, err := p.rpc.L2.BlockNumber(ctx)
if err != nil {
log.Error("guardian prover error getting latestL2Block", err)
continue
}

if err := p.guardianProverSender.SendHeartbeat(
ctx,
latestL1Block,
latestL2Block,
); err != nil {
log.Error("Failed to send guardian prover heartbeat", "error", err)
}
}
Expand Down
2 changes: 2 additions & 0 deletions prover/prover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ func (s *ProverTestSuite) initProver(
Allowance: allowance,
RPCTimeout: 3 * time.Second,
BackOffMaxRetrys: 3,
L1NodeVersion: "1.0.0",
L2NodeVersion: "0.1.0",
}))
p.srv = testutils.NewTestProverServer(
&s.ClientTestSuite,
Expand Down

0 comments on commit 6fefa6e

Please sign in to comment.