github.com/algorand/go-algorand-sdk@v1.24.0/crypto/crypto.go (about)

     1  package crypto
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"crypto/sha256"
     7  	"crypto/sha512"
     8  	"encoding/base32"
     9  	"encoding/base64"
    10  	"encoding/binary"
    11  	"fmt"
    12  
    13  	"golang.org/x/crypto/ed25519"
    14  
    15  	"github.com/algorand/go-algorand-sdk/encoding/msgpack"
    16  	"github.com/algorand/go-algorand-sdk/types"
    17  )
    18  
    19  // txidPrefix is prepended to a transaction when computing its txid
    20  var txidPrefix = []byte("TX")
    21  
    22  // tgidPrefix is prepended to a transaction group when computing the group ID
    23  var tgidPrefix = []byte("TG")
    24  
    25  // bidPrefix is prepended to a bid when signing it
    26  var bidPrefix = []byte("aB")
    27  
    28  // bytesPrefix is prepended to a message when signing
    29  var bytesPrefix = []byte("MX")
    30  
    31  // programPrefix is prepended to a logic program when computing a hash
    32  var programPrefix = []byte("Program")
    33  
    34  // programDataPrefix is prepended to teal sign data
    35  var programDataPrefix = []byte("ProgData")
    36  
    37  // appIDPrefix is prepended to application IDs in order to compute addresses
    38  var appIDPrefix = []byte("appID")
    39  
    40  // StateProofMessagePrefix is prepended to the canonical msgpack encoded state proof message when computing its hash.
    41  var StateProofMessagePrefix = []byte("spm")
    42  
    43  // LightBlockHeaderPrefix is prepended to the canonical msgpack encoded light block header when computing its vector commitment leaf.
    44  var LightBlockHeaderPrefix = []byte("B256")
    45  
    46  // RandomBytes fills the passed slice with randomness, and panics if it is
    47  // unable to do so
    48  func RandomBytes(s []byte) {
    49  	_, err := rand.Read(s)
    50  	if err != nil {
    51  		panic(err)
    52  	}
    53  }
    54  
    55  // GenerateAddressFromSK take a secret key and returns the corresponding Address
    56  func GenerateAddressFromSK(sk []byte) (types.Address, error) {
    57  	edsk := ed25519.PrivateKey(sk)
    58  
    59  	var a types.Address
    60  	pk := edsk.Public()
    61  	n := copy(a[:], []byte(pk.(ed25519.PublicKey)))
    62  	if n != ed25519.PublicKeySize {
    63  		return [32]byte{}, fmt.Errorf("generated public key has the wrong size, expected %d, got %d", ed25519.PublicKeySize, n)
    64  	}
    65  	return a, nil
    66  }
    67  
    68  func GetTxID(tx types.Transaction) string {
    69  	rawTx := rawTransactionBytesToSign(tx)
    70  	return txIDFromRawTxnBytesToSign(rawTx)
    71  }
    72  
    73  // SignTransaction accepts a private key and a transaction, and returns the
    74  // bytes of a signed transaction ready to be broadcasted to the network
    75  // If the SK's corresponding address is different than the txn sender's, the SK's
    76  // corresponding address will be assigned as AuthAddr
    77  func SignTransaction(sk ed25519.PrivateKey, tx types.Transaction) (txid string, stxBytes []byte, err error) {
    78  	s, txid, err := rawSignTransaction(sk, tx)
    79  	if err != nil {
    80  		return
    81  	}
    82  	// Construct the SignedTxn
    83  	stx := types.SignedTxn{
    84  		Sig: s,
    85  		Txn: tx,
    86  	}
    87  
    88  	a, err := GenerateAddressFromSK(sk)
    89  	if err != nil {
    90  		return
    91  	}
    92  
    93  	if stx.Txn.Sender != a {
    94  		stx.AuthAddr = a
    95  	}
    96  
    97  	// Encode the SignedTxn
    98  	stxBytes = msgpack.Encode(stx)
    99  	return
   100  }
   101  
   102  // rawTransactionBytesToSign returns the byte form of the tx that we actually sign
   103  // and compute txID from.
   104  func rawTransactionBytesToSign(tx types.Transaction) []byte {
   105  	// Encode the transaction as msgpack
   106  	encodedTx := msgpack.Encode(tx)
   107  
   108  	// Prepend the hashable prefix
   109  	msgParts := [][]byte{txidPrefix, encodedTx}
   110  	return bytes.Join(msgParts, nil)
   111  }
   112  
   113  // txID computes a transaction id base32 string from raw transaction bytes
   114  func txIDFromRawTxnBytesToSign(toBeSigned []byte) (txid string) {
   115  	txidBytes := sha512.Sum512_256(toBeSigned)
   116  	txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(txidBytes[:])
   117  	return
   118  }
   119  
   120  // txIDFromTransaction is a convenience function for generating txID from txn
   121  func txIDFromTransaction(tx types.Transaction) (txid string) {
   122  	txidBytes := TransactionID(tx)
   123  	txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(txidBytes[:])
   124  	return
   125  }
   126  
   127  // TransactionID is the unique identifier for a Transaction in progress
   128  func TransactionID(tx types.Transaction) (txid []byte) {
   129  	toBeSigned := rawTransactionBytesToSign(tx)
   130  	txid32 := sha512.Sum512_256(toBeSigned)
   131  	txid = txid32[:]
   132  	return
   133  }
   134  
   135  // TransactionIDString is a base32 representation of a TransactionID
   136  func TransactionIDString(tx types.Transaction) (txid string) {
   137  	txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(TransactionID(tx))
   138  	return
   139  }
   140  
   141  // rawSignTransaction signs the msgpack-encoded tx (with prepended "TX" prefix), and returns the sig and txid
   142  func rawSignTransaction(sk ed25519.PrivateKey, tx types.Transaction) (s types.Signature, txid string, err error) {
   143  	toBeSigned := rawTransactionBytesToSign(tx)
   144  
   145  	// Sign the encoded transaction
   146  	signature := ed25519.Sign(sk, toBeSigned)
   147  
   148  	// Copy the resulting signature into a Signature, and check that it's
   149  	// the expected length
   150  	n := copy(s[:], signature)
   151  	if n != len(s) {
   152  		err = errInvalidSignatureReturned
   153  		return
   154  	}
   155  	// Populate txID
   156  	txid = txIDFromRawTxnBytesToSign(toBeSigned)
   157  	return
   158  }
   159  
   160  // SignBytes signs the bytes and returns the signature
   161  func SignBytes(sk ed25519.PrivateKey, bytesToSign []byte) (signature []byte, err error) {
   162  	// prepend the prefix for signing bytes
   163  	toBeSigned := bytes.Join([][]byte{bytesPrefix, bytesToSign}, nil)
   164  
   165  	// sign the bytes
   166  	signature = ed25519.Sign(sk, toBeSigned)
   167  	return
   168  }
   169  
   170  // VerifyBytes verifies that the signature is valid
   171  func VerifyBytes(pk ed25519.PublicKey, message, signature []byte) bool {
   172  	msgParts := [][]byte{bytesPrefix, message}
   173  	toBeVerified := bytes.Join(msgParts, nil)
   174  	return ed25519.Verify(pk, toBeVerified, signature)
   175  }
   176  
   177  // SignBid accepts a private key and a bid, and returns the signature of the
   178  // bid under that key
   179  func SignBid(sk ed25519.PrivateKey, bid types.Bid) (signedBid []byte, err error) {
   180  	// Encode the bid as msgpack
   181  	encodedBid := msgpack.Encode(bid)
   182  
   183  	// Prepend the hashable prefix
   184  	msgParts := [][]byte{bidPrefix, encodedBid}
   185  	toBeSigned := bytes.Join(msgParts, nil)
   186  
   187  	// Sign the encoded bid
   188  	sig := ed25519.Sign(sk, toBeSigned)
   189  
   190  	var s types.Signature
   191  	n := copy(s[:], sig)
   192  	if n != len(s) {
   193  		err = errInvalidSignatureReturned
   194  		return
   195  	}
   196  
   197  	sb := types.SignedBid{
   198  		Bid: bid,
   199  		Sig: s,
   200  	}
   201  
   202  	nf := types.NoteField{
   203  		Type:      types.NoteBid,
   204  		SignedBid: sb,
   205  	}
   206  
   207  	signedBid = msgpack.Encode(nf)
   208  	return
   209  }
   210  
   211  /* Multisig Support */
   212  
   213  type signer func() (signature types.Signature, err error)
   214  
   215  // Service function to make a single signature in Multisig
   216  func multisigSingle(sk ed25519.PrivateKey, ma MultisigAccount, customSigner signer) (msig types.MultisigSig, myIndex int, err error) {
   217  	// check that sk.pk exists in the list of public keys in MultisigAccount ma
   218  	myIndex = len(ma.Pks)
   219  	myPublicKey := sk.Public().(ed25519.PublicKey)
   220  	for i := 0; i < len(ma.Pks); i++ {
   221  		if bytes.Equal(myPublicKey, ma.Pks[i]) {
   222  			myIndex = i
   223  		}
   224  	}
   225  	if myIndex == len(ma.Pks) {
   226  		err = errMsigInvalidSecretKey
   227  		return
   228  	}
   229  
   230  	// now, create the signed transaction
   231  	msig.Version = ma.Version
   232  	msig.Threshold = ma.Threshold
   233  	msig.Subsigs = make([]types.MultisigSubsig, len(ma.Pks))
   234  	for i := 0; i < len(ma.Pks); i++ {
   235  		c := make([]byte, len(ma.Pks[i]))
   236  		copy(c, ma.Pks[i])
   237  		msig.Subsigs[i].Key = c
   238  	}
   239  	rawSig, err := customSigner()
   240  	if err != nil {
   241  		return
   242  	}
   243  	msig.Subsigs[myIndex].Sig = rawSig
   244  	return
   245  }
   246  
   247  // SignMultisigTransaction signs the given transaction, and multisig preimage, with the
   248  // private key, returning the bytes of a signed transaction with the multisig field
   249  // partially populated, ready to be passed to other multisig signers to sign or broadcast.
   250  func SignMultisigTransaction(sk ed25519.PrivateKey, ma MultisigAccount, tx types.Transaction) (txid string, stxBytes []byte, err error) {
   251  	err = ma.Validate()
   252  	if err != nil {
   253  		return
   254  	}
   255  
   256  	// this signer signs a transaction and sets txid from the closure
   257  	customSigner := func() (rawSig types.Signature, err error) {
   258  		rawSig, txid, err = rawSignTransaction(sk, tx)
   259  		return rawSig, err
   260  	}
   261  
   262  	sig, _, err := multisigSingle(sk, ma, customSigner)
   263  	if err != nil {
   264  		return
   265  	}
   266  
   267  	// Encode the signedTxn
   268  	stx := types.SignedTxn{
   269  		Msig: sig,
   270  		Txn:  tx,
   271  	}
   272  
   273  	maAddress, err := ma.Address()
   274  	if err != nil {
   275  		return
   276  	}
   277  
   278  	if stx.Txn.Sender != maAddress {
   279  		stx.AuthAddr = maAddress
   280  	}
   281  
   282  	stxBytes = msgpack.Encode(stx)
   283  	return
   284  }
   285  
   286  // MergeMultisigTransactions merges the given (partially) signed multisig transactions, and
   287  // returns an encoded signed multisig transaction with the component signatures.
   288  func MergeMultisigTransactions(stxsBytes ...[]byte) (txid string, stxBytes []byte, err error) {
   289  	if len(stxsBytes) < 2 {
   290  		err = errMsigMergeLessThanTwo
   291  		return
   292  	}
   293  	var sig types.MultisigSig
   294  	var refAddr *types.Address
   295  	var refTx types.Transaction
   296  	var refAuthAddr types.Address
   297  	for _, partStxBytes := range stxsBytes {
   298  		partStx := types.SignedTxn{}
   299  		err = msgpack.Decode(partStxBytes, &partStx)
   300  		if err != nil {
   301  			return
   302  		}
   303  		// check that multisig parameters match
   304  		partMa, innerErr := MultisigAccountFromSig(partStx.Msig)
   305  		if innerErr != nil {
   306  			err = innerErr
   307  			return
   308  		}
   309  		partAddr, innerErr := partMa.Address()
   310  		if innerErr != nil {
   311  			err = innerErr
   312  			return
   313  		}
   314  		if refAddr == nil {
   315  			refAddr = &partAddr
   316  			// add parameters to new merged txn
   317  			sig.Version = partStx.Msig.Version
   318  			sig.Threshold = partStx.Msig.Threshold
   319  			sig.Subsigs = make([]types.MultisigSubsig, len(partStx.Msig.Subsigs))
   320  			for i := 0; i < len(sig.Subsigs); i++ {
   321  				c := make([]byte, len(partStx.Msig.Subsigs[i].Key))
   322  				copy(c, partStx.Msig.Subsigs[i].Key)
   323  				sig.Subsigs[i].Key = c
   324  			}
   325  			refTx = partStx.Txn
   326  			refAuthAddr = partStx.AuthAddr
   327  		}
   328  
   329  		if partAddr != *refAddr {
   330  			err = errMsigMergeKeysMismatch
   331  			return
   332  		}
   333  
   334  		if partStx.AuthAddr != refAuthAddr {
   335  			err = errMsigMergeAuthAddrMismatch
   336  			return
   337  		}
   338  
   339  		// now, add subsignatures appropriately
   340  		zeroSig := types.Signature{}
   341  		for i := 0; i < len(sig.Subsigs); i++ {
   342  			mSubsig := partStx.Msig.Subsigs[i]
   343  			if mSubsig.Sig != zeroSig {
   344  				if sig.Subsigs[i].Sig == zeroSig {
   345  					sig.Subsigs[i].Sig = mSubsig.Sig
   346  				} else if sig.Subsigs[i].Sig != mSubsig.Sig {
   347  					err = errMsigMergeInvalidDups
   348  					return
   349  				}
   350  			}
   351  		}
   352  	}
   353  	// Encode the signedTxn
   354  	stx := types.SignedTxn{
   355  		Msig:     sig,
   356  		Txn:      refTx,
   357  		AuthAddr: refAuthAddr,
   358  	}
   359  	stxBytes = msgpack.Encode(stx)
   360  	// let's also compute the txid.
   361  	txid = txIDFromTransaction(refTx)
   362  	return
   363  }
   364  
   365  // AppendMultisigTransaction appends the signature corresponding to the given private key,
   366  // returning an encoded signed multisig transaction including the signature.
   367  // While we could compute the multisig preimage from the multisig blob, we ask the caller
   368  // to pass it back in, to explicitly check that they know who they are signing as.
   369  func AppendMultisigTransaction(sk ed25519.PrivateKey, ma MultisigAccount, preStxBytes []byte) (txid string, stxBytes []byte, err error) {
   370  	preStx := types.SignedTxn{}
   371  	err = msgpack.Decode(preStxBytes, &preStx)
   372  	if err != nil {
   373  		return
   374  	}
   375  	_, partStxBytes, err := SignMultisigTransaction(sk, ma, preStx.Txn)
   376  	if err != nil {
   377  		return
   378  	}
   379  	txid, stxBytes, err = MergeMultisigTransactions(partStxBytes, preStxBytes)
   380  	return
   381  }
   382  
   383  // VerifyMultisig verifies an assembled MultisigSig
   384  //
   385  // addr is the address of the Multisig account
   386  // message is the bytes there were signed
   387  // msig is the Multisig signature to verify
   388  func VerifyMultisig(addr types.Address, message []byte, msig types.MultisigSig) bool {
   389  	msigAccount, err := MultisigAccountFromSig(msig)
   390  	if err != nil {
   391  		return false
   392  	}
   393  
   394  	if msigAddress, err := msigAccount.Address(); err != nil || msigAddress != addr {
   395  		return false
   396  	}
   397  
   398  	// check that we don't have too many multisig subsigs
   399  	if len(msig.Subsigs) > 255 {
   400  		return false
   401  	}
   402  
   403  	// check that we don't have too few multisig subsigs
   404  	if len(msig.Subsigs) < int(msig.Threshold) {
   405  		return false
   406  	}
   407  
   408  	// checks the number of non-blank signatures is no less than threshold
   409  	var counter int
   410  	for _, subsigi := range msig.Subsigs {
   411  		if (subsigi.Sig != types.Signature{}) {
   412  			counter++
   413  		}
   414  	}
   415  	if counter < int(msig.Threshold) {
   416  		return false
   417  	}
   418  
   419  	// checks individual signature verifies
   420  	var verifiedCount uint8
   421  	for _, subsigi := range msig.Subsigs {
   422  		if (subsigi.Sig != types.Signature{}) {
   423  			if !ed25519.Verify(subsigi.Key, message, subsigi.Sig[:]) {
   424  				return false
   425  			}
   426  			verifiedCount++
   427  		}
   428  	}
   429  
   430  	if verifiedCount < msig.Threshold {
   431  		return false
   432  	}
   433  
   434  	return true
   435  }
   436  
   437  // ComputeGroupID returns group ID for a group of transactions
   438  func ComputeGroupID(txgroup []types.Transaction) (gid types.Digest, err error) {
   439  	if len(txgroup) > types.MaxTxGroupSize {
   440  		err = fmt.Errorf("txgroup too large, %v > max size %v", len(txgroup), types.MaxTxGroupSize)
   441  		return
   442  	}
   443  	var group types.TxGroup
   444  	empty := types.Digest{}
   445  	for _, tx := range txgroup {
   446  		if tx.Group != empty {
   447  			err = fmt.Errorf("transaction %v already has a group %v", tx, tx.Group)
   448  			return
   449  		}
   450  
   451  		txID := sha512.Sum512_256(rawTransactionBytesToSign(tx))
   452  		group.TxGroupHashes = append(group.TxGroupHashes, txID)
   453  	}
   454  
   455  	encoded := msgpack.Encode(group)
   456  
   457  	// Prepend the hashable prefix and hash it
   458  	msgParts := [][]byte{tgidPrefix, encoded}
   459  	return sha512.Sum512_256(bytes.Join(msgParts, nil)), nil
   460  }
   461  
   462  /* LogicSig support */
   463  
   464  func isAsciiPrintableByte(symbol byte) bool {
   465  	isBreakLine := symbol == '\n'
   466  	isStdPrintable := symbol >= ' ' && symbol <= '~'
   467  	return isBreakLine || isStdPrintable
   468  }
   469  
   470  func isAsciiPrintable(program []byte) bool {
   471  	for _, b := range program {
   472  		if !isAsciiPrintableByte(b) {
   473  			return false
   474  		}
   475  	}
   476  	return true
   477  }
   478  
   479  // sanityCheckProgram performs heuristic program validation:
   480  // check if passed in bytes are Algorand address or is B64 encoded, rather than Teal bytes
   481  func sanityCheckProgram(program []byte) error {
   482  	if len(program) == 0 {
   483  		return fmt.Errorf("empty program")
   484  	}
   485  	if isAsciiPrintable(program) {
   486  		if _, err := types.DecodeAddress(string(program)); err == nil {
   487  			return fmt.Errorf("requesting program bytes, get Algorand address")
   488  		}
   489  		if _, err := base64.StdEncoding.DecodeString(string(program)); err == nil {
   490  			return fmt.Errorf("program should not be b64 encoded")
   491  		}
   492  		return fmt.Errorf("program bytes are all ASCII printable characters, not looking like Teal byte code")
   493  	}
   494  	return nil
   495  }
   496  
   497  // VerifyLogicSig verifies that a LogicSig contains a valid program and, if a
   498  // delegated signature is present, that the signature is valid.
   499  //
   500  // The singleSigner argument is only used in the case of a delegated LogicSig
   501  // whose delegating account is backed by a single private key (i.e. not a
   502  // multsig account). In that case, it should be the address of the delegating
   503  // account.
   504  func VerifyLogicSig(lsig types.LogicSig, singleSigner types.Address) (result bool) {
   505  	if err := sanityCheckProgram(lsig.Logic); err != nil {
   506  		return false
   507  	}
   508  
   509  	hasSig := lsig.Sig != (types.Signature{})
   510  	hasMsig := !lsig.Msig.Blank()
   511  
   512  	// require only one or zero sig
   513  	if hasSig && hasMsig {
   514  		return false
   515  	}
   516  
   517  	toBeSigned := programToSign(lsig.Logic)
   518  
   519  	if hasSig {
   520  		return ed25519.Verify(singleSigner[:], toBeSigned, lsig.Sig[:])
   521  	}
   522  
   523  	if hasMsig {
   524  		msigAccount, err := MultisigAccountFromSig(lsig.Msig)
   525  		if err != nil {
   526  			return false
   527  		}
   528  		addr, err := msigAccount.Address()
   529  		if err != nil {
   530  			return false
   531  		}
   532  		return VerifyMultisig(addr, toBeSigned, lsig.Msig)
   533  	}
   534  
   535  	// the lsig account is the hash of its program bytes, nothing left to verify
   536  	return true
   537  }
   538  
   539  // signLogicSigTransactionWithAddress signs a transaction with a LogicSig.
   540  //
   541  // lsigAddress is the address of the account that the LogicSig represents.
   542  func signLogicSigTransactionWithAddress(lsig types.LogicSig, lsigAddress types.Address, tx types.Transaction) (txid string, stxBytes []byte, err error) {
   543  
   544  	if !VerifyLogicSig(lsig, lsigAddress) {
   545  		err = errLsigInvalidSignature
   546  		return
   547  	}
   548  
   549  	txid = txIDFromTransaction(tx)
   550  	// Construct the SignedTxn
   551  	stx := types.SignedTxn{
   552  		Lsig: lsig,
   553  		Txn:  tx,
   554  	}
   555  
   556  	if stx.Txn.Sender != lsigAddress {
   557  		stx.AuthAddr = lsigAddress
   558  	}
   559  
   560  	// Encode the SignedTxn
   561  	stxBytes = msgpack.Encode(stx)
   562  	return
   563  }
   564  
   565  // SignLogicSigAccountTransaction signs a transaction with a LogicSigAccount. It
   566  // returns the TxID of the signed transaction and the raw bytes ready to be
   567  // broadcast to the network. Note: any type of transaction can be signed by a
   568  // LogicSig, but the network will reject the transaction if the LogicSig's
   569  // program declines the transaction.
   570  func SignLogicSigAccountTransaction(logicSigAccount LogicSigAccount, tx types.Transaction) (txid string, stxBytes []byte, err error) {
   571  	addr, err := logicSigAccount.Address()
   572  	if err != nil {
   573  		return
   574  	}
   575  
   576  	txid, stxBytes, err = signLogicSigTransactionWithAddress(logicSigAccount.Lsig, addr, tx)
   577  	return
   578  }
   579  
   580  // SignLogicsigTransaction takes LogicSig object and a transaction and returns the
   581  // bytes of a signed transaction ready to be broadcasted to the network
   582  // Note, LogicSig actually can be attached to any transaction and it is a
   583  // program's responsibility to approve/decline the transaction
   584  //
   585  // This function supports signing transactions with a sender that differs from
   586  // the LogicSig's address, EXCEPT IF the LogicSig is delegated to a non-multisig
   587  // account. In order to properly handle that case, create a LogicSigAccount and
   588  // use SignLogicSigAccountTransaction instead.
   589  func SignLogicsigTransaction(lsig types.LogicSig, tx types.Transaction) (txid string, stxBytes []byte, err error) {
   590  	hasSig := lsig.Sig != (types.Signature{})
   591  	hasMsig := !lsig.Msig.Blank()
   592  
   593  	// the address that the LogicSig represents
   594  	var lsigAddress types.Address
   595  	if hasSig {
   596  		// For a LogicSig with a non-multisig delegating account, we cannot derive
   597  		// the address of that account from only its signature, so assume the
   598  		// delegating account is the sender. If that's not the case, the signing
   599  		// will fail.
   600  		lsigAddress = tx.Header.Sender
   601  	} else if hasMsig {
   602  		var msigAccount MultisigAccount
   603  		msigAccount, err = MultisigAccountFromSig(lsig.Msig)
   604  		if err != nil {
   605  			return
   606  		}
   607  		lsigAddress, err = msigAccount.Address()
   608  		if err != nil {
   609  			return
   610  		}
   611  	} else {
   612  		lsigAddress = LogicSigAddress(lsig)
   613  	}
   614  
   615  	txid, stxBytes, err = signLogicSigTransactionWithAddress(lsig, lsigAddress, tx)
   616  	return
   617  }
   618  
   619  func programToSign(program []byte) []byte {
   620  	parts := [][]byte{programPrefix, program}
   621  	toBeSigned := bytes.Join(parts, nil)
   622  	return toBeSigned
   623  }
   624  
   625  func signProgram(sk ed25519.PrivateKey, program []byte) (sig types.Signature, err error) {
   626  	toBeSigned := programToSign(program)
   627  	rawSig := ed25519.Sign(sk, toBeSigned)
   628  	n := copy(sig[:], rawSig)
   629  	if n != len(sig) {
   630  		err = errInvalidSignatureReturned
   631  		return
   632  	}
   633  	return
   634  }
   635  
   636  // AddressFromProgram returns escrow account address derived from TEAL bytecode
   637  func AddressFromProgram(program []byte) types.Address {
   638  	toBeHashed := programToSign(program)
   639  	hash := sha512.Sum512_256(toBeHashed)
   640  	return types.Address(hash)
   641  }
   642  
   643  // MakeLogicSig produces a new LogicSig signature.
   644  //
   645  // Deprecated: THIS FUNCTION IS DEPRECATED.
   646  // It will be removed in v2 of this library.
   647  // Use one of MakeLogicSigAccountEscrow, MakeLogicSigAccountDelegated, or
   648  // MakeLogicSigAccountDelegatedMsig instead.
   649  //
   650  // The function can work in three modes:
   651  // 1. If no sk and ma provided then it returns contract-only LogicSig
   652  // 2. If no ma provides, it returns Sig delegated LogicSig
   653  // 3. If both sk and ma specified the function returns Multisig delegated LogicSig
   654  func MakeLogicSig(program []byte, args [][]byte, sk ed25519.PrivateKey, ma MultisigAccount) (lsig types.LogicSig, err error) {
   655  	if err = sanityCheckProgram(program); err != nil {
   656  		return
   657  	}
   658  
   659  	if sk == nil && ma.Blank() {
   660  		lsig.Logic = program
   661  		lsig.Args = args
   662  		return
   663  	}
   664  
   665  	if ma.Blank() {
   666  		var sig types.Signature
   667  		sig, err = signProgram(sk, program)
   668  		if err != nil {
   669  			return
   670  		}
   671  
   672  		lsig.Logic = program
   673  		lsig.Args = args
   674  		lsig.Sig = types.Signature(sig)
   675  		return
   676  	}
   677  
   678  	// Format Multisig
   679  	err = ma.Validate()
   680  	if err != nil {
   681  		return
   682  	}
   683  
   684  	// this signer signs a program
   685  	customSigner := func() (rawSig types.Signature, err error) {
   686  		return signProgram(sk, program)
   687  	}
   688  
   689  	msig, _, err := multisigSingle(sk, ma, customSigner)
   690  	if err != nil {
   691  		return
   692  	}
   693  
   694  	lsig.Logic = program
   695  	lsig.Args = args
   696  	lsig.Msig = msig
   697  
   698  	return
   699  }
   700  
   701  // AppendMultisigToLogicSig adds a new signature to multisigned LogicSig
   702  func AppendMultisigToLogicSig(lsig *types.LogicSig, sk ed25519.PrivateKey) error {
   703  	if lsig.Msig.Blank() {
   704  		return errLsigEmptyMsig
   705  	}
   706  
   707  	ma, err := MultisigAccountFromSig(lsig.Msig)
   708  	if err != nil {
   709  		return err
   710  	}
   711  
   712  	customSigner := func() (rawSig types.Signature, err error) {
   713  		return signProgram(sk, lsig.Logic)
   714  	}
   715  
   716  	msig, idx, err := multisigSingle(sk, ma, customSigner)
   717  	if err != nil {
   718  		return err
   719  	}
   720  
   721  	lsig.Msig.Subsigs[idx] = msig.Subsigs[idx]
   722  
   723  	return nil
   724  }
   725  
   726  // TealSign creates a signature compatible with ed25519verify opcode from contract address
   727  func TealSign(sk ed25519.PrivateKey, data []byte, contractAddress types.Address) (rawSig types.Signature, err error) {
   728  	msgParts := [][]byte{programDataPrefix, contractAddress[:], data}
   729  	toBeSigned := bytes.Join(msgParts, nil)
   730  
   731  	signature := ed25519.Sign(sk, toBeSigned)
   732  	// Copy the resulting signature into a Signature, and check that it's
   733  	// the expected length
   734  	n := copy(rawSig[:], signature)
   735  	if n != len(rawSig) {
   736  		err = errInvalidSignatureReturned
   737  	}
   738  	return
   739  }
   740  
   741  // TealSignFromProgram creates a signature compatible with ed25519verify opcode from raw program bytes
   742  func TealSignFromProgram(sk ed25519.PrivateKey, data []byte, program []byte) (rawSig types.Signature, err error) {
   743  	addr := AddressFromProgram(program)
   744  	return TealSign(sk, data, addr)
   745  }
   746  
   747  // TealVerify verifies signatures generated by TealSign and TealSignFromProgram
   748  func TealVerify(pk ed25519.PublicKey, data []byte, contractAddress types.Address, rawSig types.Signature) bool {
   749  	msgParts := [][]byte{programDataPrefix, contractAddress[:], data}
   750  	toBeVerified := bytes.Join(msgParts, nil)
   751  
   752  	return ed25519.Verify(pk, toBeVerified, rawSig[:])
   753  }
   754  
   755  // GetApplicationAddress returns the address corresponding to an application's escrow account.
   756  func GetApplicationAddress(appID uint64) types.Address {
   757  	encodedAppID := make([]byte, 8)
   758  	binary.BigEndian.PutUint64(encodedAppID, appID)
   759  
   760  	parts := [][]byte{appIDPrefix, encodedAppID}
   761  	toBeHashed := bytes.Join(parts, nil)
   762  
   763  	hash := sha512.Sum512_256(toBeHashed)
   764  	return types.Address(hash)
   765  }
   766  
   767  func HashStateProofMessage(stateProofMessage *types.Message) types.MessageHash {
   768  	msgPackedStateProofMessage := msgpack.Encode(stateProofMessage)
   769  
   770  	stateProofMessageData := make([]byte, 0, len(StateProofMessagePrefix)+len(msgPackedStateProofMessage))
   771  	stateProofMessageData = append(stateProofMessageData, StateProofMessagePrefix...)
   772  	stateProofMessageData = append(stateProofMessageData, msgPackedStateProofMessage...)
   773  
   774  	return sha256.Sum256(stateProofMessageData)
   775  }
   776  
   777  func HashLightBlockHeader(lightBlockHeader types.LightBlockHeader) types.Digest {
   778  	msgPackedLightBlockHeader := msgpack.Encode(lightBlockHeader)
   779  
   780  	lightBlockHeaderData := make([]byte, 0, len(LightBlockHeaderPrefix)+len(msgPackedLightBlockHeader))
   781  	lightBlockHeaderData = append(lightBlockHeaderData, LightBlockHeaderPrefix...)
   782  	lightBlockHeaderData = append(lightBlockHeaderData, msgpack.Encode(lightBlockHeader)...)
   783  
   784  	return sha256.Sum256(lightBlockHeaderData)
   785  }