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

Commit

Permalink
feat(keys): return of the eth_secp256k1 (#1264)
Browse files Browse the repository at this point in the history
  • Loading branch information
itsdevbear authored Nov 1, 2023
1 parent f659c51 commit e29bc32
Show file tree
Hide file tree
Showing 31 changed files with 2,608 additions and 24 deletions.
1,074 changes: 1,074 additions & 0 deletions cosmos/api/polaris/crypto/ethsecp256k1/v1/keys.pulsar.go

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions cosmos/crypto/codec/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2023, Berachain Foundation. All rights reserved.
// Use of this software is govered by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

package codec

import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"

"pkg.berachain.dev/polaris/cosmos/crypto/keys/ethsecp256k1"
)

// RegisterInterfaces registers the ethsecp256k1 key types.
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &ethsecp256k1.PubKey{})
registry.RegisterImplementations((*cryptotypes.PrivKey)(nil), &ethsecp256k1.PrivKey{})
}
41 changes: 41 additions & 0 deletions cosmos/crypto/codec/codec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2023, Berachain Foundation. All rights reserved.
// Use of this software is govered by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

package codec

import (
"testing"

"github.com/cosmos/cosmos-sdk/codec/types"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestCodec(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "cosmos/crypto/codec")
}

var _ = Describe("Codec", func() {
It("should not panic", func() {
RegisterInterfaces(types.NewInterfaceRegistry())
})
})
67 changes: 67 additions & 0 deletions cosmos/crypto/hd/algo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2023, Berachain Foundation. All rights reserved.
// Use of this software is govered by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

package hd

import (
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"

"pkg.berachain.dev/polaris/cosmos/crypto/keys/ethsecp256k1"
)

const (
// EthSecp256k1Type defines the ECDSA secp256k1 used on Ethereum.
EthSecp256k1Type = hd.PubKeyType(ethsecp256k1.KeyType)
)

var (
// Compile-time type assertion.
_ keyring.SignatureAlgo = EthSecp256k1
// EthSecp256k1 uses the Bitcoin secp256k1 ECDSA parameters.
EthSecp256k1 = ethSecp256k1Algo{}
)

// ethSecp256k1Algo implements the `keyring.SignatureAlgo` interface for the
// eth_secp256k1 algorithm.
type ethSecp256k1Algo struct{}

// Name returns eth_secp256k1.
func (s ethSecp256k1Algo) Name() hd.PubKeyType {
return EthSecp256k1Type
}

// Derive derives and returns the eth_secp256k1 private key for the given mnemonic
// and HD path.
func (s ethSecp256k1Algo) Derive() hd.DeriveFn {
return hd.Secp256k1.Derive()
}

// Generate generates a eth_secp256k1 private key from the given bytes.
func (s ethSecp256k1Algo) Generate() hd.GenerateFn {
return func(bz []byte) cryptotypes.PrivKey {
bzArr := make([]byte, ethsecp256k1.PrivKeySize)
copy(bzArr, bz)
return &ethsecp256k1.PrivKey{
Key: bzArr,
}
}
}
99 changes: 99 additions & 0 deletions cosmos/crypto/hd/algo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2023, Berachain Foundation. All rights reserved.
// Use of this software is govered by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

package hd

import (
"strings"

"github.com/cosmos/cosmos-sdk/crypto/keyring"

ethsecp256k1 "pkg.berachain.dev/polaris/cosmos/crypto/keys/ethsecp256k1"
"pkg.berachain.dev/polaris/eth/accounts"
"pkg.berachain.dev/polaris/eth/common"
crypto "pkg.berachain.dev/polaris/eth/crypto"
"pkg.berachain.dev/polaris/lib/utils"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

const (
mnemonic = "absurd surge gather author blanket acquire proof struggle runway attract " +
"cereal quiz tattoo shed almost sudden survey boring film memory picnic favorite " +
"verb tank"
)

var _ = Describe("HD", func() {
It("should derive the correct key", func() {
EthSecp256k1 := EthSecp256k1

// Derive the 0'th key from the mnemonic.
bz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase,
accounts.BIP44HDPath)
Expect(err).NotTo(HaveOccurred())
Expect(bz).NotTo(BeEmpty())

badBz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase,
"44'/118'/0'/0/0")
Expect(err).NotTo(HaveOccurred())
Expect(badBz).NotTo(BeEmpty())

Expect(bz).NotTo(Equal(badBz))

privkey := EthSecp256k1.Generate()(bz)
badPrivKey := EthSecp256k1.Generate()(badBz)

Expect(privkey.Equals(badPrivKey)).To(BeFalse())

pk, err := utils.MustGetAs[*ethsecp256k1.PrivKey](privkey).ToECDSA()
Expect(err).NotTo(HaveOccurred())

wallet, path, err := GenerateWallet(mnemonic)
Expect(err).NotTo(HaveOccurred())
*path = strings.Replace(*path, "H", "'", 3) // TODO: figure out why this is needed.
Expect(*path).To(Equal(accounts.BIP44HDPath))
Expect(crypto.FromECDSA(wallet)).To(Equal(privkey.Bytes()))

// Check to verify that the address is correct.
// Also verified manually with metamask: https://imgur.com/a/Bz2jLaP
Expect(crypto.PubkeyToAddress(pk.PublicKey).String()).
To(Equal("0x20f33CE90A13a4b5E7697E3544c3083B8F8A51D4"))
Expect(crypto.PubkeyToAddress(wallet.PublicKey).String()).
To(Equal("0x20f33CE90A13a4b5E7697E3544c3083B8F8A51D4"))
Expect(common.BytesToAddress(privkey.PubKey().Address().Bytes()).String()).
To(Equal("0x20f33CE90A13a4b5E7697E3544c3083B8F8A51D4"))
Expect(common.BytesToAddress(privkey.PubKey().Address()).String()).
To(Equal(crypto.PubkeyToAddress(wallet.PublicKey).String()))
})
})

