<commit_before>// Copyright (c) 2013, 2014 The btcsuite developers
// Copyright (c) 2015-2018 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package dcrutil

import (
	"errors"
	"fmt"

	"golang.org/x/crypto/ripemd160"

	"github.com/decred/base58"
	"github.com/decred/dcrd/chaincfg"
	"github.com/decred/dcrd/chaincfg/chainec"
	"github.com/decred/dcrd/dcrec"
	"github.com/decred/dcrd/dcrec/edwards"
	"github.com/decred/dcrd/dcrec/secp256k1"
	"github.com/decred/dcrd/dcrec/secp256k1/schnorr"
)

var (
	// ErrChecksumMismatch describes an error where decoding failed due
	// to a bad checksum.
	ErrChecksumMismatch = errors.New("checksum mismatch")

	// ErrUnknownAddressType describes an error where an address can not
	// decoded as a specific address type due to the string encoding
	// beginning with an identifier byte unknown to any standard or
	// registered (via chaincfg.Register) network.
	ErrUnknownAddressType = errors.New("unknown address type")

	// ErrAddressCollision describes an error where an address can not
	// be uniquely determined as either a pay-to-pubkey-hash or
	// pay-to-script-hash address since the leading identifier is used for
	// describing both address kinds, but for different networks.  Rather
	// than assuming or defaulting to one or the other, this error is
	// returned and the caller must decide how to decode the address.
	ErrAddressCollision = errors.New("address collision")

	// ErrMissingDefaultNet describes an error in DecodeAddress that
	// attempts to decode an address without defining which network to decode
	// for.
	ErrMissingDefaultNet = errors.New("default net not defined")
)

// encodeAddress returns a human-readable payment address given a ripemd160 hash
// and netID which encodes the network and address type.  It is used in both
// pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address encoding.
func encodeAddress(hash160 []byte, netID [2]byte) string {
	// Format is 2 bytes for a network and address class (i.e. P2PKH vs
	// P2SH), 20 bytes for a RIPEMD160 hash, and 4 bytes of checksum.
	return base58.CheckEncode(hash160[:ripemd160.Size], netID)
}

// encodePKAddress returns a human-readable payment address to a public key
// given a serialized public key, a netID, and a signature suite.
func encodePKAddress(serializedPK []byte, netID [2]byte, algo dcrec.SignatureType) string {
	pubKeyBytes := []byte{0x00}

	switch algo {
	case dcrec.STEcdsaSecp256k1:
		pubKeyBytes[0] = byte(dcrec.STEcdsaSecp256k1)
	case dcrec.STEd25519:
		pubKeyBytes[0] = byte(dcrec.STEd25519)
	case dcrec.STSchnorrSecp256k1:
		pubKeyBytes[0] = byte(dcrec.STSchnorrSecp256k1)
	}

	// Pubkeys are encoded as [0] = type/ybit, [1:33] = serialized pubkey
	compressed := serializedPK
	if algo == dcrec.STEcdsaSecp256k1 || algo == dcrec.STSchnorrSecp256k1 {
		pub, err := secp256k1.ParsePubKey(serializedPK)
		if err != nil {
			return ""
		}
		pubSerComp := pub.SerializeCompressed()

		// Set the y-bit if needed.
		if pubSerComp[0] == 0x03 {
			pubKeyBytes[0] |= (1 << 7)
		}

		compressed = pubSerComp[1:]
	}

	pubKeyBytes = append(pubKeyBytes, compressed...)
	return base58.CheckEncode(pubKeyBytes, netID)
}

// Address is an interface type for any type of destination a transaction
// output may spend to.  This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash
// (P2PKH), and pay-to-script-hash (P2SH).  Address is designed to be generic
// enough that other kinds of addresses may be added in the future without
// changing the decoding and encoding API.
type Address interface {
	// String returns the string encoding of the transaction output
	// destination.
	//
	// Please note that String differs subtly from EncodeAddress: String
	// will return the value as a string without any conversion, while
	// EncodeAddress may convert destination types (for example,
	// converting pubkeys to P2PKH addresses) before encoding as a
	// payment address string.
	String() string

	// EncodeAddress returns the string encoding of the payment address
	// associated with the Address value.  See the comment on String
	// for how this method differs from String.
	EncodeAddress() string

	// ScriptAddress returns the raw bytes of the address to be used
	// when inserting the address into a txout's script.
	ScriptAddress() []byte

	// Hash160 returns the Hash160(data) where data is the data normally
	// hashed to 160 bits from the respective address type.
	Hash160() *[ripemd160.Size]byte

	// IsForNet returns whether or not the address is associated with the
	// passed network.
	IsForNet(*chaincfg.Params) bool

	// DSA returns the digital signature algorithm for the address.
	DSA(*chaincfg.Params) dcrec.SignatureType

	// Net returns the network parameters of the address.
	Net() *chaincfg.Params
}

