@exodus/bitcoinjs-lib-forks 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/LICENSE +21 -0
  3. package/README.md +207 -0
  4. package/package.json +67 -0
  5. package/src/address.js +97 -0
  6. package/src/block.js +177 -0
  7. package/src/bufferutils.js +56 -0
  8. package/src/crypto.js +29 -0
  9. package/src/ecdsa.js +161 -0
  10. package/src/ecpair.js +131 -0
  11. package/src/ecsignature.js +97 -0
  12. package/src/hdnode.js +316 -0
  13. package/src/index.js +23 -0
  14. package/src/networks.js +47 -0
  15. package/src/script.js +214 -0
  16. package/src/script_number.js +68 -0
  17. package/src/templates/index.js +74 -0
  18. package/src/templates/multisig/index.js +4 -0
  19. package/src/templates/multisig/input.js +71 -0
  20. package/src/templates/multisig/output.js +64 -0
  21. package/src/templates/nulldata.js +34 -0
  22. package/src/templates/pubkey/index.js +4 -0
  23. package/src/templates/pubkey/input.js +39 -0
  24. package/src/templates/pubkey/output.js +33 -0
  25. package/src/templates/pubkeyhash/index.js +4 -0
  26. package/src/templates/pubkeyhash/input.js +51 -0
  27. package/src/templates/pubkeyhash/output.js +42 -0
  28. package/src/templates/scripthash/index.js +4 -0
  29. package/src/templates/scripthash/input.js +84 -0
  30. package/src/templates/scripthash/output.js +34 -0
  31. package/src/templates/witnesscommitment/index.js +3 -0
  32. package/src/templates/witnesscommitment/output.js +42 -0
  33. package/src/templates/witnesspubkeyhash/index.js +4 -0
  34. package/src/templates/witnesspubkeyhash/input.js +44 -0
  35. package/src/templates/witnesspubkeyhash/output.js +33 -0
  36. package/src/templates/witnessscripthash/index.js +4 -0
  37. package/src/templates/witnessscripthash/input.js +63 -0
  38. package/src/templates/witnessscripthash/output.js +33 -0
  39. package/src/transaction.js +547 -0
  40. package/src/transaction_builder.js +825 -0
  41. package/src/types.js +53 -0
