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

feat(keys): return of the eth_secp256k1 #1264

Merged
merged 3 commits into from
Nov 1, 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
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
}
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved
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
Loading