// NewAddressPubKey returns a new Address. decoded must
// be 33 bytes.
func NewAddressPubKey(decoded []byte, net *chaincfg.Params) (Address, error) {
	if len(decoded) == 33 {
		// First byte is the signature suite and ybit.
		suite := decoded[0]
		suite &= ^uint8(1 << 7)
		ybit := !(decoded[0]&(1<<7) == 0)
		toAppend := uint8(0x02)
		if ybit {
			toAppend = 0x03
		}

		switch dcrec.SignatureType(suite) {
		case dcrec.STEcdsaSecp256k1:
			return NewAddressSecpPubKey(
				append([]byte{toAppend}, decoded[1:]...),
				net)
		case dcrec.STEd25519:
			return NewAddressEdwardsPubKey(decoded, net)
		case dcrec.STSchnorrSecp256k1:
			return NewAddressSecSchnorrPubKey(
				append([]byte{toAppend}, decoded[1:]...),
				net)
		}
		return nil, ErrUnknownAddressType
	}
	return nil, ErrUnknownAddressType
}

// DecodeAddress decodes the string encoding of an address and returns
// the Address if addr is a valid encoding for a known address type
func DecodeAddress(addr string) (Address, error) {
	// Switch on decoded length to determine the type.
	decoded, netID, err := base58.CheckDecode(addr)
	if err != nil {
		if err == base58.ErrChecksum {
			return nil, ErrChecksumMismatch
		}
		return nil, fmt.Errorf("decoded address is of unknown format: %v",
			err.Error())
	}

	net, err := detectNetworkForAddress(addr)
	if err != nil {
		return nil, ErrUnknownAddressType
	}

	switch netID {
	case net.PubKeyAddrID:
		return NewAddressPubKey(decoded, net)

	case net.PubKeyHashAddrID:
		return NewAddressPubKeyHash(decoded, net, dcrec.STEcdsaSecp256k1)

	case net.PKHEdwardsAddrID:
		return NewAddressPubKeyHash(decoded, net, dcrec.STEd25519)

	case net.PKHSchnorrAddrID:
		return NewAddressPubKeyHash(decoded, net, dcrec.STSchnorrSecp256k1)

	case net.ScriptHashAddrID:
		return NewAddressScriptHashFromHash(decoded, net)

	default:
		return nil, ErrUnknownAddressType
	}
}

// detectNetworkForAddress pops the first character from a string encoded
// address and detects what network type it is for.
func detectNetworkForAddress(addr string) (*chaincfg.Params, error) {
	if len(addr) < 1 {
		return nil, fmt.Errorf("empty string given for network detection")
	}

	networkChar := addr[0:1]
	switch networkChar {
	case chaincfg.MainNetParams.NetworkAddressPrefix:
		return &chaincfg.MainNetParams, nil
	case chaincfg.TestNet3Params.NetworkAddressPrefix:
		return &chaincfg.TestNet3Params, nil
	case chaincfg.SimNetParams.NetworkAddressPrefix:
		return &chaincfg.SimNetParams, nil
	case chaincfg.RegNetParams.NetworkAddressPrefix:
		return &chaincfg.RegNetParams, nil
	}

	return nil, fmt.Errorf("unknown network type in string encoded address")
}

// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH)
// transaction.
type AddressPubKeyHash struct {
	net   *chaincfg.Params
	hash  [ripemd160.Size]byte
	netID [2]byte
}

