github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/btcutil/txscript/sign.go (about)

     1  // Copyright (c) 2013-2015 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package txscript
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"github.com/mit-dci/lit/btcutil"
    11  	"github.com/mit-dci/lit/coinparam"
    12  	"github.com/mit-dci/lit/crypto/koblitz"
    13  	"github.com/mit-dci/lit/wire"
    14  )
    15  
    16  // RawTxInWitnessSignature returns the serialized ECDA signature for the input
    17  // idx of the given transaction, with the hashType appended to it. This
    18  // function is identical to RawTxInSignature, however the signature generated
    19  // signs a new sighash digest defined in BIP0143.
    20  func RawTxInWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
    21  	amt int64, subScript []byte, hashType SigHashType,
    22  	key *koblitz.PrivateKey) ([]byte, error) {
    23  
    24  	parsedScript, err := ParseScript(subScript)
    25  	if err != nil {
    26  		return nil, fmt.Errorf("cannot parse output script: %v", err)
    27  	}
    28  
    29  	hash := CalcWitnessSignatureHash(parsedScript, sigHashes, hashType, tx,
    30  		idx, amt)
    31  	signature, err := key.Sign(hash)
    32  	if err != nil {
    33  		return nil, fmt.Errorf("cannot sign tx input: %s", err)
    34  	}
    35  
    36  	return append(signature.Serialize(), byte(hashType)), nil
    37  }
    38  
    39  // RawTxInBCHSignature returns a BCH signature for the input idx of
    40  // the given transaction, with hashType appended to it.
    41  // Similar to RawTxInWitnessSignature / BIP0143 but hashType is hardcoded
    42  func RawTxInBCHSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
    43  	amt int64, subScript []byte, hashType SigHashType,
    44  	key *koblitz.PrivateKey) ([]byte, error) {
    45  
    46  	// for BCH sigs
    47  	//	hashType := SigHashForkID | SigHashAll
    48  
    49  	parsedScript, err := ParseScript(subScript)
    50  	if err != nil {
    51  		return nil, fmt.Errorf("cannot parse output script: %v", err)
    52  	}
    53  
    54  	hash := CalcWitnessSignatureHash(parsedScript, sigHashes, hashType, tx,
    55  		idx, amt)
    56  	signature, err := key.Sign(hash)
    57  	if err != nil {
    58  		return nil, fmt.Errorf("cannot sign tx input: %s", err)
    59  	}
    60  
    61  	return append(signature.Serialize(), byte(hashType)), nil
    62  }
    63  
    64  // BCHSignatureScript is like WitnessScript but for BCH signatures.
    65  func BCHSignatureScript(tx *wire.MsgTx, sigHashes *TxSigHashes,
    66  	idx int, amt int64,
    67  	subscript []byte, hashType SigHashType,
    68  	privKey *koblitz.PrivateKey, compress bool) ([]byte, error) {
    69  
    70  	sig, err := RawTxInBCHSignature(
    71  		tx, sigHashes, idx, amt, subscript, hashType, privKey)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	pk := (*koblitz.PublicKey)(&privKey.PublicKey)
    77  	var pkData []byte
    78  	if compress {
    79  		pkData = pk.SerializeCompressed()
    80  	} else {
    81  		pkData = pk.SerializeUncompressed()
    82  	}
    83  
    84  	// It's not a stack, it's just one sig script like before
    85  	return NewScriptBuilder().AddData(sig).AddData(pkData).Script()
    86  }
    87  
    88  // WitnessSignatureScript creates an input witness stack for tx to spend BTC
    89  // sent from a previous output to the owner of privKey using the p2wkh script
    90  // template. The passed transaction must contain all the inputs and outputs as
    91  // dictated by the passed hashType. The signature generated observes the new
    92  // transaction digest algorithm defined within BIP0143.
    93  func WitnessScript(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64,
    94  	subscript []byte, hashType SigHashType,
    95  	privKey *koblitz.PrivateKey, compress bool) ([][]byte, error) {
    96  
    97  	sig, err := RawTxInWitnessSignature(tx, sigHashes, idx, amt, subscript,
    98  		hashType, privKey)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	pk := (*koblitz.PublicKey)(&privKey.PublicKey)
   104  	var pkData []byte
   105  	if compress {
   106  		pkData = pk.SerializeCompressed()
   107  	} else {
   108  		pkData = pk.SerializeUncompressed()
   109  	}
   110  
   111  	// A witness script is actually a stack, so we return an array of byte
   112  	// slices here, rather than a single byte slice.
   113  	return append([][]byte{sig}, pkData), nil
   114  }
   115  
   116  // RawTxInSignature returns the serialized ECDSA signature for the input idx of
   117  // the given transaction, with hashType appended to it.
   118  func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte,
   119  	hashType SigHashType, key *koblitz.PrivateKey) ([]byte, error) {
   120  
   121  	parsedScript, err := ParseScript(subScript)
   122  	if err != nil {
   123  		return nil, fmt.Errorf("cannot parse output script: %v", err)
   124  	}
   125  	hash := calcSignatureHash(parsedScript, hashType, tx, idx)
   126  	signature, err := key.Sign(hash)
   127  	if err != nil {
   128  		return nil, fmt.Errorf("cannot sign tx input: %s", err)
   129  	}
   130  
   131  	return append(signature.Serialize(), byte(hashType)), nil
   132  }
   133  
   134  // SignatureScript creates an input signature script for tx to spend BTC sent
   135  // from a previous output to the owner of privKey. tx must include all
   136  // transaction inputs and outputs, however txin scripts are allowed to be filled
   137  // or empty. The returned script is calculated to be used as the idx'th txin
   138  // sigscript for tx. subscript is the PkScript of the previous output being used
   139  // as the idx'th input. privKey is serialized in either a compressed or
   140  // uncompressed format based on compress. This format must match the same format
   141  // used to generate the payment address, or the script validation will fail.
   142  func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *koblitz.PrivateKey, compress bool) ([]byte, error) {
   143  	sig, err := RawTxInSignature(tx, idx, subscript, hashType, privKey)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	pk := (*koblitz.PublicKey)(&privKey.PublicKey)
   149  	var pkData []byte
   150  	if compress {
   151  		pkData = pk.SerializeCompressed()
   152  	} else {
   153  		pkData = pk.SerializeUncompressed()
   154  	}
   155  
   156  	return NewScriptBuilder().AddData(sig).AddData(pkData).Script()
   157  }
   158  
   159  func p2pkSignatureScript(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *koblitz.PrivateKey) ([]byte, error) {
   160  	sig, err := RawTxInSignature(tx, idx, subScript, hashType, privKey)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	return NewScriptBuilder().AddData(sig).Script()
   166  }
   167  
   168  // signMultiSig signs as many of the outputs in the provided multisig script as
   169  // possible. It returns the generated script and a boolean if the script fulfils
   170  // the contract (i.e. nrequired signatures are provided).  Since it is arguably
   171  // legal to not be able to sign any of the outputs, no error is returned.
   172  func signMultiSig(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType,
   173  	addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) {
   174  	// We start with a single OP_FALSE to work around the (now standard)
   175  	// but in the reference implementation that causes a spurious pop at
   176  	// the end of OP_CHECKMULTISIG.
   177  	builder := NewScriptBuilder().AddOp(OP_FALSE)
   178  	signed := 0
   179  	for _, addr := range addresses {
   180  		key, _, err := kdb.GetKey(addr)
   181  		if err != nil {
   182  			continue
   183  		}
   184  		sig, err := RawTxInSignature(tx, idx, subScript, hashType, key)
   185  		if err != nil {
   186  			continue
   187  		}
   188  
   189  		builder.AddData(sig)
   190  		signed++
   191  		if signed == nRequired {
   192  			break
   193  		}
   194  
   195  	}
   196  
   197  	script, _ := builder.Script()
   198  	return script, signed == nRequired
   199  }
   200  
   201  func sign(chainParams *coinparam.Params, tx *wire.MsgTx, idx int,
   202  	subScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB) ([]byte,
   203  	ScriptClass, []btcutil.Address, int, error) {
   204  
   205  	class, addresses, nrequired, err := ExtractPkScriptAddrs(subScript,
   206  		chainParams)
   207  	if err != nil {
   208  		return nil, NonStandardTy, nil, 0, err
   209  	}
   210  
   211  	switch class {
   212  	case PubKeyTy:
   213  		// look up key for address
   214  		key, _, err := kdb.GetKey(addresses[0])
   215  		if err != nil {
   216  			return nil, class, nil, 0, err
   217  		}
   218  
   219  		script, err := p2pkSignatureScript(tx, idx, subScript, hashType,
   220  			key)
   221  		if err != nil {
   222  			return nil, class, nil, 0, err
   223  		}
   224  
   225  		return script, class, addresses, nrequired, nil
   226  	case PubKeyHashTy:
   227  		// look up key for address
   228  		key, compressed, err := kdb.GetKey(addresses[0])
   229  		if err != nil {
   230  			return nil, class, nil, 0, err
   231  		}
   232  
   233  		script, err := SignatureScript(tx, idx, subScript, hashType,
   234  			key, compressed)
   235  		if err != nil {
   236  			return nil, class, nil, 0, err
   237  		}
   238  
   239  		return script, class, addresses, nrequired, nil
   240  	case ScriptHashTy:
   241  		script, err := sdb.GetScript(addresses[0])
   242  		if err != nil {
   243  			return nil, class, nil, 0, err
   244  		}
   245  
   246  		return script, class, addresses, nrequired, nil
   247  	case MultiSigTy:
   248  		script, _ := signMultiSig(tx, idx, subScript, hashType,
   249  			addresses, nrequired, kdb)
   250  		return script, class, addresses, nrequired, nil
   251  	case NullDataTy:
   252  		return nil, class, nil, 0,
   253  			errors.New("can't sign NULLDATA transactions")
   254  	default:
   255  		return nil, class, nil, 0,
   256  			errors.New("can't sign unknown transactions")
   257  	}
   258  }
   259  
   260  // mergeScripts merges sigScript and prevScript assuming they are both
   261  // partial solutions for pkScript spending output idx of tx. class, addresses
   262  // and nrequired are the result of extracting the addresses from pkscript.
   263  // The return value is the best effort merging of the two scripts. Calling this
   264  // function with addresses, class and nrequired that do not match pkScript is
   265  // an error and results in undefined behaviour.
   266  func mergeScripts(chainParams *coinparam.Params, tx *wire.MsgTx, idx int,
   267  	pkScript []byte, class ScriptClass, addresses []btcutil.Address,
   268  	nRequired int, sigScript, prevScript []byte) []byte {
   269  
   270  	// TODO(oga) the scripthash and multisig paths here are overly
   271  	// inefficient in that they will recompute already known data.
   272  	// some internal refactoring could probably make this avoid needless
   273  	// extra calculations.
   274  	switch class {
   275  	case ScriptHashTy:
   276  		// Remove the last push in the script and then recurse.
   277  		// this could be a lot less inefficient.
   278  		sigPops, err := ParseScript(sigScript)
   279  		if err != nil || len(sigPops) == 0 {
   280  			return prevScript
   281  		}
   282  		prevPops, err := ParseScript(prevScript)
   283  		if err != nil || len(prevPops) == 0 {
   284  			return sigScript
   285  		}
   286  
   287  		// assume that script in sigPops is the correct one, we just
   288  		// made it.
   289  		script := sigPops[len(sigPops)-1].data
   290  
   291  		// We already know this information somewhere up the stack.
   292  		class, addresses, nrequired, err :=
   293  			ExtractPkScriptAddrs(script, chainParams)
   294  		if err != nil {
   295  			return prevScript
   296  		}
   297  
   298  		// regenerate scripts.
   299  		sigScript, _ := unparseScript(sigPops)
   300  		prevScript, _ := unparseScript(prevPops)
   301  
   302  		// Merge
   303  		mergedScript := mergeScripts(chainParams, tx, idx, script,
   304  			class, addresses, nrequired, sigScript, prevScript)
   305  
   306  		// Reappend the script and return the result.
   307  		builder := NewScriptBuilder()
   308  		builder.AddOps(mergedScript)
   309  		builder.AddData(script)
   310  		finalScript, _ := builder.Script()
   311  		return finalScript
   312  	case MultiSigTy:
   313  		return mergeMultiSig(tx, idx, addresses, nRequired, pkScript,
   314  			sigScript, prevScript)
   315  
   316  	// It doesn't actually make sense to merge anything other than multiig
   317  	// and scripthash (because it could contain multisig). Everything else
   318  	// has either zero signature, can't be spent, or has a single signature
   319  	// which is either present or not. The other two cases are handled
   320  	// above. In the conflict case here we just assume the longest is
   321  	// correct (this matches behaviour of the reference implementation).
   322  	default:
   323  		if len(sigScript) > len(prevScript) {
   324  			return sigScript
   325  		}
   326  		return prevScript
   327  	}
   328  }
   329  
   330  // mergeMultiSig combines the two signature scripts sigScript and prevScript
   331  // that both provide signatures for pkScript in output idx of tx. addresses
   332  // and nRequired should be the results from extracting the addresses from
   333  // pkScript. Since this function is internal only we assume that the arguments
   334  // have come from other functions internally and thus are all consistent with
   335  // each other, behaviour is undefined if this contract is broken.
   336  func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []btcutil.Address,
   337  	nRequired int, pkScript, sigScript, prevScript []byte) []byte {
   338  
   339  	// This is an internal only function and we already parsed this script
   340  	// as ok for multisig (this is how we got here), so if this fails then
   341  	// all assumptions are broken and who knows which way is up?
   342  	pkPops, _ := ParseScript(pkScript)
   343  
   344  	sigPops, err := ParseScript(sigScript)
   345  	if err != nil || len(sigPops) == 0 {
   346  		return prevScript
   347  	}
   348  
   349  	prevPops, err := ParseScript(prevScript)
   350  	if err != nil || len(prevPops) == 0 {
   351  		return sigScript
   352  	}
   353  
   354  	// Convenience function to avoid duplication.
   355  	extractSigs := func(pops []parsedOpcode, sigs [][]byte) [][]byte {
   356  		for _, pop := range pops {
   357  			if len(pop.data) != 0 {
   358  				sigs = append(sigs, pop.data)
   359  			}
   360  		}
   361  		return sigs
   362  	}
   363  
   364  	possibleSigs := make([][]byte, 0, len(sigPops)+len(prevPops))
   365  	possibleSigs = extractSigs(sigPops, possibleSigs)
   366  	possibleSigs = extractSigs(prevPops, possibleSigs)
   367  
   368  	// Now we need to match the signatures to pubkeys, the only real way to
   369  	// do that is to try to verify them all and match it to the pubkey
   370  	// that verifies it. we then can go through the addresses in order
   371  	// to build our script. Anything that doesn't parse or doesn't verify we
   372  	// throw away.
   373  	addrToSig := make(map[string][]byte)
   374  sigLoop:
   375  	for _, sig := range possibleSigs {
   376  
   377  		// can't have a valid signature that doesn't at least have a
   378  		// hashtype, in practise it is even longer than this. but
   379  		// that'll be checked next.
   380  		if len(sig) < 1 {
   381  			continue
   382  		}
   383  		tSig := sig[:len(sig)-1]
   384  		hashType := SigHashType(sig[len(sig)-1])
   385  
   386  		pSig, err := koblitz.ParseDERSignature(tSig, koblitz.S256())
   387  		if err != nil {
   388  			continue
   389  		}
   390  
   391  		// We have to do this each round since hash types may vary
   392  		// between signatures and so the hash will vary. We can,
   393  		// however, assume no sigs etc are in the script since that
   394  		// would make the transaction nonstandard and thus not
   395  		// MultiSigTy, so we just need to hash the full thing.
   396  		hash := calcSignatureHash(pkPops, hashType, tx, idx)
   397  
   398  		for _, addr := range addresses {
   399  			// All multisig addresses should be pubkey addreses
   400  			// it is an error to call this internal function with
   401  			// bad input.
   402  			pkaddr := addr.(*btcutil.AddressPubKey)
   403  
   404  			pubKey := pkaddr.PubKey()
   405  
   406  			// If it matches we put it in the map. We only
   407  			// can take one signature per public key so if we
   408  			// already have one, we can throw this away.
   409  			if pSig.Verify(hash, pubKey) {
   410  				aStr := addr.EncodeAddress()
   411  				if _, ok := addrToSig[aStr]; !ok {
   412  					addrToSig[aStr] = sig
   413  				}
   414  				continue sigLoop
   415  			}
   416  		}
   417  	}
   418  
   419  	// Extra opcode to handle the extra arg consumed (due to previous bugs
   420  	// in the reference implementation).
   421  	builder := NewScriptBuilder().AddOp(OP_FALSE)
   422  	doneSigs := 0
   423  	// This assumes that addresses are in the same order as in the script.
   424  	for _, addr := range addresses {
   425  		sig, ok := addrToSig[addr.EncodeAddress()]
   426  		if !ok {
   427  			continue
   428  		}
   429  		builder.AddData(sig)
   430  		doneSigs++
   431  		if doneSigs == nRequired {
   432  			break
   433  		}
   434  	}
   435  
   436  	// padding for missing ones.
   437  	for i := doneSigs; i < nRequired; i++ {
   438  		builder.AddOp(OP_0)
   439  	}
   440  
   441  	script, _ := builder.Script()
   442  	return script
   443  }
   444  
   445  // KeyDB is an interface type provided to SignTxOutput, it encapsulates
   446  // any user state required to get the private keys for an address.
   447  type KeyDB interface {
   448  	GetKey(btcutil.Address) (*koblitz.PrivateKey, bool, error)
   449  }
   450  
   451  // KeyClosure implements KeyDB with a closure.
   452  type KeyClosure func(btcutil.Address) (*koblitz.PrivateKey, bool, error)
   453  
   454  // GetKey implements KeyDB by returning the result of calling the closure.
   455  func (kc KeyClosure) GetKey(address btcutil.Address) (*koblitz.PrivateKey,
   456  	bool, error) {
   457  	return kc(address)
   458  }
   459  
   460  // ScriptDB is an interface type provided to SignTxOutput, it encapsulates any
   461  // user state required to get the scripts for an pay-to-script-hash address.
   462  type ScriptDB interface {
   463  	GetScript(btcutil.Address) ([]byte, error)
   464  }
   465  
   466  // ScriptClosure implements ScriptDB with a closure.
   467  type ScriptClosure func(btcutil.Address) ([]byte, error)
   468  
   469  // GetScript implements ScriptDB by returning the result of calling the closure.
   470  func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) {
   471  	return sc(address)
   472  }
   473  
   474  // SignTxOutput signs output idx of the given tx to resolve the script given in
   475  // pkScript with a signature type of hashType. Any keys required will be
   476  // looked up by calling getKey() with the string of the given address.
   477  // Any pay-to-script-hash signatures will be similarly looked up by calling
   478  // getScript. If previousScript is provided then the results in previousScript
   479  // will be merged in a type-dependent manner with the newly generated.
   480  // signature script.
   481  func SignTxOutput(chainParams *coinparam.Params, tx *wire.MsgTx, idx int,
   482  	pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB,
   483  	previousScript []byte) ([]byte, error) {
   484  
   485  	sigScript, class, addresses, nrequired, err := sign(chainParams, tx,
   486  		idx, pkScript, hashType, kdb, sdb)
   487  	if err != nil {
   488  		return nil, err
   489  	}
   490  
   491  	if class == ScriptHashTy {
   492  		// TODO keep the sub addressed and pass down to merge.
   493  		realSigScript, _, _, _, err := sign(chainParams, tx, idx,
   494  			sigScript, hashType, kdb, sdb)
   495  		if err != nil {
   496  			return nil, err
   497  		}
   498  
   499  		// Append the p2sh script as the last push in the script.
   500  		builder := NewScriptBuilder()
   501  		builder.AddOps(realSigScript)
   502  		builder.AddData(sigScript)
   503  
   504  		sigScript, _ = builder.Script()
   505  		// TODO keep a copy of the script for merging.
   506  	}
   507  
   508  	// Merge scripts. with any previous data, if any.
   509  	mergedScript := mergeScripts(chainParams, tx, idx, pkScript, class,
   510  		addresses, nrequired, sigScript, previousScript)
   511  	return mergedScript, nil
   512  }