Skip to content

Commit

Permalink
feat: Integrate op-node with op-signer for block payload signing (#59)
Browse files Browse the repository at this point in the history
* feat: integrate op-signer with op-node for block payload signing

* Update README.md

* Add missing erorr handling

* Modify to use BlockPayloadArgs and use the new opsigner rpc namespace

* Temporarily update go.mod to use counterpart monorepo pr

* Add tests for blockPayload signing
  • Loading branch information
mininny authored Dec 3, 2024
1 parent 7900a49 commit 6a5462e
Show file tree
Hide file tree
Showing 12 changed files with 497 additions and 236 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This repository is an extension of the [Optimism monorepo](https://github.com/et

## Components
- op-conductor-mon: Monitors multiple op-conductor instances and provides a unified interface for reporting metrics.
- op-signer: Thin gateway that supports `eth_signTransaction` RPC endpoint to sign ethereum tx payloads using private key stored in KMS
- op-signer: Thin gateway that supports various RPC endpoints to sign payloads from op-stack components using private key stored in KMS.
- op-ufm: User facing monitoring creates transactions at regular intervals and observe transaction propagation across different RPC providers.

## Release Process
Expand Down
4 changes: 2 additions & 2 deletions op-signer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
FROM golang:1.21.3-alpine3.18 as builder
FROM golang:1.22.7-alpine3.20 as builder

COPY ./op-signer /app

WORKDIR /app
RUN apk --no-cache add make jq bash git alpine-sdk
RUN make build

FROM alpine:3.18
FROM alpine:3.20
RUN apk --no-cache add ca-certificates

RUN addgroup -S app && adduser -S app -G app
Expand Down
17 changes: 16 additions & 1 deletion op-signer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,26 @@ Signer service and client library

## Setup

Install go1.18
Install go1.21

```bash
make build

source .env.example # (or copy to .envrc if using direnv)
./bin/signer
```

## Configuring Cloud KMS
Modify the `config.yaml` file to connect op-signer with your cloud KMS.
- `name`: DNS name of the client connecting to op-signer. Must match the DNS name in the TLS certificate.
- `key`: key resource name of the Cloud KMS.

You can add a list of `name`/`key` to use different keys for each client connecting with op-signer.

## Testing with local tls
Running op-signer requires mTLS connection between the op-signer and the requesting server.

To test services in your local environment
1. run `./gen-local-tls.sh`
2. Check that `/tls` folder has been created with certificates and keys
2. Set the appropriate flags (`tls.cert`, `tls.key`, `tls.ca`) to the corresponding files under `/tls`
93 changes: 65 additions & 28 deletions op-signer/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/urfave/cli/v2"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -197,43 +198,79 @@ func MainAppAction(version string) cliapp.LifecycleAction {
}
}

