func (a *AddressScriptHash) EncodeAddress() string {
	return encodeAddress(a.hash[:], a.netID)
}
EncodeAddress returns the string encoding of a pay-to-script-hash
address.  Part of the Address interface.
package soterutil
import (
	"bytes"
	"encoding/hex"
	"errors"
	"fmt"
	"strings"
	"github.com/soteria-dag/soterd/soterec"
	"github.com/soteria-dag/soterd/chaincfg"
	"github.com/soteria-dag/soterd/soterutil/base58"
	"github.com/soteria-dag/soterd/soterutil/bech32"
	"golang.org/x/crypto/ripemd160"
)
type UnsupportedWitnessVerError byte
func (e UnsupportedWitnessVerError) Error() string {
	return "unsupported witness version: " + string(e)
}
type UnsupportedWitnessProgLenError int
func (e UnsupportedWitnessProgLenError) Error() string {
	return "unsupported witness program length: " + string(e)
}
var (
	ErrChecksumMismatch = errors.New("checksum mismatch")
	ErrUnknownAddressType = errors.New("unknown address type")
	ErrAddressCollision = errors.New("address collision")
)
func encodeAddress(hash160 []byte, netID byte) string {
	return base58.CheckEncode(hash160[:ripemd160.Size], netID)
}
func encodeSegWitAddress(hrp string, witnessVersion byte, witnessProgram []byte) (string, error) {
	converted, err := bech32.ConvertBits(witnessProgram, 8, 5, true)
	if err != nil {
		return "", err
	}
	combined := make([]byte, len(converted)+1)
	combined[0] = witnessVersion
	copy(combined[1:], converted)
	bech, err := bech32.Encode(hrp, combined)
	if err != nil {
		return "", err
	}
	version, program, err := decodeSegWitAddress(bech)
	if err != nil {
		return "", fmt.Errorf("invalid segwit address: %v", err)
	}
	if version != witnessVersion || !bytes.Equal(program, witnessProgram) {
		return "", fmt.Errorf("invalid segwit address")
	}
	return bech, nil
}
type Address interface {
	String() string
	EncodeAddress() string
	ScriptAddress() []byte
	IsForNet(*chaincfg.Params) bool
}
func DecodeAddress(addr string, defaultNet *chaincfg.Params) (Address, error) {
	oneIndex := strings.LastIndexByte(addr, '1')
	if oneIndex > 1 {
		prefix := addr[:oneIndex+1]
		if chaincfg.IsBech32SegwitPrefix(prefix) {
			witnessVer, witnessProg, err := decodeSegWitAddress(addr)
			if err != nil {
				return nil, err
			}
			if witnessVer != 0 {
				return nil, UnsupportedWitnessVerError(witnessVer)
			}
			hrp := prefix[:len(prefix)-1]
			switch len(witnessProg) {
			case 20:
				return newAddressWitnessPubKeyHash(hrp, witnessProg)
			case 32:
				return newAddressWitnessScriptHash(hrp, witnessProg)
			default:
				return nil, UnsupportedWitnessProgLenError(len(witnessProg))
			}
		}
	}
	if len(addr) == 130 || len(addr) == 66 {
		serializedPubKey, err := hex.DecodeString(addr)
		if err != nil {
			return nil, err
		}
		return NewAddressPubKey(serializedPubKey, defaultNet)
	}
	decoded, netID, err := base58.CheckDecode(addr)
	if err != nil {
		if err == base58.ErrChecksum {
			return nil, ErrChecksumMismatch
		}
		return nil, errors.New("decoded address is of unknown format")
	}
	switch len(decoded) {
	case ripemd160.Size:  
		isP2PKH := chaincfg.IsPubKeyHashAddrID(netID)
		isP2SH := chaincfg.IsScriptHashAddrID(netID)
		switch hash160 := decoded; {
		case isP2PKH && isP2SH:
			return nil, ErrAddressCollision
		case isP2PKH:
			return newAddressPubKeyHash(hash160, netID)
		case isP2SH:
			return newAddressScriptHashFromHash(hash160, netID)
		default:
			return nil, ErrUnknownAddressType
		}
	default:
		return nil, errors.New("decoded address is of unknown size")
	}
}
func decodeSegWitAddress(address string) (byte, []byte, error) {
	_, data, err := bech32.Decode(address)
	if err != nil {
		return 0, nil, err
	}
	if len(data) < 1 {
		return 0, nil, fmt.Errorf("no witness version")
	}
	version := data[0]
	if version > 16 {
		return 0, nil, fmt.Errorf("invalid witness version: %v", version)
	}
	regrouped, err := bech32.ConvertBits(data[1:], 5, 8, false)
	if err != nil {
		return 0, nil, err
	}
	if len(regrouped) < 2 || len(regrouped) > 40 {
		return 0, nil, fmt.Errorf("invalid data length")
	}
	if version == 0 && len(regrouped) != 20 && len(regrouped) != 32 {
		return 0, nil, fmt.Errorf("invalid data length for witness "+
			"version 0: %v", len(regrouped))
	}
	return version, regrouped, nil
}
type AddressPubKeyHash struct {
	hash  [ripemd160.Size]byte
	netID byte
}
func NewAddressPubKeyHash(pkHash []byte, net *chaincfg.Params) (*AddressPubKeyHash, error) {
	return newAddressPubKeyHash(pkHash, net.PubKeyHashAddrID)
}
func newAddressPubKeyHash(pkHash []byte, netID byte) (*AddressPubKeyHash, error) {
	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
}
func (a *AddressPubKeyHash) EncodeAddress() string {
	return encodeAddress(a.hash[:], a.netID)
}
func (a *AddressPubKeyHash) ScriptAddress() []byte {
	return a.hash[:]
}
func (a *AddressPubKeyHash) IsForNet(net *chaincfg.Params) bool {
	return a.netID == net.PubKeyHashAddrID
}
func (a *AddressPubKeyHash) String() string {
	return a.EncodeAddress()
}
func (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte {
	return &a.hash
}
type AddressScriptHash struct {
	hash  [ripemd160.Size]byte
	netID byte
}
func NewAddressScriptHash(serializedScript []byte, net *chaincfg.Params) (*AddressScriptHash, error) {
	scriptHash := Hash160(serializedScript)
	return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
}
func NewAddressScriptHashFromHash(scriptHash []byte, net *chaincfg.Params) (*AddressScriptHash, error) {
	return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
}
func newAddressScriptHashFromHash(scriptHash []byte, netID byte) (*AddressScriptHash, error) {
	if len(scriptHash) != ripemd160.Size {
		return nil, errors.New("scriptHash must be 20 bytes")
	}
	addr := &AddressScriptHash{netID: netID}
	copy(addr.hash[:], scriptHash)
	return addr, nil
}