From 2e293f28bfdd81e08b012bd83b7ccdb12e19a94a Mon Sep 17 00:00:00 2001 From: Donald Adu-Poku Date: Wed, 16 May 2018 21:28:06 +0000 Subject: [PATCH] multi: use secp256k1 types and fields directly. The chainec package is scheduled to be removed. This PR replaces chainec function calls within the hdkeychain package with the underlining secp256k1 types and fields which breaks its dependence on a package soon to be removed. memwallet, a member of rpctest which calls hdkeychain functions is also updated. --- hdkeychain/bench_test.go | 2 +- hdkeychain/extendedkey.go | 33 +++++++++++++++++---------------- rpctest/memwallet.go | 8 ++++---- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/hdkeychain/bench_test.go b/hdkeychain/bench_test.go index 476770f6..1a908765 100644 --- a/hdkeychain/bench_test.go +++ b/hdkeychain/bench_test.go @@ -80,6 +80,6 @@ func BenchmarkSerialize(b *testing.B) { b.StartTimer() for i := 0; i < b.N; i++ { - masterKey.String() + _ = masterKey.String() } } diff --git a/hdkeychain/extendedkey.go b/hdkeychain/extendedkey.go index b80cdbd3..bc47f924 100644 --- a/hdkeychain/extendedkey.go +++ b/hdkeychain/extendedkey.go @@ -23,6 +23,7 @@ import ( "github.com/decred/dcrd/chaincfg" "github.com/decred/dcrd/chaincfg/chainec" "github.com/decred/dcrd/chaincfg/chainhash" + "github.com/decred/dcrd/dcrec/secp256k1" "github.com/decred/dcrd/dcrutil" ) @@ -145,8 +146,8 @@ func (k *ExtendedKey) pubKeyBytes() []byte { // This is a private extended key, so calculate and memoize the public // key if needed. if len(k.pubKey) == 0 { - pkx, pky := chainec.Secp256k1.ScalarBaseMult(k.key) - pubKey := chainec.Secp256k1.NewPublicKey(pkx, pky) + pkx, pky := secp256k1.S256().ScalarBaseMult(k.key) + pubKey := secp256k1.PublicKey{Curve: secp256k1.S256(), X: pkx, Y: pky} k.pubKey = pubKey.SerializeCompressed() } @@ -248,8 +249,9 @@ func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error) { // chance (< 1 in 2^127) this condition will not hold, and in that case, // a child extended key can't be created for this index and the caller // should simply increment to the next index. + curve := secp256k1.S256() ilNum := new(big.Int).SetBytes(il) - if ilNum.Cmp(chainec.Secp256k1.GetN()) >= 0 || ilNum.Sign() == 0 { + if ilNum.Cmp(curve.N) >= 0 || ilNum.Sign() == 0 { return nil, ErrInvalidChild } @@ -271,14 +273,14 @@ func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error) { // childKey = parse256(Il) + parenKey keyNum := new(big.Int).SetBytes(k.key) ilNum.Add(ilNum, keyNum) - ilNum.Mod(ilNum, chainec.Secp256k1.GetN()) + ilNum.Mod(ilNum, curve.N) childKey = ilNum.Bytes() isPrivate = true } else { // Case #3. // Calculate the corresponding intermediate public key for // intermediate private key. - ilx, ily := chainec.Secp256k1.ScalarBaseMult(il) + ilx, ily := curve.ScalarBaseMult(il) if ilx.Sign() == 0 || ily.Sign() == 0 { return nil, ErrInvalidChild } @@ -286,7 +288,7 @@ func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error) { // Convert the serialized compressed parent public key into X // and Y coordinates so it can be added to the intermediate // public key. - pubKey, err := chainec.Secp256k1.ParsePubKey(k.key) + pubKey, err := secp256k1.ParsePubKey(k.key) if err != nil { return nil, err } @@ -295,9 +297,8 @@ func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error) { // derive the final child key. // // childKey = serP(point(parse256(Il)) + parentKey) - childX, childY := chainec.Secp256k1.Add(ilx, ily, pubKey.GetX(), - pubKey.GetY()) - pk := chainec.Secp256k1.NewPublicKey(childX, childY) + childX, childY := curve.Add(ilx, ily, pubKey.X, pubKey.Y) + pk := secp256k1.PublicKey{Curve: secp256k1.S256(), X: childX, Y: childY} childKey = pk.SerializeCompressed() } @@ -337,20 +338,20 @@ func (k *ExtendedKey) Neuter() (*ExtendedKey, error) { } // ECPubKey converts the extended key to a dcrec public key and returns it. -func (k *ExtendedKey) ECPubKey() (chainec.PublicKey, error) { - return chainec.Secp256k1.ParsePubKey(k.pubKeyBytes()) +func (k *ExtendedKey) ECPubKey() (*secp256k1.PublicKey, error) { + return secp256k1.ParsePubKey(k.pubKeyBytes()) } // ECPrivKey converts the extended key to a dcrec private key and returns it. // As you might imagine this is only possible if the extended key is a private // extended key (as determined by the IsPrivate function). The ErrNotPrivExtKey // error will be returned if this function is called on a public extended key. -func (k *ExtendedKey) ECPrivKey() (chainec.PrivateKey, error) { +func (k *ExtendedKey) ECPrivKey() (*secp256k1.PrivateKey, error) { if !k.isPrivate { return nil, ErrNotPrivExtKey } - privKey, _ := chainec.Secp256k1.PrivKeyFromBytes(k.key) + privKey, _ := secp256k1.PrivKeyFromBytes(k.key) return privKey, nil } @@ -472,7 +473,7 @@ func NewMaster(seed []byte, net *chaincfg.Params) (*ExtendedKey, error) { // Ensure the key in usable. secretKeyNum := new(big.Int).SetBytes(secretKey) - if secretKeyNum.Cmp(chainec.Secp256k1.GetN()) >= 0 || + if secretKeyNum.Cmp(secp256k1.S256().N) >= 0 || secretKeyNum.Sign() == 0 { return nil, ErrUnusableSeed } @@ -520,13 +521,13 @@ func NewKeyFromString(key string) (*ExtendedKey, error) { // of the order of the secp256k1 curve and not be 0. keyData = keyData[1:] keyNum := new(big.Int).SetBytes(keyData) - if keyNum.Cmp(chainec.Secp256k1.GetN()) >= 0 || keyNum.Sign() == 0 { + if keyNum.Cmp(secp256k1.S256().N) >= 0 || keyNum.Sign() == 0 { return nil, ErrUnusableSeed } } else { // Ensure the public key parses correctly and is actually on the // secp256k1 curve. - _, err := chainec.Secp256k1.ParsePubKey(keyData) + _, err := secp256k1.ParsePubKey(keyData) if err != nil { return nil, err } diff --git a/rpctest/memwallet.go b/rpctest/memwallet.go index 458d3d56..3d64787e 100644 --- a/rpctest/memwallet.go +++ b/rpctest/memwallet.go @@ -13,8 +13,8 @@ import ( "github.com/decred/dcrd/blockchain" "github.com/decred/dcrd/chaincfg" - "github.com/decred/dcrd/chaincfg/chainec" "github.com/decred/dcrd/chaincfg/chainhash" + "github.com/decred/dcrd/dcrec/secp256k1" "github.com/decred/dcrd/dcrutil" "github.com/decred/dcrd/hdkeychain" "github.com/decred/dcrd/rpcclient" @@ -71,7 +71,7 @@ type undoEntry struct { // wallet functionality to the harness. The wallet uses a hard-coded HD key // hierarchy which promotes reproducibility between harness test runs. type memWallet struct { - coinbaseKey chainec.PrivateKey + coinbaseKey *secp256k1.PrivateKey coinbaseAddr dcrutil.Address // hdRoot is the root master private key for the wallet. @@ -551,8 +551,8 @@ func (m *memWallet) ConfirmedBalance() dcrutil.Amount { } // keyToAddr maps the passed private to corresponding p2pkh address. -func keyToAddr(key chainec.PrivateKey, net *chaincfg.Params) (dcrutil.Address, error) { - pubKey := chainec.Secp256k1.NewPublicKey(key.Public()) +func keyToAddr(key *secp256k1.PrivateKey, net *chaincfg.Params) (dcrutil.Address, error) { + pubKey := (*secp256k1.PublicKey)(&key.PublicKey) serializedKey := pubKey.SerializeCompressed() pubKeyAddr, err := dcrutil.NewAddressSecpPubKey(serializedKey, net) if err != nil {