func ClientSign(version string) func(cliCtx *cli.Context) error {
type SignActionType string

const (
SignTransaction SignActionType = "transaction"
SignBlockPayload SignActionType = "block_payload"
)

func ClientSign(version string, action SignActionType) func(cliCtx *cli.Context) error {
return func(cliCtx *cli.Context) error {
cfg := NewConfig(cliCtx)
if err := cfg.Check(); err != nil {
return fmt.Errorf("invalid CLI flags: %w", err)
}

l := oplog.NewLogger(os.Stdout, cfg.LogConfig)
log.Root().SetHandler(l.GetHandler())

txarg := cliCtx.Args().First()
if txarg == "" {
return errors.New("no transaction argument was provided")
}
txraw, err := hexutil.Decode(txarg)
if err != nil {
return errors.New("failed to decode transaction argument")
}

client, err := client.NewSignerClient(l, cfg.ClientEndpoint, cfg.TLSConfig)
if err != nil {
return err
}

tx := &types.Transaction{}
if err := tx.UnmarshalBinary(txraw); err != nil {
return fmt.Errorf("failed to unmarshal transaction argument: %w", err)
oplog.SetGlobalLogHandler(l.Handler())

switch action {
case SignTransaction:
txarg := cliCtx.Args().Get(0)
if txarg == "" {
return errors.New("no transaction argument was provided")
}
txraw, err := hexutil.Decode(txarg)
if err != nil {
return errors.New("failed to decode transaction argument")
}

client, err := client.NewSignerClient(l, cfg.ClientEndpoint, cfg.TLSConfig)
if err != nil {
return err
}

tx := &types.Transaction{}
if err := tx.UnmarshalBinary(txraw); err != nil {
return fmt.Errorf("failed to unmarshal transaction argument: %w", err)
}

tx, err = client.SignTransaction(context.Background(), tx)
if err != nil {
return err
}

result, _ := tx.MarshalJSON()
fmt.Println(string(result))

case SignBlockPayload:
blockPayloadHash := cliCtx.Args().Get(0)
if blockPayloadHash == "" {
return errors.New("no block payload argument was provided")
}

client, err := client.NewSignerClient(l, cfg.ClientEndpoint, cfg.TLSConfig)
if err != nil {
return err
}

signingHash := common.Hash{}
if err := signingHash.UnmarshalText([]byte(blockPayloadHash)); err != nil {
return fmt.Errorf("failed to unmarshal block payload argument: %w", err)
}

signature, err := client.SignBlockPayload(context.Background(), signingHash)
if err != nil {
return err
}

fmt.Println(string(signature[:]))

case "":
return errors.New("no action was provided")
}

tx, err = client.SignTransaction(context.Background(), tx)
if err != nil {
return err
}

result, _ := tx.MarshalJSON()
fmt.Println(string(result))

return nil
}
}
14 changes: 14 additions & 0 deletions op-signer/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"os"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -89,3 +90,16 @@ func (s *SignerClient) SignTransaction(

return signed, nil
}

func (s *SignerClient) SignBlockPayload(
ctx context.Context,
signingHash common.Hash,
) ([]byte, error) {
var result []byte

if err := s.client.Call(&result, "eth_signBlockPayload", signingHash); err != nil {
return []byte{}, fmt.Errorf("eth_signTransaction failed: %w", err)
}

return result, nil
}
10 changes: 8 additions & 2 deletions op-signer/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ func main() {
Usage: "test client for signer service",
Subcommands: []*cli.Command{
{
Name: "sign",
Name: string(signer.SignTransaction),
Usage: "sign a transaction",
Action: signer.ClientSign(Version),
Action: signer.ClientSign(Version, signer.SignTransaction),
Flags: cliapp.ProtectFlags(signer.ClientSignCLIFlags("SIGNER")),
},
{
Name: string(signer.SignBlockPayload),
Usage: "sign a block payload",
Action: signer.ClientSign(Version, signer.SignBlockPayload),
Flags: cliapp.ProtectFlags(signer.ClientSignCLIFlags("SIGNER")),
},
},
Expand Down
126 changes: 65 additions & 61 deletions op-signer/go.mod
Original file line number Diff line number Diff line change
@@ -1,115 +1,119 @@
module github.com/ethereum-optimism/infra/op-signer

go 1.21
go 1.22

toolchain go1.22.0

replace github.com/ethereum-optimism/optimism v1.4.3-0.20240125020216-6a3b1ec12399 => github.com/testinprod-io/optimism v0.0.0-20241018221952-12c4820e35fb

require (
cloud.google.com/go/kms v1.10.1
cloud.google.com/go/kms v1.12.1
github.com/ethereum-optimism/optimism v1.4.3-0.20240125020216-6a3b1ec12399
github.com/ethereum/go-ethereum v1.13.5
github.com/ethereum/go-ethereum v1.14.11
github.com/golang/mock v1.6.0
github.com/googleapis/gax-go v1.0.3
github.com/googleapis/gax-go/v2 v2.11.0
github.com/holiman/uint256 v1.2.3
github.com/prometheus/client_golang v1.18.0
github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.27.1
google.golang.org/protobuf v1.33.0
github.com/holiman/uint256 v1.3.1
github.com/prometheus/client_golang v1.20.4
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.27.4
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v3 v3.0.1
)

require (
cloud.google.com/go/compute v1.20.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v0.13.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/iam v1.1.1 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.7.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cockroachdb/errors v1.11.3 // indirect
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20231018212520-f6cde3fc2fa4 // indirect
github.com/cockroachdb/pebble v1.1.2 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240123193359-a5fc767e225a // indirect
github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240910145426-b3905c89e8ac // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/go-bexpr v0.1.11 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.1 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/rs/cors v1.9.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/cors v1.11.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/supranational/blst v0.3.13 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.16.1 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/term v0.24.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/time v0.6.0 // indirect
golang.org/x/tools v0.24.0 // indirect
google.golang.org/api v0.126.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/grpc v1.55.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/grpc v1.57.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
honnef.co/go/tools v0.0.1-2020.1.4 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)

replace github.com/ethereum/go-ethereum v1.13.5 => github.com/ethereum-optimism/op-geth v1.101305.3-rc.1.0.20240124221225-5c6f10d449ab
replace github.com/ethereum/go-ethereum v1.14.11 => github.com/ethereum-optimism/op-geth v1.101408.1-0.20241002211323-d5a96613c22b
Loading

0 comments on commit 6a5462e

Please sign in to comment.