mirror of
https://github.com/LBRYFoundation/lbcutil.git
synced 2025-08-23 17:47:30 +00:00
97 lines
2.8 KiB
Go
97 lines
2.8 KiB
Go
// Copyright (c) 2013 Conformal Systems LLC.
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package btcutil
|
|
|
|
import (
|
|
"bytes"
|
|
"code.google.com/p/go.crypto/ripemd160"
|
|
"errors"
|
|
"github.com/conformal/btcwire"
|
|
)
|
|
|
|
// ErrUnknownNet describes an error where the Bitcoin network is
|
|
// not recognized.
|
|
var 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.
|
|
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 a pubkey)
|
|
// and the Bitcoin network to create a human-readable payment address string.
|
|
func EncodeAddress(addrHash []byte, net btcwire.BitcoinNet) (encoded string, err error) {
|
|
if len(addrHash) != ripemd160.Size {
|
|
return "", ErrMalformedAddress
|
|
}
|
|
|
|
var netID byte
|
|
switch net {
|
|
case btcwire.MainNet:
|
|
netID = MainNetAddr
|
|
case btcwire.TestNet3:
|
|
netID = TestNetAddr
|
|
default:
|
|
return "", ErrUnknownNet
|
|
}
|
|
|
|
tosum := append([]byte{netID}, addrHash...)
|
|
cksum := btcwire.DoubleSha256(tosum)
|
|
|
|
// Address before base58 encoding is 1 byte for netID, 20 bytes for
|
|
// hash, plus 4 bytes of checksum.
|
|
a := make([]byte, 25, 25)
|
|
a[0] = netID
|
|
copy(a[1:], addrHash)
|
|
copy(a[21:], cksum[:4])
|
|
|
|
return Base58Encode(a), nil
|
|
}
|
|
|
|
// DecodeAddress decodes a human-readable payment address string
|
|
// returning the 20-byte decoded address, along with the Bitcoin
|
|
// network for the address.
|
|
func DecodeAddress(addr string) (addrHash []byte, net btcwire.BitcoinNet, 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
|
|
}
|
|
|
|
switch decoded[0] {
|
|
case MainNetAddr:
|
|
net = btcwire.MainNet
|
|
case TestNetAddr:
|
|
net = btcwire.TestNet3
|
|
default:
|
|
return nil, 0, ErrUnknownNet
|
|
}
|
|
|
|
// 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 := decoded[:ripemd160.Size+1]
|
|
cksum := btcwire.DoubleSha256(tosum)[:4]
|
|
if !bytes.Equal(cksum, decoded[len(decoded)-4:]) {
|
|
return nil, net, ErrMalformedAddress
|
|
}
|
|
|
|
addrHash = make([]byte, ripemd160.Size, ripemd160.Size)
|
|
copy(addrHash, decoded[1:ripemd160.Size+1])
|
|
|
|
return addrHash, net, nil
|
|
}
|