address: refactor common code into AddressSegWit

To avoid a lot of code duplication, we extract the common parts of the
AddressWitnessPubKeyHash and AddressWitnessScriptHash types into a
common base type called AddressSegWit.
This commit is contained in:
Oliver Gugger 2021-09-27 13:40:05 +02:00
parent 43b172ec93
commit 4a0c04f989
No known key found for this signature in database
GPG key ID: 8E4256593F177720
2 changed files with 98 additions and 123 deletions

View file

@ -506,25 +506,88 @@ func (a *AddressPubKey) PubKey() *btcec.PublicKey {
return a.pubKey return a.pubKey
} }
// AddressSegWit is the base address type for all SegWit addresses.
type AddressSegWit struct {
hrp string
witnessVersion byte
witnessProgram []byte
}
// EncodeAddress returns the bech32 (or bech32m for SegWit v1) string encoding
// of an AddressSegWit.
//
// NOTE: This method is part of the Address interface.
func (a *AddressSegWit) EncodeAddress() string {
str, err := encodeSegWitAddress(
a.hrp, a.witnessVersion, a.witnessProgram[:],
)
if err != nil {
return ""
}
return str
}
// ScriptAddress returns the witness program for this address.
//
// NOTE: This method is part of the Address interface.
func (a *AddressSegWit) ScriptAddress() []byte {
return a.witnessProgram[:]
}
// IsForNet returns whether the AddressSegWit is associated with the passed
// bitcoin network.
//
// NOTE: This method is part of the Address interface.
func (a *AddressSegWit) IsForNet(net *chaincfg.Params) bool {
return a.hrp == net.Bech32HRPSegwit
}
// String returns a human-readable string for the AddressWitnessPubKeyHash.
// This is equivalent to calling EncodeAddress, but is provided so the type
// can be used as a fmt.Stringer.
//
// NOTE: This method is part of the Address interface.
func (a *AddressSegWit) String() string {
return a.EncodeAddress()
}
// Hrp returns the human-readable part of the bech32 (or bech32m for SegWit v1)
// encoded AddressSegWit.
func (a *AddressSegWit) Hrp() string {
return a.hrp
}
// WitnessVersion returns the witness version of the AddressSegWit.
func (a *AddressSegWit) WitnessVersion() byte {
return a.witnessVersion
}
// WitnessProgram returns the witness program of the AddressSegWit.
func (a *AddressSegWit) WitnessProgram() []byte {
return a.witnessProgram[:]
}
// AddressWitnessPubKeyHash is an Address for a pay-to-witness-pubkey-hash // AddressWitnessPubKeyHash is an Address for a pay-to-witness-pubkey-hash
// (P2WPKH) output. See BIP 173 for further details regarding native segregated // (P2WPKH) output. See BIP 173 for further details regarding native segregated
// witness address encoding: // witness address encoding:
// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
type AddressWitnessPubKeyHash struct { type AddressWitnessPubKeyHash struct {
hrp string AddressSegWit
witnessVersion byte
witnessProgram [20]byte
} }
// NewAddressWitnessPubKeyHash returns a new AddressWitnessPubKeyHash. // NewAddressWitnessPubKeyHash returns a new AddressWitnessPubKeyHash.
func NewAddressWitnessPubKeyHash(witnessProg []byte, net *chaincfg.Params) (*AddressWitnessPubKeyHash, error) { func NewAddressWitnessPubKeyHash(witnessProg []byte,
net *chaincfg.Params) (*AddressWitnessPubKeyHash, error) {
return newAddressWitnessPubKeyHash(net.Bech32HRPSegwit, witnessProg) return newAddressWitnessPubKeyHash(net.Bech32HRPSegwit, witnessProg)
} }
// newAddressWitnessPubKeyHash is an internal helper function to create an // newAddressWitnessPubKeyHash is an internal helper function to create an
// AddressWitnessPubKeyHash with a known human-readable part, rather than // AddressWitnessPubKeyHash with a known human-readable part, rather than
// looking it up through its parameters. // looking it up through its parameters.
func newAddressWitnessPubKeyHash(hrp string, witnessProg []byte) (*AddressWitnessPubKeyHash, error) { func newAddressWitnessPubKeyHash(hrp string,
witnessProg []byte) (*AddressWitnessPubKeyHash, error) {
// Check for valid program length for witness version 0, which is 20 // Check for valid program length for witness version 0, which is 20
// for P2WPKH. // for P2WPKH.
if len(witnessProg) != 20 { if len(witnessProg) != 20 {
@ -533,68 +596,22 @@ func newAddressWitnessPubKeyHash(hrp string, witnessProg []byte) (*AddressWitnes
} }
addr := &AddressWitnessPubKeyHash{ addr := &AddressWitnessPubKeyHash{
AddressSegWit{
hrp: strings.ToLower(hrp), hrp: strings.ToLower(hrp),
witnessVersion: 0x00, witnessVersion: 0x00,
witnessProgram: witnessProg,
},
} }
copy(addr.witnessProgram[:], witnessProg)
return addr, nil return addr, nil
} }
// EncodeAddress returns the bech32 string encoding of an
// AddressWitnessPubKeyHash.
// Part of the Address interface.
func (a *AddressWitnessPubKeyHash) EncodeAddress() string {
str, err := encodeSegWitAddress(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 *AddressWitnessPubKeyHash) ScriptAddress() []byte {
return a.witnessProgram[:]
}
// IsForNet returns whether or not the AddressWitnessPubKeyHash is associated
// with the passed bitcoin network.
// Part of the Address interface.
func (a *AddressWitnessPubKeyHash) IsForNet(net *chaincfg.Params) bool {
return a.hrp == net.Bech32HRPSegwit
}
// String returns a human-readable string for the AddressWitnessPubKeyHash.
// This is equivalent to calling EncodeAddress, but is provided so the type
// can be used as a fmt.Stringer.
// Part of the Address interface.
func (a *AddressWitnessPubKeyHash) String() string {
return a.EncodeAddress()
}
// Hrp returns the human-readable part of the bech32 encoded
// AddressWitnessPubKeyHash.
func (a *AddressWitnessPubKeyHash) Hrp() string {
return a.hrp
}
// WitnessVersion returns the witness version of the AddressWitnessPubKeyHash.
func (a *AddressWitnessPubKeyHash) WitnessVersion() byte {
return a.witnessVersion
}
// WitnessProgram returns the witness program of the AddressWitnessPubKeyHash.
func (a *AddressWitnessPubKeyHash) WitnessProgram() []byte {
return a.witnessProgram[:]
}
// Hash160 returns the witness program of the AddressWitnessPubKeyHash as a // Hash160 returns the witness program of the AddressWitnessPubKeyHash as a
// byte array. // byte array.
func (a *AddressWitnessPubKeyHash) Hash160() *[20]byte { func (a *AddressWitnessPubKeyHash) Hash160() *[20]byte {
return &a.witnessProgram var pubKeyHashWitnessProgram [20]byte
copy(pubKeyHashWitnessProgram[:], a.witnessProgram)
return &pubKeyHashWitnessProgram
} }
// AddressWitnessScriptHash is an Address for a pay-to-witness-script-hash // AddressWitnessScriptHash is an Address for a pay-to-witness-script-hash
@ -602,20 +619,22 @@ func (a *AddressWitnessPubKeyHash) Hash160() *[20]byte {
// witness address encoding: // witness address encoding:
// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
type AddressWitnessScriptHash struct { type AddressWitnessScriptHash struct {
hrp string AddressSegWit
witnessVersion byte
witnessProgram [32]byte
} }
// NewAddressWitnessScriptHash returns a new AddressWitnessPubKeyHash. // NewAddressWitnessScriptHash returns a new AddressWitnessPubKeyHash.
func NewAddressWitnessScriptHash(witnessProg []byte, net *chaincfg.Params) (*AddressWitnessScriptHash, error) { func NewAddressWitnessScriptHash(witnessProg []byte,
net *chaincfg.Params) (*AddressWitnessScriptHash, error) {
return newAddressWitnessScriptHash(net.Bech32HRPSegwit, witnessProg) return newAddressWitnessScriptHash(net.Bech32HRPSegwit, witnessProg)
} }
// newAddressWitnessScriptHash is an internal helper function to create an // newAddressWitnessScriptHash is an internal helper function to create an
// AddressWitnessScriptHash with a known human-readable part, rather than // AddressWitnessScriptHash with a known human-readable part, rather than
// looking it up through its parameters. // looking it up through its parameters.
func newAddressWitnessScriptHash(hrp string, witnessProg []byte) (*AddressWitnessScriptHash, error) { func newAddressWitnessScriptHash(hrp string,
witnessProg []byte) (*AddressWitnessScriptHash, error) {
// Check for valid program length for witness version 0, which is 32 // Check for valid program length for witness version 0, which is 32
// for P2WSH. // for P2WSH.
if len(witnessProg) != 32 { if len(witnessProg) != 32 {
@ -624,60 +643,12 @@ func newAddressWitnessScriptHash(hrp string, witnessProg []byte) (*AddressWitnes
} }
addr := &AddressWitnessScriptHash{ addr := &AddressWitnessScriptHash{
AddressSegWit{
hrp: strings.ToLower(hrp), hrp: strings.ToLower(hrp),
witnessVersion: 0x00, witnessVersion: 0x00,
witnessProgram: witnessProg,
},
} }
copy(addr.witnessProgram[:], witnessProg)
return addr, nil return addr, nil
} }
// EncodeAddress returns the bech32 string encoding of an
// AddressWitnessScriptHash.
// Part of the Address interface.
func (a *AddressWitnessScriptHash) EncodeAddress() string {
str, err := encodeSegWitAddress(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 *AddressWitnessScriptHash) ScriptAddress() []byte {
return a.witnessProgram[:]
}
// IsForNet returns whether or not the AddressWitnessScriptHash is associated
// with the passed bitcoin network.
// Part of the Address interface.
func (a *AddressWitnessScriptHash) IsForNet(net *chaincfg.Params) bool {
return a.hrp == net.Bech32HRPSegwit
}
// String returns a human-readable string for the AddressWitnessScriptHash.
// This is equivalent to calling EncodeAddress, but is provided so the type
// can be used as a fmt.Stringer.
// Part of the Address interface.
func (a *AddressWitnessScriptHash) String() string {
return a.EncodeAddress()
}
// Hrp returns the human-readable part of the bech32 encoded
// AddressWitnessScriptHash.
func (a *AddressWitnessScriptHash) Hrp() string {
return a.hrp
}
// WitnessVersion returns the witness version of the AddressWitnessScriptHash.
func (a *AddressWitnessScriptHash) WitnessVersion() byte {
return a.witnessVersion
}
// WitnessProgram returns the witness program of the AddressWitnessScriptHash.
func (a *AddressWitnessScriptHash) WitnessProgram() []byte {
return a.witnessProgram[:]
}

View file

@ -59,9 +59,11 @@ func TstAddressWitnessPubKeyHash(version byte, program [20]byte,
hrp string) *AddressWitnessPubKeyHash { hrp string) *AddressWitnessPubKeyHash {
return &AddressWitnessPubKeyHash{ return &AddressWitnessPubKeyHash{
AddressSegWit{
hrp: hrp, hrp: hrp,
witnessVersion: version, witnessVersion: version,
witnessProgram: program, witnessProgram: program[:],
},
} }
} }
@ -71,9 +73,11 @@ func TstAddressWitnessScriptHash(version byte, program [32]byte,
hrp string) *AddressWitnessScriptHash { hrp string) *AddressWitnessScriptHash {
return &AddressWitnessScriptHash{ return &AddressWitnessScriptHash{
AddressSegWit{
hrp: hrp, hrp: hrp,
witnessVersion: version, witnessVersion: version,
witnessProgram: program, witnessProgram: program[:],
},
} }
} }