// NewAddressPubKeyHash returns a new AddressPubKeyHash.  pkHash must
// be 20 bytes.
func NewAddressPubKeyHash(pkHash []byte, net *chaincfg.Params, algo dcrec.SignatureType) (*AddressPubKeyHash, error) {
	var addrID [2]byte
	switch algo {
	case dcrec.STEcdsaSecp256k1:
		addrID = net.PubKeyHashAddrID
	case dcrec.STEd25519:
		addrID = net.PKHEdwardsAddrID
	case dcrec.STSchnorrSecp256k1:
		addrID = net.PKHSchnorrAddrID
	default:
		return nil, errors.New("unknown ECDSA algorithm")
	}
	apkh, err := newAddressPubKeyHash(pkHash, addrID)
	if err != nil {
		return nil, err
	}
	apkh.net = net
	return apkh, nil
}

// newAddressPubKeyHash is the internal API to create a pubkey hash address
// with a known leading identifier byte for a network, rather than looking
// it up through its parameters.  This is useful when creating a new address
// structure from a string encoding where the identifer byte is already
// known.
func newAddressPubKeyHash(pkHash []byte, netID [2]byte) (*AddressPubKeyHash, error) {
	// Check for a valid pubkey hash length.
	if len(pkHash) != ripemd160.Size {
		return nil, errors.New("pkHash must be 20 bytes")
	}
	addr := &AddressPubKeyHash{netID: netID}
	copy(addr.hash[:], pkHash)
	return addr, nil
}

// EncodeAddress returns the string encoding of a pay-to-pubkey-hash
// address.  Part of the Address interface.
func (a *AddressPubKeyHash) EncodeAddress() string {
	return encodeAddress(a.hash[:], a.netID)
}

// ScriptAddress returns the bytes to be included in a txout script to pay
// to a pubkey hash.  Part of the Address interface.
func (a *AddressPubKeyHash) ScriptAddress() []byte {
	return a.hash[:]
}

// IsForNet returns whether or not the pay-to-pubkey-hash address is associated
// with the passed network.
func (a *AddressPubKeyHash) IsForNet(net *chaincfg.Params) bool {
	return a.netID == net.PubKeyHashAddrID ||
		a.netID == net.PKHEdwardsAddrID ||
		a.netID == net.PKHSchnorrAddrID
}

// String returns a human-readable string for the pay-to-pubkey-hash address.
// This is equivalent to calling EncodeAddress, but is provided so the type can
// be used as a fmt.Stringer.
func (a *AddressPubKeyHash) String() string {
	return a.EncodeAddress()
}

// 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 (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte {
	return &a.hash
}

// DSA returns the digital signature algorithm for the associated public key
// hash.
func (a *AddressPubKeyHash) DSA(net *chaincfg.Params) dcrec.SignatureType {
	switch a.netID {
	case net.PubKeyHashAddrID:
		return dcrec.STEcdsaSecp256k1
	case net.PKHEdwardsAddrID:
		return dcrec.STEd25519
	case net.PKHSchnorrAddrID:
		return dcrec.STSchnorrSecp256k1
	}
	return -1
}

// Net returns the network for the address.
func (a *AddressPubKeyHash) Net() *chaincfg.Params {
	return a.net
}

// AddressScriptHash is an Address for a pay-to-script-hash (P2SH)
// transaction.
type AddressScriptHash struct {
	net   *chaincfg.Params
	hash  [ripemd160.Size]byte
	netID [2]byte
}

// NewAddressScriptHash returns a new AddressScriptHash.
func NewAddressScriptHash(serializedScript []byte,
	net *chaincfg.Params) (*AddressScriptHash, error) {
	scriptHash := Hash160(serializedScript)
	ash, err := newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
	if err != nil {
		return nil, err
	}
	ash.net = net

	return ash, nil
}

// NewAddressScriptHashFromHash returns a new AddressScriptHash.  scriptHash
// must be 20 bytes.
func NewAddressScriptHashFromHash(scriptHash []byte,
	net *chaincfg.Params) (*AddressScriptHash, error) {
	ash, err := newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
	if err != nil {
		return nil, err
	}
	ash.net = net

	return ash, nil
}

