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 }