github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/txscript/sign.go (about)

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