mirror of
https://github.com/muun/recovery.git
synced 2025-02-23 19:42:30 -05:00
128 lines
3.6 KiB
Go
128 lines
3.6 KiB
Go
package btcutilw
|
|
|
|
// This package wraps some methods from btcutil, using the same interface and delegating all
|
|
// supported cases to that module. It's written to be both compatible and similar in implementation,
|
|
// so it's easy to swap out in the future.
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg"
|
|
"github.com/btcsuite/btcutil"
|
|
)
|
|
|
|
// DecodeAddress uses btcutil.DecodeAddress for all cases except SegWit version 1, which is handled
|
|
// by this wrapper.
|
|
func DecodeAddress(addr string, defaultNet *chaincfg.Params) (btcutil.Address, error) {
|
|
// Try to decode the address using btcutil:
|
|
decoded, libErr := btcutil.DecodeAddress(addr, defaultNet)
|
|
if libErr == nil {
|
|
return decoded, nil
|
|
}
|
|
|
|
// If this is a Taproot address, we're here because the bech32 checksum failed. The easiest way
|
|
// to know is to try:
|
|
witnessVer, witnessProg, err := decodeSegWitAddressV1(addr)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to decode %s (%v after %w)", addr, err, libErr)
|
|
}
|
|
|
|
if witnessVer != 1 {
|
|
return nil, btcutil.UnsupportedWitnessVerError(witnessVer)
|
|
}
|
|
|
|
if len(witnessProg) != 32 {
|
|
return nil, btcutil.UnsupportedWitnessProgLenError(len(witnessProg))
|
|
}
|
|
|
|
oneIndex := strings.LastIndexByte(addr, '1')
|
|
hrp := addr[:oneIndex]
|
|
|
|
return newAddressTaprootKey(hrp, witnessProg)
|
|
}
|
|
|
|
// AddressTaprootKey is an Address for a keyspend-only P2TR output.
|
|
type AddressTaprootKey struct {
|
|
hrp string
|
|
witnessVersion byte
|
|
witnessProgram [32]byte
|
|
}
|
|
|
|
// NewAddressTaprootKey returns a new AddressTaprootKey.
|
|
func NewAddressTaprootKey(xOnlyPubKey []byte, net *chaincfg.Params) (*AddressTaprootKey, error) {
|
|
if len(xOnlyPubKey) != 32 {
|
|
return nil, fmt.Errorf("witness program must be 32 bytes for p2tr, not %d", len(xOnlyPubKey))
|
|
}
|
|
|
|
addr := &AddressTaprootKey{
|
|
hrp: net.Bech32HRPSegwit,
|
|
witnessVersion: 0x01,
|
|
witnessProgram: [32]byte{},
|
|
}
|
|
|
|
copy(addr.witnessProgram[:], xOnlyPubKey)
|
|
|
|
return addr, nil
|
|
}
|
|
|
|
// EncodeAddress returns the bech32m string encoding of an AddressTaprootKey.
|
|
// Part of the Address interface.
|
|
func (a *AddressTaprootKey) EncodeAddress() string {
|
|
str, err := encodeSegWitAddressV1(a.hrp, a.witnessVersion, a.witnessProgram[:])
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
// ScriptAddress returns the witness program for this address.
|
|
// Part of the Address interface.
|
|
func (a *AddressTaprootKey) ScriptAddress() []byte {
|
|
return a.witnessProgram[:]
|
|
}
|
|
|
|
// IsForNet returns whether or not the AddressTaprootKey is associated with a network.
|
|
// Part of the Address interface.
|
|
func (a *AddressTaprootKey) IsForNet(net *chaincfg.Params) bool {
|
|
return a.hrp == net.Bech32HRPSegwit
|
|
}
|
|
|
|
// String returns a human-readable string for the AddressTaprootKey.
|
|
// This is equivalent to calling EncodeAddress, but allows use of fmt.Stringer.
|
|
// Part of the Address interface.
|
|
func (a *AddressTaprootKey) String() string {
|
|
return a.EncodeAddress()
|
|
}
|
|
|
|
// Hrp returns the human-readable part of the bech32 encoded AddressTaprootKey.
|
|
func (a *AddressTaprootKey) Hrp() string {
|
|
return a.hrp
|
|
}
|
|
|
|
// WitnessVersion returns the witness version of the AddressTaprootKey.
|
|
func (a *AddressTaprootKey) WitnessVersion() byte {
|
|
return a.witnessVersion
|
|
}
|
|
|
|
// WitnessProgram returns the witness program of the AddressTaprootKey.
|
|
func (a *AddressTaprootKey) WitnessProgram() []byte {
|
|
return a.witnessProgram[:]
|
|
}
|
|
|
|
func newAddressTaprootKey(hrp string, witnessProg []byte) (*AddressTaprootKey, error) {
|
|
if len(witnessProg) != 32 {
|
|
return nil, fmt.Errorf("witness program must be 32 bytes for p2tr")
|
|
}
|
|
|
|
addr := &AddressTaprootKey{
|
|
hrp: strings.ToLower(hrp),
|
|
witnessVersion: 0x01,
|
|
}
|
|
|
|
copy(addr.witnessProgram[:], witnessProg)
|
|
|
|
return addr, nil
|
|
}
|