Skip to content

Commit

Permalink
feat: Add remote eots manager (ethereum-optimism#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry authored Oct 17, 2023
1 parent 6a0a843 commit 6858a1b
Show file tree
Hide file tree
Showing 33 changed files with 2,183 additions and 166 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ proto-all: proto-gen

proto-gen:
./proto/scripts/protocgen.sh
make -C eotsmanager proto-gen

.PHONY: proto-gen

Expand Down
10 changes: 10 additions & 0 deletions eotsmanager/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
###############################################################################
### Protobuf ###
###############################################################################

proto-all: proto-gen

proto-gen:
./proto/scripts/protocgen.sh

.PHONY: proto-gen
124 changes: 124 additions & 0 deletions eotsmanager/client/rpcclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package client

import (
"context"
"fmt"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/babylonchain/btc-validator/eotsmanager"
"github.com/babylonchain/btc-validator/eotsmanager/proto"
"github.com/babylonchain/btc-validator/eotsmanager/types"
)

var _ eotsmanager.EOTSManager = &EOTSManagerGRpcClient{}

type EOTSManagerGRpcClient struct {
client proto.EOTSManagerClient
conn *grpc.ClientConn
}

func NewEOTSManagerGRpcClient(remoteAddr string) (*EOTSManagerGRpcClient, error) {
conn, err := grpc.Dial(remoteAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err)
}

return &EOTSManagerGRpcClient{
client: proto.NewEOTSManagerClient(conn),
conn: conn,
}, nil
}

func (c *EOTSManagerGRpcClient) CreateKey(name, passPhrase string) ([]byte, error) {
req := &proto.CreateKeyRequest{Name: name, PassPhrase: passPhrase}
res, err := c.client.CreateKey(context.Background(), req)
if err != nil {
return nil, err
}

return res.Pk, nil
}

func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) {
req := &proto.CreateRandomnessPairListRequest{
Uid: uid,
ChainId: chainID,
StartHeight: startHeight,
Num: num,
}
res, err := c.client.CreateRandomnessPairList(context.Background(), req)
if err != nil {
return nil, err
}

pubRandFieldValList := make([]*btcec.FieldVal, 0, len(res.PubRandList))
for _, r := range res.PubRandList {
var fieldVal *btcec.FieldVal
fieldVal.SetByteSlice(r)
pubRandFieldValList = append(pubRandFieldValList, fieldVal)
}

return pubRandFieldValList, nil
}

func (c *EOTSManagerGRpcClient) CreateRandomnessPairListWithExistenceCheck(uid, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) {
// TODO consider remove this API when we no longer store randomness
return c.CreateRandomnessPairList(uid, chainID, startHeight, num)
}

func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passPhrase string) (*types.KeyRecord, error) {
req := &proto.KeyRecordRequest{Uid: uid, PassPhrase: passPhrase}

res, err := c.client.KeyRecord(context.Background(), req)
if err != nil {
return nil, err
}

privKey, _ := btcec.PrivKeyFromBytes(res.PrivateKey)

return &types.KeyRecord{
Name: res.Name,
PrivKey: privKey,
}, nil
}

func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64) (*btcec.ModNScalar, error) {
req := &proto.SignEOTSRequest{
Uid: uid,
ChainId: chaiID,
Msg: msg,
Height: height,
}
res, err := c.client.SignEOTS(context.Background(), req)
if err != nil {
return nil, err
}

var s *btcec.ModNScalar
s.SetByteSlice(res.Sig)

return s, nil
}

func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte) (*schnorr.Signature, error) {
req := &proto.SignSchnorrSigRequest{Uid: uid, Msg: msg}
res, err := c.client.SignSchnorrSig(context.Background(), req)
if err != nil {
return nil, err
}

sig, err := schnorr.ParseSignature(res.Sig)
if err != nil {
return nil, err
}

return sig, nil
}

func (c *EOTSManagerGRpcClient) Close() error {
return c.conn.Close()
}
66 changes: 66 additions & 0 deletions eotsmanager/cmd/eotscli/admin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package main

import (
"fmt"

"github.com/jessevdk/go-flags"
"github.com/urfave/cli"

eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config"
)

var adminCommands = []cli.Command{
{
Name: "admin",
ShortName: "ad",
Usage: "Different utility and admin commands.",
Category: "Admin",
Subcommands: []cli.Command{
dumpCfgCommand,
},
},
}

const (
configFileDirFlag = "config-file-dir"
)

var (
defaultConfigPath = eotscfg.DefaultConfigFile
)

var dumpCfgCommand = cli.Command{
Name: "dump-config",
ShortName: "dc",
Usage: "Dump default configuration file.",
Flags: []cli.Flag{
cli.StringFlag{
Name: configFileDirFlag,
Usage: "Path to where the default config file will be dumped",
Value: defaultConfigPath,
},
},
Action: dumpCfg,
}

func dumpCfg(c *cli.Context) error {
configPath := c.String(configFileDirFlag)

if eotscfg.FileExists(configPath) {
return cli.NewExitError(
fmt.Sprintf("config already exists under provided path: %s", configPath),
1,
)
}

defaultConfig := eotscfg.DefaultConfig()
fileParser := flags.NewParser(&defaultConfig, flags.Default)

err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults)

if err != nil {
return err
}

return nil
}
24 changes: 24 additions & 0 deletions eotsmanager/cmd/eotscli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"fmt"
"os"

"github.com/urfave/cli"
)

func fatal(err error) {
fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err)
os.Exit(1)
}

func main() {
app := cli.NewApp()
app.Name = "eotscli"
app.Usage = "Control plane for the EOTS Manager Daemon (eotsd)."
app.Commands = append(app.Commands, adminCommands...)

if err := app.Run(os.Args); err != nil {
fatal(err)
}
}
48 changes: 48 additions & 0 deletions eotsmanager/cmd/eotsd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"fmt"
"os"

"github.com/jessevdk/go-flags"
"github.com/lightningnetwork/lnd/signal"

"github.com/babylonchain/btc-validator/eotsmanager"
"github.com/babylonchain/btc-validator/eotsmanager/config"
eotsservice "github.com/babylonchain/btc-validator/eotsmanager/service"
)

func main() {
// Hook interceptor for os signals.
shutdownInterceptor, err := signal.Intercept()
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

cfg, cfgLogger, err := config.LoadConfig()
if err != nil {
if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
// Print error if not due to help request.
err = fmt.Errorf("failed to load config: %w", err)
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

// Help was requested, exit normally.
os.Exit(0)
}

eotsManager, err := eotsmanager.NewLocalEOTSManager(cfg, cfgLogger)
if err != nil {
cfgLogger.Errorf("failed to create EOTS manager: %v", err)
os.Exit(1)
}

eotsServer := eotsservice.NewEOTSManagerServer(cfg, cfgLogger, eotsManager, shutdownInterceptor)

if err := eotsServer.RunUntilShutdown(); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
Loading

0 comments on commit 6858a1b

Please sign in to comment.