Skip to content
This repository was archived by the owner on Apr 4, 2024. It is now read-only.

Commit 95c4c15

Browse files
authored
bump btcd for security fix (#1716)
* bump btcd for security fix Solution: - update cosmos-sdk to 0.46.11 - bump btcd * remove go-ethereum-hdwallet dependency * gomod2nix * miss file
1 parent 647ab1a commit 95c4c15

File tree

8 files changed

+319
-146
lines changed

8 files changed

+319
-146
lines changed

crypto/hd/algorithm.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
package hd
1717

1818
import (
19+
"github.com/btcsuite/btcd/btcutil/hdkeychain"
1920
"github.com/btcsuite/btcd/chaincfg"
20-
"github.com/btcsuite/btcutil/hdkeychain"
2121
bip39 "github.com/tyler-smith/go-bip39"
2222

2323
"github.com/ethereum/go-ethereum/accounts"

crypto/hd/algorithm_test.go

+5-7
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import (
99

1010
"github.com/ethereum/go-ethereum/common"
1111

12-
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
13-
1412
amino "github.com/cosmos/cosmos-sdk/codec"
1513
"github.com/cosmos/cosmos-sdk/codec/types"
1614
"github.com/cosmos/cosmos-sdk/crypto/keyring"
@@ -75,11 +73,11 @@ func TestKeyring(t *testing.T) {
7573
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
7674

7775
os.Setenv(hdWalletFixEnv, "true")
78-
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
76+
wallet, err := NewFromMnemonic(mnemonic)
7977
os.Setenv(hdWalletFixEnv, "")
8078
require.NoError(t, err)
8179

82-
path := hdwallet.MustParseDerivationPath(hdPath)
80+
path := MustParseDerivationPath(hdPath)
8381

8482
account, err := wallet.Derive(path, false)
8583
require.NoError(t, err)
@@ -102,14 +100,14 @@ func TestDerivation(t *testing.T) {
102100

103101
require.False(t, privkey.Equals(badPrivKey))
104102

105-
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
103+
wallet, err := NewFromMnemonic(mnemonic)
106104
require.NoError(t, err)
107105

108-
path := hdwallet.MustParseDerivationPath(ethermint.BIP44HDPath)
106+
path := MustParseDerivationPath(ethermint.BIP44HDPath)
109107
account, err := wallet.Derive(path, false)
110108
require.NoError(t, err)
111109

112-
badPath := hdwallet.MustParseDerivationPath("44'/60'/0'/0/0")
110+
badPath := MustParseDerivationPath("44'/60'/0'/0/0")
113111
badAccount, err := wallet.Derive(badPath, false)
114112
require.NoError(t, err)
115113

crypto/hd/utils_test.go

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// NOTE: This code is being used as test helper functions.
2+
package hd
3+
4+
import (
5+
"crypto/ecdsa"
6+
"errors"
7+
"os"
8+
"sync"
9+
10+
"github.com/ethereum/go-ethereum/accounts"
11+
"github.com/ethereum/go-ethereum/common"
12+
"github.com/ethereum/go-ethereum/crypto"
13+
14+
"github.com/btcsuite/btcd/btcutil/hdkeychain"
15+
"github.com/btcsuite/btcd/chaincfg"
16+
bip39 "github.com/tyler-smith/go-bip39"
17+
)
18+
19+
const issue179FixEnvar = "GO_ETHEREUM_HDWALLET_FIX_ISSUE_179"
20+
21+
// Wallet is the underlying wallet struct.
22+
type Wallet struct {
23+
mnemonic string
24+
masterKey *hdkeychain.ExtendedKey
25+
seed []byte
26+
paths map[common.Address]accounts.DerivationPath
27+
accounts []accounts.Account
28+
stateLock sync.RWMutex
29+
fixIssue172 bool
30+
}
31+
32+
// NewFromMnemonic returns a new wallet from a BIP-39 mnemonic.
33+
func NewFromMnemonic(mnemonic string) (*Wallet, error) {
34+
if mnemonic == "" {
35+
return nil, errors.New("mnemonic is required")
36+
}
37+
38+
if !bip39.IsMnemonicValid(mnemonic) {
39+
return nil, errors.New("mnemonic is invalid")
40+
}
41+
42+
seed, err := NewSeedFromMnemonic(mnemonic)
43+
if err != nil {
44+
return nil, err
45+
}
46+
47+
wallet, err := newWallet(seed)
48+
if err != nil {
49+
return nil, err
50+
}
51+
wallet.mnemonic = mnemonic
52+
53+
return wallet, nil
54+
}
55+
56+
// NewSeedFromMnemonic returns a BIP-39 seed based on a BIP-39 mnemonic.
57+
func NewSeedFromMnemonic(mnemonic string) ([]byte, error) {
58+
if mnemonic == "" {
59+
return nil, errors.New("mnemonic is required")
60+
}
61+
62+
return bip39.NewSeedWithErrorChecking(mnemonic, "")
63+
}
64+
65+
func newWallet(seed []byte) (*Wallet, error) {
66+
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
67+
if err != nil {
68+
return nil, err
69+
}
70+
71+
return &Wallet{
72+
masterKey: masterKey,
73+
seed: seed,
74+
accounts: []accounts.Account{},
75+
paths: map[common.Address]accounts.DerivationPath{},
76+
fixIssue172: false || len(os.Getenv(issue179FixEnvar)) > 0,
77+
}, nil
78+
}
79+
80+
// Derive implements accounts.Wallet, deriving a new account at the specific
81+
// derivation path. If pin is set to true, the account will be added to the list
82+
// of tracked accounts.
83+
func (w *Wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) {
84+
// Try to derive the actual account and update its URL if successful
85+
w.stateLock.RLock() // Avoid device disappearing during derivation
86+
87+
address, err := w.deriveAddress(path)
88+
89+
w.stateLock.RUnlock()
90+
91+
// If an error occurred or no pinning was requested, return
92+
if err != nil {
93+
return accounts.Account{}, err
94+
}
95+
96+
account := accounts.Account{
97+
Address: address,
98+
URL: accounts.URL{
99+
Scheme: "",
100+
Path: path.String(),
101+
},
102+
}
103+
104+
if !pin {
105+
return account, nil
106+
}
107+
108+
// Pinning needs to modify the state
109+
w.stateLock.Lock()
110+
defer w.stateLock.Unlock()
111+
112+
if _, ok := w.paths[address]; !ok {
113+
w.accounts = append(w.accounts, account)
114+
w.paths[address] = path
115+
}
116+
117+
return account, nil
118+
}
119+
120+
// MustParseDerivationPath parses the derivation path in string format into
121+
// []uint32 but will panic if it can't parse it.
122+
func MustParseDerivationPath(path string) accounts.DerivationPath {
123+
parsed, err := accounts.ParseDerivationPath(path)
124+
if err != nil {
125+
panic(err)
126+
}
127+
128+
return parsed
129+
}
130+
131+
// DerivePrivateKey derives the private key of the derivation path.
132+
func (w *Wallet) derivePrivateKey(path accounts.DerivationPath) (*ecdsa.PrivateKey, error) {
133+
var err error
134+
key := w.masterKey
135+
for _, n := range path {
136+
if w.fixIssue172 && key.IsAffectedByIssue172() {
137+
key, err = key.Derive(n)
138+
} else {
139+
//lint:ignore SA1019 this is used for testing only
140+
//nolint:all
141+
key, err = key.DeriveNonStandard(n)
142+
}
143+
if err != nil {
144+
return nil, err
145+
}
146+
}
147+
148+
privateKey, err := key.ECPrivKey()
149+
privateKeyECDSA := privateKey.ToECDSA()
150+
if err != nil {
151+
return nil, err
152+
}
153+
154+
return privateKeyECDSA, nil
155+
}
156+
157+
// derivePublicKey derives the public key of the derivation path.
158+
func (w *Wallet) derivePublicKey(path accounts.DerivationPath) (*ecdsa.PublicKey, error) {
159+
privateKeyECDSA, err := w.derivePrivateKey(path)
160+
if err != nil {
161+
return nil, err
162+
}
163+
164+
publicKey := privateKeyECDSA.Public()
165+
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
166+
if !ok {
167+
return nil, errors.New("failed to get public key")
168+
}
169+
170+
return publicKeyECDSA, nil
171+
}
172+
173+
// DeriveAddress derives the account address of the derivation path.
174+
func (w *Wallet) deriveAddress(path accounts.DerivationPath) (common.Address, error) {
175+
publicKeyECDSA, err := w.derivePublicKey(path)
176+
if err != nil {
177+
return common.Address{}, err
178+
}
179+
180+
address := crypto.PubkeyToAddress(*publicKeyECDSA)
181+
return address, nil
182+
}

go.mod

+13-11
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ require (
66
cosmossdk.io/errors v1.0.0-beta.7
77
cosmossdk.io/math v1.0.0-rc.0
88
github.com/armon/go-metrics v0.4.1
9-
github.com/btcsuite/btcd v0.22.2
10-
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
9+
github.com/btcsuite/btcd v0.23.4
10+
github.com/btcsuite/btcd/btcutil v1.1.3
1111
github.com/cosmos/cosmos-proto v1.0.0-beta.3
12-
github.com/cosmos/cosmos-sdk v0.46.8
12+
github.com/cosmos/cosmos-sdk v0.46.11
1313
github.com/cosmos/go-bip39 v1.0.0
1414
github.com/cosmos/gogoproto v1.4.6
1515
github.com/cosmos/ibc-go/v6 v6.1.0
@@ -22,7 +22,6 @@ require (
2222
github.com/grpc-ecosystem/grpc-gateway v1.16.0
2323
github.com/holiman/uint256 v1.2.2
2424
github.com/improbable-eng/grpc-web v0.15.0
25-
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
2625
github.com/onsi/ginkgo/v2 v2.9.1
2726
github.com/onsi/gomega v1.27.4
2827
github.com/pkg/errors v0.9.1
@@ -33,7 +32,7 @@ require (
3332
github.com/spf13/viper v1.15.0
3433
github.com/status-im/keycard-go v0.2.0
3534
github.com/stretchr/testify v1.8.2
36-
github.com/tendermint/tendermint v0.34.24
35+
github.com/tendermint/tendermint v0.34.27
3736
github.com/tendermint/tm-db v0.6.7
3837
github.com/tyler-smith/go-bip39 v1.1.0
3938
golang.org/x/net v0.8.0
@@ -67,10 +66,11 @@ require (
6766
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
6867
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
6968
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
69+
github.com/cometbft/cometbft-db v0.7.0 // indirect
7070
github.com/confio/ics23/go v0.9.0 // indirect
7171
github.com/cosmos/btcutil v1.0.5 // indirect
7272
github.com/cosmos/gorocksdb v1.2.0 // indirect
73-
github.com/cosmos/iavl v0.19.4 // indirect
73+
github.com/cosmos/iavl v0.19.5 // indirect
7474
github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect
7575
github.com/creachadair/taskgroup v0.3.2 // indirect
7676
github.com/danieljoos/wincred v1.1.2 // indirect
@@ -101,7 +101,7 @@ require (
101101
github.com/golang/glog v1.0.0 // indirect
102102
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
103103
github.com/golang/snappy v0.0.4 // indirect
104-
github.com/google/btree v1.0.1 // indirect
104+
github.com/google/btree v1.1.2 // indirect
105105
github.com/google/go-cmp v0.5.9 // indirect
106106
github.com/google/orderedcode v0.0.1 // indirect
107107
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
@@ -147,9 +147,9 @@ require (
147147
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
148148
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
149149
github.com/pmezard/go-difflib v1.0.0 // indirect
150-
github.com/prometheus/client_golang v1.12.2 // indirect
151-
github.com/prometheus/client_model v0.2.0 // indirect
152-
github.com/prometheus/common v0.34.0 // indirect
150+
github.com/prometheus/client_golang v1.14.0 // indirect
151+
github.com/prometheus/client_model v0.3.0 // indirect
152+
github.com/prometheus/common v0.37.0 // indirect
153153
github.com/prometheus/procfs v0.8.0 // indirect
154154
github.com/prometheus/tsdb v0.7.1 // indirect
155155
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
@@ -164,6 +164,7 @@ require (
164164
github.com/stretchr/objx v0.5.0 // indirect
165165
github.com/subosito/gotenv v1.4.2 // indirect
166166
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
167+
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
167168
github.com/tendermint/go-amino v0.16.0 // indirect
168169
github.com/tidwall/btree v1.5.0 // indirect
169170
github.com/tklauser/go-sysconf v0.3.10 // indirect
@@ -173,7 +174,7 @@ require (
173174
github.com/zondax/ledger-go v0.14.1 // indirect
174175
go.etcd.io/bbolt v1.3.6 // indirect
175176
go.opencensus.io v0.24.0 // indirect
176-
golang.org/x/crypto v0.3.0 // indirect
177+
golang.org/x/crypto v0.5.0 // indirect
177178
golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 // indirect
178179
golang.org/x/oauth2 v0.4.0 // indirect
179180
golang.org/x/sync v0.1.0 // indirect
@@ -199,4 +200,5 @@ replace (
199200
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
200201
// use cosmos flavored protobufs
201202
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
203+
github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27
202204
)

0 commit comments

Comments
 (0)