diff --git a/address.go b/address.go index 8bef8b7..295d565 100644 --- a/address.go +++ b/address.go @@ -10,78 +10,43 @@ import ( "encoding/hex" "errors" "github.com/conformal/btcec" + "github.com/conformal/btcnet" "github.com/conformal/btcwire" ) var ( - // ErrUnknownNet describes an error where the Bitcoin network is - // not recognized. - ErrUnknownNet = errors.New("unrecognized bitcoin network") - - // ErrMalformedAddress describes an error where an address is improperly - // formatted, either due to an incorrect length of the hashed pubkey or - // a non-matching checksum. - ErrMalformedAddress = errors.New("malformed address") - // ErrChecksumMismatch describes an error where decoding failed due // to a bad checksum. ErrChecksumMismatch = errors.New("checksum mismatch") - // ErrUnknownIdentifier describes an error where decoding failed due - // to an unknown magic byte identifier. - ErrUnknownIdentifier = errors.New("unknown identifier byte") + // ErrUnknownAddressType describes an error where an address can not + // decoded as a specific address type due to the string encoding + // begining with an identifier byte unknown to any standard or + // registered (via btcnet.Register) network. + ErrUnknownAddressType = errors.New("unknown address type") + + // ErrAddressCollision describes an error where an address can not + // be uniquely determined as either a pay-to-pubkey-hash or + // pay-to-script-hash address since the leading identifier is used for + // describing both address kinds, but for different networks. Rather + // than assuming or defaulting to one or the other, this error is + // returned and the caller must decide how to decode the address. + ErrAddressCollision = errors.New("address collision") ) -// Constants used to specify which network a payment address belongs -// to. Mainnet address cannot be used on the Testnet, and vice versa. -const ( - // MainNetAddr is the address identifier for MainNet - MainNetAddr = 0x00 - - // TestNetAddr is the address identifier for TestNet - TestNetAddr = 0x6f - - // MainNetScriptHash is the script hash identifier for MainNet - MainNetScriptHash = 0x05 - - // TestNetScriptHash is the script hash identifier for TestNet - TestNetScriptHash = 0xc4 -) - -// checkBitcoinNet returns an error if the bitcoin network is not supported. -func checkBitcoinNet(net btcwire.BitcoinNet) error { - // Check for a valid bitcoin network. - switch net { - case btcwire.MainNet: - fallthrough - case btcwire.TestNet: - fallthrough - case btcwire.TestNet3: - return nil - default: - return ErrUnknownNet - } -} - // encodeAddress returns a human-readable payment address given a ripemd160 hash -// and netid which encodes the bitcoin network and address type. It is used +// and netID which encodes the bitcoin network and address type. It is used // in both pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address // encoding. func encodeAddress(hash160 []byte, netID byte) string { - tosum := make([]byte, ripemd160.Size+1) - tosum[0] = netID - copy(tosum[1:], hash160) - cksum := btcwire.DoubleSha256(tosum) - - // Address before base58 encoding is 1 byte for netID, ripemd160 hash - // size, plus 4 bytes of checksum (total 25). - b := make([]byte, ripemd160.Size+5, ripemd160.Size+5) - b[0] = netID - copy(b[1:], hash160) - copy(b[ripemd160.Size+1:], cksum[:4]) - + // Format is 1 byte for a network and address class (i.e. P2PKH vs + // P2SH), 20 bytes for a RIPEMD160 hash, and 4 bytes of checksum. + b := make([]byte, 0, 1+ripemd160.Size+4) + b = append(b, netID) + b = append(b, hash160...) + cksum := btcwire.DoubleSha256(b)[:4] + b = append(b, cksum...) return Base58Encode(b) - } // Address is an interface type for any type of destination a transaction @@ -99,7 +64,7 @@ type Address interface { // IsForNet returns whether or not the address is associated with the // passed bitcoin network. - IsForNet(btcwire.BitcoinNet) bool + IsForNet(*btcnet.Params) bool } // DecodeAddress decodes the string encoding of an address and returns @@ -108,7 +73,7 @@ type Address interface { // The bitcoin network the address is associated with is extracted if possible. // When the address does not encode the network, such as in the case of a raw // public key, the address will be associated with the passed defaultNet. -func DecodeAddress(addr string, defaultNet btcwire.BitcoinNet) (Address, error) { +func DecodeAddress(addr string, defaultNet *btcnet.Params) (Address, error) { // Serialized public keys are either 65 bytes (130 hex chars) if // uncompressed/hybrid or 33 bytes (66 hex chars) if compressed. if len(addr) == 130 || len(addr) == 66 { @@ -123,28 +88,6 @@ func DecodeAddress(addr string, defaultNet btcwire.BitcoinNet) (Address, error) decoded := Base58Decode(addr) switch len(decoded) { case 1 + ripemd160.Size + 4: // P2PKH or P2SH - // Parse the network and hash type (pubkey hash vs script - // hash) from the first byte. - net := btcwire.MainNet - isscript := false - switch decoded[0] { - case MainNetAddr: - // Use defaults. - - case TestNetAddr: - net = btcwire.TestNet3 - - case MainNetScriptHash: - isscript = true - - case TestNetScriptHash: - isscript = true - net = btcwire.TestNet3 - - default: - return nil, ErrUnknownIdentifier - } - // Verify hash checksum. Checksum is calculated as the first // four bytes of double SHA256 of the network byte and hash. tosum := decoded[:ripemd160.Size+1] @@ -153,13 +96,19 @@ func DecodeAddress(addr string, defaultNet btcwire.BitcoinNet) (Address, error) return nil, ErrChecksumMismatch } - // Return concrete type. - if isscript { - return NewAddressScriptHashFromHash( - decoded[1:ripemd160.Size+1], net) + netID := decoded[0] + isP2PKH := btcnet.IsPubKeyHashAddrID(netID) + isP2SH := btcnet.IsScriptHashAddrID(netID) + switch hash160 := decoded[1 : ripemd160.Size+1]; { + case isP2PKH && isP2SH: + return nil, ErrAddressCollision + case isP2PKH: + return newAddressPubKeyHash(hash160, netID) + case isP2SH: + return newAddressScriptHashFromHash(hash160, netID) + default: + return nil, ErrUnknownAddressType } - return NewAddressPubKeyHash(decoded[1:ripemd160.Size+1], - net) default: return nil, errors.New("decoded address is of unknown size") @@ -175,30 +124,21 @@ type AddressPubKeyHash struct { // NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash must // be 20 bytes. -func NewAddressPubKeyHash(pkHash []byte, net btcwire.BitcoinNet) (*AddressPubKeyHash, error) { +func NewAddressPubKeyHash(pkHash []byte, net *btcnet.Params) (*AddressPubKeyHash, error) { + return newAddressPubKeyHash(pkHash, net.PubKeyHashAddrID) +} + +// newAddressPubKeyHash is the internal API to create a pubkey hash address +// with a known leading identifier byte for a network, rather than looking +// it up through its parameters. This is useful when creating a new address +// structure from a string encoding where the identifer byte is already +// known. +func newAddressPubKeyHash(pkHash []byte, netID byte) (*AddressPubKeyHash, error) { // Check for a valid pubkey hash length. if len(pkHash) != ripemd160.Size { return nil, errors.New("pkHash must be 20 bytes") } - // Check for a valid bitcoin network. - if err := checkBitcoinNet(net); err != nil { - return nil, err - } - - // Choose the appropriate network ID for the address based on the - // network. - var netID byte - switch net { - case btcwire.MainNet: - netID = MainNetAddr - - case btcwire.TestNet: - fallthrough - case btcwire.TestNet3: - netID = TestNetAddr - } - addr := &AddressPubKeyHash{netID: netID} copy(addr.hash[:], pkHash) return addr, nil @@ -218,18 +158,8 @@ func (a *AddressPubKeyHash) ScriptAddress() []byte { // IsForNet returns whether or not the pay-to-pubkey-hash address is associated // with the passed bitcoin network. -func (a *AddressPubKeyHash) IsForNet(net btcwire.BitcoinNet) bool { - switch net { - case btcwire.MainNet: - return a.netID == MainNetAddr - - case btcwire.TestNet: - fallthrough - case btcwire.TestNet3: - return a.netID == TestNetAddr - } - - return false +func (a *AddressPubKeyHash) IsForNet(net *btcnet.Params) bool { + return a.netID == net.PubKeyHashAddrID } // String returns a human-readable string for the pay-to-pubkey-hash address. @@ -253,41 +183,29 @@ type AddressScriptHash struct { netID byte } -// NewAddressScriptHash returns a new AddressScriptHash. net must be -// btcwire.MainNet or btcwire.TestNet3. -func NewAddressScriptHash(serializedScript []byte, net btcwire.BitcoinNet) (*AddressScriptHash, error) { - // Create hash of serialized script. +// NewAddressScriptHash returns a new AddressScriptHash. +func NewAddressScriptHash(serializedScript []byte, net *btcnet.Params) (*AddressScriptHash, error) { scriptHash := Hash160(serializedScript) - - return NewAddressScriptHashFromHash(scriptHash, net) + return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID) } // NewAddressScriptHashFromHash returns a new AddressScriptHash. scriptHash // must be 20 bytes. -func NewAddressScriptHashFromHash(scriptHash []byte, net btcwire.BitcoinNet) (*AddressScriptHash, error) { +func NewAddressScriptHashFromHash(scriptHash []byte, net *btcnet.Params) (*AddressScriptHash, error) { + return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID) +} + +// newAddressScriptHashFromHash is the internal API to create a script hash +// address with a known leading identifier byte for a network, rather than +// looking it up through its parameters. This is useful when creating a new +// address structure from a string encoding where the identifer byte is already +// known. +func newAddressScriptHashFromHash(scriptHash []byte, netID byte) (*AddressScriptHash, error) { // Check for a valid script hash length. if len(scriptHash) != ripemd160.Size { return nil, errors.New("scriptHash must be 20 bytes") } - // Check for a valid bitcoin network. - if err := checkBitcoinNet(net); err != nil { - return nil, err - } - - // Choose the appropriate network ID for the address based on the - // network. - var netID byte - switch net { - case btcwire.MainNet: - netID = MainNetScriptHash - - case btcwire.TestNet: - fallthrough - case btcwire.TestNet3: - netID = TestNetScriptHash - } - addr := &AddressScriptHash{netID: netID} copy(addr.hash[:], scriptHash) return addr, nil @@ -307,17 +225,8 @@ func (a *AddressScriptHash) ScriptAddress() []byte { // IsForNet returns whether or not the pay-to-script-hash address is associated // with the passed bitcoin network. -func (a *AddressScriptHash) IsForNet(net btcwire.BitcoinNet) bool { - switch net { - case btcwire.MainNet: - return a.netID == MainNetScriptHash - case btcwire.TestNet: - fallthrough - case btcwire.TestNet3: - return a.netID == TestNetScriptHash - } - - return false +func (a *AddressScriptHash) IsForNet(net *btcnet.Params) bool { + return a.netID == net.ScriptHashAddrID } // String returns a human-readable string for the pay-to-script-hash address. @@ -355,13 +264,13 @@ const ( type AddressPubKey struct { pubKeyFormat PubKeyFormat pubKey *btcec.PublicKey - netID byte + pubKeyHashID byte } // NewAddressPubKey returns a new AddressPubKey which represents a pay-to-pubkey // address. The serializedPubKey parameter must be a valid pubkey and can be // uncompressed, compressed, or hybrid. -func NewAddressPubKey(serializedPubKey []byte, net btcwire.BitcoinNet) (*AddressPubKey, error) { +func NewAddressPubKey(serializedPubKey []byte, net *btcnet.Params) (*AddressPubKey, error) { pubKey, err := btcec.ParsePubKey(serializedPubKey, btcec.S256()) if err != nil { return nil, err @@ -373,61 +282,34 @@ func NewAddressPubKey(serializedPubKey []byte, net btcwire.BitcoinNet) (*Address // the leading byte to get the format. pkFormat := PKFUncompressed switch serializedPubKey[0] { - case 0x02: - fallthrough - case 0x03: + case 0x02, 0x03: pkFormat = PKFCompressed - - case 0x06: - fallthrough - case 0x07: + case 0x06, 0x07: pkFormat = PKFHybrid } - // Check for a valid bitcoin network. - if err := checkBitcoinNet(net); err != nil { - return nil, err - } - - // Choose the appropriate network ID for the address based on the - // network. - var netID byte - switch net { - case btcwire.MainNet: - netID = MainNetAddr - - case btcwire.TestNet: - fallthrough - case btcwire.TestNet3: - netID = TestNetAddr - } - - ecPubKey := pubKey return &AddressPubKey{ pubKeyFormat: pkFormat, - pubKey: ecPubKey, - netID: netID, + pubKey: pubKey, + pubKeyHashID: net.PubKeyHashAddrID, }, nil } // serialize returns the serialization of the public key according to the // format associated with the address. func (a *AddressPubKey) serialize() []byte { - var serializedPubKey []byte switch a.pubKeyFormat { default: fallthrough case PKFUncompressed: - serializedPubKey = a.pubKey.SerializeUncompressed() + return a.pubKey.SerializeUncompressed() case PKFCompressed: - serializedPubKey = a.pubKey.SerializeCompressed() + return a.pubKey.SerializeCompressed() case PKFHybrid: - serializedPubKey = a.pubKey.SerializeHybrid() + return a.pubKey.SerializeHybrid() } - - return serializedPubKey } // EncodeAddress returns the string encoding of the public key as a @@ -439,7 +321,7 @@ func (a *AddressPubKey) serialize() []byte { // // Part of the Address interface. func (a *AddressPubKey) EncodeAddress() string { - return encodeAddress(Hash160(a.serialize()), a.netID) + return encodeAddress(Hash160(a.serialize()), a.pubKeyHashID) } // ScriptAddress returns the bytes to be included in a txout script to pay @@ -451,18 +333,8 @@ func (a *AddressPubKey) ScriptAddress() []byte { // IsForNet returns whether or not the pay-to-pubkey address is associated // with the passed bitcoin network. -func (a *AddressPubKey) IsForNet(net btcwire.BitcoinNet) bool { - switch net { - case btcwire.MainNet: - return a.netID == MainNetAddr - - case btcwire.TestNet: - fallthrough - case btcwire.TestNet3: - return a.netID == TestNetAddr - } - - return false +func (a *AddressPubKey) IsForNet(net *btcnet.Params) bool { + return a.pubKeyHashID == net.PubKeyHashAddrID } // String returns the hex-encoded human-readable string for the pay-to-pubkey @@ -490,10 +362,9 @@ func (a *AddressPubKey) SetFormat(pkFormat PubKeyFormat) { // differs with the format. At the time of this writing, most Bitcoin addresses // are pay-to-pubkey-hash constructed from the uncompressed public key. func (a *AddressPubKey) AddressPubKeyHash() *AddressPubKeyHash { - addr := &AddressPubKeyHash{netID: a.netID} + addr := &AddressPubKeyHash{netID: a.pubKeyHashID} copy(addr.hash[:], Hash160(a.serialize())) return addr - } // PubKey returns the underlying public key for the address. diff --git a/address_test.go b/address_test.go index 80ef225..170acb0 100644 --- a/address_test.go +++ b/address_test.go @@ -6,13 +6,16 @@ package btcutil_test import ( "bytes" - "code.google.com/p/go.crypto/ripemd160" "encoding/hex" "fmt" - "github.com/conformal/btcutil" - "github.com/conformal/btcwire" "reflect" "testing" + + "code.google.com/p/go.crypto/ripemd160" + + "github.com/conformal/btcnet" + "github.com/conformal/btcutil" + "github.com/conformal/btcwire" ) // invalidNet is an invalid bitcoin network. @@ -26,7 +29,7 @@ func TestAddresses(t *testing.T) { valid bool result btcutil.Address f func() (btcutil.Address, error) - net btcwire.BitcoinNet + net *btcnet.Params }{ // Positive P2PKH tests. { @@ -38,14 +41,14 @@ func TestAddresses(t *testing.T) { [ripemd160.Size]byte{ 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84}, - btcutil.MainNetAddr), + btcnet.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { pkHash := []byte{ 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84} - return btcutil.NewAddressPubKeyHash(pkHash, btcwire.MainNet) + return btcutil.NewAddressPubKeyHash(pkHash, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { name: "mainnet p2pkh 2", @@ -56,14 +59,14 @@ func TestAddresses(t *testing.T) { [ripemd160.Size]byte{ 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa}, - btcutil.MainNetAddr), + btcnet.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { pkHash := []byte{ 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa} - return btcutil.NewAddressPubKeyHash(pkHash, btcwire.MainNet) + return btcutil.NewAddressPubKeyHash(pkHash, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { name: "testnet p2pkh", @@ -74,29 +77,17 @@ func TestAddresses(t *testing.T) { [ripemd160.Size]byte{ 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f}, - btcutil.TestNetAddr), + btcnet.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { pkHash := []byte{ 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f} - return btcutil.NewAddressPubKeyHash(pkHash, btcwire.TestNet3) + return btcutil.NewAddressPubKeyHash(pkHash, &btcnet.TestNet3Params) }, - net: btcwire.TestNet3, + net: &btcnet.TestNet3Params, }, // Negative P2PKH tests. - { - name: "p2pkh wrong byte identifier/net", - addr: "MrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", - encoded: "MrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", - valid: false, - f: func() (btcutil.Address, error) { - pkHash := []byte{ - 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, - 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f} - return btcutil.NewAddressPubKeyHash(pkHash, invalidNet) - }, - }, { name: "p2pkh wrong hash length", addr: "", @@ -106,7 +97,7 @@ func TestAddresses(t *testing.T) { 0x00, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa} - return btcutil.NewAddressPubKeyHash(pkHash, btcwire.MainNet) + return btcutil.NewAddressPubKeyHash(pkHash, &btcnet.MainNetParams) }, }, { @@ -128,7 +119,7 @@ func TestAddresses(t *testing.T) { [ripemd160.Size]byte{ 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0xf2, 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0x10}, - btcutil.MainNetScriptHash), + btcnet.MainNetParams.ScriptHashAddrID), f: func() (btcutil.Address, error) { script := []byte{ 0x52, 0x41, 0x04, 0x91, 0xbb, 0xa2, 0x51, 0x09, 0x12, 0xa5, @@ -152,9 +143,9 @@ func TestAddresses(t *testing.T) { 0xdb, 0xfb, 0x1e, 0x75, 0x4e, 0x35, 0xfa, 0x1c, 0x78, 0x44, 0xc4, 0x1f, 0x32, 0x2a, 0x18, 0x63, 0xd4, 0x62, 0x13, 0x53, 0xae} - return btcutil.NewAddressScriptHash(script, btcwire.MainNet) + return btcutil.NewAddressScriptHash(script, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { // Taken from transactions: @@ -168,14 +159,14 @@ func TestAddresses(t *testing.T) { [ripemd160.Size]byte{ 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4}, - btcutil.MainNetScriptHash), + btcnet.MainNetParams.ScriptHashAddrID), f: func() (btcutil.Address, error) { hash := []byte{ 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4} - return btcutil.NewAddressScriptHashFromHash(hash, btcwire.MainNet) + return btcutil.NewAddressScriptHashFromHash(hash, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { // Taken from bitcoind base58_keys_valid. @@ -187,14 +178,14 @@ func TestAddresses(t *testing.T) { [ripemd160.Size]byte{ 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a}, - btcutil.TestNetScriptHash), + btcnet.TestNet3Params.ScriptHashAddrID), f: func() (btcutil.Address, error) { hash := []byte{ 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a} - return btcutil.NewAddressScriptHashFromHash(hash, btcwire.TestNet3) + return btcutil.NewAddressScriptHashFromHash(hash, &btcnet.TestNet3Params) }, - net: btcwire.TestNet3, + net: &btcnet.TestNet3Params, }, // Negative P2SH tests. @@ -207,18 +198,7 @@ func TestAddresses(t *testing.T) { 0x00, 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0xf2, 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0x10} - return btcutil.NewAddressScriptHashFromHash(hash, btcwire.MainNet) - }, - }, - { - name: "p2sh wrong byte identifier/net", - addr: "0NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", - valid: false, - f: func() (btcutil.Address, error) { - hash := []byte{ - 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, - 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a} - return btcutil.NewAddressScriptHashFromHash(hash, invalidNet) + return btcutil.NewAddressScriptHashFromHash(hash, &btcnet.MainNetParams) }, }, @@ -234,16 +214,16 @@ func TestAddresses(t *testing.T) { 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4}, - btcutil.PKFCompressed, btcutil.MainNetAddr), + btcutil.PKFCompressed, btcnet.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.MainNet) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { name: "mainnet p2pk compressed (0x03)", @@ -256,16 +236,16 @@ func TestAddresses(t *testing.T) { 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65}, - btcutil.PKFCompressed, btcutil.MainNetAddr), + btcutil.PKFCompressed, btcnet.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.MainNet) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { name: "mainnet p2pk uncompressed (0x04)", @@ -282,7 +262,7 @@ func TestAddresses(t *testing.T) { 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3}, - btcutil.PKFUncompressed, btcutil.MainNetAddr), + btcutil.PKFUncompressed, btcnet.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, @@ -292,9 +272,9 @@ func TestAddresses(t *testing.T) { 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.MainNet) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { name: "mainnet p2pk hybrid (0x06)", @@ -311,7 +291,7 @@ func TestAddresses(t *testing.T) { 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e}, - btcutil.PKFHybrid, btcutil.MainNetAddr), + btcutil.PKFHybrid, btcnet.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, @@ -321,9 +301,9 @@ func TestAddresses(t *testing.T) { 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.MainNet) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { name: "mainnet p2pk hybrid (0x07)", @@ -340,7 +320,7 @@ func TestAddresses(t *testing.T) { 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b}, - btcutil.PKFHybrid, btcutil.MainNetAddr), + btcutil.PKFHybrid, btcnet.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, @@ -350,9 +330,9 @@ func TestAddresses(t *testing.T) { 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.MainNet) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.MainNetParams) }, - net: btcwire.MainNet, + net: &btcnet.MainNetParams, }, { name: "testnet p2pk compressed (0x02)", @@ -365,16 +345,16 @@ func TestAddresses(t *testing.T) { 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4}, - btcutil.PKFCompressed, btcutil.TestNetAddr), + btcutil.PKFCompressed, btcnet.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.TestNet3) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.TestNet3Params) }, - net: btcwire.TestNet3, + net: &btcnet.TestNet3Params, }, { name: "testnet p2pk compressed (0x03)", @@ -387,16 +367,16 @@ func TestAddresses(t *testing.T) { 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65}, - btcutil.PKFCompressed, btcutil.TestNetAddr), + btcutil.PKFCompressed, btcnet.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.TestNet3) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.TestNet3Params) }, - net: btcwire.TestNet3, + net: &btcnet.TestNet3Params, }, { name: "testnet p2pk uncompressed (0x04)", @@ -413,7 +393,7 @@ func TestAddresses(t *testing.T) { 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3}, - btcutil.PKFUncompressed, btcutil.TestNetAddr), + btcutil.PKFUncompressed, btcnet.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, @@ -423,9 +403,9 @@ func TestAddresses(t *testing.T) { 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.TestNet3) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.TestNet3Params) }, - net: btcwire.TestNet3, + net: &btcnet.TestNet3Params, }, { name: "testnet p2pk hybrid (0x06)", @@ -442,7 +422,7 @@ func TestAddresses(t *testing.T) { 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e}, - btcutil.PKFHybrid, btcutil.TestNetAddr), + btcutil.PKFHybrid, btcnet.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, @@ -452,9 +432,9 @@ func TestAddresses(t *testing.T) { 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.TestNet3) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.TestNet3Params) }, - net: btcwire.TestNet3, + net: &btcnet.TestNet3Params, }, { name: "testnet p2pk hybrid (0x07)", @@ -471,7 +451,7 @@ func TestAddresses(t *testing.T) { 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b}, - btcutil.PKFHybrid, btcutil.TestNetAddr), + btcutil.PKFHybrid, btcnet.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, @@ -481,9 +461,9 @@ func TestAddresses(t *testing.T) { 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b} - return btcutil.NewAddressPubKey(serializedPubKey, btcwire.TestNet3) + return btcutil.NewAddressPubKey(serializedPubKey, &btcnet.TestNet3Params) }, - net: btcwire.TestNet3, + net: &btcnet.TestNet3Params, }, } diff --git a/internal_test.go b/internal_test.go index 2a0937f..1e6fef8 100644 --- a/internal_test.go +++ b/internal_test.go @@ -60,7 +60,7 @@ func TstAddressPubKey(serializedPubKey []byte, pubKeyFormat PubKeyFormat, return &AddressPubKey{ pubKeyFormat: pubKeyFormat, pubKey: (*btcec.PublicKey)(pubKey), - netID: netID, + pubKeyHashID: netID, } } diff --git a/test_coverage.txt b/test_coverage.txt index bffcb63..8d48c52 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,65 +2,66 @@ github.com/conformal/btcutil/base58.go Base58Decode 100.00% (20/20) github.com/conformal/btcutil/base58.go Base58Encode 100.00% (15/15) github.com/conformal/btcutil/block.go Block.Tx 100.00% (12/12) -github.com/conformal/btcutil/wif.go WIF.String 100.00% (11/11) github.com/conformal/btcutil/block.go Block.Transactions 100.00% (11/11) -github.com/conformal/btcutil/address.go encodeAddress 100.00% (9/9) +github.com/conformal/btcutil/wif.go WIF.String 100.00% (11/11) github.com/conformal/btcutil/amount.go NewAmount 100.00% (9/9) github.com/conformal/btcutil/amount.go AmountUnit.String 100.00% (8/8) github.com/conformal/btcutil/block.go NewBlockFromBytes 100.00% (7/7) github.com/conformal/btcutil/tx.go NewTxFromBytes 100.00% (7/7) -github.com/conformal/btcutil/block.go Block.Sha 100.00% (5/5) +github.com/conformal/btcutil/address.go encodeAddress 100.00% (6/6) +github.com/conformal/btcutil/address.go newAddressScriptHashFromHash 100.00% (5/5) github.com/conformal/btcutil/tx.go Tx.Sha 100.00% (5/5) -github.com/conformal/btcutil/address.go checkBitcoinNet 100.00% (5/5) +github.com/conformal/btcutil/block.go Block.Sha 100.00% (5/5) +github.com/conformal/btcutil/address.go newAddressPubKeyHash 100.00% (5/5) github.com/conformal/btcutil/hash160.go calcHash 100.00% (2/2) -github.com/conformal/btcutil/amount.go Amount.Format 100.00% (2/2) github.com/conformal/btcutil/address.go NewAddressScriptHash 100.00% (2/2) -github.com/conformal/btcutil/block.go NewBlockFromBlockAndBytes 100.00% (1/1) -github.com/conformal/btcutil/amount.go Amount.ToUnit 100.00% (1/1) +github.com/conformal/btcutil/amount.go Amount.Format 100.00% (2/2) github.com/conformal/btcutil/amount.go Amount.String 100.00% (1/1) -github.com/conformal/btcutil/address.go AddressPubKeyHash.String 100.00% (1/1) +github.com/conformal/btcutil/address.go AddressPubKeyHash.Hash160 100.00% (1/1) +github.com/conformal/btcutil/block.go OutOfRangeError.Error 100.00% (1/1) github.com/conformal/btcutil/block.go Block.MsgBlock 100.00% (1/1) -github.com/conformal/btcutil/block.go NewBlock 100.00% (1/1) -github.com/conformal/btcutil/block.go Block.SetHeight 100.00% (1/1) -github.com/conformal/btcutil/block.go Block.Height 100.00% (1/1) +github.com/conformal/btcutil/tx.go Tx.SetIndex 100.00% (1/1) +github.com/conformal/btcutil/address.go NewAddressPubKeyHash 100.00% (1/1) github.com/conformal/btcutil/address.go AddressPubKeyHash.EncodeAddress 100.00% (1/1) github.com/conformal/btcutil/address.go AddressPubKeyHash.ScriptAddress 100.00% (1/1) -github.com/conformal/btcutil/address.go AddressPubKeyHash.Hash160 100.00% (1/1) -github.com/conformal/btcutil/tx.go NewTx 100.00% (1/1) +github.com/conformal/btcutil/address.go AddressPubKeyHash.IsForNet 100.00% (1/1) +github.com/conformal/btcutil/address.go AddressPubKeyHash.String 100.00% (1/1) +github.com/conformal/btcutil/address.go NewAddressScriptHashFromHash 100.00% (1/1) github.com/conformal/btcutil/address.go AddressScriptHash.EncodeAddress 100.00% (1/1) github.com/conformal/btcutil/address.go AddressScriptHash.ScriptAddress 100.00% (1/1) -github.com/conformal/btcutil/tx.go Tx.SetIndex 100.00% (1/1) +github.com/conformal/btcutil/address.go AddressScriptHash.IsForNet 100.00% (1/1) github.com/conformal/btcutil/address.go AddressScriptHash.String 100.00% (1/1) github.com/conformal/btcutil/address.go AddressScriptHash.Hash160 100.00% (1/1) -github.com/conformal/btcutil/tx.go Tx.Index 100.00% (1/1) github.com/conformal/btcutil/address.go AddressPubKey.EncodeAddress 100.00% (1/1) github.com/conformal/btcutil/address.go AddressPubKey.ScriptAddress 100.00% (1/1) -github.com/conformal/btcutil/tx.go Tx.MsgTx 100.00% (1/1) +github.com/conformal/btcutil/address.go AddressPubKey.IsForNet 100.00% (1/1) github.com/conformal/btcutil/address.go AddressPubKey.String 100.00% (1/1) +github.com/conformal/btcutil/amount.go Amount.ToUnit 100.00% (1/1) +github.com/conformal/btcutil/block.go Block.Height 100.00% (1/1) +github.com/conformal/btcutil/block.go Block.SetHeight 100.00% (1/1) +github.com/conformal/btcutil/block.go NewBlock 100.00% (1/1) +github.com/conformal/btcutil/block.go NewBlockFromBlockAndBytes 100.00% (1/1) github.com/conformal/btcutil/hash160.go Hash160 100.00% (1/1) -github.com/conformal/btcutil/block.go OutOfRangeError.Error 100.00% (1/1) -github.com/conformal/btcutil/address.go DecodeAddress 95.65% (22/23) +github.com/conformal/btcutil/tx.go Tx.MsgTx 100.00% (1/1) +github.com/conformal/btcutil/tx.go Tx.Index 100.00% (1/1) +github.com/conformal/btcutil/tx.go NewTx 100.00% (1/1) github.com/conformal/btcutil/appdata.go appDataDir 92.00% (23/25) -github.com/conformal/btcutil/address.go NewAddressPubKeyHash 91.67% (11/12) -github.com/conformal/btcutil/address.go NewAddressScriptHashFromHash 91.67% (11/12) github.com/conformal/btcutil/block.go Block.TxLoc 88.89% (8/9) github.com/conformal/btcutil/block.go Block.Bytes 88.89% (8/9) -github.com/conformal/btcutil/address.go AddressPubKey.serialize 85.71% (6/7) -github.com/conformal/btcutil/address.go NewAddressPubKey 83.33% (15/18) -github.com/conformal/btcutil/wif.go DecodeWIF 81.82% (18/22) -github.com/conformal/btcutil/wif.go NewWIF 75.00% (3/4) +github.com/conformal/btcutil/address.go NewAddressPubKey 87.50% (7/8) +github.com/conformal/btcutil/address.go DecodeAddress 85.00% (17/20) +github.com/conformal/btcutil/wif.go DecodeWIF 85.00% (17/20) +github.com/conformal/btcutil/address.go AddressPubKey.serialize 80.00% (4/5) github.com/conformal/btcutil/block.go Block.TxSha 75.00% (3/4) github.com/conformal/btcutil/wif.go paddedAppend 66.67% (2/3) -github.com/conformal/btcutil/address.go AddressPubKey.IsForNet 60.00% (3/5) -github.com/conformal/btcutil/address.go AddressScriptHash.IsForNet 60.00% (3/5) -github.com/conformal/btcutil/address.go AddressPubKeyHash.IsForNet 60.00% (3/5) +github.com/conformal/btcutil/wif.go NewWIF 66.67% (2/3) github.com/conformal/btcutil/certgen.go NewTLSCertPair 0.00% (0/50) github.com/conformal/btcutil/wif.go WIF.SerializePubKey 0.00% (0/4) -github.com/conformal/btcutil/wif.go WIF.IsForNet 0.00% (0/4) github.com/conformal/btcutil/address.go AddressPubKey.AddressPubKeyHash 0.00% (0/3) -github.com/conformal/btcutil/appdata.go AppDataDir 0.00% (0/1) -github.com/conformal/btcutil/address.go AddressPubKey.Format 0.00% (0/1) github.com/conformal/btcutil/address.go AddressPubKey.SetFormat 0.00% (0/1) +github.com/conformal/btcutil/appdata.go AppDataDir 0.00% (0/1) github.com/conformal/btcutil/address.go AddressPubKey.PubKey 0.00% (0/1) -github.com/conformal/btcutil ------------------------------- 76.70% (293/382) +github.com/conformal/btcutil/wif.go WIF.IsForNet 0.00% (0/1) +github.com/conformal/btcutil/address.go AddressPubKey.Format 0.00% (0/1) +github.com/conformal/btcutil ------------------------------- 76.60% (252/329) diff --git a/wif.go b/wif.go index 900debf..c892be5 100644 --- a/wif.go +++ b/wif.go @@ -9,6 +9,7 @@ import ( "errors" "github.com/conformal/btcec" + "github.com/conformal/btcnet" "github.com/conformal/btcwire" ) @@ -18,21 +19,9 @@ import ( // encountered. var ErrMalformedPrivateKey = errors.New("malformed private key") -// These constants define the magic numbers used for identifing components -// of a WIF-encoded private key and the bitcoin address associated with it. -const ( - // mainNetKey is the magic number identifying a WIF private key for - // the MainNet bitcoin network. - mainNetKey byte = 0x80 - - // testNetKey is the magic number identifying a WIF private key for - // the regression test and TestNet3 bitcoin networks. - testNetKey byte = 0xef - - // compressMagic is the magic byte used to identify a WIF encoding for - // an address created from a compressed serialized public key. - compressMagic byte = 0x01 -) +// compressMagic is the magic byte used to identify a WIF encoding for +// an address created from a compressed serialized public key. +const compressMagic byte = 0x01 // WIF contains the individual components described by the Wallet Import Format // (WIF). A WIF string is typically used to represent a private key and its @@ -56,35 +45,20 @@ type WIF struct { } // NewWIF creates a new WIF structure to export an address and its private key -// as a string encoded in the Wallet Import Format. The net argument must be -// either btcwire.MainNet, btcwire.TestNet3 or btcwire.TestNet. The compress -// argument specifies whether the address intended to be imported or exported -// was created by serializing the public key compressed rather than -// uncompressed. -func NewWIF(privKey *btcec.PrivateKey, net btcwire.BitcoinNet, compress bool) (*WIF, error) { - // Determine the key's network identifier byte. The same byte is - // shared for TestNet3 and TestNet (the regression test network). - switch net { - case btcwire.MainNet: - return &WIF{privKey, compress, mainNetKey}, nil - case btcwire.TestNet, btcwire.TestNet3: - return &WIF{privKey, compress, testNetKey}, nil - default: - return nil, ErrUnknownNet +// as a string encoded in the Wallet Import Format. The compress argument +// specifies whether the address intended to be imported or exported was created +// by serializing the public key compressed rather than uncompressed. +func NewWIF(privKey *btcec.PrivateKey, net *btcnet.Params, compress bool) (*WIF, error) { + if net == nil { + return nil, errors.New("no network") } + return &WIF{privKey, compress, net.PrivateKeyID}, nil } // IsForNet returns whether or not the decoded WIF structure is associated // with the passed bitcoin network. -func (w *WIF) IsForNet(net btcwire.BitcoinNet) bool { - switch net { - case btcwire.MainNet: - return w.netID == mainNetKey - case btcwire.TestNet, btcwire.TestNet3: - return w.netID == testNetKey - default: - return false - } +func (w *WIF) IsForNet(net *btcnet.Params) bool { + return w.netID == net.PrivateKeyID } // DecodeWIF creates a new WIF structure by decoding the string encoding of @@ -126,11 +100,6 @@ func DecodeWIF(wif string) (*WIF, error) { return nil, ErrMalformedPrivateKey } - netID := decoded[0] - if netID != mainNetKey && netID != testNetKey { - return nil, ErrUnknownNet - } - // Checksum is first four bytes of double SHA256 of the identifier byte // and privKey. Verify this matches the final 4 bytes of the decoded // private key. @@ -145,6 +114,7 @@ func DecodeWIF(wif string) (*WIF, error) { return nil, ErrChecksumMismatch } + netID := decoded[0] privKeyBytes := decoded[1 : 1+btcec.PrivKeyBytesLen] privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) return &WIF{privKey, compress, netID}, nil diff --git a/wif_test.go b/wif_test.go index f59a289..f7c0127 100644 --- a/wif_test.go +++ b/wif_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/conformal/btcec" + "github.com/conformal/btcnet" . "github.com/conformal/btcutil" - "github.com/conformal/btcwire" ) func TestEncodeDecodeWIF(t *testing.T) { @@ -25,11 +25,11 @@ func TestEncodeDecodeWIF(t *testing.T) { 0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9, 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98}) - wif1, err := NewWIF(priv1, btcwire.MainNet, false) + wif1, err := NewWIF(priv1, &btcnet.MainNetParams, false) if err != nil { t.Fatal(err) } - wif2, err := NewWIF(priv2, btcwire.TestNet3, true) + wif2, err := NewWIF(priv2, &btcnet.TestNet3Params, true) if err != nil { t.Fatal(err) }