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 }