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