79 lines
2.4 KiB
Go
79 lines
2.4 KiB
Go
package btcutil
|
|
|
|
import (
|
|
"bytes"
|
|
"code.google.com/p/go.crypto/ripemd160"
|
|
"errors"
|
|
"github.com/conformal/btcwire"
|
|
)
|
|
|
|
// ErrAddrUnknownNet describes an error where the address identifier
|
|
// byte is not recognized as belonging to neither the Bitcoin MainNet nor
|
|
// TestNet.
|
|
var ErrAddrUnknownNet = errors.New("unrecognized network identifier byte")
|
|
|
|
// 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.
|
|
var ErrMalformedAddress = errors.New("malformed address")
|
|
|
|
// 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
|
|
)
|
|
|
|
// EncodeAddress takes a 20-byte raw payment address (hash160 of the
|
|
// uncompressed pubkey) and a network identifying byte and encodes the
|
|
// payment address in a human readable string.
|
|
func EncodeAddress(addrHash []byte, netID byte) (encoded string, err error) {
|
|
if len(addrHash) != ripemd160.Size {
|
|
return "", ErrMalformedAddress
|
|
}
|
|
if netID != MainNetAddr && netID != TestNetAddr {
|
|
return "", ErrAddrUnknownNet
|
|
}
|
|
|
|
tosum := append([]byte{netID}, addrHash...)
|
|
cksum := btcwire.DoubleSha256(tosum)
|
|
|
|
a := append([]byte{netID}, addrHash...)
|
|
a = append(a, cksum[:4]...)
|
|
|
|
return Base58Encode(a), nil
|
|
}
|
|
|
|
// DecodeAddress decodes a human readable payment address string
|
|
// returning the 20-byte decoded address, along with the network
|
|
// identifying byte.
|
|
func DecodeAddress(addr string) (addrHash []byte, netID byte, err error) {
|
|
decoded := Base58Decode(addr)
|
|
|
|
// Length of decoded address must be 20 bytes + 1 byte for a network
|
|
// identifier byte + 4 bytes of checksum.
|
|
if len(decoded) != ripemd160.Size+5 {
|
|
return nil, 0x00, ErrMalformedAddress
|
|
}
|
|
|
|
netID = decoded[0]
|
|
if netID != MainNetAddr && netID != TestNetAddr {
|
|
return nil, 0x00, ErrAddrUnknownNet
|
|
}
|
|
addrHash = decoded[1:21]
|
|
|
|
// Checksum is first four bytes of double SHA256 of the network byte
|
|
// and addrHash. Verify this matches the final 4 bytes of the decoded
|
|
// address.
|
|
tosum := append([]byte{netID}, addrHash...)
|
|
cksum := btcwire.DoubleSha256(tosum)[:4]
|
|
if !bytes.Equal(cksum, decoded[len(decoded)-4:]) {
|
|
return nil, 0x00, ErrMalformedAddress
|
|
}
|
|
|
|
return addrHash, netID, nil
|
|
}
|