func TealSignFromProgram(sk ed25519.PrivateKey, data []byte, program []byte) (rawSig types.Signature, err error) {
	addr := AddressFromProgram(program)
	return TealSign(sk, data, addr)
}
TealSignFromProgram creates a signature compatible with ed25519verify opcode from raw program bytes
package crypto
import (
	"bytes"
	"crypto/rand"
	"crypto/sha512"
	"encoding/base32"
	"encoding/binary"
	"fmt"
	"golang.org/x/crypto/ed25519"
	"github.com/algorand/go-algorand-sdk/encoding/msgpack"
	"github.com/algorand/go-algorand-sdk/logic"
	"github.com/algorand/go-algorand-sdk/types"
)
var txidPrefix = []byte("TX")
var tgidPrefix = []byte("TG")
var bidPrefix = []byte("aB")
var bytesPrefix = []byte("MX")
var programPrefix = []byte("Program")
var programDataPrefix = []byte("ProgData")
var appIDPrefix = []byte("appID")
func RandomBytes(s []byte) {
	_, err := rand.Read(s)
	if err != nil {
		panic(err)
	}
}
func GenerateAddressFromSK(sk []byte) (types.Address, error) {
	edsk := ed25519.PrivateKey(sk)
	var a types.Address
	pk := edsk.Public()
	n := copy(a[:], []byte(pk.(ed25519.PublicKey)))
	if n != ed25519.PublicKeySize {
		return [32]byte{}, fmt.Errorf("generated public key has the wrong size, expected %d, got %d", ed25519.PublicKeySize, n)
	}
	return a, nil
}
func SignTransaction(sk ed25519.PrivateKey, tx types.Transaction) (txid string, stxBytes []byte, err error) {
	s, txid, err := rawSignTransaction(sk, tx)
	if err != nil {
		return
	}
	stx := types.SignedTxn{
		Sig: s,
		Txn: tx,
	}
	a, err := GenerateAddressFromSK(sk)
	if err != nil {
		return
	}
	if stx.Txn.Sender != a {
		stx.AuthAddr = a
	}
	stxBytes = msgpack.Encode(stx)
	return
}
func rawTransactionBytesToSign(tx types.Transaction) []byte {
	encodedTx := msgpack.Encode(tx)
	msgParts := [][]byte{txidPrefix, encodedTx}
	return bytes.Join(msgParts, nil)
}
func txIDFromRawTxnBytesToSign(toBeSigned []byte) (txid string) {
	txidBytes := sha512.Sum512_256(toBeSigned)
	txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(txidBytes[:])
	return
}
func txIDFromTransaction(tx types.Transaction) (txid string) {
	txidBytes := TransactionID(tx)
	txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(txidBytes[:])
	return
}
func TransactionID(tx types.Transaction) (txid []byte) {
	toBeSigned := rawTransactionBytesToSign(tx)
	txid32 := sha512.Sum512_256(toBeSigned)
	txid = txid32[:]
	return
}
func TransactionIDString(tx types.Transaction) (txid string) {
	txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(TransactionID(tx))
	return
}
func rawSignTransaction(sk ed25519.PrivateKey, tx types.Transaction) (s types.Signature, txid string, err error) {
	toBeSigned := rawTransactionBytesToSign(tx)
	signature := ed25519.Sign(sk, toBeSigned)
	n := copy(s[:], signature)
	if n != len(s) {
		err = errInvalidSignatureReturned
		return
	}
	txid = txIDFromRawTxnBytesToSign(toBeSigned)
	return
}
func SignBytes(sk ed25519.PrivateKey, bytesToSign []byte) (signature []byte, err error) {
	toBeSigned := bytes.Join([][]byte{bytesPrefix, bytesToSign}, nil)
	signature = ed25519.Sign(sk, toBeSigned)
	return
}
func VerifyBytes(pk ed25519.PublicKey, message, signature []byte) bool {
	msgParts := [][]byte{bytesPrefix, message}
	toBeVerified := bytes.Join(msgParts, nil)
	return ed25519.Verify(pk, toBeVerified, signature)
}
func SignBid(sk ed25519.PrivateKey, bid types.Bid) (signedBid []byte, err error) {
	encodedBid := msgpack.Encode(bid)
	msgParts := [][]byte{bidPrefix, encodedBid}
	toBeSigned := bytes.Join(msgParts, nil)
	sig := ed25519.Sign(sk, toBeSigned)
	var s types.Signature
	n := copy(s[:], sig)
	if n != len(s) {
		err = errInvalidSignatureReturned
		return
	}
	sb := types.SignedBid{
		Bid: bid,
		Sig: s,
	}
	nf := types.NoteField{
		Type:      types.NoteBid,
		SignedBid: sb,
	}
	signedBid = msgpack.Encode(nf)
	return
}
type signer func() (signature types.Signature, err error)
func multisigSingle(sk ed25519.PrivateKey, ma MultisigAccount, customSigner signer) (msig types.MultisigSig, myIndex int, err error) {
	myIndex = len(ma.Pks)
	myPublicKey := sk.Public().(ed25519.PublicKey)
	for i := 0; i < len(ma.Pks); i++ {
		if bytes.Equal(myPublicKey, ma.Pks[i]) {
			myIndex = i
		}
	}
	if myIndex == len(ma.Pks) {
		err = errMsigInvalidSecretKey
		return
	}
	msig.Version = ma.Version
	msig.Threshold = ma.Threshold
	msig.Subsigs = make([]types.MultisigSubsig, len(ma.Pks))
	for i := 0; i < len(ma.Pks); i++ {
		c := make([]byte, len(ma.Pks[i]))
		copy(c, ma.Pks[i])
		msig.Subsigs[i].Key = c
	}
	rawSig, err := customSigner()
	if err != nil {
		return
	}
	msig.Subsigs[myIndex].Sig = rawSig
	return
}
func SignMultisigTransaction(sk ed25519.PrivateKey, ma MultisigAccount, tx types.Transaction) (txid string, stxBytes []byte, err error) {
	err = ma.Validate()
	if err != nil {
		return
	}
	customSigner := func() (rawSig types.Signature, err error) {
		rawSig, txid, err = rawSignTransaction(sk, tx)
		return rawSig, err
	}
	sig, _, err := multisigSingle(sk, ma, customSigner)
	if err != nil {
		return
	}
	stx := types.SignedTxn{
		Msig: sig,
		Txn:  tx,
	}
	maAddress, err := ma.Address()
	if err != nil {
		return
	}
	if stx.Txn.Sender != maAddress {
		stx.AuthAddr = maAddress
	}
	stxBytes = msgpack.Encode(stx)
	return
}
func MergeMultisigTransactions(stxsBytes ...[]byte) (txid string, stxBytes []byte, err error) {
	if len(stxsBytes) < 2 {
		err = errMsigMergeLessThanTwo
		return
	}
	var sig types.MultisigSig
	var refAddr *types.Address
	var refTx types.Transaction
	var refAuthAddr types.Address
	for _, partStxBytes := range stxsBytes {
		partStx := types.SignedTxn{}
		err = msgpack.Decode(partStxBytes, &partStx)
		if err != nil {
			return
		}
		partMa, innerErr := MultisigAccountFromSig(partStx.Msig)
		if innerErr != nil {
			err = innerErr
			return
		}
		partAddr, innerErr := partMa.Address()
		if innerErr != nil {
			err = innerErr
			return
		}
		if refAddr == nil {
			refAddr = &partAddr
			sig.Version = partStx.Msig.Version
			sig.Threshold = partStx.Msig.Threshold
			sig.Subsigs = make([]types.MultisigSubsig, len(partStx.Msig.Subsigs))
			for i := 0; i < len(sig.Subsigs); i++ {
				c := make([]byte, len(partStx.Msig.Subsigs[i].Key))
				copy(c, partStx.Msig.Subsigs[i].Key)
				sig.Subsigs[i].Key = c
			}
			refTx = partStx.Txn
			refAuthAddr = partStx.AuthAddr
		}
		if partAddr != *refAddr {
			err = errMsigMergeKeysMismatch
			return
		}
		if partStx.AuthAddr != refAuthAddr {
			err = errMsigMergeAuthAddrMismatch
			return
		}
		zeroSig := types.Signature{}
		for i := 0; i < len(sig.Subsigs); i++ {
			mSubsig := partStx.Msig.Subsigs[i]
			if mSubsig.Sig != zeroSig {
				if sig.Subsigs[i].Sig == zeroSig {
					sig.Subsigs[i].Sig = mSubsig.Sig
				} else if sig.Subsigs[i].Sig != mSubsig.Sig {
					err = errMsigMergeInvalidDups
					return
				}
			}
		}
	}
	stx := types.SignedTxn{
		Msig:     sig,
		Txn:      refTx,
		AuthAddr: refAuthAddr,
	}
	stxBytes = msgpack.Encode(stx)
	txid = txIDFromTransaction(refTx)
	return
}
func AppendMultisigTransaction(sk ed25519.PrivateKey, ma MultisigAccount, preStxBytes []byte) (txid string, stxBytes []byte, err error) {
	preStx := types.SignedTxn{}
	err = msgpack.Decode(preStxBytes, &preStx)
	if err != nil {
		return
	}
	_, partStxBytes, err := SignMultisigTransaction(sk, ma, preStx.Txn)
	if err != nil {
		return
	}
	txid, stxBytes, err = MergeMultisigTransactions(partStxBytes, preStxBytes)
	return
}
func VerifyMultisig(addr types.Address, message []byte, msig types.MultisigSig) bool {
	msigAccount, err := MultisigAccountFromSig(msig)
	if err != nil {
		return false
	}
	if msigAddress, err := msigAccount.Address(); err != nil || msigAddress != addr {
		return false
	}
	if len(msig.Subsigs) > 255 {
		return false
	}
	if len(msig.Subsigs) < int(msig.Threshold) {
		return false
	}
	var counter int
	for _, subsigi := range msig.Subsigs {
		if (subsigi.Sig != types.Signature{}) {
			counter++
		}
	}
	if counter < int(msig.Threshold) {
		return false
	}
	var verifiedCount uint8
	for _, subsigi := range msig.Subsigs {
		if (subsigi.Sig != types.Signature{}) {
			if !ed25519.Verify(subsigi.Key, message, subsigi.Sig[:]) {
				return false
			}
			verifiedCount++
		}
	}
	if verifiedCount < msig.Threshold {
		return false
	}
	return true
}
func ComputeGroupID(txgroup []types.Transaction) (gid types.Digest, err error) {
	if len(txgroup) > types.MaxTxGroupSize {
		err = fmt.Errorf("txgroup too large, %v > max size %v", len(txgroup), types.MaxTxGroupSize)
		return
	}
	var group types.TxGroup
	empty := types.Digest{}
	for _, tx := range txgroup {
		if tx.Group != empty {
			err = fmt.Errorf("transaction %v already has a group %v", tx, tx.Group)
			return
		}
		txID := sha512.Sum512_256(rawTransactionBytesToSign(tx))
		group.TxGroupHashes = append(group.TxGroupHashes, txID)
	}
	encoded := msgpack.Encode(group)
	msgParts := [][]byte{tgidPrefix, encoded}
	return sha512.Sum512_256(bytes.Join(msgParts, nil)), nil
}
func VerifyLogicSig(lsig types.LogicSig, singleSigner types.Address) (result bool) {
	if err := logic.CheckProgram(lsig.Logic, lsig.Args); err != nil {
		return false
	}
	hasSig := lsig.Sig != (types.Signature{})
	hasMsig := !lsig.Msig.Blank()
	if hasSig && hasMsig {
		return false
	}
	toBeSigned := programToSign(lsig.Logic)
	if hasSig {
		return ed25519.Verify(singleSigner[:], toBeSigned, lsig.Sig[:])
	}
	if hasMsig {
		msigAccount, err := MultisigAccountFromSig(lsig.Msig)
		if err != nil {
			return false
		}
		addr, err := msigAccount.Address()
		if err != nil {
			return false
		}
		return VerifyMultisig(addr, toBeSigned, lsig.Msig)
	}
	return true
}
func signLogicSigTransactionWithAddress(lsig types.LogicSig, lsigAddress types.Address, tx types.Transaction) (txid string, stxBytes []byte, err error) {
	if !VerifyLogicSig(lsig, lsigAddress) {
		err = errLsigInvalidSignature
		return
	}
	txid = txIDFromTransaction(tx)
	stx := types.SignedTxn{
		Lsig: lsig,
		Txn:  tx,
	}
	if stx.Txn.Sender != lsigAddress {
		stx.AuthAddr = lsigAddress
	}
	stxBytes = msgpack.Encode(stx)
	return
}
func SignLogicSigAccountTransaction(logicSigAccount LogicSigAccount, tx types.Transaction) (txid string, stxBytes []byte, err error) {
	addr, err := logicSigAccount.Address()
	if err != nil {
		return
	}
	txid, stxBytes, err = signLogicSigTransactionWithAddress(logicSigAccount.Lsig, addr, tx)
	return
}
func SignLogicsigTransaction(lsig types.LogicSig, tx types.Transaction) (txid string, stxBytes []byte, err error) {
	hasSig := lsig.Sig != (types.Signature{})
	hasMsig := !lsig.Msig.Blank()
	var lsigAddress types.Address
	if hasSig {
		lsigAddress = tx.Header.Sender
	} else if hasMsig {
		var msigAccount MultisigAccount
		msigAccount, err = MultisigAccountFromSig(lsig.Msig)
		if err != nil {
			return
		}
		lsigAddress, err = msigAccount.Address()
		if err != nil {
			return
		}
	} else {
		lsigAddress = LogicSigAddress(lsig)
	}
	txid, stxBytes, err = signLogicSigTransactionWithAddress(lsig, lsigAddress, tx)
	return
}
func programToSign(program []byte) []byte {
	parts := [][]byte{programPrefix, program}
	toBeSigned := bytes.Join(parts, nil)
	return toBeSigned
}
func signProgram(sk ed25519.PrivateKey, program []byte) (sig types.Signature, err error) {
	toBeSigned := programToSign(program)
	rawSig := ed25519.Sign(sk, toBeSigned)
	n := copy(sig[:], rawSig)
	if n != len(sig) {
		err = errInvalidSignatureReturned
		return
	}
	return
}
func AddressFromProgram(program []byte) types.Address {
	toBeHashed := programToSign(program)
	hash := sha512.Sum512_256(toBeHashed)
	return types.Address(hash)
}
func MakeLogicSig(program []byte, args [][]byte, sk ed25519.PrivateKey, ma MultisigAccount) (lsig types.LogicSig, err error) {
	if len(program) == 0 {
		err = errLsigInvalidProgram
		return
	}
	if err = logic.CheckProgram(program, args); err != nil {
		return
	}
	if sk == nil && ma.Blank() {
		lsig.Logic = program
		lsig.Args = args
		return
	}
	if ma.Blank() {
		var sig types.Signature
		sig, err = signProgram(sk, program)
		if err != nil {
			return
		}
		lsig.Logic = program
		lsig.Args = args
		lsig.Sig = types.Signature(sig)
		return
	}
	err = ma.Validate()
	if err != nil {
		return
	}
	customSigner := func() (rawSig types.Signature, err error) {
		return signProgram(sk, program)
	}
	msig, _, err := multisigSingle(sk, ma, customSigner)
	if err != nil {
		return
	}
	lsig.Logic = program
	lsig.Args = args
	lsig.Msig = msig
	return
}
func AppendMultisigToLogicSig(lsig *types.LogicSig, sk ed25519.PrivateKey) error {
	if lsig.Msig.Blank() {
		return errLsigEmptyMsig
	}
	ma, err := MultisigAccountFromSig(lsig.Msig)
	if err != nil {
		return err
	}
	customSigner := func() (rawSig types.Signature, err error) {
		return signProgram(sk, lsig.Logic)
	}
	msig, idx, err := multisigSingle(sk, ma, customSigner)
	if err != nil {
		return err
	}
	lsig.Msig.Subsigs[idx] = msig.Subsigs[idx]
	return nil
}
func TealSign(sk ed25519.PrivateKey, data []byte, contractAddress types.Address) (rawSig types.Signature, err error) {
	msgParts := [][]byte{programDataPrefix, contractAddress[:], data}
	toBeSigned := bytes.Join(msgParts, nil)
	signature := ed25519.Sign(sk, toBeSigned)
	n := copy(rawSig[:], signature)
	if n != len(rawSig) {
		err = errInvalidSignatureReturned
	}
	return
}