smartledger-bsv 3.0.0

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 (76) hide show
  1. package/LICENSE +36 -0
  2. package/README.md +305 -0
  3. package/SECURITY.md +75 -0
  4. package/bsv-ecies.min.js +12 -0
  5. package/bsv-message.min.js +10 -0
  6. package/bsv-mnemonic.min.js +12 -0
  7. package/bsv.d.ts +440 -0
  8. package/bsv.min.js +37 -0
  9. package/ecies/index.js +1 -0
  10. package/index.js +101 -0
  11. package/lib/address.js +526 -0
  12. package/lib/block/block.js +277 -0
  13. package/lib/block/blockheader.js +294 -0
  14. package/lib/block/index.js +4 -0
  15. package/lib/block/merkleblock.js +316 -0
  16. package/lib/crypto/bn.js +278 -0
  17. package/lib/crypto/ecdsa.js +330 -0
  18. package/lib/crypto/elliptic-fixed.js +74 -0
  19. package/lib/crypto/hash.browser.js +171 -0
  20. package/lib/crypto/hash.js +2 -0
  21. package/lib/crypto/hash.node.js +171 -0
  22. package/lib/crypto/point.js +217 -0
  23. package/lib/crypto/random.js +37 -0
  24. package/lib/crypto/signature.js +410 -0
  25. package/lib/crypto/smartledger_verify.js +109 -0
  26. package/lib/ecies/bitcore-ecies.js +163 -0
  27. package/lib/ecies/electrum-ecies.js +175 -0
  28. package/lib/ecies/errors.js +16 -0
  29. package/lib/ecies/index.js +1 -0
  30. package/lib/encoding/base58.js +108 -0
  31. package/lib/encoding/base58check.js +112 -0
  32. package/lib/encoding/bufferreader.js +200 -0
  33. package/lib/encoding/bufferwriter.js +150 -0
  34. package/lib/encoding/varint.js +71 -0
  35. package/lib/errors/index.js +57 -0
  36. package/lib/errors/spec.js +184 -0
  37. package/lib/hdprivatekey.js +655 -0
  38. package/lib/hdpublickey.js +509 -0
  39. package/lib/message/index.js +4 -0
  40. package/lib/message/message.js +181 -0
  41. package/lib/mnemonic/errors.js +18 -0
  42. package/lib/mnemonic/index.js +4 -0
  43. package/lib/mnemonic/mnemonic.js +304 -0
  44. package/lib/mnemonic/pbkdf2.js +68 -0
  45. package/lib/mnemonic/words/chinese.js +5 -0
  46. package/lib/mnemonic/words/english.js +5 -0
  47. package/lib/mnemonic/words/french.js +5 -0
  48. package/lib/mnemonic/words/index.js +8 -0
  49. package/lib/mnemonic/words/italian.js +5 -0
  50. package/lib/mnemonic/words/japanese.js +5 -0
  51. package/lib/mnemonic/words/spanish.js +5 -0
  52. package/lib/networks.js +392 -0
  53. package/lib/opcode.js +248 -0
  54. package/lib/privatekey.js +373 -0
  55. package/lib/publickey.js +387 -0
  56. package/lib/script/index.js +3 -0
  57. package/lib/script/interpreter.js +1807 -0
  58. package/lib/script/script.js +1153 -0
  59. package/lib/transaction/index.js +7 -0
  60. package/lib/transaction/input/index.js +6 -0
  61. package/lib/transaction/input/input.js +202 -0
  62. package/lib/transaction/input/multisig.js +220 -0
  63. package/lib/transaction/input/multisigscripthash.js +189 -0
  64. package/lib/transaction/input/publickey.js +96 -0
  65. package/lib/transaction/input/publickeyhash.js +103 -0
  66. package/lib/transaction/output.js +192 -0
  67. package/lib/transaction/sighash.js +288 -0
  68. package/lib/transaction/signature.js +88 -0
  69. package/lib/transaction/transaction.js +1208 -0
  70. package/lib/transaction/unspentoutput.js +97 -0
  71. package/lib/util/_.js +44 -0
  72. package/lib/util/js.js +91 -0
  73. package/lib/util/preconditions.js +34 -0
  74. package/message/index.js +1 -0
  75. package/mnemonic/index.js +1 -0
  76. package/package.json +86 -0
