hdkeychain: Introduce NetworkParams interface.

This introduces a new interface named NetworkParams and updates the
functions that currently take a pointer to a chaincfg.Params struct to
accept the interface instead.

This removes the tight coupling between the two packages at the API
boundary and allows callers to easily provide custom values without
having to create and register and entire chaincfg network as previous
required.

Finally, the README.md is updated accordingly.
This commit is contained in:
Dave Collins 2019-03-25 14:10:42 -05:00
parent 4ea06ed7df
commit a8960587fa
No known key found for this signature in database
GPG Key ID: B8904D9D9C93D1F2
2 changed files with 20 additions and 8 deletions

View File

@ -22,7 +22,7 @@ report.
- Support for multi-layer derivation
- Easy serialization and deserialization for both private and public extended
keys
- Support for custom networks by registering them with chaincfg
- Support for custom networks by accepting a network parameters interface
- Obtaining the underlying EC pubkeys and EC privkeys ties in seamlessly with
existing secp256k1 types which provide powerful tools for working with them to
do things like sign transactions and generate payment scripts

View File

@ -20,7 +20,6 @@ import (
"math/big"
"github.com/decred/base58"
"github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/dcrd/dcrec/secp256k1"
"github.com/decred/dcrd/dcrutil"
@ -100,6 +99,19 @@ var (
// the master node in the hierarchical tree.
var masterKey = []byte("Bitcoin seed")
// NetworkParams defines an interface that is used throughout the package to
// access the hierarchical deterministic extended key magic versions that
// uniquely identify a network.
type NetworkParams interface {
// HDPrivKeyVersion returns the hierarchical deterministic extended private
// key magic version bytes.
HDPrivKeyVersion() [4]byte
// HDPubKeyVersion returns the hierarchical deterministic extended public
// key magic version bytes.
HDPubKeyVersion() [4]byte
}
// ExtendedKey houses all the information needed to support a hierarchical
// deterministic extended key. See the package overview documentation for
// more details on how to use extended keys.
@ -432,7 +444,7 @@ func (k *ExtendedKey) Zero() {
// will derive to an unusable secret key. The ErrUnusable error will be
// returned if this should occur, so the caller must check for it and generate a
// new seed accordingly.
func NewMaster(seed []byte, net *chaincfg.Params) (*ExtendedKey, error) {
func NewMaster(seed []byte, net NetworkParams) (*ExtendedKey, error) {
// Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes].
if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes {
return nil, ErrInvalidSeedLen
@ -458,13 +470,13 @@ func NewMaster(seed []byte, net *chaincfg.Params) (*ExtendedKey, error) {
}
parentFP := []byte{0x00, 0x00, 0x00, 0x00}
return newExtendedKey(net.HDPrivateKeyID, net.HDPublicKeyID, secretKey,
chainCode, parentFP, 0, 0, true), nil
return newExtendedKey(net.HDPrivKeyVersion(), net.HDPubKeyVersion(),
secretKey, chainCode, parentFP, 0, 0, true), nil
}
// NewKeyFromString returns a new extended key instance from a base58-encoded
// extended key which is required to be for the provided network.
func NewKeyFromString(key string, net *chaincfg.Params) (*ExtendedKey, error) {
func NewKeyFromString(key string, net NetworkParams) (*ExtendedKey, error) {
// The base58-decoded extended key must consist of a serialized payload
// plus an additional 4 bytes for the checksum.
decoded := base58.Decode(key)
@ -485,8 +497,8 @@ func NewKeyFromString(key string, net *chaincfg.Params) (*ExtendedKey, error) {
}
// Ensure the version encoded in the payload matches the provided network.
privVersion := net.HDPrivateKeyID
pubVersion := net.HDPublicKeyID
privVersion := net.HDPrivKeyVersion()
pubVersion := net.HDPubKeyVersion()
version := payload[:4]
if !bytes.Equal(version, privVersion[:]) &&
!bytes.Equal(version, pubVersion[:]) {