func ripemd160h(data []byte) []byte {
	h := ripemd160.New()
	h.Write(data)
	return h.Sum(nil)
}
ripemd160h returns the RIPEMD160 hash of the given data.
package txscript
import (
	"crypto/sha256"
	"errors"
	"fmt"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
	"golang.org/x/crypto/ripemd160"
)
const (
	minPubKeyHashSigScriptLen = 1 + btcec.MinSigLen + 1 + 1 + 33
	maxPubKeyHashSigScriptLen = 1 + 72 + 1 + 1 + 33
	compressedPubKeyLen = 33
	pubKeyHashLen = 25
	witnessV0PubKeyHashLen = 22
	scriptHashLen = 23
	witnessV0ScriptHashLen = 34
	maxLen = witnessV0ScriptHashLen
)
var (
	ErrUnsupportedScriptType = errors.New("unsupported script type")
)
type PkScript struct {
	class ScriptClass
	script [maxLen]byte
}
func ParsePkScript(pkScript []byte) (PkScript, error) {
	var outputScript PkScript
	scriptClass, _, _, err := ExtractPkScriptAddrs(
		pkScript, &chaincfg.MainNetParams,
	)
	if err != nil {
		return outputScript, fmt.Errorf("unable to parse script type: "+
			"%v", err)
	}
	if !isSupportedScriptType(scriptClass) {
		return outputScript, ErrUnsupportedScriptType
	}
	outputScript.class = scriptClass
	copy(outputScript.script[:], pkScript)
	return outputScript, nil
}
func isSupportedScriptType(class ScriptClass) bool {
	switch class {
	case PubKeyHashTy, WitnessV0PubKeyHashTy, ScriptHashTy,
		WitnessV0ScriptHashTy:
		return true
	default:
		return false
	}
}
func (s PkScript) Class() ScriptClass {
	return s.class
}
func (s PkScript) Script() []byte {
	var script []byte
	switch s.class {
	case PubKeyHashTy:
		script = make([]byte, pubKeyHashLen)
		copy(script, s.script[:pubKeyHashLen])
	case WitnessV0PubKeyHashTy:
		script = make([]byte, witnessV0PubKeyHashLen)
		copy(script, s.script[:witnessV0PubKeyHashLen])
	case ScriptHashTy:
		script = make([]byte, scriptHashLen)
		copy(script, s.script[:scriptHashLen])
	case WitnessV0ScriptHashTy:
		script = make([]byte, witnessV0ScriptHashLen)
		copy(script, s.script[:witnessV0ScriptHashLen])
	default:
		return nil
	}
	return script
}
func (s PkScript) Address(chainParams *chaincfg.Params) (btcutil.Address, error) {
	_, addrs, _, err := ExtractPkScriptAddrs(s.Script(), chainParams)
	if err != nil {
		return nil, fmt.Errorf("unable to parse address: %v", err)
	}
	return addrs[0], nil
}
func (s PkScript) String() string {
	str, _ := DisasmString(s.Script())
	return str
}
func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) {
	switch {
	case len(sigScript) > 0:
		return computeNonWitnessPkScript(sigScript)
	case len(witness) > 0:
		return computeWitnessPkScript(witness)
	default:
		return PkScript{}, ErrUnsupportedScriptType
	}
}
func computeNonWitnessPkScript(sigScript []byte) (PkScript, error) {
	switch {
	case !IsPushOnlyScript(sigScript):
		return PkScript{}, ErrUnsupportedScriptType
	case len(sigScript) >= minPubKeyHashSigScriptLen &&
		len(sigScript) <= maxPubKeyHashSigScriptLen:
		pubKey := sigScript[len(sigScript)-compressedPubKeyLen:]
		if btcec.IsCompressedPubKey(pubKey) {
			pubKeyHash := hash160(pubKey)
			script, err := payToPubKeyHashScript(pubKeyHash)
			if err != nil {
				return PkScript{}, err
			}
			pkScript := PkScript{class: PubKeyHashTy}
			copy(pkScript.script[:], script)
			return pkScript, nil
		}
		fallthrough
	default:
		parsedOpcodes, err := parseScript(sigScript)
		if err != nil {
			return PkScript{}, err
		}
		redeemScript := parsedOpcodes[len(parsedOpcodes)-1].data
		scriptHash := hash160(redeemScript)
		script, err := payToScriptHashScript(scriptHash)
		if err != nil {
			return PkScript{}, err
		}
		pkScript := PkScript{class: ScriptHashTy}
		copy(pkScript.script[:], script)
		return pkScript, nil
	}
}
func computeWitnessPkScript(witness wire.TxWitness) (PkScript, error) {
	lastWitnessItem := witness[len(witness)-1]
	var pkScript PkScript
	switch {
	case len(witness) == 2 && len(lastWitnessItem) == compressedPubKeyLen:
		pubKeyHash := hash160(lastWitnessItem)
		script, err := payToWitnessPubKeyHashScript(pubKeyHash)
		if err != nil {
			return pkScript, err
		}
		pkScript.class = WitnessV0PubKeyHashTy
		copy(pkScript.script[:], script)
	default:
		scriptHash := sha256.Sum256(lastWitnessItem)
		script, err := payToWitnessScriptHashScript(scriptHash[:])
		if err != nil {
			return pkScript, err
		}
		pkScript.class = WitnessV0ScriptHashTy
		copy(pkScript.script[:], script)
	}
	return pkScript, nil
}
func hash160(data []byte) []byte {
	h := sha256.Sum256(data)
	return ripemd160h(h[:])
}