Verify Signature on Signed Transaction

// txidPrefix is prepended to a transaction when computing its txid
var txidPrefix = []byte("TX")

// RawTransactionBytesToSign returns the byte form of the tx that we actually sign
// and compute txID from.
func RawTransactionBytesToSign(tx types.Transaction) []byte {
	// Encode the transaction as msgpack
	encodedTx := msgpack.Encode(tx)

	// Prepend the hashable prefix
	msgParts := [][]byte{txidPrefix, encodedTx}
	return bytes.Join(msgParts, nil)
}

// VerifySignature verifies a simple signature (not a multisig or logicsig)
func VerifySignature(tx types.Transaction, pk ed25519.PublicKey, sig types.Signature) bool {
	toBeSigned := RawTransactionBytesToSign(tx)
	return ed25519.Verify(pk, toBeSigned, sig[:])
}

// AddrToED25519PublicKey copies an address to pk
func AddrToED25519PublicKey(a types.Address) (pk ed25519.PublicKey) {
	pk = make([]byte, len(a))
	copy(pk, a[:])
	return
}

// CheckSignature verifies that stx is either a single signature
func CheckSignature(stx types.SignedTxn) error {

	if (stx.Sig != types.Signature{}) { // contains a regular signature
		// Single signature
		// Check msig is empty
		if len(stx.Msig.Subsigs) != 0 || stx.Msig.Version != 0 || stx.Msig.Threshold != 0 {
			return errors.New("tx has both a sig and msig")
		}
		// Check lsig is empty
		if !stx.Lsig.Blank() {
			return errors.New("tx has both a sig and lsig")
		}
		pk := AddrToED25519PublicKey(stx.Txn.Sender)
		if (stx.Sig == types.Signature{}) && !requireSigned {
			return nil
		}
		if !VerifySignature(stx.Txn, pk, stx.Sig) {
			return errors.New("signature does not verify")
		}
	}
	return errors.New("msig/lsig not supported")
}