sign.go raw

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