// newAddressScriptHashFromHash is the internal API to create a script hash
// address with a known leading identifier byte for a network, rather than
// looking it up through its parameters.  This is useful when creating a new
// address structure from a string encoding where the identifer byte is already
// known.
func newAddressScriptHashFromHash(scriptHash []byte,
	netID [2]byte) (*AddressScriptHash, error) {<commit_msg>dcrutil: Fix typos found by misspell.<commit_after>// Copyright (c) 2013, 2014 The btcsuite developers
// Copyright (c) 2015-2018 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package dcrutil

import (
	"errors"
	"fmt"

	"golang.org/x/crypto/ripemd160"

	"github.com/decred/base58"
	"github.com/decred/dcrd/chaincfg"
	"github.com/decred/dcrd/chaincfg/chainec"
	"github.com/decred/dcrd/dcrec"
	"github.com/decred/dcrd/dcrec/edwards"
	"github.com/decred/dcrd/dcrec/secp256k1"
	"github.com/decred/dcrd/dcrec/secp256k1/schnorr"
)

var (
	// ErrChecksumMismatch describes an error where decoding failed due
	// to a bad checksum.
	ErrChecksumMismatch = errors.New("checksum mismatch")

	// ErrUnknownAddressType describes an error where an address can not
	// decoded as a specific address type due to the string encoding
	// beginning with an identifier byte unknown to any standard or
	// registered (via chaincfg.Register) network.
	ErrUnknownAddressType = errors.New("unknown address type")

	// ErrAddressCollision describes an error where an address can not
	// be uniquely determined as either a pay-to-pubkey-hash or
	// pay-to-script-hash address since the leading identifier is used for
	// describing both address kinds, but for different networks.  Rather
	// than assuming or defaulting to one or the other, this error is
	// returned and the caller must decide how to decode the address.
	ErrAddressCollision = errors.New("address collision")

	// ErrMissingDefaultNet describes an error in DecodeAddress that
	// attempts to decode an address without defining which network to decode
	// for.
	ErrMissingDefaultNet = errors.New("default net not defined")
)

// encodeAddress returns a human-readable payment address given a ripemd160 hash
// and netID which encodes the network and address type.  It is used in both
// pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address encoding.
func encodeAddress(hash160 []byte, netID [2]byte) string {
	// Format is 2 bytes for a network and address class (i.e. P2PKH vs
	// P2SH), 20 bytes for a RIPEMD160 hash, and 4 bytes of checksum.
	return base58.CheckEncode(hash160[:ripemd160.Size], netID)
}

// encodePKAddress returns a human-readable payment address to a public key
// given a serialized public key, a netID, and a signature suite.
func encodePKAddress(serializedPK []byte, netID [2]byte, algo dcrec.SignatureType) string {
	pubKeyBytes := []byte{0x00}

	switch algo {
	case dcrec.STEcdsaSecp256k1:
		pubKeyBytes[0] = byte(dcrec.STEcdsaSecp256k1)
	case dcrec.STEd25519:
		pubKeyBytes[0] = byte(dcrec.STEd25519)
	case dcrec.STSchnorrSecp256k1:
		pubKeyBytes[0] = byte(dcrec.STSchnorrSecp256k1)
	}

	// Pubkeys are encoded as [0] = type/ybit, [1:33] = serialized pubkey
	compressed := serializedPK
	if algo == dcrec.STEcdsaSecp256k1 || algo == dcrec.STSchnorrSecp256k1 {
		pub, err := secp256k1.ParsePubKey(serializedPK)
		if err != nil {
			return ""
		}
		pubSerComp := pub.SerializeCompressed()

		// Set the y-bit if needed.
		if pubSerComp[0] == 0x03 {
			pubKeyBytes[0] |= (1 << 7)
		}

		compressed = pubSerComp[1:]
	}

	pubKeyBytes = append(pubKeyBytes, compressed...)
	return base58.CheckEncode(pubKeyBytes, netID)
}

// Address is an interface type for any type of destination a transaction
// output may spend to.  This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash
// (P2PKH), and pay-to-script-hash (P2SH).  Address is designed to be generic
// enough that other kinds of addresses may be added in the future without
// changing the decoding and encoding API.
type Address interface {
	// String returns the string encoding of the transaction output
	// destination.
	//
	// Please note that String differs subtly from EncodeAddress: String
	// will return the value as a string without any conversion, while
	// EncodeAddress may convert destination types (for example,
	// converting pubkeys to P2PKH addresses) before encoding as a
	// payment address string.
	String() string

	// EncodeAddress returns the string encoding of the payment address
	// associated with the Address value.  See the comment on String
	// for how this method differs from String.
	EncodeAddress() string

	// ScriptAddress returns the raw bytes of the address to be used
	// when inserting the address into a txout's script.
	ScriptAddress() []byte

	// Hash160 returns the Hash160(data) where data is the data normally
	// hashed to 160 bits from the respective address type.
	Hash160() *[ripemd160.Size]byte

	// IsForNet returns whether or not the address is associated with the
	// passed network.
	IsForNet(*chaincfg.Params) bool

	// DSA returns the digital signature algorithm for the address.
	DSA(*chaincfg.Params) dcrec.SignatureType

	// Net returns the network parameters of the address.
	Net() *chaincfg.Params
}

// NewAddressPubKey returns a new Address. decoded must
// be 33 bytes.
func NewAddressPubKey(decoded []byte, net *chaincfg.Params) (Address, error) {
	if len(decoded) == 33 {
		// First byte is the signature suite and ybit.
		suite := decoded[0]
		suite &= ^uint8(1 << 7)
		ybit := !(decoded[0]&(1<<7) == 0)
		toAppend := uint8(0x02)
		if ybit {
			toAppend = 0x03
		}

		switch dcrec.SignatureType(suite) {
		case dcrec.STEcdsaSecp256k1:
			return NewAddressSecpPubKey(
				append([]byte{toAppend}, decoded[1:]...),
				net)
		case dcrec.STEd25519:
			return NewAddressEdwardsPubKey(decoded, net)
		case dcrec.STSchnorrSecp256k1:
			return NewAddressSecSchnorrPubKey(
				append([]byte{toAppend}, decoded[1:]...),
				net)
		}
		return nil, ErrUnknownAddressType
	}
	return nil, ErrUnknownAddressType
}

// DecodeAddress decodes the string encoding of an address and returns
// the Address if addr is a valid encoding for a known address type
func DecodeAddress(addr string) (Address, error) {
	// Switch on decoded length to determine the type.
	decoded, netID, err := base58.CheckDecode(addr)
	if err != nil {
		if err == base58.ErrChecksum {
			return nil, ErrChecksumMismatch
		}
		return nil, fmt.Errorf("decoded address is of unknown format: %v",
			err.Error())
	}

	net, err := detectNetworkForAddress(addr)
	if err != nil {
		return nil, ErrUnknownAddressType
	}

	switch netID {
	case net.PubKeyAddrID:
		return NewAddressPubKey(decoded, net)

	case net.PubKeyHashAddrID:
		return NewAddressPubKeyHash(decoded, net, dcrec.STEcdsaSecp256k1)

	case net.PKHEdwardsAddrID:
		return NewAddressPubKeyHash(decoded, net, dcrec.STEd25519)

	case net.PKHSchnorrAddrID:
		return NewAddressPubKeyHash(decoded, net, dcrec.STSchnorrSecp256k1)

	case net.ScriptHashAddrID:
		return NewAddressScriptHashFromHash(decoded, net)

	default:
		return nil, ErrUnknownAddressType
	}
}

// detectNetworkForAddress pops the first character from a string encoded
// address and detects what network type it is for.
func detectNetworkForAddress(addr string) (*chaincfg.Params, error) {
	if len(addr) < 1 {
		return nil, fmt.Errorf("empty string given for network detection")
	}

	networkChar := addr[0:1]
	switch networkChar {
	case chaincfg.MainNetParams.NetworkAddressPrefix:
		return &chaincfg.MainNetParams, nil
	case chaincfg.TestNet3Params.NetworkAddressPrefix:
		return &chaincfg.TestNet3Params, nil
	case chaincfg.SimNetParams.NetworkAddressPrefix:
		return &chaincfg.SimNetParams, nil
	case chaincfg.RegNetParams.NetworkAddressPrefix:
		return &chaincfg.RegNetParams, nil
	}

	return nil, fmt.Errorf("unknown network type in string encoded address")
}

// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH)
// transaction.
type AddressPubKeyHash struct {
	net   *chaincfg.Params
	hash  [ripemd160.Size]byte
	netID [2]byte
}

// NewAddressPubKeyHash returns a new AddressPubKeyHash.  pkHash must
// be 20 bytes.
func NewAddressPubKeyHash(pkHash []byte, net *chaincfg.Params, algo dcrec.SignatureType) (*AddressPubKeyHash, error) {
	var addrID [2]byte
	switch algo {
	case dcrec.STEcdsaSecp256k1:
		addrID = net.PubKeyHashAddrID
	case dcrec.STEd25519:
		addrID = net.PKHEdwardsAddrID
	case dcrec.STSchnorrSecp256k1:
		addrID = net.PKHSchnorrAddrID
	default:
		return nil, errors.New("unknown ECDSA algorithm")
	}
	apkh, err := newAddressPubKeyHash(pkHash, addrID)
	if err != nil {
		return nil, err
	}
	apkh.net = net
	return apkh, nil
}

// newAddressPubKeyHash is the internal API to create a pubkey hash address
// with a known leading identifier byte for a network, rather than looking
// it up through its parameters.  This is useful when creating a new address
// structure from a string encoding where the identifier byte is already
// known.
func newAddressPubKeyHash(pkHash []byte, netID [2]byte) (*AddressPubKeyHash, error) {
	// Check for a valid pubkey hash length.
	if len(pkHash) != ripemd160.Size {
		return nil, errors.New("pkHash must be 20 bytes")
	}
	addr := &AddressPubKeyHash{netID: netID}
	copy(addr.hash[:], pkHash)
	return addr, nil
}

// EncodeAddress returns the string encoding of a pay-to-pubkey-hash
// address.  Part of the Address interface.
func (a *AddressPubKeyHash) EncodeAddress() string {
	return encodeAddress(a.hash[:], a.netID)
}

// ScriptAddress returns the bytes to be included in a txout script to pay
// to a pubkey hash.  Part of the Address interface.
func (a *AddressPubKeyHash) ScriptAddress() []byte {
	return a.hash[:]
}

// IsForNet returns whether or not the pay-to-pubkey-hash address is associated
// with the passed network.
func (a *AddressPubKeyHash) IsForNet(net *chaincfg.Params) bool {
	return a.netID == net.PubKeyHashAddrID ||
		a.netID == net.PKHEdwardsAddrID ||
		a.netID == net.PKHSchnorrAddrID
}

// String returns a human-readable string for the pay-to-pubkey-hash address.
// This is equivalent to calling EncodeAddress, but is provided so the type can
// be used as a fmt.Stringer.
func (a *AddressPubKeyHash) String() string {
	return a.EncodeAddress()
}

// 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 (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte {
	return &a.hash
}