@@ -0,0 +1,825 @@
1
+ var Buffer = require('safe-buffer').Buffer
2
+ var baddress = require('./address')
3
+ var bcrypto = require('./crypto')
4
+ var bscript = require('./script')
5
+ var btemplates = require('./templates')
6
+ var networks = require('./networks')
7
+ var ops = require('bitcoin-ops')
8
+ var typeforce = require('typeforce')
9
+ var types = require('./types')
10
+ var scriptTypes = btemplates.types
11
+ var SIGNABLE = [btemplates.types.P2PKH, btemplates.types.P2PK, btemplates.types.MULTISIG]
12
+ var P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH])
13
+
14
+ var ECPair = require('./ecpair')
15
+ var ECSignature = require('./ecsignature')
16
+ var Transaction = require('./transaction')
17
+
18
+ function supportedType (type) {
19
+ return SIGNABLE.indexOf(type) !== -1
20
+ }
21
+
22
+ function supportedP2SHType (type) {
23
+ return P2SH.indexOf(type) !== -1
24
+ }
25
+
26
+ function extractChunks (type, chunks, script) {
27
+ var pubKeys = []
28
+ var signatures = []
29
+ switch (type) {
30
+ case scriptTypes.P2PKH:
31
+ // if (redeemScript) throw new Error('Nonstandard... P2SH(P2PKH)')
32
+ pubKeys = chunks.slice(1)
33
+ signatures = chunks.slice(0, 1)
34
+ break
35
+
36
+ case scriptTypes.P2PK:
37
+ pubKeys[0] = script ? btemplates.pubKey.output.decode(script) : undefined
38
+ signatures = chunks.slice(0, 1)
39
+ break
40
+
41
+ case scriptTypes.MULTISIG:
42
+ if (script) {
43
+ var multisig = btemplates.multisig.output.decode(script)
44
+ pubKeys = multisig.pubKeys
45
+ }
46
+
47
+ signatures = chunks.slice(1).map(function (chunk) {
48
+ return chunk.length === 0 ? undefined : chunk
49
+ })
50
+ break
51
+ }
52
+
53
+ return {
54
+ pubKeys: pubKeys,
55
+ signatures: signatures
56
+ }
57
+ }
58
+ function expandInput (scriptSig, witnessStack) {
59
+ if (scriptSig.length === 0 && witnessStack.length === 0) return {}
60
+
61
+ var prevOutScript
62
+ var prevOutType
63
+ var scriptType
64
+ var script
65
+ var redeemScript
66
+ var witnessScript
67
+ var witnessScriptType
68
+ var redeemScriptType
69
+ var witness = false
70
+ var p2wsh = false
71
+ var p2sh = false
72
+ var witnessProgram
73
+ var chunks
74
+
75
+ var scriptSigChunks = bscript.decompile(scriptSig)
76
+ var sigType = btemplates.classifyInput(scriptSigChunks, true)
77
+ if (sigType === scriptTypes.P2SH) {
78
+ p2sh = true
79
+ redeemScript = scriptSigChunks[scriptSigChunks.length - 1]
80
+ redeemScriptType = btemplates.classifyOutput(redeemScript)
81
+ prevOutScript = btemplates.scriptHash.output.encode(bcrypto.hash160(redeemScript))
82
+ prevOutType = scriptTypes.P2SH
83
+ script = redeemScript
84
+ }
85
+
86
+ var classifyWitness = btemplates.classifyWitness(witnessStack, true)
87
+ if (classifyWitness === scriptTypes.P2WSH) {
88
+ witnessScript = witnessStack[witnessStack.length - 1]
89
+ witnessScriptType = btemplates.classifyOutput(witnessScript)
90
+ p2wsh = true
91
+ witness = true
92
+ if (scriptSig.length === 0) {
93
+ prevOutScript = btemplates.witnessScriptHash.output.encode(bcrypto.sha256(witnessScript))
94
+ prevOutType = scriptTypes.P2WSH
95
+ if (redeemScript !== undefined) {
96
+ throw new Error('Redeem script given when unnecessary')
97
+ }
98
+ // bare witness
99
+ } else {
100
+ if (!redeemScript) {
101
+ throw new Error('No redeemScript provided for P2WSH, but scriptSig non-empty')
102
+ }
103
+ witnessProgram = btemplates.witnessScriptHash.output.encode(bcrypto.sha256(witnessScript))
104
+ if (!redeemScript.equals(witnessProgram)) {
105
+ throw new Error('Redeem script didn\'t match witnessScript')
106
+ }
107
+ }
108
+
109
+ if (!supportedType(btemplates.classifyOutput(witnessScript))) {
110
+ throw new Error('unsupported witness script')
111
+ }
112
+
113
+ script = witnessScript
114
+ scriptType = witnessScriptType
115
+ chunks = witnessStack.slice(0, -1)
116
+ } else if (classifyWitness === scriptTypes.P2WPKH) {
117
+ witness = true
118
+ var key = witnessStack[witnessStack.length - 1]
119
+ var keyHash = bcrypto.hash160(key)
120
+ if (scriptSig.length === 0) {
121
+ prevOutScript = btemplates.witnessPubKeyHash.output.encode(keyHash)
122
+ prevOutType = scriptTypes.P2WPKH
123
+ if (typeof redeemScript !== 'undefined') {
124
+ throw new Error('Redeem script given when unnecessary')
125
+ }
126
+ } else {
127
+ if (!redeemScript) {
128
+ throw new Error('No redeemScript provided for P2WPKH, but scriptSig wasn\'t empty')
129
+ }
130
+ witnessProgram = btemplates.witnessPubKeyHash.output.encode(keyHash)
131
+ if (!redeemScript.equals(witnessProgram)) {
132
+ throw new Error('Redeem script did not have the right witness program')
133
+ }
134
+ }
135
+
136
+ scriptType = scriptTypes.P2PKH
137
+ chunks = witnessStack
138
+ } else if (redeemScript) {
139
+ if (!supportedP2SHType(redeemScriptType)) {
140
+ throw new Error('Bad redeemscript!')
141
+ }
142
+
143
+ script = redeemScript
144
+ scriptType = redeemScriptType
145
+ chunks = scriptSigChunks.slice(0, -1)
146
+ } else {
147
+ prevOutType = scriptType = btemplates.classifyInput(scriptSig)
148
+ chunks = scriptSigChunks
149
+ }
150
+
151
+ var expanded = extractChunks(scriptType, chunks, script)
152
+
153
+ var result = {
154
+ pubKeys: expanded.pubKeys,
155
+ signatures: expanded.signatures,
156
+ prevOutScript: prevOutScript,
157
+ prevOutType: prevOutType,
158
+ signType: scriptType,
159
+ signScript: script,
160
+ witness: Boolean(witness)
161
+ }
162
+
163
+ if (p2sh) {
164
+ result.redeemScript = redeemScript
165
+ result.redeemScriptType = redeemScriptType
166
+ }
167
+
168
+ if (p2wsh) {
169
+ result.witnessScript = witnessScript
170
+ result.witnessScriptType = witnessScriptType
171
+ }
172
+
173
+ return result
174
+ }
175
+
176
+ // could be done in expandInput, but requires the original Transaction for hashForSignature
177
+ function fixMultisigOrder (input, transaction, vin, value, forkId) {
178
+ if (input.redeemScriptType !== scriptTypes.MULTISIG || !input.redeemScript) return
179
+ if (input.pubKeys.length === input.signatures.length) return
180
+
181
+ var unmatched = input.signatures.concat()
182
+
183
+ input.signatures = input.pubKeys.map(function (pubKey) {
184
+ var keyPair = ECPair.fromPublicKeyBuffer(pubKey)
185
+ var match
186
+
187
+ // check for a signature
188
+ unmatched.some(function (signature, i) {
189
+ // skip if undefined || OP_0
190
+ if (!signature) return false
191
+
192
+ // TODO: avoid O(n) hashForSignature
193
+ var parsed = ECSignature.parseScriptSignature(signature)
194
+ var hash
195
+ switch (forkId) {
196
+ case Transaction.FORKID_BCH:
197
+ hash = transaction.hashForCashSignature(vin, input.signScript, value, parsed.hashType)
198
+ break
199
+ case Transaction.FORKID_BTG:
200
+ hash = transaction.hashForGoldSignature(vin, input.signScript, value, parsed.hashType)
201
+ break
202
+ default:
203
+ if (input.witness) {
204
+ hash = transaction.hashForWitnessV0(vin, input.signScript, value, parsed.hashType)
205
+ } else {
206
+ hash = transaction.hashForSignature(vin, input.signScript, parsed.hashType)
207
+ }
208
+ break
209
+ }
210
+
211
+ // skip if signature does not match pubKey
212
+ if (!keyPair.verify(hash, parsed.signature)) return false
213
+
214
+ // remove matched signature from unmatched
215
+ unmatched[i] = undefined
216
+ match = signature
217
+
218
+ return true
219
+ })
220
+
221
+ return match
222
+ })
223
+ }
224
+
225
+ function expandOutput (script, scriptType, ourPubKey) {
226
+ typeforce(types.Buffer, script)
227
+
228
+ var scriptChunks = bscript.decompile(script)
229
+ if (!scriptType) {
230
+ scriptType = btemplates.classifyOutput(script)
231
+ }
232
+
233
+ var pubKeys = []
234
+
235
+ switch (scriptType) {
236
+ // does our hash160(pubKey) match the output scripts?
237
+ case scriptTypes.P2PKH:
238
+ if (!ourPubKey) break
239
+
240
+ var pkh1 = scriptChunks[2]
241
+ var pkh2 = bcrypto.hash160(ourPubKey)
242
+ if (pkh1.equals(pkh2)) pubKeys = [ourPubKey]
243
+ break
244
+
245
+ // does our hash160(pubKey) match the output scripts?
246
+ case scriptTypes.P2WPKH:
247
+ if (!ourPubKey) break
248
+
249
+ var wpkh1 = scriptChunks[1]
250
+ var wpkh2 = bcrypto.hash160(ourPubKey)
251
+ if (wpkh1.equals(wpkh2)) pubKeys = [ourPubKey]
252
+ break
253
+
254
+ case scriptTypes.P2PK:
255
+ pubKeys = scriptChunks.slice(0, 1)
256
+ break
257
+
258
+ case scriptTypes.MULTISIG:
259
+ pubKeys = scriptChunks.slice(1, -2)
260
+ break
261
+
262
+ default: return { scriptType: scriptType }
263
+ }
264
+
265
+ return {
266
+ pubKeys: pubKeys,
267
+ scriptType: scriptType,
268
+ signatures: pubKeys.map(function () { return undefined })
269
+ }
270
+ }
271
+
272
+ function checkP2SHInput (input, redeemScriptHash) {
273
+ if (input.prevOutType) {
274
+ if (input.prevOutType !== scriptTypes.P2SH) throw new Error('PrevOutScript must be P2SH')
275
+
276
+ var prevOutScriptScriptHash = bscript.decompile(input.prevOutScript)[1]
277
+ if (!prevOutScriptScriptHash.equals(redeemScriptHash)) throw new Error('Inconsistent hash160(RedeemScript)')
278
+ }
279
+ }
280
+
281
+ function checkP2WSHInput (input, witnessScriptHash) {
282
+ if (input.prevOutType) {
283
+ if (input.prevOutType !== scriptTypes.P2WSH) throw new Error('PrevOutScript must be P2WSH')
284
+
285
+ var scriptHash = bscript.decompile(input.prevOutScript)[1]
286
+ if (!scriptHash.equals(witnessScriptHash)) throw new Error('Inconsistent sha25(WitnessScript)')
287
+ }
288
+ }
289
+
290
+ function prepareInput (input, kpPubKey, redeemScript, witnessValue, witnessScript) {
291
+ var expanded
292
+ var prevOutType
293
+ var prevOutScript
294
+
295
+ var p2sh = false
296
+ var p2shType
297
+ var redeemScriptHash
298
+
299
+ var witness = false
300
+ var p2wsh = false
301
+ var witnessType
302
+ var witnessScriptHash
303
+
304
+ var signType
305
+ var signScript
306
+
307
+ if (redeemScript && witnessScript) {
308
+ redeemScriptHash = bcrypto.hash160(redeemScript)
309
+ witnessScriptHash = bcrypto.sha256(witnessScript)
310
+ checkP2SHInput(input, redeemScriptHash)
311
+
312
+ if (!redeemScript.equals(btemplates.witnessScriptHash.output.encode(witnessScriptHash))) throw new Error('Witness script inconsistent with redeem script')
313
+
314
+ expanded = expandOutput(witnessScript, undefined, kpPubKey)
315
+ if (!expanded.pubKeys) throw new Error('WitnessScript not supported "' + bscript.toASM(redeemScript) + '"')
316
+
317
+ prevOutType = btemplates.types.P2SH
318
+ prevOutScript = btemplates.scriptHash.output.encode(redeemScriptHash)
319
+ p2sh = witness = p2wsh = true
320
+ p2shType = btemplates.types.P2WSH
321
+ signType = witnessType = expanded.scriptType
322
+ signScript = witnessScript
323
+ } else if (redeemScript) {
324
+ redeemScriptHash = bcrypto.hash160(redeemScript)
325
+ checkP2SHInput(input, redeemScriptHash)
326
+
327
+ expanded = expandOutput(redeemScript, undefined, kpPubKey)
328
+ if (!expanded.pubKeys) throw new Error('RedeemScript not supported "' + bscript.toASM(redeemScript) + '"')
329
+
330
+ prevOutType = btemplates.types.P2SH
331
+ prevOutScript = btemplates.scriptHash.output.encode(redeemScriptHash)
332
+ p2sh = true
333
+ signType = p2shType = expanded.scriptType
334
+ signScript = redeemScript
335
+ witness = signType === btemplates.types.P2WPKH
336
+ } else if (witnessScript) {
337
+ witnessScriptHash = bcrypto.sha256(witnessScript)
338
+ checkP2WSHInput(input, witnessScriptHash)
339
+
340
+ expanded = expandOutput(witnessScript, undefined, kpPubKey)
341
+ if (!expanded.pubKeys) throw new Error('WitnessScript not supported "' + bscript.toASM(redeemScript) + '"')
342
+
343
+ prevOutType = btemplates.types.P2WSH
344
+ prevOutScript = btemplates.witnessScriptHash.output.encode(witnessScriptHash)
345
+ witness = p2wsh = true
346
+ signType = witnessType = expanded.scriptType
347
+ signScript = witnessScript
348
+ } else if (input.prevOutType) {
349
+ // embedded scripts are not possible without a redeemScript
350
+ if (input.prevOutType === scriptTypes.P2SH ||
351
+ input.prevOutType === scriptTypes.P2WSH) {
352
+ throw new Error('PrevOutScript is ' + input.prevOutType + ', requires redeemScript')
353
+ }
354
+
355
+ prevOutType = input.prevOutType
356
+ prevOutScript = input.prevOutScript
357
+ expanded = expandOutput(input.prevOutScript, input.prevOutType, kpPubKey)
358
+ if (!expanded.pubKeys) return
359
+
360
+ witness = (input.prevOutType === scriptTypes.P2WPKH)
361
+ signType = prevOutType
362
+ signScript = prevOutScript
363
+ } else {
364
+ prevOutScript = btemplates.pubKeyHash.output.encode(bcrypto.hash160(kpPubKey))
365
+ expanded = expandOutput(prevOutScript, scriptTypes.P2PKH, kpPubKey)
366
+
367
+ prevOutType = scriptTypes.P2PKH
368
+ witness = false
369
+ signType = prevOutType
370
+ signScript = prevOutScript
371
+ }
372
+
373
+ if (signType === scriptTypes.P2WPKH) {
374
+ signScript = btemplates.pubKeyHash.output.encode(btemplates.witnessPubKeyHash.output.decode(signScript))
375
+ }
376
+
377
+ if (p2sh) {
378
+ input.redeemScript = redeemScript
379
+ input.redeemScriptType = p2shType
380
+ }
381
+
382
+ if (p2wsh) {
383
+ input.witnessScript = witnessScript
384
+ input.witnessScriptType = witnessType
385
+ }
386
+
387
+ input.pubKeys = expanded.pubKeys
388
+ input.signatures = expanded.signatures
389
+ input.signScript = signScript
390
+ input.signType = signType
391
+ input.prevOutScript = prevOutScript
392
+ input.prevOutType = prevOutType
393
+ input.witness = witness
394
+ }
395
+
396
+ function buildStack (type, signatures, pubKeys, allowIncomplete) {
397
+ if (type === scriptTypes.P2PKH) {
398
+ if (signatures.length === 1 && Buffer.isBuffer(signatures[0]) && pubKeys.length === 1) return btemplates.pubKeyHash.input.encodeStack(signatures[0], pubKeys[0])
399
+ } else if (type === scriptTypes.P2PK) {
400
+ if (signatures.length === 1 && Buffer.isBuffer(signatures[0])) return btemplates.pubKey.input.encodeStack(signatures[0])
401
+ } else if (type === scriptTypes.MULTISIG) {
402
+ if (signatures.length > 0) {
403
+ signatures = signatures.map(function (signature) {
404
+ return signature || ops.OP_0
405
+ })
406
+ if (!allowIncomplete) {
407
+ // remove blank signatures
408
+ signatures = signatures.filter(function (x) { return x !== ops.OP_0 })
409
+ }
410
+
411
+ return btemplates.multisig.input.encodeStack(signatures)
412
+ }
413
+ } else {
414
+ throw new Error('Not yet supported')
415
+ }
416
+
417
+ if (!allowIncomplete) throw new Error('Not enough signatures provided')
418
+ return []
419
+ }
420
+
421
+ function buildInput (input, allowIncomplete) {
422
+ var scriptType = input.prevOutType
423
+ var sig = []
424
+ var witness = []
425
+
426
+ if (supportedType(scriptType)) {
427
+ sig = buildStack(scriptType, input.signatures, input.pubKeys, allowIncomplete)
428
+ }
429
+
430
+ var p2sh = false
431
+ if (scriptType === btemplates.types.P2SH) {
432
+ // We can remove this error later when we have a guarantee prepareInput
433
+ // rejects unsignable scripts - it MUST be signable at this point.
434
+ if (!allowIncomplete && !supportedP2SHType(input.redeemScriptType)) {
435
+ throw new Error('Impossible to sign this type')
436
+ }
437
+
438
+ if (supportedType(input.redeemScriptType)) {
439
+ sig = buildStack(input.redeemScriptType, input.signatures, input.pubKeys, allowIncomplete)
440
+ }
441
+
442
+ // If it wasn't SIGNABLE, it's witness, defer to that
443
+ if (input.redeemScriptType) {
444
+ p2sh = true
445
+ scriptType = input.redeemScriptType
446
+ }
447
+ }
448
+
449
+ switch (scriptType) {
450
+ // P2WPKH is a special case of P2PKH
451
+ case btemplates.types.P2WPKH:
452
+ witness = buildStack(btemplates.types.P2PKH, input.signatures, input.pubKeys, allowIncomplete)
453
+ break
454
+
455
+ case btemplates.types.P2WSH:
456
+ // We can remove this check later
457
+ if (!allowIncomplete && !supportedType(input.witnessScriptType)) {
458
+ throw new Error('Impossible to sign this type')
459
+ }
460
+
461
+ if (supportedType(input.witnessScriptType)) {
462
+ witness = buildStack(input.witnessScriptType, input.signatures, input.pubKeys, allowIncomplete)
463
+ witness.push(input.witnessScript)
464
+ scriptType = input.witnessScriptType
465
+ }
466
+
467
+ break
468
+ }
469
+
470
+ // append redeemScript if necessary
471
+ if (p2sh) {
472
+ sig.push(input.redeemScript)
473
+ }
474
+
475
+ return {
476
+ type: scriptType,
477
+ script: bscript.compile(sig),
478
+ witness: witness
479
+ }
480
+ }
481
+
482
+ function TransactionBuilder (network, maximumFeeRate) {
483
+ this.prevTxMap = {}
484
+ this.network = network || networks.bitcoin
485
+
486
+ // WARNING: This is __NOT__ to be relied on, its just another potential safety mechanism (safety in-depth)
487
+ this.maximumFeeRate = maximumFeeRate || 2500
488
+
489
+ this.inputs = []
490
+ this.bitcoinCash = false
491
+ this.bitcoinGold = false
492
+ this.tx = new Transaction()
493
+ }
494
+
495
+ TransactionBuilder.prototype.enableBitcoinCash = function (enable) {
496
+ if (typeof enable === 'undefined') {
497
+ enable = true
498
+ }
499
+
500
+ this.bitcoinCash = enable
501
+ }
502
+
503
+ TransactionBuilder.prototype.enableBitcoinGold = function (enable) {
504
+ if (typeof enable === 'undefined') {
505
+ enable = true
506
+ }
507
+
508
+ this.bitcoinGold = enable
509
+ }
510
+
511
+ TransactionBuilder.prototype.setLockTime = function (locktime) {
512
+ typeforce(types.UInt32, locktime)
513
+
514
+ // if any signatures exist, throw
515
+ if (this.inputs.some(function (input) {
516
+ if (!input.signatures) return false
517
+
518
+ return input.signatures.some(function (s) { return s })
519
+ })) {
520
+ throw new Error('No, this would invalidate signatures')
521
+ }
522
+
523
+ this.tx.locktime = locktime
524
+ }
525
+
526
+ TransactionBuilder.prototype.setVersion = function (version) {
527
+ typeforce(types.UInt32, version)
528
+
529
+ // XXX: this might eventually become more complex depending on what the versions represent
530
+ this.tx.version = version
531
+ }
532
+
533
+ TransactionBuilder.fromTransaction = function (transaction, network, forkId) {
534
+ var txb = new TransactionBuilder(network)
535
+
536
+ if (typeof forkId === 'number') {
537
+ if (forkId === Transaction.FORKID_BTG) {
538
+ txb.enableBitcoinGold(true)
539
+ } else if (forkId === Transaction.FORKID_BCH) {
540
+ txb.enableBitcoinCash(true)
541
+ }
542
+ }
543
+
544
+ // Copy transaction fields
545
+ txb.setVersion(transaction.version)
546
+ txb.setLockTime(transaction.locktime)
547
+
548
+ // Copy outputs (done first to avoid signature invalidation)
549
+ transaction.outs.forEach(function (txOut) {
550
+ txb.addOutput(txOut.script, txOut.value)
551
+ })
552
+
553
+ // Copy inputs
554
+ transaction.ins.forEach(function (txIn) {
555
+ txb.__addInputUnsafe(txIn.hash, txIn.index, {
556
+ sequence: txIn.sequence,
557
+ script: txIn.script,
558
+ witness: txIn.witness,
559
+ value: txIn.value
560
+ })
561
+ })
562
+
563
+ // fix some things not possible through the public API
564
+ txb.inputs.forEach(function (input, i) {
565
+ fixMultisigOrder(input, transaction, i, input.value, forkId)
566
+ })
567
+
568
+ return txb
569
+ }
570
+
571
+ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOutScript) {
572
+ if (!this.__canModifyInputs()) {
573
+ throw new Error('No, this would invalidate signatures')
574
+ }
575
+
576
+ var value
577
+
578
+ // is it a hex string?
579
+ if (typeof txHash === 'string') {
580
+ // transaction hashs's are displayed in reverse order, un-reverse it
581
+ txHash = Buffer.from(txHash, 'hex').reverse()
582
+
583
+ // is it a Transaction object?
584
+ } else if (txHash instanceof Transaction) {
585
+ var txOut = txHash.outs[vout]
586
+ prevOutScript = txOut.script
587
+ value = txOut.value
588
+
589
+ txHash = txHash.getHash()
590
+ }
591
+
592
+ return this.__addInputUnsafe(txHash, vout, {
593
+ sequence: sequence,
594
+ prevOutScript: prevOutScript,
595
+ value: value
596
+ })
597
+ }
598
+
599
+ TransactionBuilder.prototype.__addInputUnsafe = function (txHash, vout, options) {
600
+ if (Transaction.isCoinbaseHash(txHash)) {
601
+ throw new Error('coinbase inputs not supported')
602
+ }
603
+
604
+ var prevTxOut = txHash.toString('hex') + ':' + vout
605
+ if (this.prevTxMap[prevTxOut] !== undefined) throw new Error('Duplicate TxOut: ' + prevTxOut)
606
+
607
+ var input = {}
608
+
609
+ // derive what we can from the scriptSig
610
+ if (options.script !== undefined) {
611
+ input = expandInput(options.script, options.witness || [])
612
+ }
613
+
614
+ // if an input value was given, retain it
615
+ if (options.value !== undefined) {
616
+ input.value = options.value
617
+ }
618
+
619
+ // derive what we can from the previous transactions output script
620
+ if (!input.prevOutScript && options.prevOutScript) {
621
+ var prevOutType
622
+
623
+ if (!input.pubKeys && !input.signatures) {
624
+ var expanded = expandOutput(options.prevOutScript)
625
+
626
+ if (expanded.pubKeys) {
627
+ input.pubKeys = expanded.pubKeys
628
+ input.signatures = expanded.signatures
629
+ }
630
+
631
+ prevOutType = expanded.scriptType
632
+ }
633
+
634
+ input.prevOutScript = options.prevOutScript
635
+ input.prevOutType = prevOutType || btemplates.classifyOutput(options.prevOutScript)
636
+ }
637
+
638
+ var vin = this.tx.addInput(txHash, vout, options.sequence, options.scriptSig)
639
+ this.inputs[vin] = input
640
+ this.prevTxMap[prevTxOut] = vin
641
+ return vin
642
+ }
643
+
644
+ TransactionBuilder.prototype.addOutput = function (scriptPubKey, value) {
645
+ if (!this.__canModifyOutputs()) {
646
+ throw new Error('No, this would invalidate signatures')
647
+ }
648
+
649
+ // Attempt to get a script if it's a base58 address string
650
+ if (typeof scriptPubKey === 'string') {
651
+ scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network)
652
+ }
653
+
654
+ return this.tx.addOutput(scriptPubKey, value)
655
+ }
656
+
657
+ TransactionBuilder.prototype.build = function () {
658
+ return this.__build(false)
659
+ }
660
+ TransactionBuilder.prototype.buildIncomplete = function () {
661
+ return this.__build(true)
662
+ }
663
+
664
+ TransactionBuilder.prototype.__build = function (allowIncomplete) {
665
+ if (!allowIncomplete) {
666
+ if (!this.tx.ins.length) throw new Error('Transaction has no inputs')
667
+ if (!this.tx.outs.length) throw new Error('Transaction has no outputs')
668
+ }
669
+
670
+ var tx = this.tx.clone()
671
+ // Create script signatures from inputs
672
+ this.inputs.forEach(function (input, i) {
673
+ var scriptType = input.witnessScriptType || input.redeemScriptType || input.prevOutType
674
+ if (!scriptType && !allowIncomplete) throw new Error('Transaction is not complete')
675
+ var result = buildInput(input, allowIncomplete)
676
+
677
+ // skip if no result
678
+ if (!allowIncomplete) {
679
+ if (!supportedType(result.type) && result.type !== btemplates.types.P2WPKH) {
680
+ throw new Error(result.type + ' not supported')
681
+ }
682
+ }
683
+
684
+ tx.setInputScript(i, result.script)
685
+ tx.setWitness(i, result.witness)
686
+ })
687
+
688
+ if (!allowIncomplete) {
689
+ // do not rely on this, its merely a last resort
690
+ if (this.__overMaximumFees(tx.virtualSize())) {
691
+ throw new Error('Transaction has absurd fees')
692
+ }
693
+ }
694
+
695
+ return tx
696
+ }
697
+
698
+ function canSign (input) {
699
+ return input.prevOutScript !== undefined &&
700
+ input.signScript !== undefined &&
701
+ input.pubKeys !== undefined &&
702
+ input.signatures !== undefined &&
703
+ input.signatures.length === input.pubKeys.length &&
704
+ input.pubKeys.length > 0 &&
705
+ (
706
+ input.witness === false ||
707
+ (input.witness === true && input.value !== undefined)
708
+ )
709
+ }
710
+
711
+ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashType, witnessValue, witnessScript) {
712
+ // TODO: remove keyPair.network matching in 4.0.0
713
+ if (keyPair.network && keyPair.network !== this.network) throw new TypeError('Inconsistent network')
714
+ if (!this.inputs[vin]) throw new Error('No input at index: ' + vin)
715
+ hashType = hashType || Transaction.SIGHASH_ALL
716
+
717
+ var input = this.inputs[vin]
718
+
719
+ // if redeemScript was previously provided, enforce consistency
720
+ if (input.redeemScript !== undefined &&
721
+ redeemScript &&
722
+ !input.redeemScript.equals(redeemScript)) {
723
+ throw new Error('Inconsistent redeemScript')
724
+ }
725
+
726
+ var kpPubKey = keyPair.publicKey || keyPair.getPublicKeyBuffer()
727
+ if (!canSign(input)) {
728
+ if (witnessValue !== undefined) {
729
+ if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue')
730
+ typeforce(types.Satoshi, witnessValue)
731
+ input.value = witnessValue
732
+ }
733
+
734
+ if (!canSign(input)) prepareInput(input, kpPubKey, redeemScript, witnessValue, witnessScript)
735
+ if (!canSign(input)) throw Error(input.prevOutType + ' not supported')
736
+ }
737
+
738
+ // ready to sign
739
+ var signatureHash
740
+ if (this.bitcoinGold) {
741
+ signatureHash = this.tx.hashForGoldSignature(vin, input.signScript, witnessValue, hashType, input.witness)
742
+ } else if (this.bitcoinCash) {
743
+ signatureHash = this.tx.hashForCashSignature(vin, input.signScript, witnessValue, hashType)
744
+ } else {
745
+ if (input.witness) {
746
+ signatureHash = this.tx.hashForWitnessV0(vin, input.signScript, witnessValue, hashType)
747
+ } else {
748
+ signatureHash = this.tx.hashForSignature(vin, input.signScript, hashType)
749
+ }
750
+ }
751
+
752
+ // enforce in order signing of public keys
753
+ var signed = input.pubKeys.some(function (pubKey, i) {
754
+ if (!kpPubKey.equals(pubKey)) return false
755
+ if (input.signatures[i]) throw new Error('Signature already exists')
756
+ if (kpPubKey.length !== 33 &&
757
+ input.signType === scriptTypes.P2WPKH) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH')
758
+
759
+ var signature = keyPair.sign(signatureHash)
760
+ if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature)
761
+
762
+ input.signatures[i] = signature.toScriptSignature(hashType)
763
+ return true
764
+ })
765
+
766
+ if (!signed) throw new Error('Key pair cannot sign for this input')
767
+ }
768
+
769
+ function signatureHashType (buffer) {
770
+ return buffer.readUInt8(buffer.length - 1)
771
+ }
772
+
773
+ TransactionBuilder.prototype.__canModifyInputs = function () {
774
+ return this.inputs.every(function (input) {
775
+ // any signatures?
776
+ if (input.signatures === undefined) return true
777
+
778
+ return input.signatures.every(function (signature) {
779
+ if (!signature) return true
780
+ var hashType = signatureHashType(signature)
781
+
782
+ // if SIGHASH_ANYONECANPAY is set, signatures would not
783
+ // be invalidated by more inputs
784
+ return hashType & Transaction.SIGHASH_ANYONECANPAY
785
+ })
786
+ })
787
+ }
788
+
789
+ TransactionBuilder.prototype.__canModifyOutputs = function () {
790
+ var nInputs = this.tx.ins.length
791
+ var nOutputs = this.tx.outs.length
792
+
793
+ return this.inputs.every(function (input) {
794
+ if (input.signatures === undefined) return true
795
+
796
+ return input.signatures.every(function (signature) {
797
+ if (!signature) return true
798
+ var hashType = signatureHashType(signature)
799
+
800
+ var hashTypeMod = hashType & 0x1f
801
+ if (hashTypeMod === Transaction.SIGHASH_NONE) return true
802
+ if (hashTypeMod === Transaction.SIGHASH_SINGLE) {
803
+ // if SIGHASH_SINGLE is set, and nInputs > nOutputs
804
+ // some signatures would be invalidated by the addition
805
+ // of more outputs
806
+ return nInputs <= nOutputs
807
+ }
808
+ })
809
+ })
810
+ }
811
+
812
+ TransactionBuilder.prototype.__overMaximumFees = function (bytes) {
813
+ // not all inputs will have .value defined
814
+ var incoming = this.inputs.reduce(function (a, x) { return a + (x.value >>> 0) }, 0)
815
+
816
+ // but all outputs do, and if we have any input value
817
+ // we can immediately determine if the outputs are too small
818
+ var outgoing = this.tx.outs.reduce(function (a, x) { return a + x.value }, 0)
819
+ var fee = incoming - outgoing
820
+ var feeRate = fee / bytes
821
+
822
+ return feeRate > this.maximumFeeRate
823
+ }
824
+
825
+ module.exports = TransactionBuilder