From 1941ed3e9ce5c726ebc33972c3ad49c3fa98b33f Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Fri, 13 Dec 2024 11:20:48 -0500 Subject: [PATCH 1/6] feat: wip adds bls signer --- tools/bls-signature-creator/.goreleaser.yml | 64 ++++++++++ tools/bls-signature-creator/main.go | 127 ++++++++++++++++++++ tools/go.mod | 1 + tools/go.sum | 2 + 4 files changed, 194 insertions(+) create mode 100644 tools/bls-signature-creator/.goreleaser.yml create mode 100644 tools/bls-signature-creator/main.go diff --git a/tools/bls-signature-creator/.goreleaser.yml b/tools/bls-signature-creator/.goreleaser.yml new file mode 100644 index 000000000..8b6032f4e --- /dev/null +++ b/tools/bls-signature-creator/.goreleaser.yml @@ -0,0 +1,64 @@ +version: 1 + +project_name: bls-signature-creator +dist: /tmp/dist/bls-signature-creator + +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + goarch: + - amd64 + - arm64 + dir: ./tools/bls-signature-creator + binary: "{{ .ProjectName }}" + flags: + - -v + - -trimpath + +archives: + - format: tar.gz + name_template: >- + {{- .Binary }}_ + {{- with index .Env "RELEASE_VERSION" -}} + {{ . }} + {{- else -}} + {{- if .IsSnapshot }}{{ .ShortCommit }} + {{- else }}{{ .Version }} + {{- end }} + {{- end -}} + {{- with index .Env "DIRTY_SUFFIX" -}} + {{ . }} + {{- end -}}_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }} + {{- end }} + {{- if .Arm }}v{{ .Arm }}{{ end }} + format_overrides: + - goos: windows + format: zip + +checksum: + name_template: >- + {{ .ProjectName }}_ + {{- with index .Env "RELEASE_VERSION" -}} + {{ . }} + {{- else -}} + {{- if .IsSnapshot }}{{ .ShortCommit }} + {{- else }}{{ .Version }} + {{- end }} + {{- end -}} + {{- with index .Env "DIRTY_SUFFIX" -}} + {{ . }} + {{- end -}} + _checksums.txt + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" diff --git a/tools/bls-signature-creator/main.go b/tools/bls-signature-creator/main.go new file mode 100644 index 000000000..2eec5631c --- /dev/null +++ b/tools/bls-signature-creator/main.go @@ -0,0 +1,127 @@ +package main + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "io" + "log/slog" + "net/http" + "os" + "strings" + + "github.com/cloudflare/circl/sign/bls" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/urfave/cli/v2" +) + +type Topology struct { + Self struct { + EthereumAddress string `json:"Ethereum Address"` + } `json:"self"` +} + +var ( + optionPrivateKey = &cli.StringFlag{ + Name: "private-key", + Usage: "BLS private key as hex encoded string (with optional 0x prefix). Must be a valid hex string representing a BLS private key.", + } + + optionServerAddr = &cli.StringFlag{ + Name: "server", + Usage: "Provider server address", + Value: "localhost:8545", + } +) + +func main() { + app := &cli.App{ + Name: "bls-signature-creator", + Usage: "Create BLS signatures", + Flags: []cli.Flag{ + optionPrivateKey, + optionServerAddr, + }, + Action: run, + } + + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func run(c *cli.Context) error { + blsPrivKeyHex := c.String("private-key") + serverAddr := c.String("server") + + if blsPrivKeyHex == "" { + return fmt.Errorf("--private-key flag is required") + } + + // Strip 0x prefix if present + blsPrivKeyHex = strings.TrimPrefix(blsPrivKeyHex, "0x") + + // Validate hex string + privKeyBytes, err := hexutil.Decode("0x" + blsPrivKeyHex) + if err != nil { + return fmt.Errorf("invalid private key hex string: %v", err) + } + + logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) + + // Get topology from debug endpoint + resp, err := http.Get(fmt.Sprintf("http://%s/v1/debug/topology", serverAddr)) + if err != nil { + logger.Error("failed to get topology", "error", err) + return err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + logger.Error("failed to read response body", "error", err) + return err + } + + var topology Topology + if err := json.Unmarshal(body, &topology); err != nil { + logger.Error("failed to unmarshal topology", "error", err) + return err + } + + ethAddress := topology.Self.EthereumAddress + + // Create BLS signature + hashedMessage := crypto.Keccak256(common.HexToAddress(ethAddress).Bytes()) + privateKey := new(bls.PrivateKey[bls.G1]) + if err := privateKey.UnmarshalBinary(privKeyBytes); err != nil { + logger.Error("failed to unmarshal private key", "error", err) + return err + } + + publicKey := privateKey.PublicKey() + signature := bls.Sign(privateKey, hashedMessage) + + // Verify the signature + if !bls.Verify(publicKey, hashedMessage, signature) { + logger.Error("failed to verify generated BLS signature") + return fmt.Errorf("failed to verify generated BLS signature") + } + + pubkeyb, err := publicKey.MarshalBinary() + if err != nil { + logger.Error("failed to marshal public key", "error", err) + return err + } + + logger.Info("generated BLS signature", + "eth_address", ethAddress, + "public_key", hex.EncodeToString(pubkeyb), + "signature", hex.EncodeToString(signature)) + + return nil +} diff --git a/tools/go.mod b/tools/go.mod index 2e8095caa..9c64860ab 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -5,6 +5,7 @@ go 1.23 toolchain go1.23.0 require ( + github.com/cloudflare/circl v1.5.0 github.com/ethereum/go-ethereum v1.14.11 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/primev/mev-commit/contracts-abi v0.0.1 diff --git a/tools/go.sum b/tools/go.sum index a418f1698..8cbecece8 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -20,6 +20,8 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= +github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= github.com/cockroachdb/fifo v0.0.0-20240616162244-4768e80dfb9a h1:f52TdbU4D5nozMAhO9TvTJ2ZMCXtN4VIAmfrrZ0JXQ4= From eb6ab8a9b4d6f396fd7e132070630278990d88f5 Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Fri, 13 Dec 2024 11:44:24 -0500 Subject: [PATCH 2/6] chore: adds a readme --- tools/bls-signature-creator/README.md | 21 ++++++++++++ tools/bls-signature-creator/main.go | 46 ++++++--------------------- 2 files changed, 30 insertions(+), 37 deletions(-) create mode 100644 tools/bls-signature-creator/README.md diff --git a/tools/bls-signature-creator/README.md b/tools/bls-signature-creator/README.md new file mode 100644 index 000000000..e17806eae --- /dev/null +++ b/tools/bls-signature-creator/README.md @@ -0,0 +1,21 @@ +# BLS Signature Creator + +A tool for creating BLS signatures for provider registration. + +## Installation + +Download the latest release binary for your platform from the [releases page](../../releases). + +The binary is named `bls-signature-creator` and is available for Linux x86_64 and arm64 architectures. + +## Usage +The tool requires: +- A BLS private key (provided as a hex encoded string with optional 0x prefix) via the `--private-key` flag +- An Ethereum address (provided as a hex string with optional 0x prefix) via the `--eth-address` flag + +The tool will log: +- The Ethereum address that was provided +- The hex-encoded BLS public key derived from your private key +- The hex-encoded BLS signature + +The logged public key and signature should be used when making a staking request to register as a provider. diff --git a/tools/bls-signature-creator/main.go b/tools/bls-signature-creator/main.go index 2eec5631c..5124ddd0d 100644 --- a/tools/bls-signature-creator/main.go +++ b/tools/bls-signature-creator/main.go @@ -2,11 +2,8 @@ package main import ( "encoding/hex" - "encoding/json" "fmt" - "io" "log/slog" - "net/http" "os" "strings" @@ -18,22 +15,15 @@ import ( "github.com/urfave/cli/v2" ) -type Topology struct { - Self struct { - EthereumAddress string `json:"Ethereum Address"` - } `json:"self"` -} - var ( optionPrivateKey = &cli.StringFlag{ Name: "private-key", Usage: "BLS private key as hex encoded string (with optional 0x prefix). Must be a valid hex string representing a BLS private key.", } - optionServerAddr = &cli.StringFlag{ - Name: "server", - Usage: "Provider server address", - Value: "localhost:8545", + optionEthAddress = &cli.StringFlag{ + Name: "eth-address", + Usage: "Ethereum address as hex string (with optional 0x prefix)", } ) @@ -43,7 +33,7 @@ func main() { Usage: "Create BLS signatures", Flags: []cli.Flag{ optionPrivateKey, - optionServerAddr, + optionEthAddress, }, Action: run, } @@ -56,12 +46,16 @@ func main() { func run(c *cli.Context) error { blsPrivKeyHex := c.String("private-key") - serverAddr := c.String("server") + ethAddress := c.String("eth-address") if blsPrivKeyHex == "" { return fmt.Errorf("--private-key flag is required") } + if ethAddress == "" { + return fmt.Errorf("--eth-address flag is required") + } + // Strip 0x prefix if present blsPrivKeyHex = strings.TrimPrefix(blsPrivKeyHex, "0x") @@ -73,28 +67,6 @@ func run(c *cli.Context) error { logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) - // Get topology from debug endpoint - resp, err := http.Get(fmt.Sprintf("http://%s/v1/debug/topology", serverAddr)) - if err != nil { - logger.Error("failed to get topology", "error", err) - return err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - logger.Error("failed to read response body", "error", err) - return err - } - - var topology Topology - if err := json.Unmarshal(body, &topology); err != nil { - logger.Error("failed to unmarshal topology", "error", err) - return err - } - - ethAddress := topology.Self.EthereumAddress - // Create BLS signature hashedMessage := crypto.Keccak256(common.HexToAddress(ethAddress).Bytes()) privateKey := new(bls.PrivateKey[bls.G1]) From 42386b13b1bbc6627582360a56e49ca73ec98637 Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Fri, 13 Dec 2024 14:52:37 -0500 Subject: [PATCH 3/6] chore: make updates based on pr requests --- tools/bls-signature-creator/.goreleaser.yml | 4 +-- tools/bls-signature-creator/README.md | 8 +++--- tools/bls-signature-creator/main.go | 28 ++++++++------------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/tools/bls-signature-creator/.goreleaser.yml b/tools/bls-signature-creator/.goreleaser.yml index 8b6032f4e..324bc2fcb 100644 --- a/tools/bls-signature-creator/.goreleaser.yml +++ b/tools/bls-signature-creator/.goreleaser.yml @@ -1,7 +1,7 @@ version: 1 -project_name: bls-signature-creator -dist: /tmp/dist/bls-signature-creator +project_name: bls-signer +dist: /tmp/dist/bls-signer builds: - env: diff --git a/tools/bls-signature-creator/README.md b/tools/bls-signature-creator/README.md index e17806eae..bad1eb92f 100644 --- a/tools/bls-signature-creator/README.md +++ b/tools/bls-signature-creator/README.md @@ -1,6 +1,6 @@ -# BLS Signature Creator +# BLS Signer -A tool for creating BLS signatures for provider registration. +Tool for signing payloads using BLS keys. It takes a BLS private key and payload as input and generates a BLS signature that can be used for provider registration and other signing operations. ## Installation @@ -11,10 +11,10 @@ The binary is named `bls-signature-creator` and is available for Linux x86_64 an ## Usage The tool requires: - A BLS private key (provided as a hex encoded string with optional 0x prefix) via the `--private-key` flag -- An Ethereum address (provided as a hex string with optional 0x prefix) via the `--eth-address` flag +- A payload (provided as a hex string with optional 0x prefix) via the `--payload` flag The tool will log: -- The Ethereum address that was provided +- The payload that was provided - The hex-encoded BLS public key derived from your private key - The hex-encoded BLS signature diff --git a/tools/bls-signature-creator/main.go b/tools/bls-signature-creator/main.go index 5124ddd0d..cb310651d 100644 --- a/tools/bls-signature-creator/main.go +++ b/tools/bls-signature-creator/main.go @@ -17,13 +17,15 @@ import ( var ( optionPrivateKey = &cli.StringFlag{ - Name: "private-key", - Usage: "BLS private key as hex encoded string (with optional 0x prefix). Must be a valid hex string representing a BLS private key.", + Name: "private-key", + Usage: "BLS private key as hex encoded string (with optional 0x prefix). Must be a valid hex string representing a BLS private key.", + Required: true, } - optionEthAddress = &cli.StringFlag{ - Name: "eth-address", - Usage: "Ethereum address as hex string (with optional 0x prefix)", + optionPayload = &cli.StringFlag{ + Name: "payload", + Usage: "Payload as hex string (with optional 0x prefix)", + Required: true, } ) @@ -33,7 +35,7 @@ func main() { Usage: "Create BLS signatures", Flags: []cli.Flag{ optionPrivateKey, - optionEthAddress, + optionPayload, }, Action: run, } @@ -46,15 +48,7 @@ func main() { func run(c *cli.Context) error { blsPrivKeyHex := c.String("private-key") - ethAddress := c.String("eth-address") - - if blsPrivKeyHex == "" { - return fmt.Errorf("--private-key flag is required") - } - - if ethAddress == "" { - return fmt.Errorf("--eth-address flag is required") - } + payload := c.String("payload") // Strip 0x prefix if present blsPrivKeyHex = strings.TrimPrefix(blsPrivKeyHex, "0x") @@ -68,7 +62,7 @@ func run(c *cli.Context) error { logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) // Create BLS signature - hashedMessage := crypto.Keccak256(common.HexToAddress(ethAddress).Bytes()) + hashedMessage := crypto.Keccak256(common.HexToAddress(payload).Bytes()) privateKey := new(bls.PrivateKey[bls.G1]) if err := privateKey.UnmarshalBinary(privKeyBytes); err != nil { logger.Error("failed to unmarshal private key", "error", err) @@ -91,7 +85,7 @@ func run(c *cli.Context) error { } logger.Info("generated BLS signature", - "eth_address", ethAddress, + "payload", payload, "public_key", hex.EncodeToString(pubkeyb), "signature", hex.EncodeToString(signature)) From aff2a56035bf02cb719ed38449d88389ce914a2b Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Fri, 13 Dec 2024 15:15:03 -0500 Subject: [PATCH 4/6] chore: adds tool to release strategy --- .github/workflows/releaser.yml | 2 +- tools/{bls-signature-creator => bls-signer}/.goreleaser.yml | 0 tools/{bls-signature-creator => bls-signer}/README.md | 0 tools/{bls-signature-creator => bls-signer}/main.go | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename tools/{bls-signature-creator => bls-signer}/.goreleaser.yml (100%) rename tools/{bls-signature-creator => bls-signer}/README.md (100%) rename tools/{bls-signature-creator => bls-signer}/main.go (100%) diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index f097a498d..0941eab82 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 60 strategy: matrix: - module: [ bridge/standard, external/geth, oracle, p2p, tools/bidder-cli ] + module: [ bridge/standard, external/geth, oracle, p2p, tools/bidder-cli, tools/bls-signer ] steps: - if: ${{ !startsWith(github.ref, 'refs/tags/v') }} diff --git a/tools/bls-signature-creator/.goreleaser.yml b/tools/bls-signer/.goreleaser.yml similarity index 100% rename from tools/bls-signature-creator/.goreleaser.yml rename to tools/bls-signer/.goreleaser.yml diff --git a/tools/bls-signature-creator/README.md b/tools/bls-signer/README.md similarity index 100% rename from tools/bls-signature-creator/README.md rename to tools/bls-signer/README.md diff --git a/tools/bls-signature-creator/main.go b/tools/bls-signer/main.go similarity index 100% rename from tools/bls-signature-creator/main.go rename to tools/bls-signer/main.go From 513537d309b4720c40a6819b44901da6a25945b4 Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Fri, 13 Dec 2024 15:22:34 -0500 Subject: [PATCH 5/6] feat: use app writer --- tools/bls-signer/README.md | 2 +- tools/bls-signer/main.go | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tools/bls-signer/README.md b/tools/bls-signer/README.md index bad1eb92f..103325cd2 100644 --- a/tools/bls-signer/README.md +++ b/tools/bls-signer/README.md @@ -6,7 +6,7 @@ Tool for signing payloads using BLS keys. It takes a BLS private key and payload Download the latest release binary for your platform from the [releases page](../../releases). -The binary is named `bls-signature-creator` and is available for Linux x86_64 and arm64 architectures. +The binary is named `bls-signer` and is available for Linux x86_64 and arm64 architectures. ## Usage The tool requires: diff --git a/tools/bls-signer/main.go b/tools/bls-signer/main.go index cb310651d..0abbfc190 100644 --- a/tools/bls-signer/main.go +++ b/tools/bls-signer/main.go @@ -3,7 +3,6 @@ package main import ( "encoding/hex" "fmt" - "log/slog" "os" "strings" @@ -31,7 +30,7 @@ var ( func main() { app := &cli.App{ - Name: "bls-signature-creator", + Name: "bls-signer", Usage: "Create BLS signatures", Flags: []cli.Flag{ optionPrivateKey, @@ -59,13 +58,11 @@ func run(c *cli.Context) error { return fmt.Errorf("invalid private key hex string: %v", err) } - logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) - // Create BLS signature hashedMessage := crypto.Keccak256(common.HexToAddress(payload).Bytes()) privateKey := new(bls.PrivateKey[bls.G1]) if err := privateKey.UnmarshalBinary(privKeyBytes); err != nil { - logger.Error("failed to unmarshal private key", "error", err) + fmt.Fprintf(c.App.Writer, "Failed to unmarshal private key: %v\n", err) return err } @@ -74,20 +71,20 @@ func run(c *cli.Context) error { // Verify the signature if !bls.Verify(publicKey, hashedMessage, signature) { - logger.Error("failed to verify generated BLS signature") + fmt.Fprintln(c.App.Writer, "Failed to verify generated BLS signature") return fmt.Errorf("failed to verify generated BLS signature") } pubkeyb, err := publicKey.MarshalBinary() if err != nil { - logger.Error("failed to marshal public key", "error", err) + fmt.Fprintf(c.App.Writer, "Failed to marshal public key: %v\n", err) return err } - logger.Info("generated BLS signature", - "payload", payload, - "public_key", hex.EncodeToString(pubkeyb), - "signature", hex.EncodeToString(signature)) + fmt.Fprintf(c.App.Writer, "Generated BLS signature:\n") + fmt.Fprintf(c.App.Writer, "Payload: %s\n", payload) + fmt.Fprintf(c.App.Writer, "Public key: %s\n", hex.EncodeToString(pubkeyb)) + fmt.Fprintf(c.App.Writer, "Signature: %s\n", hex.EncodeToString(signature)) return nil } From 476cff1b9647efb0bd3daab75b3b7bc887c471e7 Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Fri, 13 Dec 2024 15:26:18 -0500 Subject: [PATCH 6/6] chore: adds more details on usage --- tools/bls-signer/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/bls-signer/README.md b/tools/bls-signer/README.md index 103325cd2..13648279d 100644 --- a/tools/bls-signer/README.md +++ b/tools/bls-signer/README.md @@ -19,3 +19,8 @@ The tool will log: - The hex-encoded BLS signature The logged public key and signature should be used when making a staking request to register as a provider. + +Example usage: +``` +bls-signer --private-key 0x30B67395EDA0B03F5E400498690FB8D7CF7BAC53132F89CCED0D65559DB065C9 --payload 0xdeadbeef +```