stdaddr: Add v0 p2pkh-ecdsa-secp256k1 support.
This adds a new type to fully support version 0 pay-to-pubkey-hash-ecdsa-secp256k1 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
461a15a626
commit
c6d7cd71ac
1
go.mod
1
go.mod
@ -15,6 +15,7 @@ require (
|
||||
github.com/decred/dcrd/chaincfg/v3 v3.0.0
|
||||
github.com/decred/dcrd/connmgr/v3 v3.0.0
|
||||
github.com/decred/dcrd/container/apbf v1.0.0
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0
|
||||
github.com/decred/dcrd/crypto/ripemd160 v1.0.1
|
||||
github.com/decred/dcrd/database/v2 v2.0.3-0.20210129190127-4ebd135a82f1
|
||||
github.com/decred/dcrd/dcrec v1.0.0
|
||||
|
||||
@ -283,9 +283,16 @@ func NewAddressPubKeySchnorrSecp256k1(scriptVersion uint16,
|
||||
// compressed format since it occupies less space on the chain and is more
|
||||
// consistent with other address formats where uncompressed public keys are NOT
|
||||
// supported.
|
||||
//
|
||||
// NOTE: Version 0 scripts are the only currently supported version.
|
||||
func NewAddressPubKeyHashEcdsaSecp256k1(scriptVersion uint16, pkHash []byte,
|
||||
params AddressParams) (Address, error) {
|
||||
|
||||
switch scriptVersion {
|
||||
case 0:
|
||||
return NewAddressPubKeyHashEcdsaSecp256k1V0(pkHash, params)
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("pubkey hash addresses for version %d are not "+
|
||||
"supported", scriptVersion)
|
||||
return nil, makeError(ErrUnsupportedScriptVersion, str)
|
||||
|
||||
@ -651,6 +651,108 @@ func TestAddresses(t *testing.T) {
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "21030844ee70d8384d5250e9bb3a6a73d4b5bec770e8b31d6a0ae9fb739009d91af552be",
|
||||
}, {
|
||||
// ---------------------------------------------------------------------
|
||||
// Negative P2PKH ECDSA secp256k1 tests.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
name: "p2pkh-ecdsa-secp256k1 wrong hash length",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("000ef030107fd26e0b6bf40512bca2ceb1dd80adaa")
|
||||
return NewAddressPubKeyHashEcdsaSecp256k1(0, hash, mainNetParams)
|
||||
},
|
||||
makeErr: ErrInvalidHashLen,
|
||||
}, {
|
||||
name: "p2pkh-ecdsa-secp256k1 unsupported script version",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("2789d58cfa0957d206f025c2af056fc8a77cebb0")
|
||||
return NewAddressPubKeyHashEcdsaSecp256k1(9999, hash, mainNetParams)
|
||||
},
|
||||
makeErr: ErrUnsupportedScriptVersion,
|
||||
}, {
|
||||
// ---------------------------------------------------------------------
|
||||
// Positive P2PKH ECDSA secp256k1 tests.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
name: "mainnet p2pkh-ecdsa-secp256k1",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("2789d58cfa0957d206f025c2af056fc8a77cebb0")
|
||||
return NewAddressPubKeyHashEcdsaSecp256k1(0, hash, mainNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "DsUZxxoHJSty8DCfwfartwTYbuhmVct7tJu",
|
||||
net: mainNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a9142789d58cfa0957d206f025c2af056fc8a77cebb088ac",
|
||||
voteScript: "ba76a9142789d58cfa0957d206f025c2af056fc8a77cebb088ac",
|
||||
rewardAmount: 1e8,
|
||||
feeLimits: 0x5800,
|
||||
rewardScript: "6a1e2789d58cfa0957d206f025c2af056fc8a77cebb000e1f505000000000058",
|
||||
changeScript: "bd76a9142789d58cfa0957d206f025c2af056fc8a77cebb088ac",
|
||||
commitScript: "bb76a9142789d58cfa0957d206f025c2af056fc8a77cebb088ac",
|
||||
revokeScript: "bc76a9142789d58cfa0957d206f025c2af056fc8a77cebb088ac",
|
||||
trsyScript: "c376a9142789d58cfa0957d206f025c2af056fc8a77cebb088ac",
|
||||
}, {
|
||||
name: "mainnet p2pkh-ecdsa-secp256k1 2",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("229ebac30efd6a69eec9c1a48e048b7c975c25f2")
|
||||
return NewAddressPubKeyHashEcdsaSecp256k1(0, hash, mainNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "DsU7xcg53nxaKLLcAUSKyRndjG78Z2VZnX9",
|
||||
net: mainNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a914229ebac30efd6a69eec9c1a48e048b7c975c25f288ac",
|
||||
voteScript: "ba76a914229ebac30efd6a69eec9c1a48e048b7c975c25f288ac",
|
||||
rewardAmount: 9556193632,
|
||||
feeLimits: 0x5900,
|
||||
rewardScript: "6a1e229ebac30efd6a69eec9c1a48e048b7c975c25f260f19739020000000059",
|
||||
changeScript: "bd76a914229ebac30efd6a69eec9c1a48e048b7c975c25f288ac",
|
||||
commitScript: "bb76a914229ebac30efd6a69eec9c1a48e048b7c975c25f288ac",
|
||||
revokeScript: "bc76a914229ebac30efd6a69eec9c1a48e048b7c975c25f288ac",
|
||||
trsyScript: "c376a914229ebac30efd6a69eec9c1a48e048b7c975c25f288ac",
|
||||
}, {
|
||||
name: "testnet p2pkh-ecdsa-secp256k1",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("f15da1cb8d1bcb162c6ab446c95757a6e791c916")
|
||||
return NewAddressPubKeyHashEcdsaSecp256k1(0, hash, testNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "Tso2MVTUeVrjHTBFedFhiyM7yVTbieqp91h",
|
||||
net: testNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
voteScript: "ba76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
rewardAmount: 2428220961,
|
||||
feeLimits: 0x5800,
|
||||
rewardScript: "6a1ef15da1cb8d1bcb162c6ab446c95757a6e791c91621b6bb90000000000058",
|
||||
changeScript: "bd76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
commitScript: "bb76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
revokeScript: "bc76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
trsyScript: "c376a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
}, {
|
||||
name: "regnet p2pkh-sep256k1-ecdsa",
|
||||
makeAddr: func() (Address, error) {
|
||||
hash := hexToBytes("f15da1cb8d1bcb162c6ab446c95757a6e791c916")
|
||||
return NewAddressPubKeyHashEcdsaSecp256k1(0, hash, regNetParams)
|
||||
},
|
||||
makeErr: nil,
|
||||
addr: "RsWM2w5LPJip56uxcZ1Scq7Tcbg97EfiwPA",
|
||||
net: regNetParams,
|
||||
decodeErr: nil,
|
||||
version: 0,
|
||||
payScript: "76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
voteScript: "ba76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
rewardAmount: 2428220961,
|
||||
feeLimits: 0x5800,
|
||||
rewardScript: "6a1ef15da1cb8d1bcb162c6ab446c95757a6e791c91621b6bb90000000000058",
|
||||
changeScript: "bd76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
commitScript: "bb76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
revokeScript: "bc76a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
trsyScript: "c376a914f15da1cb8d1bcb162c6ab446c95757a6e791c91688ac",
|
||||
}}
|
||||
|
||||
for _, test := range tests {
|
||||
@ -840,6 +942,24 @@ func TestAddresses(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure the AddressPubKeyHash method for the address types that
|
||||
// support it returns the expected address.
|
||||
var pkhAddr Address
|
||||
var wantPkhAddr string
|
||||
switch a := decodedAddr.(type) {
|
||||
case *AddressPubKeyEcdsaSecp256k1V0:
|
||||
id := test.net.AddrIDPubKeyHashECDSAV0()
|
||||
wantPkhAddr = base58.CheckEncode(Hash160(a.serializedPubKey), id)
|
||||
pkhAddr = a.AddressPubKeyHash()
|
||||
}
|
||||
if pkhAddr != nil {
|
||||
gotAddr := pkhAddr.Address()
|
||||
if gotAddr != wantPkhAddr {
|
||||
t.Errorf("%s: mismatched pkh address -- got %s, want %s",
|
||||
test.name, gotAddr, wantPkhAddr)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the Hash160 method for the addresses that support it returns
|
||||
// the expected value.
|
||||
if h160er, ok := decodedAddr.(Hash160er); ok {
|
||||
|
||||
@ -5,10 +5,13 @@
|
||||
package stdaddr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/decred/base58"
|
||||
"github.com/decred/dcrd/crypto/blake256"
|
||||
"github.com/decred/dcrd/crypto/ripemd160"
|
||||
"github.com/decred/dcrd/dcrec"
|
||||
"github.com/decred/dcrd/dcrec/edwards/v2"
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
@ -20,12 +23,23 @@ import (
|
||||
// create a cyclic dependency since txscript will need to depend on this package
|
||||
// for signing.
|
||||
const (
|
||||
opData20 = 0x14
|
||||
opData30 = 0x1e
|
||||
opData32 = 0x20
|
||||
opData33 = 0x21
|
||||
op1 = 0x51
|
||||
op2 = 0x52
|
||||
opReturn = 0x6a
|
||||
opDup = 0x76
|
||||
opEqualVerify = 0x88
|
||||
opHash160 = 0xa9
|
||||
opCheckSig = 0xac
|
||||
opSSTx = 0xba
|
||||
opSSGen = 0xbb
|
||||
opSSRTx = 0xbc
|
||||
opSSTxChange = 0xbd
|
||||
opCheckSigAlt = 0xbe
|
||||
opTGen = 0xc3
|
||||
)
|
||||
|
||||
const (
|
||||
@ -41,6 +55,16 @@ const (
|
||||
// pubkey address signature type byte for those that deal with compressed
|
||||
// secp256k1 pubkeys to specify the omitted y coordinate is odd.
|
||||
sigTypeSecp256k1PubKeyCompOddFlag = uint8(1 << 7)
|
||||
|
||||
// commitP2SHFlag specifies the bitmask to apply to an amount in a ticket
|
||||
// commitment in order to specify if it is a pay-to-script-hash commitment.
|
||||
// The value is derived from the fact it is encoded as the most significant
|
||||
// bit in the amount.
|
||||
commitP2SHFlag = uint64(1 << 63)
|
||||
|
||||
// p2pkhPaymentScriptLen is the length of a standard version 0 P2PKH script
|
||||
// for secp256k1+ecdsa.
|
||||
p2pkhPaymentScriptLen = 25
|
||||
)
|
||||
|
||||
// AddressParamsV0 defines an interface that is used to provide the parameters
|
||||
@ -83,6 +107,14 @@ func encodeAddressV0(data []byte, netID [2]byte) string {
|
||||
return base58.CheckEncode(data, netID)
|
||||
}
|
||||
|
||||
// Hash160 calculates the hash ripemd160(blake256(b)).
|
||||
func Hash160(buf []byte) []byte {
|
||||
b256Hash := blake256.Sum256(buf)
|
||||
hasher := ripemd160.New()
|
||||
hasher.Write(b256Hash[:])
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
// AddressPubKeyEcdsaSecp256k1V0 specifies an address that represents a payment
|
||||
// destination which imposes an encumbrance that requires a valid ECDSA
|
||||
// signature for a specific secp256k1 public key.
|
||||
@ -97,8 +129,10 @@ type AddressPubKeyEcdsaSecp256k1V0 struct {
|
||||
serializedPubKey []byte
|
||||
}
|
||||
|
||||
// Ensure AddressPubKeyEcdsaSecp256k1V0 implements the Address interface.
|
||||
// Ensure AddressPubKeyEcdsaSecp256k1V0 implements the Address and
|
||||
// AddressPubKeyHasher interfaces.
|
||||
var _ Address = (*AddressPubKeyEcdsaSecp256k1V0)(nil)
|
||||
var _ AddressPubKeyHasher = (*AddressPubKeyEcdsaSecp256k1V0)(nil)
|
||||
|
||||
// NewAddressPubKeyEcdsaSecp256k1V0Raw returns an address that represents a
|
||||
// payment destination which imposes an encumbrance that requires a valid ECDSA
|
||||
@ -203,6 +237,23 @@ func (addr *AddressPubKeyEcdsaSecp256k1V0) PaymentScript() (uint16, []byte) {
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// AddressPubKeyHash returns the address converted to a
|
||||
// pay-to-pubkey-hash-ecdsa-secp256k1 address.
|
||||
//
|
||||
// Note that the hash used in resulting address is the hash of the serialized
|
||||
// public key and the address constructor intentionally only supports public
|
||||
// keys in the compressed format. In other words, the resulting address will
|
||||
// impose an encumbrance that requires the public key to be provided in the
|
||||
// compressed format.
|
||||
func (addr *AddressPubKeyEcdsaSecp256k1V0) AddressPubKeyHash() Address {
|
||||
pkHash := Hash160(addr.serializedPubKey)
|
||||
addrPKH := &AddressPubKeyHashEcdsaSecp256k1V0{
|
||||
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
|
||||
@ -439,6 +490,213 @@ func (addr *AddressPubKeySchnorrSecp256k1V0) String() string {
|
||||
return addr.Address()
|
||||
}
|
||||
|
||||
// AddressPubKeyHashEcdsaSecp256k1V0 specifies an address that represents a
|
||||
// payment destination which imposes an encumbrance that requires a secp256k1
|
||||
// public key that hashes to the given public key hash along with a valid ECDSA
|
||||
// signature for that public key.
|
||||
//
|
||||
// This is commonly referred to as pay-to-pubkey-hash (P2PKH) for legacy
|
||||
// reasons, however, since it is possible to support multiple algorithm and
|
||||
// signature scheme combinations, it is technically more accurate to refer to it
|
||||
// as pay-to-pubkey-hash-ecdsa-secp256k1.
|
||||
type AddressPubKeyHashEcdsaSecp256k1V0 struct {
|
||||
netID [2]byte
|
||||
hash [ripemd160.Size]byte
|
||||
}
|
||||
|
||||
// Ensure AddressPubKeyHashEcdsaSecp256k1V0 implements the Address,
|
||||
// StakeAddress, and Hash160er interfaces.
|
||||
var _ Address = (*AddressPubKeyHashEcdsaSecp256k1V0)(nil)
|
||||
var _ StakeAddress = (*AddressPubKeyHashEcdsaSecp256k1V0)(nil)
|
||||
var _ Hash160er = (*AddressPubKeyHashEcdsaSecp256k1V0)(nil)
|
||||
|
||||
// NewAddressPubKeyHashEcdsaSecp256k1V0 returns an address that represents a
|
||||
// payment destination which imposes an encumbrance that requires a secp256k1
|
||||
// public key that hashes to the provided public key hash along with a valid
|
||||
// ECDSA signature for that public key using version 0 scripts.
|
||||
//
|
||||
// The provided public key hash must be 20 bytes and is expected to be the
|
||||
// Hash160 of the associated secp256k1 public key serialized in the _compressed_
|
||||
// format.
|
||||
//
|
||||
// It is important to note that while it is technically possible for legacy
|
||||
// reasons to create this specific type of address based on the hash of a public
|
||||
// key in the uncompressed format, so long as it is also redeemed with that same
|
||||
// public key in uncompressed format, it is *HIGHLY* recommended to use the
|
||||
// compressed format since it occupies less space on the chain and is more
|
||||
// consistent with other address formats where uncompressed public keys are NOT
|
||||
// supported.
|
||||
func NewAddressPubKeyHashEcdsaSecp256k1V0(pkHash []byte,
|
||||
params AddressParamsV0) (*AddressPubKeyHashEcdsaSecp256k1V0, 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 := &AddressPubKeyHashEcdsaSecp256k1V0{
|
||||
netID: params.AddrIDPubKeyHashECDSAV0(),
|
||||
}
|
||||
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 *AddressPubKeyHashEcdsaSecp256k1V0) 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)
|
||||
}
|
||||
|
||||
// putPaymentScript serializes the payment script associated with the address
|
||||
// directly into the passed byte slice which must be at least
|
||||
// p2pkhPaymentScriptLen bytes in length or it will panic.
|
||||
func (addr *AddressPubKeyHashEcdsaSecp256k1V0) putPaymentScript(script []byte) {
|
||||
// A pay-to-pubkey-hash-ecdsa-secp256k1 script is of the form:
|
||||
// DUP HASH160 <20-byte hash> EQUALVERIFY CHECKSIG
|
||||
script[0] = opDup
|
||||
script[1] = opHash160
|
||||
script[2] = opData20
|
||||
copy(script[3:23], addr.hash[:])
|
||||
script[23] = opEqualVerify
|
||||
script[24] = opCheckSig
|
||||
}
|
||||
|
||||
// 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 *AddressPubKeyHashEcdsaSecp256k1V0) PaymentScript() (uint16, []byte) {
|
||||
// A pay-to-pubkey-hash-ecdsa-secp256k1 script is of the form:
|
||||
// DUP HASH160 <20-byte hash> EQUALVERIFY CHECKSIG
|
||||
var script [p2pkhPaymentScriptLen]byte
|
||||
addr.putPaymentScript(script[:])
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// VotingRightsScript returns the script version associated with the address
|
||||
// along with a script to give voting rights to the address. It is only valid
|
||||
// when used in stake ticket purchase transactions.
|
||||
//
|
||||
// This is part of the StakeAddress interface implementation.
|
||||
func (addr *AddressPubKeyHashEcdsaSecp256k1V0) VotingRightsScript() (uint16, []byte) {
|
||||
// A script that assigns voting rights for a ticket to this address type is
|
||||
// of the form:
|
||||
// SSTX [standard pay-to-pubkey-hash-ecdsa-secp256k1 script]
|
||||
var script [p2pkhPaymentScriptLen + 1]byte
|
||||
script[0] = opSSTx
|
||||
addr.putPaymentScript(script[1:])
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// RewardCommitmentScript returns the script version associated with the address
|
||||
// along with a script that commits the original funds locked to purchase a
|
||||
// ticket plus the reward to the address along with limits to impose on any
|
||||
// fees.
|
||||
//
|
||||
// This is part of the StakeAddress interface implementation.
|
||||
func (addr *AddressPubKeyHashEcdsaSecp256k1V0) RewardCommitmentScript(amount int64, limits uint16) (uint16, []byte) {
|
||||
// The reward commitment output of a ticket purchase is a provably pruneable
|
||||
// script of the form:
|
||||
// RETURN <20-byte hash || 8-byte amount || 2-byte fee limits>
|
||||
//
|
||||
// The high bit of the amount is used to indicate whether the provided hash
|
||||
// is a public key hash that represents a pay-to-pubkey-hash-ecdsa-secp256k1
|
||||
// script or a script hash that represents a pay-to-script-hash script. It
|
||||
// is NOT set for a public key hash.
|
||||
var script [32]byte
|
||||
script[0] = opReturn
|
||||
script[1] = opData30
|
||||
copy(script[2:22], addr.hash[:])
|
||||
binary.LittleEndian.PutUint64(script[22:30], uint64(amount) & ^commitP2SHFlag)
|
||||
binary.LittleEndian.PutUint16(script[30:32], limits)
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// StakeChangeScript returns the script version associated with the address
|
||||
// along with a script to pay change to the address. It is only valid when used
|
||||
// in stake ticket purchase and treasury add transactions.
|
||||
//
|
||||
// This is part of the StakeAddress interface implementation.
|
||||
func (addr *AddressPubKeyHashEcdsaSecp256k1V0) StakeChangeScript() (uint16, []byte) {
|
||||
// A stake change script to this address type is of the form:
|
||||
// SSTXCHANGE [standard pay-to-pubkey-hash-ecdsa-secp256k1 script]
|
||||
var script [p2pkhPaymentScriptLen + 1]byte
|
||||
script[0] = opSSTxChange
|
||||
addr.putPaymentScript(script[1:])
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// PayVoteCommitmentScript returns the script version associated with the
|
||||
// address along with a script to pay the original funds locked to purchase a
|
||||
// ticket plus the reward to the address. The address must have previously been
|
||||
// committed to by the ticket purchase. The script is only valid when used in
|
||||
// stake vote transactions whose associated tickets are eligible to vote.
|
||||
//
|
||||
// This is part of the StakeAddress interface implementation.
|
||||
func (addr *AddressPubKeyHashEcdsaSecp256k1V0) PayVoteCommitmentScript() (uint16, []byte) {
|
||||
// A script that pays a ticket commitment as part of a vote to this address
|
||||
// type is of the form:
|
||||
// SSGEN [standard pay-to-pubkey-hash-ecdsa-secp256k1 script]
|
||||
var script [p2pkhPaymentScriptLen + 1]byte
|
||||
script[0] = opSSGen
|
||||
addr.putPaymentScript(script[1:])
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// PayRevokeCommitmentScript returns the script version associated with the
|
||||
// address along with a script to revoke an expired or missed ticket which pays
|
||||
// the original funds locked to purchase a ticket to the address. The address
|
||||
// must have previously been committed to by the ticket purchase. The script is
|
||||
// only valid when used in stake revocation transactions whose associated
|
||||
// tickets have been missed or expired.
|
||||
//
|
||||
// This is part of the StakeAddress interface implementation.
|
||||
func (addr *AddressPubKeyHashEcdsaSecp256k1V0) PayRevokeCommitmentScript() (uint16, []byte) {
|
||||
// A ticket revocation script to this address type is of the form:
|
||||
// SSRTX [standard pay-to-pubkey-hash-ecdsa-secp256k1 script]
|
||||
var script [p2pkhPaymentScriptLen + 1]byte
|
||||
script[0] = opSSRTx
|
||||
addr.putPaymentScript(script[1:])
|
||||
return 0, script[:]
|
||||
}
|
||||
|
||||
// PayFromTreasuryScript returns the script version associated with the address
|
||||
// along with a script that pays funds from the treasury to the address. The
|
||||
// script is only valid when used in treasury spend transactions.
|
||||
//
|
||||
// This is part of the StakeAddress interface implementation.
|
||||
func (addr *AddressPubKeyHashEcdsaSecp256k1V0) PayFromTreasuryScript() (uint16, []byte) {
|
||||
// A script that pays from the treasury as a part of a treasury spend to
|
||||
// this address type is of the form:
|
||||
// TGEN [standard pay-to-pubkey-hash-ecdsa-secp256k1 script]
|
||||
var script [p2pkhPaymentScriptLen + 1]byte
|
||||
script[0] = opTGen
|
||||
addr.putPaymentScript(script[1:])
|
||||
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 *AddressPubKeyHashEcdsaSecp256k1V0) 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 *AddressPubKeyHashEcdsaSecp256k1V0) 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.
|
||||
|
||||
@ -35,6 +35,10 @@ const (
|
||||
// ErrInvalidPubKeyFormat indicates that a serialized public key parsed
|
||||
// successfully, but is not one of the allowed formats.
|
||||
ErrInvalidPubKeyFormat = ErrorKind("ErrInvalidPubKeyFormat")
|
||||
|
||||
// ErrInvalidHashLen indicates that either a public key hash or a script
|
||||
// hash is not an allowed length.
|
||||
ErrInvalidHashLen = ErrorKind("ErrInvalidHashLen")
|
||||
)
|
||||
|
||||
// Error satisfies the error interface and prints human-readable errors.
|
||||
|
||||
@ -23,6 +23,7 @@ func TestErrorKindStringer(t *testing.T) {
|
||||
{ErrBadAddressChecksum, "ErrBadAddressChecksum"},
|
||||
{ErrInvalidPubKey, "ErrInvalidPubKey"},
|
||||
{ErrInvalidPubKeyFormat, "ErrInvalidPubKeyFormat"},
|
||||
{ErrInvalidHashLen, "ErrInvalidHashLen"},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user