@smartledger/bsv 1.5.6-fix1
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.
- package/LICENSE +36 -0
- package/README.md +305 -0
- package/SECURITY.md +75 -0
- package/bsv-ecies.min.js +12 -0
- package/bsv-message.min.js +10 -0
- package/bsv-mnemonic.min.js +12 -0
- package/bsv.d.ts +440 -0
- package/bsv.min.js +37 -0
- package/ecies/index.js +1 -0
- package/index.js +101 -0
- package/lib/address.js +526 -0
- package/lib/block/block.js +277 -0
- package/lib/block/blockheader.js +294 -0
- package/lib/block/index.js +4 -0
- package/lib/block/merkleblock.js +316 -0
- package/lib/crypto/bn.js +278 -0
- package/lib/crypto/ecdsa.js +330 -0
- package/lib/crypto/elliptic-fixed.js +74 -0
- package/lib/crypto/hash.browser.js +171 -0
- package/lib/crypto/hash.js +2 -0
- package/lib/crypto/hash.node.js +171 -0
- package/lib/crypto/point.js +217 -0
- package/lib/crypto/random.js +37 -0
- package/lib/crypto/signature.js +410 -0
- package/lib/crypto/smartledger_verify.js +109 -0
- package/lib/ecies/bitcore-ecies.js +163 -0
- package/lib/ecies/electrum-ecies.js +175 -0
- package/lib/ecies/errors.js +16 -0
- package/lib/ecies/index.js +1 -0
- package/lib/encoding/base58.js +108 -0
- package/lib/encoding/base58check.js +112 -0
- package/lib/encoding/bufferreader.js +200 -0
- package/lib/encoding/bufferwriter.js +150 -0
- package/lib/encoding/varint.js +71 -0
- package/lib/errors/index.js +57 -0
- package/lib/errors/spec.js +184 -0
- package/lib/hdprivatekey.js +655 -0
- package/lib/hdpublickey.js +509 -0
- package/lib/message/index.js +4 -0
- package/lib/message/message.js +181 -0
- package/lib/mnemonic/errors.js +18 -0
- package/lib/mnemonic/index.js +4 -0
- package/lib/mnemonic/mnemonic.js +304 -0
- package/lib/mnemonic/pbkdf2.js +68 -0
- package/lib/mnemonic/words/chinese.js +5 -0
- package/lib/mnemonic/words/english.js +5 -0
- package/lib/mnemonic/words/french.js +5 -0
- package/lib/mnemonic/words/index.js +8 -0
- package/lib/mnemonic/words/italian.js +5 -0
- package/lib/mnemonic/words/japanese.js +5 -0
- package/lib/mnemonic/words/spanish.js +5 -0
- package/lib/networks.js +392 -0
- package/lib/opcode.js +248 -0
- package/lib/privatekey.js +373 -0
- package/lib/publickey.js +387 -0
- package/lib/script/index.js +3 -0
- package/lib/script/interpreter.js +1807 -0
- package/lib/script/script.js +1153 -0
- package/lib/transaction/index.js +7 -0
- package/lib/transaction/input/index.js +6 -0
- package/lib/transaction/input/input.js +202 -0
- package/lib/transaction/input/multisig.js +220 -0
- package/lib/transaction/input/multisigscripthash.js +189 -0
- package/lib/transaction/input/publickey.js +96 -0
- package/lib/transaction/input/publickeyhash.js +103 -0
- package/lib/transaction/output.js +192 -0
- package/lib/transaction/sighash.js +288 -0
- package/lib/transaction/signature.js +88 -0
- package/lib/transaction/transaction.js +1208 -0
- package/lib/transaction/unspentoutput.js +97 -0
- package/lib/util/_.js +44 -0
- package/lib/util/js.js +91 -0
- package/lib/util/preconditions.js +34 -0
- package/message/index.js +1 -0
- package/mnemonic/index.js +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var _ = require('../util/_')
|
|
4
|
+
var BlockHeader = require('./blockheader')
|
|
5
|
+
var BufferReader = require('../encoding/bufferreader')
|
|
6
|
+
var BufferWriter = require('../encoding/bufferwriter')
|
|
7
|
+
var Hash = require('../crypto/hash')
|
|
8
|
+
var Transaction = require('../transaction')
|
|
9
|
+
var errors = require('../errors')
|
|
10
|
+
var $ = require('../util/preconditions')
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Instantiate a MerkleBlock from a Buffer, JSON object, or Object with
|
|
14
|
+
* the properties of the Block
|
|
15
|
+
*
|
|
16
|
+
* @param {*} - A Buffer, JSON string, or Object representing a MerkleBlock
|
|
17
|
+
* @returns {MerkleBlock}
|
|
18
|
+
* @constructor
|
|
19
|
+
*/
|
|
20
|
+
function MerkleBlock (arg) {
|
|
21
|
+
if (!(this instanceof MerkleBlock)) {
|
|
22
|
+
return new MerkleBlock(arg)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var info = {}
|
|
26
|
+
if (Buffer.isBuffer(arg)) {
|
|
27
|
+
info = MerkleBlock._fromBufferReader(BufferReader(arg))
|
|
28
|
+
} else if (_.isObject(arg)) {
|
|
29
|
+
var header
|
|
30
|
+
if (arg.header instanceof BlockHeader) {
|
|
31
|
+
header = arg.header
|
|
32
|
+
} else {
|
|
33
|
+
header = BlockHeader.fromObject(arg.header)
|
|
34
|
+
}
|
|
35
|
+
info = {
|
|
36
|
+
/**
|
|
37
|
+
* @name MerkleBlock#header
|
|
38
|
+
* @type {BlockHeader}
|
|
39
|
+
*/
|
|
40
|
+
header: header,
|
|
41
|
+
/**
|
|
42
|
+
* @name MerkleBlock#numTransactions
|
|
43
|
+
* @type {Number}
|
|
44
|
+
*/
|
|
45
|
+
numTransactions: arg.numTransactions,
|
|
46
|
+
/**
|
|
47
|
+
* @name MerkleBlock#hashes
|
|
48
|
+
* @type {String[]}
|
|
49
|
+
*/
|
|
50
|
+
hashes: arg.hashes,
|
|
51
|
+
/**
|
|
52
|
+
* @name MerkleBlock#flags
|
|
53
|
+
* @type {Number[]}
|
|
54
|
+
*/
|
|
55
|
+
flags: arg.flags
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
throw new TypeError('Unrecognized argument for MerkleBlock')
|
|
59
|
+
}
|
|
60
|
+
_.extend(this, info)
|
|
61
|
+
this._flagBitsUsed = 0
|
|
62
|
+
this._hashesUsed = 0
|
|
63
|
+
|
|
64
|
+
return this
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {Buffer} - MerkleBlock data in a Buffer object
|
|
69
|
+
* @returns {MerkleBlock} - A MerkleBlock object
|
|
70
|
+
*/
|
|
71
|
+
MerkleBlock.fromBuffer = function fromBuffer (buf) {
|
|
72
|
+
return MerkleBlock.fromBufferReader(BufferReader(buf))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {BufferReader} - MerkleBlock data in a BufferReader object
|
|
77
|
+
* @returns {MerkleBlock} - A MerkleBlock object
|
|
78
|
+
*/
|
|
79
|
+
MerkleBlock.fromBufferReader = function fromBufferReader (br) {
|
|
80
|
+
return new MerkleBlock(MerkleBlock._fromBufferReader(br))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @returns {Buffer} - A buffer of the block
|
|
85
|
+
*/
|
|
86
|
+
MerkleBlock.prototype.toBuffer = function toBuffer () {
|
|
87
|
+
return this.toBufferWriter().concat()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param {BufferWriter} - An existing instance of BufferWriter
|
|
92
|
+
* @returns {BufferWriter} - An instance of BufferWriter representation of the MerkleBlock
|
|
93
|
+
*/
|
|
94
|
+
MerkleBlock.prototype.toBufferWriter = function toBufferWriter (bw) {
|
|
95
|
+
if (!bw) {
|
|
96
|
+
bw = new BufferWriter()
|
|
97
|
+
}
|
|
98
|
+
bw.write(this.header.toBuffer())
|
|
99
|
+
bw.writeUInt32LE(this.numTransactions)
|
|
100
|
+
bw.writeVarintNum(this.hashes.length)
|
|
101
|
+
for (var i = 0; i < this.hashes.length; i++) {
|
|
102
|
+
bw.write(Buffer.from(this.hashes[i], 'hex'))
|
|
103
|
+
}
|
|
104
|
+
bw.writeVarintNum(this.flags.length)
|
|
105
|
+
for (i = 0; i < this.flags.length; i++) {
|
|
106
|
+
bw.writeUInt8(this.flags[i])
|
|
107
|
+
}
|
|
108
|
+
return bw
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @returns {Object} - A plain object with the MerkleBlock properties
|
|
113
|
+
*/
|
|
114
|
+
MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObject () {
|
|
115
|
+
return {
|
|
116
|
+
header: this.header.toObject(),
|
|
117
|
+
numTransactions: this.numTransactions,
|
|
118
|
+
hashes: this.hashes,
|
|
119
|
+
flags: this.flags
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Verify that the MerkleBlock is valid
|
|
125
|
+
* @returns {Boolean} - True/False whether this MerkleBlock is Valid
|
|
126
|
+
*/
|
|
127
|
+
MerkleBlock.prototype.validMerkleTree = function validMerkleTree () {
|
|
128
|
+
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array')
|
|
129
|
+
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array')
|
|
130
|
+
|
|
131
|
+
// Can't have more hashes than numTransactions
|
|
132
|
+
if (this.hashes.length > this.numTransactions) {
|
|
133
|
+
return false
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Can't have more flag bits than num hashes
|
|
137
|
+
if (this.flags.length * 8 < this.hashes.length) {
|
|
138
|
+
return false
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
var height = this._calcTreeHeight()
|
|
142
|
+
var opts = { hashesUsed: 0, flagBitsUsed: 0 }
|
|
143
|
+
var root = this._traverseMerkleTree(height, 0, opts)
|
|
144
|
+
if (opts.hashesUsed !== this.hashes.length) {
|
|
145
|
+
return false
|
|
146
|
+
}
|
|
147
|
+
return root.equals(this.header.merkleRoot)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* WARNING: This method is deprecated. Use filteredTxsHash instead.
|
|
152
|
+
*
|
|
153
|
+
* Return a list of all the txs hash that match the filter
|
|
154
|
+
* @returns {Array} - txs hash that match the filter
|
|
155
|
+
*/
|
|
156
|
+
MerkleBlock.prototype.filterdTxsHash = function filterdTxsHash () {
|
|
157
|
+
throw new Error('filterdTxsHash has been deprecated. use filteredTxsHash.')
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Return a list of all the txs hash that match the filter
|
|
162
|
+
* @returns {Array} - txs hash that match the filter
|
|
163
|
+
*/
|
|
164
|
+
MerkleBlock.prototype.filteredTxsHash = function filteredTxsHash () {
|
|
165
|
+
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array')
|
|
166
|
+
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array')
|
|
167
|
+
|
|
168
|
+
// Can't have more hashes than numTransactions
|
|
169
|
+
if (this.hashes.length > this.numTransactions) {
|
|
170
|
+
throw new errors.MerkleBlock.InvalidMerkleTree()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Can't have more flag bits than num hashes
|
|
174
|
+
if (this.flags.length * 8 < this.hashes.length) {
|
|
175
|
+
throw new errors.MerkleBlock.InvalidMerkleTree()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// If there is only one hash the filter do not match any txs in the block
|
|
179
|
+
if (this.hashes.length === 1) {
|
|
180
|
+
return []
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
var height = this._calcTreeHeight()
|
|
184
|
+
var opts = { hashesUsed: 0, flagBitsUsed: 0 }
|
|
185
|
+
var txs = this._traverseMerkleTree(height, 0, opts, true)
|
|
186
|
+
if (opts.hashesUsed !== this.hashes.length) {
|
|
187
|
+
throw new errors.MerkleBlock.InvalidMerkleTree()
|
|
188
|
+
}
|
|
189
|
+
return txs
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Traverse a the tree in this MerkleBlock, validating it along the way
|
|
194
|
+
* Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
|
|
195
|
+
* @param {Number} - depth - Current height
|
|
196
|
+
* @param {Number} - pos - Current position in the tree
|
|
197
|
+
* @param {Object} - opts - Object with values that need to be mutated throughout the traversal
|
|
198
|
+
* @param {Boolean} - checkForTxs - if true return opts.txs else return the Merkle Hash
|
|
199
|
+
* @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0
|
|
200
|
+
* @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0
|
|
201
|
+
* @param {Array} - opts.txs - Will finish populated by transactions found during traversal that match the filter
|
|
202
|
+
* @returns {Buffer|null} - Buffer containing the Merkle Hash for that height
|
|
203
|
+
* @returns {Array} - transactions found during traversal that match the filter
|
|
204
|
+
* @private
|
|
205
|
+
*/
|
|
206
|
+
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree (depth, pos, opts, checkForTxs) {
|
|
207
|
+
opts = opts || {}
|
|
208
|
+
opts.txs = opts.txs || []
|
|
209
|
+
opts.flagBitsUsed = opts.flagBitsUsed || 0
|
|
210
|
+
opts.hashesUsed = opts.hashesUsed || 0
|
|
211
|
+
checkForTxs = checkForTxs || false
|
|
212
|
+
|
|
213
|
+
if (opts.flagBitsUsed > this.flags.length * 8) {
|
|
214
|
+
return null
|
|
215
|
+
}
|
|
216
|
+
var isParentOfMatch = (this.flags[opts.flagBitsUsed >> 3] >>> (opts.flagBitsUsed++ & 7)) & 1
|
|
217
|
+
if (depth === 0 || !isParentOfMatch) {
|
|
218
|
+
if (opts.hashesUsed >= this.hashes.length) {
|
|
219
|
+
return null
|
|
220
|
+
}
|
|
221
|
+
var hash = this.hashes[opts.hashesUsed++]
|
|
222
|
+
if (depth === 0 && isParentOfMatch) {
|
|
223
|
+
opts.txs.push(hash)
|
|
224
|
+
}
|
|
225
|
+
return Buffer.from(hash, 'hex')
|
|
226
|
+
} else {
|
|
227
|
+
var left = this._traverseMerkleTree(depth - 1, pos * 2, opts)
|
|
228
|
+
var right = left
|
|
229
|
+
if (pos * 2 + 1 < this._calcTreeWidth(depth - 1)) {
|
|
230
|
+
right = this._traverseMerkleTree(depth - 1, pos * 2 + 1, opts)
|
|
231
|
+
}
|
|
232
|
+
if (checkForTxs) {
|
|
233
|
+
return opts.txs
|
|
234
|
+
} else {
|
|
235
|
+
return Hash.sha256sha256(Buffer.concat([left, right]))
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Calculates the width of a merkle tree at a given height.
|
|
241
|
+
* Modeled after Bitcoin Core merkleblock.h CalcTreeWidth()
|
|
242
|
+
* @param {Number} - Height at which we want the tree width
|
|
243
|
+
* @returns {Number} - Width of the tree at a given height
|
|
244
|
+
* @private
|
|
245
|
+
*/
|
|
246
|
+
MerkleBlock.prototype._calcTreeWidth = function calcTreeWidth (height) {
|
|
247
|
+
return (this.numTransactions + (1 << height) - 1) >> height
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Calculates the height of the merkle tree in this MerkleBlock
|
|
251
|
+
* @param {Number} - Height at which we want the tree width
|
|
252
|
+
* @returns {Number} - Height of the merkle tree in this MerkleBlock
|
|
253
|
+
* @private
|
|
254
|
+
*/
|
|
255
|
+
MerkleBlock.prototype._calcTreeHeight = function calcTreeHeight () {
|
|
256
|
+
var height = 0
|
|
257
|
+
while (this._calcTreeWidth(height) > 1) {
|
|
258
|
+
height++
|
|
259
|
+
}
|
|
260
|
+
return height
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* @param {Transaction|String} - Transaction or Transaction ID Hash
|
|
265
|
+
* @returns {Boolean} - return true/false if this MerkleBlock has the TX or not
|
|
266
|
+
* @private
|
|
267
|
+
*/
|
|
268
|
+
MerkleBlock.prototype.hasTransaction = function hasTransaction (tx) {
|
|
269
|
+
$.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined')
|
|
270
|
+
$.checkArgument(tx instanceof Transaction || typeof tx === 'string',
|
|
271
|
+
'Invalid tx given, tx must be a "string" or "Transaction"')
|
|
272
|
+
|
|
273
|
+
var hash = tx
|
|
274
|
+
if (tx instanceof Transaction) {
|
|
275
|
+
// We need to reverse the id hash for the lookup
|
|
276
|
+
hash = Buffer.from(tx.id, 'hex').reverse().toString('hex')
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
var txs = []
|
|
280
|
+
var height = this._calcTreeHeight()
|
|
281
|
+
this._traverseMerkleTree(height, 0, { txs: txs })
|
|
282
|
+
return txs.indexOf(hash) !== -1
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @param {Buffer} - MerkleBlock data
|
|
287
|
+
* @returns {Object} - An Object representing merkleblock data
|
|
288
|
+
* @private
|
|
289
|
+
*/
|
|
290
|
+
MerkleBlock._fromBufferReader = function _fromBufferReader (br) {
|
|
291
|
+
$.checkState(!br.finished(), 'No merkleblock data received')
|
|
292
|
+
var info = {}
|
|
293
|
+
info.header = BlockHeader.fromBufferReader(br)
|
|
294
|
+
info.numTransactions = br.readUInt32LE()
|
|
295
|
+
var numHashes = br.readVarintNum()
|
|
296
|
+
info.hashes = []
|
|
297
|
+
for (var i = 0; i < numHashes; i++) {
|
|
298
|
+
info.hashes.push(br.read(32).toString('hex'))
|
|
299
|
+
}
|
|
300
|
+
var numFlags = br.readVarintNum()
|
|
301
|
+
info.flags = []
|
|
302
|
+
for (i = 0; i < numFlags; i++) {
|
|
303
|
+
info.flags.push(br.readUInt8())
|
|
304
|
+
}
|
|
305
|
+
return info
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* @param {Object} - A plain JavaScript object
|
|
310
|
+
* @returns {Block} - An instance of block
|
|
311
|
+
*/
|
|
312
|
+
MerkleBlock.fromObject = function fromObject (obj) {
|
|
313
|
+
return new MerkleBlock(obj)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
module.exports = MerkleBlock
|
package/lib/crypto/bn.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var BN = require('bn.js')
|
|
4
|
+
var $ = require('../util/preconditions')
|
|
5
|
+
var _ = require('../util/_')
|
|
6
|
+
|
|
7
|
+
var reversebuf = function (buf) {
|
|
8
|
+
var buf2 = Buffer.alloc(buf.length)
|
|
9
|
+
for (var i = 0; i < buf.length; i++) {
|
|
10
|
+
buf2[i] = buf[buf.length - 1 - i]
|
|
11
|
+
}
|
|
12
|
+
return buf2
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
BN.Zero = new BN(0)
|
|
16
|
+
BN.One = new BN(1)
|
|
17
|
+
BN.Minus1 = new BN(-1)
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Convert a number into a big number.
|
|
21
|
+
*
|
|
22
|
+
* @param {number} n Any positive or negative integer.
|
|
23
|
+
*/
|
|
24
|
+
BN.fromNumber = function (n) {
|
|
25
|
+
$.checkArgument(_.isNumber(n))
|
|
26
|
+
return new BN(n)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert a string number into a big number.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} str Any positive or negative integer formatted as a string.
|
|
33
|
+
* @param {number} base The base of the number, defaults to 10.
|
|
34
|
+
*/
|
|
35
|
+
BN.fromString = function (str, base) {
|
|
36
|
+
$.checkArgument(_.isString(str))
|
|
37
|
+
return new BN(str, base)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Convert a buffer (such as a 256 bit binary private key) into a big number.
|
|
42
|
+
* Sometimes these numbers can be formatted either as 'big endian' or 'little
|
|
43
|
+
* endian', and so there is an opts parameter that lets you specify which
|
|
44
|
+
* endianness is specified.
|
|
45
|
+
*
|
|
46
|
+
* @param {Buffer} buf A buffer number, such as a 256 bit hash or key.
|
|
47
|
+
* @param {Object} opts With a property 'endian' that can be either 'big' or 'little'. Defaults big endian (most significant digit first).
|
|
48
|
+
*/
|
|
49
|
+
BN.fromBuffer = function (buf, opts) {
|
|
50
|
+
if (typeof opts !== 'undefined' && opts.endian === 'little') {
|
|
51
|
+
buf = reversebuf(buf)
|
|
52
|
+
}
|
|
53
|
+
var hex = buf.toString('hex')
|
|
54
|
+
var bn = new BN(hex, 16)
|
|
55
|
+
return bn
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Instantiate a BigNumber from a "signed magnitude buffer". (a buffer where the
|
|
60
|
+
* most significant bit represents the sign (0 = positive, 1 = negative)
|
|
61
|
+
*
|
|
62
|
+
* @param {Buffer} buf A buffer number, such as a 256 bit hash or key.
|
|
63
|
+
* @param {Object} opts With a property 'endian' that can be either 'big' or 'little'. Defaults big endian (most significant digit first).
|
|
64
|
+
*/
|
|
65
|
+
BN.fromSM = function (buf, opts) {
|
|
66
|
+
var ret
|
|
67
|
+
if (buf.length === 0) {
|
|
68
|
+
return BN.fromBuffer(Buffer.from([0]))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var endian = 'big'
|
|
72
|
+
if (opts) {
|
|
73
|
+
endian = opts.endian
|
|
74
|
+
}
|
|
75
|
+
if (endian === 'little') {
|
|
76
|
+
buf = reversebuf(buf)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (buf[0] & 0x80) {
|
|
80
|
+
buf[0] = buf[0] & 0x7f
|
|
81
|
+
ret = BN.fromBuffer(buf)
|
|
82
|
+
ret.neg().copy(ret)
|
|
83
|
+
} else {
|
|
84
|
+
ret = BN.fromBuffer(buf)
|
|
85
|
+
}
|
|
86
|
+
return ret
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Convert a big number into a number.
|
|
91
|
+
*/
|
|
92
|
+
BN.prototype.toNumber = function () {
|
|
93
|
+
return parseInt(this.toString(10), 10)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Convert a big number into a buffer. This is somewhat ambiguous, so there is
|
|
98
|
+
* an opts parameter that let's you specify the endianness or the size.
|
|
99
|
+
* opts.endian can be either 'big' or 'little' and opts.size can be any
|
|
100
|
+
* sufficiently large number of bytes. If you always want to create a 32 byte
|
|
101
|
+
* big endian number, then specify opts = { endian: 'big', size: 32 }
|
|
102
|
+
*
|
|
103
|
+
* @param {Object} opts Defaults to { endian: 'big', size: 32 }
|
|
104
|
+
*/
|
|
105
|
+
BN.prototype.toBuffer = function (opts) {
|
|
106
|
+
var buf, hex
|
|
107
|
+
if (opts && opts.size) {
|
|
108
|
+
hex = this.toString(16, 2)
|
|
109
|
+
var natlen = hex.length / 2
|
|
110
|
+
buf = Buffer.from(hex, 'hex')
|
|
111
|
+
|
|
112
|
+
if (natlen === opts.size) {
|
|
113
|
+
// buf = buf
|
|
114
|
+
} else if (natlen > opts.size) {
|
|
115
|
+
buf = BN.trim(buf, natlen)
|
|
116
|
+
} else if (natlen < opts.size) {
|
|
117
|
+
buf = BN.pad(buf, natlen, opts.size)
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
hex = this.toString(16, 2)
|
|
121
|
+
buf = Buffer.from(hex, 'hex')
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (typeof opts !== 'undefined' && opts.endian === 'little') {
|
|
125
|
+
buf = reversebuf(buf)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return buf
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* For big numbers that are either positive or negative, you can convert to
|
|
133
|
+
* "sign magnitude" format whereby the first bit specifies whether the number is
|
|
134
|
+
* positive or negative.
|
|
135
|
+
*/
|
|
136
|
+
BN.prototype.toSMBigEndian = function () {
|
|
137
|
+
var buf
|
|
138
|
+
if (this.cmp(BN.Zero) === -1) {
|
|
139
|
+
buf = this.neg().toBuffer()
|
|
140
|
+
if (buf[0] & 0x80) {
|
|
141
|
+
buf = Buffer.concat([Buffer.from([0x80]), buf])
|
|
142
|
+
} else {
|
|
143
|
+
buf[0] = buf[0] | 0x80
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
buf = this.toBuffer()
|
|
147
|
+
if (buf[0] & 0x80) {
|
|
148
|
+
buf = Buffer.concat([Buffer.from([0x00]), buf])
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (buf.length === 1 & buf[0] === 0) {
|
|
153
|
+
buf = Buffer.from([])
|
|
154
|
+
}
|
|
155
|
+
return buf
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* For big numbers that are either positive or negative, you can convert to
|
|
160
|
+
* "sign magnitude" format whereby the first bit specifies whether the number is
|
|
161
|
+
* positive or negative.
|
|
162
|
+
*
|
|
163
|
+
* @param {Object} opts Defaults to { endian: 'big' }
|
|
164
|
+
*/
|
|
165
|
+
BN.prototype.toSM = function (opts) {
|
|
166
|
+
var endian = opts ? opts.endian : 'big'
|
|
167
|
+
var buf = this.toSMBigEndian()
|
|
168
|
+
|
|
169
|
+
if (endian === 'little') {
|
|
170
|
+
buf = reversebuf(buf)
|
|
171
|
+
}
|
|
172
|
+
return buf
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Create a BN from a "ScriptNum": This is analogous to the constructor for
|
|
177
|
+
* CScriptNum in bitcoind. Many ops in bitcoind's script interpreter use
|
|
178
|
+
* CScriptNum, which is not really a proper bignum. Instead, an error is thrown
|
|
179
|
+
* if trying to input a number bigger than 4 bytes. We copy that behavior here.
|
|
180
|
+
* A third argument, `size`, is provided to extend the hard limit of 4 bytes, as
|
|
181
|
+
* some usages require more than 4 bytes.
|
|
182
|
+
*
|
|
183
|
+
* @param {Buffer} buf A buffer of a number.
|
|
184
|
+
* @param {boolean} fRequireMinimal Whether to require minimal size encoding.
|
|
185
|
+
* @param {number} size The maximum size.
|
|
186
|
+
*/
|
|
187
|
+
BN.fromScriptNumBuffer = function (buf, fRequireMinimal, size) {
|
|
188
|
+
var nMaxNumSize = size || 4
|
|
189
|
+
$.checkArgument(buf.length <= nMaxNumSize, new Error('script number overflow'))
|
|
190
|
+
if (fRequireMinimal && buf.length > 0) {
|
|
191
|
+
// Check that the number is encoded with the minimum possible
|
|
192
|
+
// number of bytes.
|
|
193
|
+
//
|
|
194
|
+
// If the most-significant-byte - excluding the sign bit - is zero
|
|
195
|
+
// then we're not minimal. Note how this test also rejects the
|
|
196
|
+
// negative-zero encoding, 0x80.
|
|
197
|
+
if ((buf[buf.length - 1] & 0x7f) === 0) {
|
|
198
|
+
// One exception: if there's more than one byte and the most
|
|
199
|
+
// significant bit of the second-most-significant-byte is set
|
|
200
|
+
// it would conflict with the sign bit. An example of this case
|
|
201
|
+
// is +-255, which encode to 0xff00 and 0xff80 respectively.
|
|
202
|
+
// (big-endian).
|
|
203
|
+
if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
|
|
204
|
+
throw new Error('non-minimally encoded script number')
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return BN.fromSM(buf, {
|
|
209
|
+
endian: 'little'
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* The corollary to the above, with the notable exception that we do not throw
|
|
215
|
+
* an error if the output is larger than four bytes. (Which can happen if
|
|
216
|
+
* performing a numerical operation that results in an overflow to more than 4
|
|
217
|
+
* bytes).
|
|
218
|
+
*/
|
|
219
|
+
BN.prototype.toScriptNumBuffer = function () {
|
|
220
|
+
return this.toSM({
|
|
221
|
+
endian: 'little'
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Trims a buffer if it starts with zeros.
|
|
227
|
+
*
|
|
228
|
+
* @param {Buffer} buf A buffer formatted number.
|
|
229
|
+
* @param {number} natlen The natural length of the number.
|
|
230
|
+
*/
|
|
231
|
+
BN.trim = function (buf, natlen) {
|
|
232
|
+
return buf.slice(natlen - buf.length, buf.length)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Adds extra zeros to the start of a number.
|
|
237
|
+
*
|
|
238
|
+
* @param {Buffer} buf A buffer formatted number.
|
|
239
|
+
* @param {number} natlen The natural length of the number.
|
|
240
|
+
* @param {number} size How big to pad the number in bytes.
|
|
241
|
+
*/
|
|
242
|
+
BN.pad = function (buf, natlen, size) {
|
|
243
|
+
var rbuf = Buffer.alloc(size)
|
|
244
|
+
for (var i = 0; i < buf.length; i++) {
|
|
245
|
+
rbuf[rbuf.length - 1 - i] = buf[buf.length - 1 - i]
|
|
246
|
+
}
|
|
247
|
+
for (i = 0; i < size - natlen; i++) {
|
|
248
|
+
rbuf[i] = 0
|
|
249
|
+
}
|
|
250
|
+
return rbuf
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Convert a big number into a hex string. This is somewhat ambiguous, so there
|
|
254
|
+
* is an opts parameter that let's you specify the endianness or the size.
|
|
255
|
+
* opts.endian can be either 'big' or 'little' and opts.size can be any
|
|
256
|
+
* sufficiently large number of bytes. If you always want to create a 32 byte
|
|
257
|
+
* big endian number, then specify opts = { endian: 'big', size: 32 }
|
|
258
|
+
*
|
|
259
|
+
* @param {Object} opts Defaults to { endian: 'big', size: 32 }
|
|
260
|
+
*/
|
|
261
|
+
BN.prototype.toHex = function (...args) {
|
|
262
|
+
return this.toBuffer(...args).toString('hex')
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Convert a hex string (such as a 256 bit binary private key) into a big
|
|
267
|
+
* number. Sometimes these numbers can be formatted either as 'big endian' or
|
|
268
|
+
* 'little endian', and so there is an opts parameter that lets you specify
|
|
269
|
+
* which endianness is specified.
|
|
270
|
+
*
|
|
271
|
+
* @param {Buffer} buf A buffer number, such as a 256 bit hash or key.
|
|
272
|
+
* @param {Object} opts With a property 'endian' that can be either 'big' or 'little'. Defaults big endian (most significant digit first).
|
|
273
|
+
*/
|
|
274
|
+
BN.fromHex = function (hex, ...args) {
|
|
275
|
+
return BN.fromBuffer(Buffer.from(hex, 'hex'), ...args)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
module.exports = BN
|