@@ -0,0 +1,7 @@
1
+ module.exports = require('./transaction')
2
+
3
+ module.exports.Input = require('./input')
4
+ module.exports.Output = require('./output')
5
+ module.exports.UnspentOutput = require('./unspentoutput')
6
+ module.exports.Signature = require('./signature')
7
+ module.exports.Sighash = require('./sighash')
@@ -0,0 +1,6 @@
1
+ module.exports = require('./input')
2
+
3
+ module.exports.PublicKey = require('./publickey')
4
+ module.exports.PublicKeyHash = require('./publickeyhash')
5
+ module.exports.MultiSig = require('./multisig.js')
6
+ module.exports.MultiSigScriptHash = require('./multisigscripthash.js')
@@ -0,0 +1,202 @@
1
+ 'use strict'
2
+
3
+ var _ = require('../../util/_')
4
+ var $ = require('../../util/preconditions')
5
+ var errors = require('../../errors')
6
+ var BufferWriter = require('../../encoding/bufferwriter')
7
+ var buffer = require('buffer')
8
+ var JSUtil = require('../../util/js')
9
+ var Script = require('../../script')
10
+ var Sighash = require('../sighash')
11
+ var Output = require('../output')
12
+
13
+ var MAXINT = 0xffffffff // Math.pow(2, 32) - 1;
14
+ var DEFAULT_RBF_SEQNUMBER = MAXINT - 2
15
+ var DEFAULT_SEQNUMBER = MAXINT
16
+ var DEFAULT_LOCKTIME_SEQNUMBER = MAXINT - 1
17
+
18
+ function Input (params) {
19
+ if (!(this instanceof Input)) {
20
+ return new Input(params)
21
+ }
22
+ if (params) {
23
+ return this._fromObject(params)
24
+ }
25
+ }
26
+
27
+ Input.MAXINT = MAXINT
28
+ Input.DEFAULT_SEQNUMBER = DEFAULT_SEQNUMBER
29
+ Input.DEFAULT_LOCKTIME_SEQNUMBER = DEFAULT_LOCKTIME_SEQNUMBER
30
+ Input.DEFAULT_RBF_SEQNUMBER = DEFAULT_RBF_SEQNUMBER
31
+ // txid + output index + sequence number
32
+ Input.BASE_SIZE = 32 + 4 + 4
33
+
34
+ Object.defineProperty(Input.prototype, 'script', {
35
+ configurable: false,
36
+ enumerable: true,
37
+ get: function () {
38
+ if (this.isNull()) {
39
+ return null
40
+ }
41
+ if (!this._script) {
42
+ this._script = new Script(this._scriptBuffer)
43
+ this._script._isInput = true
44
+ }
45
+ return this._script
46
+ }
47
+ })
48
+
49
+ Input.fromObject = function (obj) {
50
+ $.checkArgument(_.isObject(obj))
51
+ var input = new Input()
52
+ return input._fromObject(obj)
53
+ }
54
+
55
+ Input.prototype._fromObject = function (params) {
56
+ var prevTxId
57
+ if (_.isString(params.prevTxId) && JSUtil.isHexa(params.prevTxId)) {
58
+ prevTxId = buffer.Buffer.from(params.prevTxId, 'hex')
59
+ } else {
60
+ prevTxId = params.prevTxId
61
+ }
62
+ this.output = params.output
63
+ ? (params.output instanceof Output ? params.output : new Output(params.output)) : undefined
64
+ this.prevTxId = prevTxId || params.txidbuf
65
+ this.outputIndex = _.isUndefined(params.outputIndex) ? params.txoutnum : params.outputIndex
66
+ this.sequenceNumber = _.isUndefined(params.sequenceNumber)
67
+ ? (_.isUndefined(params.seqnum) ? DEFAULT_SEQNUMBER : params.seqnum) : params.sequenceNumber
68
+ if (_.isUndefined(params.script) && _.isUndefined(params.scriptBuffer)) {
69
+ throw new errors.Transaction.Input.MissingScript()
70
+ }
71
+ this.setScript(params.scriptBuffer || params.script)
72
+ return this
73
+ }
74
+
75
+ Input.prototype.toObject = Input.prototype.toJSON = function toObject () {
76
+ var obj = {
77
+ prevTxId: this.prevTxId.toString('hex'),
78
+ outputIndex: this.outputIndex,
79
+ sequenceNumber: this.sequenceNumber,
80
+ script: this._scriptBuffer.toString('hex')
81
+ }
82
+ // add human readable form if input contains valid script
83
+ if (this.script) {
84
+ obj.scriptString = this.script.toString()
85
+ }
86
+ if (this.output) {
87
+ obj.output = this.output.toObject()
88
+ }
89
+ return obj
90
+ }
91
+
92
+ Input.fromBufferReader = function (br) {
93
+ var input = new Input()
94
+ input.prevTxId = br.readReverse(32)
95
+ input.outputIndex = br.readUInt32LE()
96
+ input._scriptBuffer = br.readVarLengthBuffer()
97
+ input.sequenceNumber = br.readUInt32LE()
98
+ // TODO: return different classes according to which input it is
99
+ // e.g: CoinbaseInput, PublicKeyHashInput, MultiSigScriptHashInput, etc.
100
+ return input
101
+ }
102
+
103
+ Input.prototype.toBufferWriter = function (writer) {
104
+ if (!writer) {
105
+ writer = new BufferWriter()
106
+ }
107
+ writer.writeReverse(this.prevTxId)
108
+ writer.writeUInt32LE(this.outputIndex)
109
+ var script = this._scriptBuffer
110
+ writer.writeVarintNum(script.length)
111
+ writer.write(script)
112
+ writer.writeUInt32LE(this.sequenceNumber)
113
+ return writer
114
+ }
115
+
116
+ Input.prototype.setScript = function (script) {
117
+ this._script = null
118
+ if (script instanceof Script) {
119
+ this._script = script
120
+ this._script._isInput = true
121
+ this._scriptBuffer = script.toBuffer()
122
+ } else if (script === null) {
123
+ this._script = Script.empty()
124
+ this._script._isInput = true
125
+ this._scriptBuffer = this._script.toBuffer()
126
+ } else if (JSUtil.isHexa(script)) {
127
+ // hex string script
128
+ this._scriptBuffer = buffer.Buffer.from(script, 'hex')
129
+ } else if (_.isString(script)) {
130
+ // human readable string script
131
+ this._script = new Script(script)
132
+ this._script._isInput = true
133
+ this._scriptBuffer = this._script.toBuffer()
134
+ } else if (Buffer.isBuffer(script)) {
135
+ // buffer script
136
+ this._scriptBuffer = buffer.Buffer.from(script)
137
+ } else {
138
+ throw new TypeError('Invalid argument type: script')
139
+ }
140
+ return this
141
+ }
142
+
143
+ /**
144
+ * Retrieve signatures for the provided PrivateKey.
145
+ *
146
+ * @param {Transaction} transaction - the transaction to be signed
147
+ * @param {PrivateKey} privateKey - the private key to use when signing
148
+ * @param {number} inputIndex - the index of this input in the provided transaction
149
+ * @param {number} sigType - defaults to Signature.SIGHASH_ALL
150
+ * @param {Buffer} addressHash - if provided, don't calculate the hash of the
151
+ * public key associated with the private key provided
152
+ * @abstract
153
+ */
154
+ Input.prototype.getSignatures = function () {
155
+ throw new errors.AbstractMethodInvoked(
156
+ 'Trying to sign unsupported output type (only P2PKH and P2SH multisig inputs are supported)' +
157
+ ' for input: ' + JSON.stringify(this)
158
+ )
159
+ }
160
+
161
+ Input.prototype.isFullySigned = function () {
162
+ throw new errors.AbstractMethodInvoked('Input#isFullySigned')
163
+ }
164
+
165
+ Input.prototype.isFinal = function () {
166
+ return this.sequenceNumber === Input.MAXINT
167
+ }
168
+
169
+ Input.prototype.addSignature = function () {
170
+ throw new errors.AbstractMethodInvoked('Input#addSignature')
171
+ }
172
+
173
+ Input.prototype.clearSignatures = function () {
174
+ throw new errors.AbstractMethodInvoked('Input#clearSignatures')
175
+ }
176
+
177
+ Input.prototype.isValidSignature = function (transaction, signature) {
178
+ // FIXME: Refactor signature so this is not necessary
179
+ signature.signature.nhashtype = signature.sigtype
180
+ return Sighash.verify(
181
+ transaction,
182
+ signature.signature,
183
+ signature.publicKey,
184
+ signature.inputIndex,
185
+ this.output.script,
186
+ this.output.satoshisBN
187
+ )
188
+ }
189
+
190
+ /**
191
+ * @returns true if this is a coinbase input (represents no input)
192
+ */
193
+ Input.prototype.isNull = function () {
194
+ return this.prevTxId.toString('hex') === '0000000000000000000000000000000000000000000000000000000000000000' &&
195
+ this.outputIndex === 0xffffffff
196
+ }
197
+
198
+ Input.prototype._estimateSize = function () {
199
+ return this.toBufferWriter().toBuffer().length
200
+ }
201
+
202
+ module.exports = Input
@@ -0,0 +1,220 @@
1
+ 'use strict'
2
+
3
+ var _ = require('../../util/_')
4
+ var inherits = require('inherits')
5
+ var Input = require('./input')
6
+ var Output = require('../output')
7
+ var $ = require('../../util/preconditions')
8
+
9
+ var Script = require('../../script')
10
+ var Signature = require('../../crypto/signature')
11
+ var Sighash = require('../sighash')
12
+ var TransactionSignature = require('../signature')
13
+ var PublicKey = require('../../publickey')
14
+ var Varint = require('../../encoding/varint')
15
+
16
+ /**
17
+ * @constructor
18
+ */
19
+ function MultiSigInput (input, pubkeys, threshold, signatures) {
20
+ Input.apply(this, arguments)
21
+ var self = this
22
+ pubkeys = pubkeys || input.publicKeys
23
+ threshold = threshold || input.threshold
24
+ signatures = signatures || input.signatures
25
+ this.publicKeys = pubkeys.map(k => k.toString('hex')).sort().map(k => new PublicKey(k))
26
+ $.checkState(Script.buildMultisigOut(this.publicKeys, threshold).equals(this.output.script),
27
+ 'Provided public keys don\'t match to the provided output script')
28
+ this.publicKeyIndex = {}
29
+ _.each(this.publicKeys, function (publicKey, index) {
30
+ self.publicKeyIndex[publicKey.toString()] = index
31
+ })
32
+ this.threshold = threshold
33
+ // Empty array of signatures
34
+ this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length)
35
+ }
36
+ inherits(MultiSigInput, Input)
37
+
38
+ MultiSigInput.prototype.toObject = function () {
39
+ var obj = Input.prototype.toObject.apply(this, arguments)
40
+ obj.threshold = this.threshold
41
+ obj.publicKeys = _.map(this.publicKeys, function (publicKey) { return publicKey.toString() })
42
+ obj.signatures = this._serializeSignatures()
43
+ return obj
44
+ }
45
+
46
+ MultiSigInput.prototype._deserializeSignatures = function (signatures) {
47
+ return _.map(signatures, function (signature) {
48
+ if (!signature) {
49
+ return undefined
50
+ }
51
+ return new TransactionSignature(signature)
52
+ })
53
+ }
54
+
55
+ MultiSigInput.prototype._serializeSignatures = function () {
56
+ return _.map(this.signatures, function (signature) {
57
+ if (!signature) {
58
+ return undefined
59
+ }
60
+ return signature.toObject()
61
+ })
62
+ }
63
+
64
+ MultiSigInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype) {
65
+ $.checkState(this.output instanceof Output)
66
+ sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID)
67
+
68
+ var self = this
69
+ var results = []
70
+ _.each(this.publicKeys, function (publicKey) {
71
+ if (publicKey.toString() === privateKey.publicKey.toString()) {
72
+ results.push(new TransactionSignature({
73
+ publicKey: privateKey.publicKey,
74
+ prevTxId: self.prevTxId,
75
+ outputIndex: self.outputIndex,
76
+ inputIndex: index,
77
+ signature: Sighash.sign(transaction, privateKey, sigtype, index, self.output.script, self.output.satoshisBN),
78
+ sigtype: sigtype
79
+ }))
80
+ }
81
+ })
82
+
83
+ return results
84
+ }
85
+
86
+ MultiSigInput.prototype.addSignature = function (transaction, signature) {
87
+ $.checkState(!this.isFullySigned(), 'All needed signatures have already been added')
88
+ $.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()]),
89
+ 'Signature has no matching public key')
90
+ $.checkState(this.isValidSignature(transaction, signature))
91
+ this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature
92
+ this._updateScript()
93
+ return this
94
+ }
95
+
96
+ MultiSigInput.prototype._updateScript = function () {
97
+ this.setScript(Script.buildMultisigIn(
98
+ this.publicKeys,
99
+ this.threshold,
100
+ this._createSignatures()
101
+ ))
102
+ return this
103
+ }
104
+
105
+ MultiSigInput.prototype._createSignatures = function () {
106
+ return _.map(
107
+ _.filter(this.signatures, function (signature) { return !_.isUndefined(signature) }),
108
+ function (signature) {
109
+ return Buffer.concat([
110
+ signature.signature.toDER(),
111
+ Buffer.from([signature.sigtype & 0xff])
112
+ ])
113
+ }
114
+ )
115
+ }
116
+
117
+ MultiSigInput.prototype.clearSignatures = function () {
118
+ this.signatures = new Array(this.publicKeys.length)
119
+ this._updateScript()
120
+ }
121
+
122
+ MultiSigInput.prototype.isFullySigned = function () {
123
+ return this.countSignatures() === this.threshold
124
+ }
125
+
126
+ MultiSigInput.prototype.countMissingSignatures = function () {
127
+ return this.threshold - this.countSignatures()
128
+ }
129
+
130
+ MultiSigInput.prototype.countSignatures = function () {
131
+ return _.reduce(this.signatures, function (sum, signature) {
132
+ return sum + (!!signature)
133
+ }, 0)
134
+ }
135
+
136
+ MultiSigInput.prototype.publicKeysWithoutSignature = function () {
137
+ var self = this
138
+ return _.filter(this.publicKeys, function (publicKey) {
139
+ return !(self.signatures[self.publicKeyIndex[publicKey.toString()]])
140
+ })
141
+ }
142
+
143
+ MultiSigInput.prototype.isValidSignature = function (transaction, signature) {
144
+ // FIXME: Refactor signature so this is not necessary
145
+ signature.signature.nhashtype = signature.sigtype
146
+ return Sighash.verify(
147
+ transaction,
148
+ signature.signature,
149
+ signature.publicKey,
150
+ signature.inputIndex,
151
+ this.output.script,
152
+ this.output.satoshisBN
153
+ )
154
+ }
155
+
156
+ /**
157
+ *
158
+ * @param {Buffer[]} signatures
159
+ * @param {PublicKey[]} publicKeys
160
+ * @param {Transaction} transaction
161
+ * @param {Integer} inputIndex
162
+ * @param {Input} input
163
+ * @returns {TransactionSignature[]}
164
+ */
165
+ MultiSigInput.normalizeSignatures = function (transaction, input, inputIndex, signatures, publicKeys) {
166
+ return publicKeys.map(function (pubKey) {
167
+ var signatureMatch = null
168
+ signatures = signatures.filter(function (signatureBuffer) {
169
+ if (signatureMatch) {
170
+ return true
171
+ }
172
+
173
+ var signature = new TransactionSignature({
174
+ signature: Signature.fromTxFormat(signatureBuffer),
175
+ publicKey: pubKey,
176
+ prevTxId: input.prevTxId,
177
+ outputIndex: input.outputIndex,
178
+ inputIndex: inputIndex,
179
+ sigtype: Signature.SIGHASH_ALL
180
+ })
181
+
182
+ signature.signature.nhashtype = signature.sigtype
183
+ var isMatch = Sighash.verify(
184
+ transaction,
185
+ signature.signature,
186
+ signature.publicKey,
187
+ signature.inputIndex,
188
+ input.output.script
189
+ )
190
+
191
+ if (isMatch) {
192
+ signatureMatch = signature
193
+ return false
194
+ }
195
+
196
+ return true
197
+ })
198
+
199
+ return signatureMatch || null
200
+ })
201
+ }
202
+
203
+ // 32 txid
204
+ // 4 output index
205
+ // --- script ---
206
+ // ??? script size (VARINT)
207
+ // 1 OP_0
208
+ // --- signature list ---
209
+ // 1 signature size (OP_PUSHDATA)
210
+ // <=72 signature (DER + SIGHASH type)
211
+ //
212
+ // 4 sequence number
213
+ MultiSigInput.SIGNATURE_SIZE = 73
214
+
215
+ MultiSigInput.prototype._estimateSize = function () {
216
+ var scriptSize = 1 + this.threshold * MultiSigInput.SIGNATURE_SIZE
217
+ return Input.BASE_SIZE + Varint(scriptSize).toBuffer().length + scriptSize
218
+ }
219
+
220
+ module.exports = MultiSigInput
@@ -0,0 +1,189 @@
1
+ 'use strict'
2
+
3
+ var _ = require('../../util/_')
4
+ var inherits = require('inherits')
5
+ var Input = require('./input')
6
+ var Output = require('../output')
7
+ var $ = require('../../util/preconditions')
8
+
9
+ var Script = require('../../script')
10
+ var Signature = require('../../crypto/signature')
11
+ var Sighash = require('../sighash')
12
+ var TransactionSignature = require('../signature')
13
+ var PublicKey = require('../../publickey')
14
+ var Varint = require('../../encoding/varint')
15
+
16
+ /**
17
+ * @constructor
18
+ */
19
+ function MultiSigScriptHashInput (input, pubkeys, threshold, signatures) {
20
+ Input.apply(this, arguments)
21
+ var self = this
22
+ pubkeys = pubkeys || input.publicKeys
23
+ threshold = threshold || input.threshold
24
+ signatures = signatures || input.signatures
25
+ this.publicKeys = pubkeys.map(k => k.toString('hex')).sort().map(k => new PublicKey(k))
26
+ this.redeemScript = Script.buildMultisigOut(this.publicKeys, threshold)
27
+ $.checkState(Script.buildScriptHashOut(this.redeemScript).equals(this.output.script),
28
+ 'Provided public keys don\'t hash to the provided output')
29
+ this.publicKeyIndex = {}
30
+ _.each(this.publicKeys, function (publicKey, index) {
31
+ self.publicKeyIndex[publicKey.toString()] = index
32
+ })
33
+ this.threshold = threshold
34
+ // Empty array of signatures
35
+ this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length)
36
+ }
37
+ inherits(MultiSigScriptHashInput, Input)
38
+
39
+ MultiSigScriptHashInput.prototype.toObject = function () {
40
+ var obj = Input.prototype.toObject.apply(this, arguments)
41
+ obj.threshold = this.threshold
42
+ obj.publicKeys = _.map(this.publicKeys, function (publicKey) { return publicKey.toString() })
43
+ obj.signatures = this._serializeSignatures()
44
+ return obj
45
+ }
46
+
47
+ MultiSigScriptHashInput.prototype._deserializeSignatures = function (signatures) {
48
+ return _.map(signatures, function (signature) {
49
+ if (!signature) {
50
+ return undefined
51
+ }
52
+ return new TransactionSignature(signature)
53
+ })
54
+ }
55
+
56
+ MultiSigScriptHashInput.prototype._serializeSignatures = function () {
57
+ return _.map(this.signatures, function (signature) {
58
+ if (!signature) {
59
+ return undefined
60
+ }
61
+ return signature.toObject()
62
+ })
63
+ }
64
+
65
+ MultiSigScriptHashInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype) {
66
+ $.checkState(this.output instanceof Output)
67
+ sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID)
68
+
69
+ var self = this
70
+ var results = []
71
+ _.each(this.publicKeys, function (publicKey) {
72
+ if (publicKey.toString() === privateKey.publicKey.toString()) {
73
+ results.push(new TransactionSignature({
74
+ publicKey: privateKey.publicKey,
75
+ prevTxId: self.prevTxId,
76
+ outputIndex: self.outputIndex,
77
+ inputIndex: index,
78
+ signature: Sighash.sign(transaction, privateKey, sigtype, index, self.redeemScript, self.output.satoshisBN),
79
+ sigtype: sigtype
80
+ }))
81
+ }
82
+ })
83
+ return results
84
+ }
85
+
86
+ MultiSigScriptHashInput.prototype.addSignature = function (transaction, signature) {
87
+ $.checkState(!this.isFullySigned(), 'All needed signatures have already been added')
88
+ $.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()]),
89
+ 'Signature has no matching public key')
90
+ $.checkState(this.isValidSignature(transaction, signature))
91
+ this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature
92
+ this._updateScript()
93
+ return this
94
+ }
95
+
96
+ MultiSigScriptHashInput.prototype._updateScript = function () {
97
+ this.setScript(Script.buildP2SHMultisigIn(
98
+ this.publicKeys,
99
+ this.threshold,
100
+ this._createSignatures(),
101
+ { cachedMultisig: this.redeemScript }
102
+ ))
103
+ return this
104
+ }
105
+
106
+ MultiSigScriptHashInput.prototype._createSignatures = function () {
107
+ return _.map(
108
+ _.filter(this.signatures, function (signature) { return !_.isUndefined(signature) }),
109
+ function (signature) {
110
+ return Buffer.concat([
111
+ signature.signature.toDER(),
112
+ Buffer.from([signature.sigtype & 0xff])
113
+ ])
114
+ }
115
+ )
116
+ }
117
+
118
+ MultiSigScriptHashInput.prototype.clearSignatures = function () {
119
+ this.signatures = new Array(this.publicKeys.length)
120
+ this._updateScript()
121
+ }
122
+
123
+ MultiSigScriptHashInput.prototype.isFullySigned = function () {
124
+ return this.countSignatures() === this.threshold
125
+ }
126
+
127
+ MultiSigScriptHashInput.prototype.countMissingSignatures = function () {
128
+ return this.threshold - this.countSignatures()
129
+ }
130
+
131
+ MultiSigScriptHashInput.prototype.countSignatures = function () {
132
+ return _.reduce(this.signatures, function (sum, signature) {
133
+ return sum + (!!signature)
134
+ }, 0)
135
+ }
136
+
137
+ MultiSigScriptHashInput.prototype.publicKeysWithoutSignature = function () {
138
+ var self = this
139
+ return _.filter(this.publicKeys, function (publicKey) {
140
+ return !(self.signatures[self.publicKeyIndex[publicKey.toString()]])
141
+ })
142
+ }
143
+
144
+ MultiSigScriptHashInput.prototype.isValidSignature = function (transaction, signature) {
145
+ // FIXME: Refactor signature so this is not necessary
146
+ signature.signature.nhashtype = signature.sigtype
147
+ return Sighash.verify(
148
+ transaction,
149
+ signature.signature,
150
+ signature.publicKey,
151
+ signature.inputIndex,
152
+ this.redeemScript,
153
+ this.output.satoshisBN
154
+ )
155
+ }
156
+
157
+ // 32 txid
158
+ // 4 output index
159
+ // --- script ---
160
+ // ??? script size (VARINT)
161
+ // 1 OP_0
162
+ // --- signature list ---
163
+ // 1 signature size (OP_PUSHDATA)
164
+ // <=72 signature (DER + SIGHASH type)
165
+ //
166
+ // ??? redeem script size (OP_PUSHDATA)
167
+ // --- redeem script ---
168
+ // 1 OP_2
169
+ // --- public key list ---
170
+ // 1 public key size (OP_PUSHDATA)
171
+ // 33 compressed public key
172
+ //
173
+ // 1 OP_3
174
+ // 1 OP_CHECKMULTISIG
175
+ //
176
+ // 4 sequence number
177
+ MultiSigScriptHashInput.SIGNATURE_SIZE = 73
178
+ MultiSigScriptHashInput.PUBKEY_SIZE = 34
179
+
180
+ MultiSigScriptHashInput.prototype._estimateSize = function () {
181
+ var pubKeysSize = this.publicKeys.length * MultiSigScriptHashInput.PUBKEY_SIZE
182
+ var sigsSize = this.threshold * MultiSigScriptHashInput.SIGNATURE_SIZE
183
+ var redeemScriptSize = 3 + pubKeysSize
184
+ var redeemScriptPushdataSize = redeemScriptSize <= 75 ? 1 : redeemScriptSize <= 255 ? 2 : 3
185
+ var scriptLength = sigsSize + 1 + redeemScriptPushdataSize + redeemScriptSize
186
+ return Input.BASE_SIZE + Varint(scriptLength).toBuffer().length + scriptLength
187
+ }
188
+
189
+ module.exports = MultiSigScriptHashInput