// DSA returns the digital signature algorithm for the associated public key
// hash.
func (a *AddressPubKeyHash) DSA(net *chaincfg.Params) dcrec.SignatureType {
	switch a.netID {
	case net.PubKeyHashAddrID:
		return dcrec.STEcdsaSecp256k1
	case net.PKHEdwardsAddrID:
		return dcrec.STEd25519
	case net.PKHSchnorrAddrID:
		return dcrec.STSchnorrSecp256k1
	}
	return -1
}

// Net returns the network for the address.
func (a *AddressPubKeyHash) Net() *chaincfg.Params {
	return a.net
}

// AddressScriptHash is an Address for a pay-to-script-hash (P2SH)
// transaction.
type AddressScriptHash struct {
	net   *chaincfg.Params
	hash  [ripemd160.Size]byte
	netID [2]byte
}

// NewAddressScriptHash returns a new AddressScriptHash.
func NewAddressScriptHash(serializedScript []byte,
	net *chaincfg.Params) (*AddressScriptHash, error) {
	scriptHash := Hash160(serializedScript)
	ash, err := newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
	if err != nil {
		return nil, err
	}
	ash.net = net

	return ash, nil
}

// NewAddressScriptHashFromHash returns a new AddressScriptHash.  scriptHash
// must be 20 bytes.
func NewAddressScriptHashFromHash(scriptHash []byte,
	net *chaincfg.Params) (*AddressScriptHash, error) {
	ash, err := newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
	if err != nil {
		return nil, err
	}
	ash.net = net

	return ash, nil
}

// newAddressScriptHashFromHash is the internal API to create a script hash
// address with a known leading identifier byte for a network, rather than
// looking it up through its parameters.  This is useful when creating a new
// address structure from a string encoding where the identifier byte is already
// known.
func newAddressScriptHashFromHash(scriptHash []byte,
	netID [2]byte) (*AddressScriptHash, error) {
{'fraction_non_alphanumeric': 0.09223422970595627, 'fraction_numerical': 0.020943285582642204, 'mean_word_length': 4.184581976112921, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2802790', 'n_tokens_mistral': 8142, 'n_tokens_neox': 7579, 'n_words': 2549}