var _ = Describe("Prove EDSCAify isn't needed", func() {
It("should round trip", func() {
// Generate a random private key.
key, err := ethsecp256k1.GenPrivKey()
Expect(err).NotTo(HaveOccurred())

// Convert the private key to an ECDSA private key.
x, err := ethsecp256k1.PrivKey{Key: key.Key}.ToECDSA()
Expect(err).NotTo(HaveOccurred())
Expect(key.Key).To(Equal(crypto.FromECDSA(x)))
})
})
73 changes: 73 additions & 0 deletions cosmos/crypto/hd/hd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2023, Berachain Foundation. All rights reserved.
// Use of this software is govered by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

//
//nolint:gomnd // ignore magic numbers
package hd

import (
"crypto/ecdsa"

"github.com/btcsuite/btcd/btcutil/hdkeychain"
"github.com/btcsuite/btcd/chaincfg"
"github.com/cosmos/go-bip39"
)

func GenerateWallet(mnemonic string) (*ecdsa.PrivateKey, *string, error) {
// Generate a Bip32 HD wallet for the mnemonic and a user supplied password
seed := bip39.NewSeed(mnemonic, "")
// Generate a new master node using the seed.
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
return nil, nil, err
}
// This gives the path: m/44H
acc44H, err := masterKey.Derive(hdkeychain.HardenedKeyStart + 44)
if err != nil {
return nil, nil, err
}
// This gives the path: m/44H/60H
acc44H60H, err := acc44H.Derive(hdkeychain.HardenedKeyStart + 60)
if err != nil {
return nil, nil, err
}
// This gives the path: m/44H/60H/0H
acc44H60H0H, err := acc44H60H.Derive(hdkeychain.HardenedKeyStart + 0)
if err != nil {
return nil, nil, err
}
// This gives the path: m/44H/60H/0H/0
acc44H60H0H0, err := acc44H60H0H.Derive(0)
if err != nil {
return nil, nil, err
}
// This gives the path: m/44H/60H/0H/0/0
acc44H60H0H00, err := acc44H60H0H0.Derive(0)
if err != nil {
return nil, nil, err
}
btcecPrivKey, err := acc44H60H0H00.ECPrivKey()
if err != nil {
return nil, nil, err
}
privateKey := btcecPrivKey.ToECDSA()
path := "m/44H/60H/0H/0/0"
return privateKey, &path, nil
}
33 changes: 33 additions & 0 deletions cosmos/crypto/hd/hd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2023, Berachain Foundation. All rights reserved.
// Use of this software is govered by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

package hd

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestHD(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "cosmos/crypto/hd")
}
35 changes: 35 additions & 0 deletions cosmos/crypto/keyring/option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: BUSL-1.1
//
// Copyright (C) 2023, Berachain Foundation. All rights reserved.
// Use of this software is govered by the Business Source License included
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
//
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
// VERSIONS OF THE LICENSED WORK.
//
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
//
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
// TITLE.

package keyring

import (
"github.com/cosmos/cosmos-sdk/crypto/keyring"

"pkg.berachain.dev/polaris/cosmos/crypto/hd"
)

// OnlyEthSecp256k1Option defines a function keys options for the ethereum Secp256k1 curve.
func OnlyEthSecp256k1Option() keyring.Option {
return func(options *keyring.Options) {
options.SupportedAlgos = keyring.SigningAlgoList{hd.EthSecp256k1}
options.SupportedAlgosLedger = keyring.SigningAlgoList{hd.EthSecp256k1}
}
}
Loading

0 comments on commit e29bc32

Please sign in to comment.