stdaddr: Add v0 p2pkh-ed25519 support.
This adds a new type to fully support version 0 pay-to-pubkey-hash-ed25519 addresses along with associated tests. This is part of a series of commits to fully implement the stdaddr package.
This commit is contained in:
parent
c6d7cd71ac
commit
48222bd7ba
@ -307,9 +307,16 @@ func NewAddressPubKeyHashEcdsaSecp256k1(scriptVersion uint16, pkHash []byte,
|
||||
// the Hash160 of the correct public key or it will not be redeemable with the
|
||||
// expected public key because it would hash to a different value than the
|
||||
// payment script generated for the provided incorrect public key hash expects.
|
||||
//
|
||||
// NOTE: Version 0 scripts are the only currently supported version.
|
||||
func NewAddressPubKeyHashEd25519(scriptVersion uint16, pkHash []byte,
|
||||
params AddressParams) (Address, error) {
|
||||
|
||||
switch scriptVersion {
|
||||
case 0:
|
||||
return NewAddressPubKeyHashEd25519V0(pkHash, params)
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("pubkey hash addresses for version %d are not "+
|
||||
"supported", scriptVersion)
|
||||
return nil, makeError(ErrUnsupportedScriptVersion, str)
|
||||
|
||||
@ -753,6 +753,80 @@ func TestAddresses(t *testing.T) {
|
||||
commitScript: "bb76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
revokeScript: "bc76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
trsyScript: "c376a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
}, {
|
||||
// ---------------------------------------------------------------------
|
||||
// Negative P2PKH ed25519 tests.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
name: "p2pkh-ed25519 wrong hash length",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("000ef030107fd26e0b6bf40512bca2ceb1dd80adaa")
|
||||
return NewAddressPubKeyHashEd25519(0, hash, mainNetParams)
|
||||
},
|
||||
makeErr: ErrInvalidHashLen,
|
||||
}, {
|
||||
name: "p2pkh-ed25519 unsupported script version",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("0ef030107fd26e0b6bf40512bca2ceb1dd80adaa")
|
||||
return NewAddressPubKeyHashEd25519(9999, hash, mainNetParams)
|
||||
},
|
||||
makeErr: ErrUnsupportedScriptVersion,
|
||||
}, {
|
||||
// ---------------------------------------------------------------------
|
||||
// Positive P2PKH Ed25519 tests.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
name: "mainnet p2pkh-ed25519",
|
||||
makeAddr: func() (Address, error) {
|
||||
// From pubkey for privkey 0x00...01.
|
||||
hash := hexToBytes("456d8ee57a4b9121987b4ecab8c3bcb5797e8a53")
|
||||
return NewAddressPubKeyHashEd25519(0, hash, mainNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "DeeUhrRoTp4DftsqddVW96yMGMW4sgQFYUE",
|
||||
net: mainNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a914456d8ee57a4b9121987b4ecab8c3bcb5797e8a538851be",
|
||||
}, {
|
||||
name: "mainnet p2pkh-ed25519 2",
|
||||
makeAddr: func() (Address, error) {
|
||||
// From pubkey for privkey 0x00...02.
|
||||
hash := hexToBytes("09788a8dcb216efa354e487d57d76255b1af4320")
|
||||
return NewAddressPubKeyHashEd25519(0, hash, mainNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "DeZ1gU2ta8auk5et79R74GYR3pnF31KXbFo",
|
||||
net: mainNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a91409788a8dcb216efa354e487d57d76255b1af43208851be",
|
||||
}, {
|
||||
name: "testnet p2pkh-ed25519",
|
||||
makeAddr: func() (Address, error) {
|
||||
// From pubkey for privkey 0x00...01.
|
||||
hash := hexToBytes("456d8ee57a4b9121987b4ecab8c3bcb5797e8a53")
|
||||
return NewAddressPubKeyHashEd25519(0, hash, testNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "TeeXvqZJrc7KnFZCT27fHfzcrTTzSF1aSRG",
|
||||
net: testNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a914456d8ee57a4b9121987b4ecab8c3bcb5797e8a538851be",
|
||||
}, {
|
||||
name: "regnet p2pkh-ed25519",
|
||||
makeAddr: func() (Address, error) {
|
||||
// From pubkey for privkey 0x00...01.
|
||||
hash := hexToBytes("456d8ee57a4b9121987b4ecab8c3bcb5797e8a53")
|
||||
return NewAddressPubKeyHashEd25519(0, hash, regNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "ReMrcHBAbQyQZuHuQwsQBXkxVZgXpnbqX72",
|
||||
net: regNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a914456d8ee57a4b9121987b4ecab8c3bcb5797e8a538851be",
|
||||
}}
|
||||
|
||||
for _, test := range tests {
|
||||
@ -951,6 +1025,11 @@ func TestAddresses(t *testing.T) {
|
||||
id := test.net.AddrIDPubKeyHashECDSAV0()
|
||||
wantPkhAddr = base58.CheckEncode(Hash160(a.serializedPubKey), id)
|
||||
pkhAddr = a.AddressPubKeyHash()
|
||||
|
||||
case *AddressPubKeyEd25519V0:
|
||||
id := test.net.AddrIDPubKeyHashEd25519V0()
|
||||
wantPkhAddr = base58.CheckEncode(Hash160(a.serializedPubKey), id)
|
||||
pkhAddr = a.AddressPubKeyHash()
|
||||
}
|
||||
if pkhAddr != nil {
|
||||
gotAddr := pkhAddr.Address()
|
||||
|
||||
@ -273,8 +273,10 @@ type AddressPubKeyEd25519V0 struct {
|
||||
serializedPubKey []byte
|
||||
}
|
||||
|
||||
// Ensure AddressPubKeyEd25519V0 implements the Address interfaces.
|
||||
// Ensure AddressPubKeyEd25519V0 implements the Address and AddressPubKeyHasher
|
||||
// interfaces.
|
||||
var _ Address = (*AddressPubKeyEd25519V0)(nil)
|
||||
var _ AddressPubKeyHasher = (*AddressPubKeyEd25519V0)(nil)
|
||||
|
||||
// NewAddressPubKeyEd25519V0Raw returns an address that represents a payment
|
||||
// destination which imposes an encumbrance that requires a valid Ed25519
|
||||
@ -356,6 +358,17 @@ func (addr *AddressPubKeyEd25519V0) PaymentScript() (uint16, []byte) {
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// AddressPubKeyHash returns the address converted to a
|
||||
// pay-to-pubkey-hash-ed25519 address.
|
||||
func (addr *AddressPubKeyEd25519V0) AddressPubKeyHash() Address {
|
||||
pkHash := Hash160(addr.serializedPubKey)
|
||||
addrPKH := &AddressPubKeyHashEd25519V0{
|
||||
netID: addr.pubKeyHashID,
|
||||
}
|
||||
copy(addrPKH.hash[:], pkHash)
|
||||
return addrPKH
|
||||
}
|
||||
|
||||
// String returns a human-readable string for the address.
|
||||
//
|
||||
// This is equivalent to calling Address, but is provided so the type can be
|
||||
@ -697,6 +710,94 @@ func (addr *AddressPubKeyHashEcdsaSecp256k1V0) String() string {
|
||||
return addr.Address()
|
||||
}
|
||||
|
||||
// AddressPubKeyHashEd25519V0 specifies an address that represents a a payment
|
||||
// destination which imposes an encumbrance that requires an Ed25519 public key
|
||||
// that hashes to the given public key hash along with a valid Ed25519 signature
|
||||
// for that public key.
|
||||
//
|
||||
// This is commonly referred to as pay-to-pubkey-hash-ed25519.
|
||||
type AddressPubKeyHashEd25519V0 struct {
|
||||
netID [2]byte
|
||||
hash [ripemd160.Size]byte
|
||||
}
|
||||
|
||||
// Ensure AddressPubKeyHashEd25519V0 implements the Address and Hash160er
|
||||
// interfaces.
|
||||
var _ Address = (*AddressPubKeyHashEd25519V0)(nil)
|
||||
var _ Hash160er = (*AddressPubKeyHashEd25519V0)(nil)
|
||||
|
||||
// NewAddressPubKeyHashEd25519V0 returns an address that represents a a payment
|
||||
// destination which imposes an encumbrance that requires an Ed25519 public key
|
||||
// that hashes to the provided public key hash along with a valid Ed25519
|
||||
// signature for that public key using version 0 scripts.
|
||||
//
|
||||
// The provided public key hash must be 20 bytes and be the Hash160 of the
|
||||
// correct public key or it will not be redeemable with the expected public key
|
||||
// because it would hash to a different value than the payment script generated
|
||||
// for the provided incorrect public key hash expects.
|
||||
func NewAddressPubKeyHashEd25519V0(pkHash []byte,
|
||||
params AddressParamsV0) (*AddressPubKeyHashEd25519V0, error) {
|
||||
|
||||
// Check for a valid script hash length.
|
||||
if len(pkHash) != ripemd160.Size {
|
||||
str := fmt.Sprintf("public key hash is %d bytes vs required %d bytes",
|
||||
len(pkHash), ripemd160.Size)
|
||||
return nil, makeError(ErrInvalidHashLen, str)
|
||||
}
|
||||
|
||||
addr := &AddressPubKeyHashEd25519V0{
|
||||
netID: params.AddrIDPubKeyHashEd25519V0(),
|
||||
}
|
||||
copy(addr.hash[:], pkHash)
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// Address returns the string encoding of the payment address for the associated
|
||||
// script version and payment script.
|
||||
//
|
||||
// This is part of the Address interface implementation.
|
||||
func (addr *AddressPubKeyHashEd25519V0) Address() string {
|
||||
// The format for the data portion of addresses that encode 160-bit hashes
|
||||
// is merely the hash itself:
|
||||
// 20-byte ripemd160 hash
|
||||
return encodeAddressV0(addr.hash[:ripemd160.Size], addr.netID)
|
||||
}
|
||||
|
||||
// PaymentScript returns the script version associated with the address along
|
||||
// with a script to pay a transaction output to the address.
|
||||
//
|
||||
// This is part of the Address interface implementation.
|
||||
func (addr *AddressPubKeyHashEd25519V0) PaymentScript() (uint16, []byte) {
|
||||
// A pay-to-pubkey-hash-ed25519 script is of the form:
|
||||
// DUP HASH160 <20-byte hash> EQUALVERIFY <1-byte sigtype> CHECKSIGALT
|
||||
//
|
||||
// Since the signature type is 1, it is pushed as a small integer.
|
||||
var script [26]byte
|
||||
script[0] = opDup
|
||||
script[1] = opHash160
|
||||
script[2] = opData20
|
||||
copy(script[3:23], addr.hash[:])
|
||||
script[23] = opEqualVerify
|
||||
script[24] = opPushSTEd25519
|
||||
script[25] = opCheckSigAlt
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// Hash160 returns the underlying array of the pubkey hash. This can be useful
|
||||
// when an array is more appropriate than a slice (for example, when used as map
|
||||
// keys).
|
||||
func (addr *AddressPubKeyHashEd25519V0) Hash160() *[ripemd160.Size]byte {
|
||||
return &addr.hash
|
||||
}
|
||||
|
||||
// String returns a human-readable string for the address.
|
||||
//
|
||||
// This is equivalent to calling Address, but is provided so the type can be
|
||||
// used as a fmt.Stringer.
|
||||
func (addr *AddressPubKeyHashEd25519V0) String() string {
|
||||
return addr.Address()
|
||||
}
|
||||
|
||||
// DecodeAddressV0 decodes the string encoding of an address and returns the
|
||||
// relevant Address if it is a valid encoding for a known version 0 address type
|
||||
// and is for the network identified by the provided parameters.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user