Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: migrate to k1 package #1685

Merged
merged 1 commit into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package app

import (
"context"
"crypto/ecdsa"
"encoding/hex"
"net/http"
"strings"
Expand All @@ -30,7 +29,7 @@ import (
"github.com/attestantio/go-eth2-client/spec/bellatrix"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/coinbase/kryptology/pkg/signatures/bls/bls_sig"
"github.com/ethereum/go-ethereum/crypto"
k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
Expand All @@ -40,6 +39,7 @@ import (
"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/eth2wrap"
"github.com/obolnetwork/charon/app/featureset"
"github.com/obolnetwork/charon/app/k1util"
"github.com/obolnetwork/charon/app/lifecycle"
"github.com/obolnetwork/charon/app/log"
"github.com/obolnetwork/charon/app/peerinfo"
Expand Down Expand Up @@ -101,7 +101,7 @@ type TestConfig struct {
// Lock provides the lock explicitly, skips loading from disk.
Lock *cluster.Lock
// P2PKey provides the p2p privkey explicitly, skips loading from keystore on disk.
P2PKey *ecdsa.PrivateKey
P2PKey *k1.PrivateKey
// ParSigExFunc provides an in-memory partial signature exchange.
ParSigExFunc func() core.ParSigEx
// LcastTransportFunc provides an in-memory leader cast transport.
Expand Down Expand Up @@ -163,7 +163,7 @@ func Run(ctx context.Context, conf Config) (err error) {
p2pKey := conf.TestConfig.P2PKey
if p2pKey == nil {
var err error
p2pKey, err = crypto.LoadECDSA(conf.PrivKeyFile)
p2pKey, err = k1util.Load(conf.PrivKeyFile)
if err != nil {
return errors.Wrap(err, "load priv key")
}
Expand Down Expand Up @@ -262,7 +262,7 @@ func wirePeerInfo(life *lifecycle.Manager, tcpNode host.Host, peers []peer.ID, l

// wireP2P constructs the p2p tcp (libp2p) and udp (discv5) nodes and registers it with the life cycle manager.
func wireP2P(ctx context.Context, life *lifecycle.Manager, conf Config,
lock cluster.Lock, p2pKey *ecdsa.PrivateKey, lockHashHex string,
lock cluster.Lock, p2pKey *k1.PrivateKey, lockHashHex string,
) (host.Host, error) {
peers, err := lock.Peers()
if err != nil {
Expand Down Expand Up @@ -313,7 +313,7 @@ func wireP2P(ctx context.Context, life *lifecycle.Manager, conf Config,
//
//nolint:gocognit
func wireCoreWorkflow(ctx context.Context, life *lifecycle.Manager, conf Config,
lock cluster.Lock, nodeIdx cluster.NodeIdx, tcpNode host.Host, p2pKey *ecdsa.PrivateKey,
lock cluster.Lock, nodeIdx cluster.NodeIdx, tcpNode host.Host, p2pKey *k1.PrivateKey,
eth2Cl eth2wrap.Client, peerIDs []peer.ID, sender *p2p.Sender,
qbftSniffer func(*pbv1.SniffedConsensusInstance), seenPubkeys func(core.PubKey),
) error {
Expand Down Expand Up @@ -489,7 +489,7 @@ func wireCoreWorkflow(ctx context.Context, life *lifecycle.Manager, conf Config,
// wirePrioritise wires the priority protocol which determines cluster wide priorities for the next epoch.
func wirePrioritise(ctx context.Context, conf Config, life *lifecycle.Manager, tcpNode host.Host,
peers []peer.ID, threshold int, sendFunc p2p.SendReceiveFunc, coreCons core.Consensus,
sched core.Scheduler, p2pKey *ecdsa.PrivateKey, deadlineFunc func(duty core.Duty) (time.Time, bool),
sched core.Scheduler, p2pKey *k1.PrivateKey, deadlineFunc func(duty core.Duty) (time.Time, bool),
) error {
if !featureset.Enabled(featureset.Priority) {
return nil
Expand Down Expand Up @@ -681,7 +681,7 @@ func newETH2Client(ctx context.Context, conf Config, life *lifecycle.Manager,
}

// newConsensus returns a new consensus component and its start lifecycle hook.
func newConsensus(conf Config, lock cluster.Lock, tcpNode host.Host, p2pKey *ecdsa.PrivateKey,
func newConsensus(conf Config, lock cluster.Lock, tcpNode host.Host, p2pKey *k1.PrivateKey,
sender *p2p.Sender, nodeIdx cluster.NodeIdx, deadliner core.Deadliner,
qbftSniffer func(*pbv1.SniffedConsensusInstance),
) (core.Consensus, lifecycle.IHookFunc, error) {
Expand Down
8 changes: 4 additions & 4 deletions app/k1util/k1util.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ func Recover(hash []byte, sig []byte) (*k1.PublicKey, error) {
return nil, errors.New("invalid recovery id", z.Any("id", sig[k1RecIdx]))
}

if sig[k1RecIdx] == 0 || sig[k1RecIdx] == 1 {
sig[k1RecIdx] += compactSigMagicOffset // Make the last byte 27 or 28 since that is required below.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this modified the input argument

}

// Put recovery ID first.
sig = append([]byte{sig[k1RecIdx]}, sig[:k1RecIdx]...)

if sig[0] == 0 || sig[0] == 1 {
sig[0] += compactSigMagicOffset // Make the recovery ID 27 or 28 since that is required below.
}

pubkey, _, err := ecdsa.RecoverCompact(sig, hash)
if err != nil {
return nil, errors.Wrap(err, "parse signature")
Expand Down
39 changes: 39 additions & 0 deletions app/k1util/k1util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,45 @@ func TestRandom(t *testing.T) {
require.True(t, key.PubKey().IsEqual(recovered))
}

// BenchmarkRecoverVerify benchmarks recovery vs verification.
//
// TL;DR: verify is slightly faster than recover, both in the order of hundreds of microseconds.
func BenchmarkRecoverVerify(b *testing.B) {
b.StopTimer()

key, err := k1.GeneratePrivateKey()
require.NoError(b, err)

digest := make([]byte, 32)
_, _ = rand.Read(digest)

sig, err := k1util.Sign(key, digest)
require.NoError(b, err)

b.StartTimer()

b.Run("recover", func(b *testing.B) {
for i := 0; i < b.N; i++ {
recovered, err := k1util.Recover(
digest,
sig)
require.NoError(b, err)
require.True(b, key.PubKey().IsEqual(recovered))
}
})

b.Run("verify", func(b *testing.B) {
for i := 0; i < b.N; i++ {
ok, err := k1util.Verify(
key.PubKey(),
digest,
sig[:len(sig)-1])
require.NoError(b, err)
require.True(b, ok)
}
})
}

func fromHex(t *testing.T, hexStr string) []byte {
t.Helper()
b, err := hex.DecodeString(hexStr)
Expand Down
4 changes: 2 additions & 2 deletions app/simnet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package app_test

import (
"context"
"crypto/ecdsa"
"flag"
"fmt"
"net"
Expand All @@ -32,6 +31,7 @@ import (
eth2v1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec"
"github.com/coinbase/kryptology/pkg/signatures/bls/bls_sig"
k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"

Expand Down Expand Up @@ -181,7 +181,7 @@ type simnetArgs struct {
N int
VMocks []bool
VAPIAddrs []string
P2PKeys []*ecdsa.PrivateKey
P2PKeys []*k1.PrivateKey
SimnetKeys []*bls_sig.SecretKey
BMockOpts []beaconmock.Option
Lock cluster.Lock
Expand Down
16 changes: 9 additions & 7 deletions cluster/cluster_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
package cluster

import (
"crypto/ecdsa"
"fmt"
"math/rand"
"testing"

k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -193,27 +193,29 @@ func TestDefinitionVerify(t *testing.T) {
}

// randomOperator returns a random ETH1 private key and populated creator struct (excluding config signature).
func randomCreator(t *testing.T) (*ecdsa.PrivateKey, Creator) {
func randomCreator(t *testing.T) (*k1.PrivateKey, Creator) {
t.Helper()

secret, err := crypto.GenerateKey()
secret, err := k1.GeneratePrivateKey()
require.NoError(t, err)

addr := crypto.PubkeyToAddress(secret.PublicKey)
pk := secret.PubKey().ToECDSA()
addr := crypto.PubkeyToAddress(*pk)

return secret, Creator{
Address: addr.Hex(),
}
}

// randomOperator returns a random ETH1 private key and populated operator struct (excluding config signature).
func randomOperator(t *testing.T) (*ecdsa.PrivateKey, Operator) {
func randomOperator(t *testing.T) (*k1.PrivateKey, Operator) {
t.Helper()

secret, err := crypto.GenerateKey()
secret, err := k1.GeneratePrivateKey()
require.NoError(t, err)

addr := crypto.PubkeyToAddress(secret.PublicKey)
pk := secret.PubKey().ToECDSA()
addr := crypto.PubkeyToAddress(*pk)

return secret, Operator{
Address: addr.Hex(),
Expand Down
9 changes: 4 additions & 5 deletions cluster/eip712sigs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
package cluster

import (
"crypto/ecdsa"

k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
ethmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/signer/core/apitypes"

"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/k1util"
"github.com/obolnetwork/charon/eth2util"
)

Expand Down Expand Up @@ -122,13 +121,13 @@ func digestEIP712(typ eip712Type, def Definition, operator Operator) ([]byte, er
}

// signEIP712 returns the EIP712 signature for the primary type.
func signEIP712(secret *ecdsa.PrivateKey, typ eip712Type, def Definition, operator Operator) ([]byte, error) {
func signEIP712(secret *k1.PrivateKey, typ eip712Type, def Definition, operator Operator) ([]byte, error) {
digest, err := digestEIP712(typ, def, operator)
if err != nil {
return nil, err
}

sig, err := crypto.Sign(digest, secret)
sig, err := k1util.Sign(secret, digest)
if err != nil {
return nil, errors.Wrap(err, "sign EIP712")
}
Expand Down
6 changes: 3 additions & 3 deletions cluster/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package cluster
import (
"bytes"
"context"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"fmt"
Expand All @@ -29,6 +28,7 @@ import (
"time"

"github.com/coinbase/kryptology/pkg/signatures/bls/bls_sig"
k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/ethereum/go-ethereum/crypto"
ssz "github.com/ferranbt/fastssz"

Expand Down Expand Up @@ -114,7 +114,7 @@ func verifySig(expectedAddr string, digest []byte, sig []byte) (bool, error) {
}

// signCreator returns the definition with signed creator config hash.
func signCreator(secret *ecdsa.PrivateKey, def Definition) (Definition, error) {
func signCreator(secret *k1.PrivateKey, def Definition) (Definition, error) {
var err error

def.Creator.ConfigSignature, err = signEIP712(secret, eip712CreatorConfigHash, def, Operator{})
Expand All @@ -126,7 +126,7 @@ func signCreator(secret *ecdsa.PrivateKey, def Definition) (Definition, error) {
}

// signOperator returns the operator with signed config hash and enr.
func signOperator(secret *ecdsa.PrivateKey, def Definition, operator Operator) (Operator, error) {
func signOperator(secret *k1.PrivateKey, def Definition, operator Operator) (Operator, error) {
var err error

operator.ConfigSignature, err = signEIP712(secret, getOperatorEIP712Type(def.Version), def, operator)
Expand Down
12 changes: 6 additions & 6 deletions cluster/test_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
package cluster

import (
"crypto/ecdsa"
crand "crypto/rand"
"io"
"math/rand"
"testing"

"github.com/coinbase/kryptology/pkg/signatures/bls/bls_sig"
k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"

Expand All @@ -35,12 +35,12 @@ import (
// It also returns the peer p2p keys and BLS secret shares. If the seed is zero a random cluster on available loopback
// ports is generated, else a deterministic cluster is generated.
// Note this is not defined in testutil since it is tightly coupled with the cluster package.
func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock, []*ecdsa.PrivateKey, [][]*bls_sig.SecretKeyShare) {
func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock, []*k1.PrivateKey, [][]*bls_sig.SecretKeyShare) {
t.Helper()

var (
vals []DistValidator
p2pKeys []*ecdsa.PrivateKey
p2pKeys []*k1.PrivateKey
ops []Operator
dvShares [][]*bls_sig.SecretKeyShare
)
Expand Down Expand Up @@ -78,13 +78,13 @@ func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock,

for i := 0; i < n; i++ {
// Generate ENR
p2pKey, err := ecdsa.GenerateKey(crypto.S256(), random)
require.NoError(t, err)
p2pKey := testutil.GenerateInsecureK1Key(t, random)

record, err := enr.New(p2pKey)
require.NoError(t, err)

addr := crypto.PubkeyToAddress(p2pKey.PublicKey)
pk := p2pKey.PubKey().ToECDSA()
addr := crypto.PubkeyToAddress(*pk)
op := Operator{
Address: addr.Hex(),
ENR: record.String(),
Expand Down
14 changes: 3 additions & 11 deletions cmd/enr.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
package cmd

import (
"crypto/ecdsa"
"fmt"
"io"
"io/fs"
"strings"

"github.com/ethereum/go-ethereum/crypto"
k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

Expand Down Expand Up @@ -80,25 +79,18 @@ func runNewENR(w io.Writer, dataDir string, verbose bool) error {
}

// writeExpandedEnr writes the expanded form of ENR to the terminal.
func writeExpandedEnr(w io.Writer, r enr.Record, privKey *ecdsa.PrivateKey) {
func writeExpandedEnr(w io.Writer, r enr.Record, privKey *k1.PrivateKey) {
var sb strings.Builder
_, _ = sb.WriteString("\n")
_, _ = sb.WriteString("***************** Decoded ENR (see https://enr-viewer.com/ for additional fields) **********************\n")
_, _ = sb.WriteString(fmt.Sprintf("secp256k1 pubkey: %#x\n", pubkeyHex(privKey.PublicKey)))
Copy link
Contributor Author

@corverroos corverroos Jan 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xenowits this was a bug, you hexed it twice

_, _ = sb.WriteString(fmt.Sprintf("secp256k1 pubkey: %#x\n", privKey.PubKey().SerializeCompressed()))
_, _ = sb.WriteString(fmt.Sprintf("signature: %#x\n", r.Signature))
_, _ = sb.WriteString("********************************************************************************************************\n")
_, _ = sb.WriteString("\n")

_, _ = w.Write([]byte(sb.String()))
}

// pubkeyHex compresses the provided public key and returns the 0x hex encoded string.
func pubkeyHex(pubkey ecdsa.PublicKey) string {
b := crypto.CompressPubkey(&pubkey)

return fmt.Sprintf("%#x", b)
}

func bindEnrFlags(flags *pflag.FlagSet, verbose *bool) {
flags.BoolVar(verbose, "verbose", false, "Prints the expanded form of ENR.")
}
Loading