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,96 @@
1
+ 'use strict'
2
+
3
+ var inherits = require('inherits')
4
+
5
+ var $ = require('../../util/preconditions')
6
+
7
+ var Input = require('./input')
8
+ var Output = require('../output')
9
+ var Sighash = require('../sighash')
10
+ var Script = require('../../script')
11
+ var Signature = require('../../crypto/signature')
12
+ var TransactionSignature = require('../signature')
13
+
14
+ /**
15
+ * Represents a special kind of input of PayToPublicKey kind.
16
+ * @constructor
17
+ */
18
+ function PublicKeyInput () {
19
+ Input.apply(this, arguments)
20
+ }
21
+ inherits(PublicKeyInput, Input)
22
+
23
+ /**
24
+ * @param {Transaction} transaction - the transaction to be signed
25
+ * @param {PrivateKey} privateKey - the private key with which to sign the transaction
26
+ * @param {number} index - the index of the input in the transaction input vector
27
+ * @param {number=} sigtype - the type of signature, defaults to Signature.SIGHASH_ALL
28
+ * @return {Array} of objects that can be
29
+ */
30
+ PublicKeyInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype) {
31
+ $.checkState(this.output instanceof Output)
32
+ sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID)
33
+ var publicKey = privateKey.toPublicKey()
34
+ if (publicKey.toString() === this.output.script.getPublicKey().toString('hex')) {
35
+ return [new TransactionSignature({
36
+ publicKey: publicKey,
37
+ prevTxId: this.prevTxId,
38
+ outputIndex: this.outputIndex,
39
+ inputIndex: index,
40
+ signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script, this.output.satoshisBN),
41
+ sigtype: sigtype
42
+ })]
43
+ }
44
+ return []
45
+ }
46
+
47
+ /**
48
+ * Add the provided signature
49
+ *
50
+ * @param {Object} signature
51
+ * @param {PublicKey} signature.publicKey
52
+ * @param {Signature} signature.signature
53
+ * @param {number=} signature.sigtype
54
+ * @return {PublicKeyInput} this, for chaining
55
+ */
56
+ PublicKeyInput.prototype.addSignature = function (transaction, signature) {
57
+ $.checkState(this.isValidSignature(transaction, signature), 'Signature is invalid')
58
+ this.setScript(Script.buildPublicKeyIn(
59
+ signature.signature.toDER(),
60
+ signature.sigtype
61
+ ))
62
+ return this
63
+ }
64
+
65
+ /**
66
+ * Clear the input's signature
67
+ * @return {PublicKeyHashInput} this, for chaining
68
+ */
69
+ PublicKeyInput.prototype.clearSignatures = function () {
70
+ this.setScript(Script.empty())
71
+ return this
72
+ }
73
+
74
+ /**
75
+ * Query whether the input is signed
76
+ * @return {boolean}
77
+ */
78
+ PublicKeyInput.prototype.isFullySigned = function () {
79
+ return this.script.isPublicKeyIn()
80
+ }
81
+
82
+ // 32 txid
83
+ // 4 output index
84
+ // ---
85
+ // 1 script size (VARINT)
86
+ // 1 signature size (OP_PUSHDATA)
87
+ // <=72 signature (DER + SIGHASH type)
88
+ // ---
89
+ // 4 sequence number
90
+ PublicKeyInput.SCRIPT_MAX_SIZE = 74
91
+
92
+ PublicKeyInput.prototype._estimateSize = function () {
93
+ return Input.BASE_SIZE + PublicKeyInput.SCRIPT_MAX_SIZE
94
+ }
95
+
96
+ module.exports = PublicKeyInput
@@ -0,0 +1,103 @@
1
+ 'use strict'
2
+
3
+ var inherits = require('inherits')
4
+
5
+ var $ = require('../../util/preconditions')
6
+
7
+ var Hash = require('../../crypto/hash')
8
+ var Input = require('./input')
9
+ var Output = require('../output')
10
+ var Sighash = require('../sighash')
11
+ var Script = require('../../script')
12
+ var Signature = require('../../crypto/signature')
13
+ var TransactionSignature = require('../signature')
14
+
15
+ /**
16
+ * Represents a special kind of input of PayToPublicKeyHash kind.
17
+ * @constructor
18
+ */
19
+ function PublicKeyHashInput () {
20
+ Input.apply(this, arguments)
21
+ }
22
+ inherits(PublicKeyHashInput, Input)
23
+
24
+ /**
25
+ * @param {Transaction} transaction - the transaction to be signed
26
+ * @param {PrivateKey} privateKey - the private key with which to sign the transaction
27
+ * @param {number} index - the index of the input in the transaction input vector
28
+ * @param {number=} sigtype - the type of signature, defaults to Signature.SIGHASH_ALL
29
+ * @param {Buffer=} hashData - the precalculated hash of the public key associated with the privateKey provided
30
+ * @return {Array} of objects that can be
31
+ */
32
+ PublicKeyHashInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype, hashData) {
33
+ $.checkState(this.output instanceof Output)
34
+ hashData = hashData || Hash.sha256ripemd160(privateKey.publicKey.toBuffer())
35
+ sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID)
36
+
37
+ if (hashData.equals(this.output.script.getPublicKeyHash())) {
38
+ return [new TransactionSignature({
39
+ publicKey: privateKey.publicKey,
40
+ prevTxId: this.prevTxId,
41
+ outputIndex: this.outputIndex,
42
+ inputIndex: index,
43
+ signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script, this.output.satoshisBN),
44
+ sigtype: sigtype
45
+ })]
46
+ }
47
+ return []
48
+ }
49
+
50
+ /**
51
+ * Add the provided signature
52
+ *
53
+ * @param {Object} signature
54
+ * @param {PublicKey} signature.publicKey
55
+ * @param {Signature} signature.signature
56
+ * @param {number=} signature.sigtype
57
+ * @return {PublicKeyHashInput} this, for chaining
58
+ */
59
+ PublicKeyHashInput.prototype.addSignature = function (transaction, signature) {
60
+ $.checkState(this.isValidSignature(transaction, signature), 'Signature is invalid')
61
+
62
+ this.setScript(Script.buildPublicKeyHashIn(
63
+ signature.publicKey,
64
+ signature.signature.toDER(),
65
+ signature.sigtype
66
+ ))
67
+ return this
68
+ }
69
+
70
+ /**
71
+ * Clear the input's signature
72
+ * @return {PublicKeyHashInput} this, for chaining
73
+ */
74
+ PublicKeyHashInput.prototype.clearSignatures = function () {
75
+ this.setScript(Script.empty())
76
+ return this
77
+ }
78
+
79
+ /**
80
+ * Query whether the input is signed
81
+ * @return {boolean}
82
+ */
83
+ PublicKeyHashInput.prototype.isFullySigned = function () {
84
+ return this.script.isPublicKeyHashIn()
85
+ }
86
+
87
+ // 32 txid
88
+ // 4 output index
89
+ // --- script ---
90
+ // 1 script size (VARINT)
91
+ // 1 signature size (OP_PUSHDATA)
92
+ // <=72 signature (DER + SIGHASH type)
93
+ // 1 public key size (OP_PUSHDATA)
94
+ // 33 compressed public key
95
+ //
96
+ // 4 sequence number
97
+ PublicKeyHashInput.SCRIPT_MAX_SIZE = 108
98
+
99
+ PublicKeyHashInput.prototype._estimateSize = function () {
100
+ return Input.BASE_SIZE + PublicKeyHashInput.SCRIPT_MAX_SIZE
101
+ }
102
+
103
+ module.exports = PublicKeyHashInput
@@ -0,0 +1,192 @@
1
+ 'use strict'
2
+
3
+ var _ = require('../util/_')
4
+ var BN = require('../crypto/bn')
5
+ var buffer = require('buffer')
6
+ var JSUtil = require('../util/js')
7
+ var BufferWriter = require('../encoding/bufferwriter')
8
+ var Varint = require('../encoding/varint')
9
+ var Script = require('../script')
10
+ var $ = require('../util/preconditions')
11
+ var errors = require('../errors')
12
+
13
+ var MAX_SAFE_INTEGER = 0x1fffffffffffff
14
+
15
+ function Output (args) {
16
+ if (!(this instanceof Output)) {
17
+ return new Output(args)
18
+ }
19
+ if (_.isObject(args)) {
20
+ this.satoshis = args.satoshis
21
+ if (Buffer.isBuffer(args.script)) {
22
+ this._scriptBuffer = args.script
23
+ } else {
24
+ var script
25
+ if (_.isString(args.script) && JSUtil.isHexa(args.script)) {
26
+ script = buffer.Buffer.from(args.script, 'hex')
27
+ } else {
28
+ script = args.script
29
+ }
30
+ this.setScript(script)
31
+ }
32
+ } else {
33
+ throw new TypeError('Unrecognized argument for Output')
34
+ }
35
+ }
36
+
37
+ Object.defineProperty(Output.prototype, 'script', {
38
+ configurable: false,
39
+ enumerable: true,
40
+ get: function () {
41
+ if (this._script) {
42
+ return this._script
43
+ } else {
44
+ this.setScriptFromBuffer(this._scriptBuffer)
45
+ return this._script
46
+ }
47
+ }
48
+ })
49
+
50
+ Object.defineProperty(Output.prototype, 'satoshis', {
51
+ configurable: false,
52
+ enumerable: true,
53
+ get: function () {
54
+ return this._satoshis
55
+ },
56
+ set: function (num) {
57
+ if (num instanceof BN) {
58
+ this._satoshisBN = num
59
+ this._satoshis = num.toNumber()
60
+ } else if (_.isString(num)) {
61
+ this._satoshis = parseInt(num)
62
+ this._satoshisBN = BN.fromNumber(this._satoshis)
63
+ } else {
64
+ $.checkArgument(
65
+ JSUtil.isNaturalNumber(num),
66
+ 'Output satoshis is not a natural number'
67
+ )
68
+ this._satoshisBN = BN.fromNumber(num)
69
+ this._satoshis = num
70
+ }
71
+ $.checkState(
72
+ JSUtil.isNaturalNumber(this._satoshis),
73
+ 'Output satoshis is not a natural number'
74
+ )
75
+ }
76
+ })
77
+
78
+ Output.prototype.invalidSatoshis = function () {
79
+ if (this._satoshis > MAX_SAFE_INTEGER) {
80
+ return 'transaction txout satoshis greater than max safe integer'
81
+ }
82
+ if (this._satoshis !== this._satoshisBN.toNumber()) {
83
+ return 'transaction txout satoshis has corrupted value'
84
+ }
85
+ if (this._satoshis < 0) {
86
+ return 'transaction txout negative'
87
+ }
88
+ return false
89
+ }
90
+
91
+ Object.defineProperty(Output.prototype, 'satoshisBN', {
92
+ configurable: false,
93
+ enumerable: true,
94
+ get: function () {
95
+ return this._satoshisBN
96
+ },
97
+ set: function (num) {
98
+ this._satoshisBN = num
99
+ this._satoshis = num.toNumber()
100
+ $.checkState(
101
+ JSUtil.isNaturalNumber(this._satoshis),
102
+ 'Output satoshis is not a natural number'
103
+ )
104
+ }
105
+ })
106
+
107
+ Output.prototype.toObject = Output.prototype.toJSON = function toObject () {
108
+ var obj = {
109
+ satoshis: this.satoshis
110
+ }
111
+ obj.script = this._scriptBuffer.toString('hex')
112
+ return obj
113
+ }
114
+
115
+ Output.fromObject = function (data) {
116
+ return new Output(data)
117
+ }
118
+
119
+ Output.prototype.setScriptFromBuffer = function (buffer) {
120
+ this._scriptBuffer = buffer
121
+ try {
122
+ this._script = Script.fromBuffer(this._scriptBuffer)
123
+ this._script._isOutput = true
124
+ } catch (e) {
125
+ if (e instanceof errors.Script.InvalidBuffer) {
126
+ this._script = null
127
+ } else {
128
+ throw e
129
+ }
130
+ }
131
+ }
132
+
133
+ Output.prototype.setScript = function (script) {
134
+ if (script instanceof Script) {
135
+ this._scriptBuffer = script.toBuffer()
136
+ this._script = script
137
+ this._script._isOutput = true
138
+ } else if (_.isString(script)) {
139
+ this._script = Script.fromString(script)
140
+ this._scriptBuffer = this._script.toBuffer()
141
+ this._script._isOutput = true
142
+ } else if (Buffer.isBuffer(script)) {
143
+ this.setScriptFromBuffer(script)
144
+ } else {
145
+ throw new TypeError('Invalid argument type: script')
146
+ }
147
+ return this
148
+ }
149
+
150
+ Output.prototype.inspect = function () {
151
+ var scriptStr
152
+ if (this.script) {
153
+ scriptStr = this.script.inspect()
154
+ } else {
155
+ scriptStr = this._scriptBuffer.toString('hex')
156
+ }
157
+ return '<Output (' + this.satoshis + ' sats) ' + scriptStr + '>'
158
+ }
159
+
160
+ Output.fromBufferReader = function (br) {
161
+ var obj = {}
162
+ obj.satoshis = br.readUInt64LEBN()
163
+ var size = br.readVarintNum()
164
+ if (size !== 0) {
165
+ obj.script = br.read(size)
166
+ } else {
167
+ obj.script = buffer.Buffer.from([])
168
+ }
169
+ return new Output(obj)
170
+ }
171
+
172
+ Output.prototype.toBufferWriter = function (writer) {
173
+ if (!writer) {
174
+ writer = new BufferWriter()
175
+ }
176
+ writer.writeUInt64LEBN(this._satoshisBN)
177
+ var script = this._scriptBuffer
178
+ writer.writeVarintNum(script.length)
179
+ writer.write(script)
180
+ return writer
181
+ }
182
+
183
+ // 8 value
184
+ // ??? script size (VARINT)
185
+ // ??? script
186
+ Output.prototype.getSize = function () {
187
+ var scriptSize = this.script.toBuffer().length
188
+ var varintSize = Varint(scriptSize).toBuffer().length
189
+ return 8 + varintSize + scriptSize
190
+ }
191
+
192
+ module.exports = Output
@@ -0,0 +1,288 @@
1
+ 'use strict'
2
+
3
+ var buffer = require('buffer')
4
+
5
+ var Signature = require('../crypto/signature')
6
+ var Script = require('../script')
7
+ var Output = require('./output')
8
+ var BufferReader = require('../encoding/bufferreader')
9
+ var BufferWriter = require('../encoding/bufferwriter')
10
+ var BN = require('../crypto/bn')
11
+ var Hash = require('../crypto/hash')
12
+ var ECDSA = require('../crypto/ecdsa')
13
+ var $ = require('../util/preconditions')
14
+ var Interpreter = require('../script/interpreter')
15
+ var _ = require('../util/_')
16
+
17
+ var SIGHASH_SINGLE_BUG = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
18
+ var BITS_64_ON = 'ffffffffffffffff'
19
+
20
+ // By default, we sign with sighash_forkid
21
+ var DEFAULT_SIGN_FLAGS = Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
22
+
23
+ var sighashPreimageForForkId = function (transaction, sighashType, inputNumber, subscript, satoshisBN) {
24
+ var input = transaction.inputs[inputNumber]
25
+ $.checkArgument(
26
+ satoshisBN instanceof BN,
27
+ 'For ForkId=0 signatures, satoshis or complete input must be provided'
28
+ )
29
+
30
+ function GetPrevoutHash (tx) {
31
+ var writer = new BufferWriter()
32
+
33
+ _.each(tx.inputs, function (input) {
34
+ writer.writeReverse(input.prevTxId)
35
+ writer.writeUInt32LE(input.outputIndex)
36
+ })
37
+
38
+ var buf = writer.toBuffer()
39
+ var ret = Hash.sha256sha256(buf)
40
+ return ret
41
+ }
42
+
43
+ function GetSequenceHash (tx) {
44
+ var writer = new BufferWriter()
45
+
46
+ _.each(tx.inputs, function (input) {
47
+ writer.writeUInt32LE(input.sequenceNumber)
48
+ })
49
+
50
+ var buf = writer.toBuffer()
51
+ var ret = Hash.sha256sha256(buf)
52
+ return ret
53
+ }
54
+
55
+ function GetOutputsHash (tx, n) {
56
+ var writer = new BufferWriter()
57
+
58
+ if (_.isUndefined(n)) {
59
+ _.each(tx.outputs, function (output) {
60
+ output.toBufferWriter(writer)
61
+ })
62
+ } else {
63
+ tx.outputs[n].toBufferWriter(writer)
64
+ }
65
+
66
+ var buf = writer.toBuffer()
67
+ var ret = Hash.sha256sha256(buf)
68
+ return ret
69
+ }
70
+
71
+ var hashPrevouts = Buffer.alloc(32)
72
+ var hashSequence = Buffer.alloc(32)
73
+ var hashOutputs = Buffer.alloc(32)
74
+
75
+ if (!(sighashType & Signature.SIGHASH_ANYONECANPAY)) {
76
+ hashPrevouts = GetPrevoutHash(transaction)
77
+ }
78
+
79
+ if (!(sighashType & Signature.SIGHASH_ANYONECANPAY) &&
80
+ (sighashType & 31) !== Signature.SIGHASH_SINGLE &&
81
+ (sighashType & 31) !== Signature.SIGHASH_NONE) {
82
+ hashSequence = GetSequenceHash(transaction)
83
+ }
84
+
85
+ if ((sighashType & 31) !== Signature.SIGHASH_SINGLE && (sighashType & 31) !== Signature.SIGHASH_NONE) {
86
+ hashOutputs = GetOutputsHash(transaction)
87
+ } else if ((sighashType & 31) === Signature.SIGHASH_SINGLE && inputNumber < transaction.outputs.length) {
88
+ hashOutputs = GetOutputsHash(transaction, inputNumber)
89
+ }
90
+
91
+ var writer = new BufferWriter()
92
+
93
+ // Version
94
+ writer.writeInt32LE(transaction.version)
95
+
96
+ // Input prevouts/nSequence (none/all, depending on flags)
97
+ writer.write(hashPrevouts)
98
+ writer.write(hashSequence)
99
+
100
+ // outpoint (32-byte hash + 4-byte little endian)
101
+ writer.writeReverse(input.prevTxId)
102
+ writer.writeUInt32LE(input.outputIndex)
103
+
104
+ // scriptCode of the input (serialized as scripts inside CTxOuts)
105
+ writer.writeVarintNum(subscript.toBuffer().length)
106
+ writer.write(subscript.toBuffer())
107
+
108
+ // value of the output spent by this input (8-byte little endian)
109
+ writer.writeUInt64LEBN(satoshisBN)
110
+
111
+ // nSequence of the input (4-byte little endian)
112
+ var sequenceNumber = input.sequenceNumber
113
+ writer.writeUInt32LE(sequenceNumber)
114
+
115
+ // Outputs (none/one/all, depending on flags)
116
+ writer.write(hashOutputs)
117
+
118
+ // Locktime
119
+ writer.writeUInt32LE(transaction.nLockTime)
120
+
121
+ // sighashType
122
+ writer.writeUInt32LE(sighashType >>> 0)
123
+
124
+ var buf = writer.toBuffer()
125
+ return buf
126
+ }
127
+
128
+ /**
129
+ * Returns a buffer with the which is hashed with sighash that needs to be signed
130
+ * for OP_CHECKSIG.
131
+ *
132
+ * @name Signing.sighash
133
+ * @param {Transaction} transaction the transaction to sign
134
+ * @param {number} sighashType the type of the hash
135
+ * @param {number} inputNumber the input index for the signature
136
+ * @param {Script} subscript the script that will be signed
137
+ * @param {satoshisBN} input's amount (for ForkId signatures)
138
+ *
139
+ */
140
+ var sighashPreimage = function sighashPreimage (transaction, sighashType, inputNumber, subscript, satoshisBN, flags) {
141
+ var Transaction = require('./transaction')
142
+ var Input = require('./input')
143
+
144
+ if (_.isUndefined(flags)) {
145
+ flags = DEFAULT_SIGN_FLAGS
146
+ }
147
+
148
+ // Copy transaction
149
+ var txcopy = Transaction.shallowCopy(transaction)
150
+
151
+ // Copy script
152
+ subscript = new Script(subscript)
153
+
154
+ if (flags & Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION) {
155
+ // Legacy chain's value for fork id must be of the form 0xffxxxx.
156
+ // By xoring with 0xdead, we ensure that the value will be different
157
+ // from the original one, even if it already starts with 0xff.
158
+ var forkValue = sighashType >> 8
159
+ var newForkValue = 0xff0000 | (forkValue ^ 0xdead)
160
+ sighashType = (newForkValue << 8) | (sighashType & 0xff)
161
+ }
162
+
163
+ if ((sighashType & Signature.SIGHASH_FORKID) && (flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID)) {
164
+ return sighashPreimageForForkId(txcopy, sighashType, inputNumber, subscript, satoshisBN)
165
+ }
166
+
167
+ // For no ForkId sighash, separators need to be removed.
168
+ subscript.removeCodeseparators()
169
+
170
+ var i
171
+
172
+ for (i = 0; i < txcopy.inputs.length; i++) {
173
+ // Blank signatures for other inputs
174
+ txcopy.inputs[i] = new Input(txcopy.inputs[i]).setScript(Script.empty())
175
+ }
176
+
177
+ txcopy.inputs[inputNumber] = new Input(txcopy.inputs[inputNumber]).setScript(subscript)
178
+
179
+ if ((sighashType & 31) === Signature.SIGHASH_NONE ||
180
+ (sighashType & 31) === Signature.SIGHASH_SINGLE) {
181
+ // clear all sequenceNumbers
182
+ for (i = 0; i < txcopy.inputs.length; i++) {
183
+ if (i !== inputNumber) {
184
+ txcopy.inputs[i].sequenceNumber = 0
185
+ }
186
+ }
187
+ }
188
+
189
+ if ((sighashType & 31) === Signature.SIGHASH_NONE) {
190
+ txcopy.outputs = []
191
+ } else if ((sighashType & 31) === Signature.SIGHASH_SINGLE) {
192
+ // The SIGHASH_SINGLE bug.
193
+ // https://bitcointalk.org/index.php?topic=260595.0
194
+ if (inputNumber >= txcopy.outputs.length) {
195
+ return SIGHASH_SINGLE_BUG
196
+ }
197
+
198
+ txcopy.outputs.length = inputNumber + 1
199
+
200
+ for (i = 0; i < inputNumber; i++) {
201
+ txcopy.outputs[i] = new Output({
202
+ satoshis: BN.fromBuffer(buffer.Buffer.from(BITS_64_ON, 'hex')),
203
+ script: Script.empty()
204
+ })
205
+ }
206
+ }
207
+
208
+ if (sighashType & Signature.SIGHASH_ANYONECANPAY) {
209
+ txcopy.inputs = [txcopy.inputs[inputNumber]]
210
+ }
211
+
212
+ var buf = new BufferWriter()
213
+ .write(txcopy.toBuffer())
214
+ .writeInt32LE(sighashType)
215
+ .toBuffer()
216
+ return buf
217
+ }
218
+
219
+ /**
220
+ * Returns a buffer of length 32 bytes with the hash that needs to be signed
221
+ * for OP_CHECKSIG.
222
+ *
223
+ * @name Signing.sighash
224
+ * @param {Transaction} transaction the transaction to sign
225
+ * @param {number} sighashType the type of the hash
226
+ * @param {number} inputNumber the input index for the signature
227
+ * @param {Script} subscript the script that will be signed
228
+ * @param {satoshisBN} input's amount (for ForkId signatures)
229
+ *
230
+ */
231
+ var sighash = function sighash (transaction, sighashType, inputNumber, subscript, satoshisBN, flags) {
232
+ var preimage = sighashPreimage(transaction, sighashType, inputNumber, subscript, satoshisBN, flags)
233
+ if (preimage.compare(SIGHASH_SINGLE_BUG) === 0) return preimage
234
+ var ret = Hash.sha256sha256(preimage)
235
+ ret = new BufferReader(ret).readReverse()
236
+ return ret
237
+ }
238
+
239
+ /**
240
+ * Create a signature
241
+ *
242
+ * @name Signing.sign
243
+ * @param {Transaction} transaction
244
+ * @param {PrivateKey} privateKey
245
+ * @param {number} sighash
246
+ * @param {number} inputIndex
247
+ * @param {Script} subscript
248
+ * @param {satoshisBN} input's amount
249
+ * @return {Signature}
250
+ */
251
+ function sign (transaction, privateKey, sighashType, inputIndex, subscript, satoshisBN, flags) {
252
+ var hashbuf = sighash(transaction, sighashType, inputIndex, subscript, satoshisBN, flags)
253
+
254
+ var sig = ECDSA.sign(hashbuf, privateKey, 'little').set({
255
+ nhashtype: sighashType
256
+ })
257
+ return sig
258
+ }
259
+
260
+ /**
261
+ * Verify a signature
262
+ *
263
+ * @name Signing.verify
264
+ * @param {Transaction} transaction
265
+ * @param {Signature} signature
266
+ * @param {PublicKey} publicKey
267
+ * @param {number} inputIndex
268
+ * @param {Script} subscript
269
+ * @param {satoshisBN} input's amount
270
+ * @param {flags} verification flags
271
+ * @return {boolean}
272
+ */
273
+ function verify (transaction, signature, publicKey, inputIndex, subscript, satoshisBN, flags) {
274
+ $.checkArgument(!_.isUndefined(transaction))
275
+ $.checkArgument(!_.isUndefined(signature) && !_.isUndefined(signature.nhashtype))
276
+ var hashbuf = sighash(transaction, signature.nhashtype, inputIndex, subscript, satoshisBN, flags)
277
+ return ECDSA.verify(hashbuf, signature, publicKey, 'little')
278
+ }
279
+
280
+ /**
281
+ * @namespace Signing
282
+ */
283
+ module.exports = {
284
+ sighashPreimage: sighashPreimage,
285
+ sighash: sighash,
286
+ sign: sign,
287
+ verify: verify
288
+ }