@smartledger/bsv 8.3.1 → 9.1.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 (169) hide show
  1. package/CHANGELOG.md +228 -0
  2. package/README.md +152 -1031
  3. package/STABILITY.md +134 -0
  4. package/bsv-gdaf.min.js +58 -53
  5. package/bsv-ltp.min.js +23 -18
  6. package/bsv-script-helper.min.js +1 -1
  7. package/bsv-smartcontract.min.js +21 -21
  8. package/bsv.bundle.js +58 -53
  9. package/bsv.d.ts +0 -4
  10. package/bsv.min.js +58 -53
  11. package/docs/BRC220_BATCH_LEAF_AMENDMENT.md +82 -7
  12. package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
  13. package/docs/README.md +2 -1
  14. package/docs/THREAT_MODEL.md +10 -2
  15. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  16. package/docs/getting-started/INSTALLATION.md +23 -23
  17. package/docs/getting-started/QUICK_START.md +7 -7
  18. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  19. package/docs/proposals/10.0.0-package-split.md +131 -0
  20. package/index.js +15 -26
  21. package/lib/block/merkleblock.js +19 -5
  22. package/lib/covenant/helpers.js +34 -35
  23. package/lib/covenant/pushtx.js +2 -2
  24. package/lib/custom-script-helper.js +0 -16
  25. package/lib/hdprivatekey.js +15 -0
  26. package/lib/ordinals/ordlock.js +1 -1
  27. package/lib/script/interpreter.js +109 -1
  28. package/lib/smart_contract/builder.js +14 -0
  29. package/lib/smart_contract/debugger.js +2 -2
  30. package/lib/smart_contract/dsl.js +2 -2
  31. package/lib/smart_contract/index.js +0 -3
  32. package/lib/smart_contract/locks.js +1 -41
  33. package/lib/smart_contract/pels.js +1 -1
  34. package/lib/smart_contract/token.js +1 -1
  35. package/lib/util/deprecate.js +159 -0
  36. package/package.json +19 -82
  37. package/tools/gen-brc220-batch-vector.js +205 -0
  38. package/version.js +1 -1
  39. package/.mocharc.json +0 -5
  40. package/test/address.js +0 -629
  41. package/test/block/block.js +0 -239
  42. package/test/block/blockheader.js +0 -270
  43. package/test/block/merkleblock.js +0 -207
  44. package/test/build/bundle_crypto_shim.js +0 -104
  45. package/test/build/bundle_externals.js +0 -125
  46. package/test/build/bundle_smoke.js +0 -55
  47. package/test/build/esbuild_main.js +0 -65
  48. package/test/build/esm_wrapper.js +0 -73
  49. package/test/build/exports_resolution.js +0 -84
  50. package/test/build/version_sync.js +0 -14
  51. package/test/cli/smoke.js +0 -261
  52. package/test/consensus/base58-vectors.js +0 -120
  53. package/test/consensus/sv-script-vectors.js +0 -81
  54. package/test/consensus/sv-sighash-vectors.js +0 -51
  55. package/test/consensus/sv-tx-vectors.js +0 -48
  56. package/test/credentials-test.js +0 -332
  57. package/test/crypto/backend_selection.js +0 -126
  58. package/test/crypto/bn.js +0 -168
  59. package/test/crypto/ecdsa.js +0 -426
  60. package/test/crypto/elliptic-fixed.js +0 -61
  61. package/test/crypto/hash.browser.js +0 -121
  62. package/test/crypto/hash.js +0 -122
  63. package/test/crypto/point.js +0 -193
  64. package/test/crypto/random.js +0 -105
  65. package/test/crypto/security.js +0 -176
  66. package/test/crypto/shamir.js +0 -177
  67. package/test/crypto/shamir_rngcap.js +0 -29
  68. package/test/crypto/signature.js +0 -399
  69. package/test/data/bip69.json +0 -215
  70. package/test/data/bitcoin-sv/README.md +0 -170
  71. package/test/data/bitcoin-sv/base58_encode_decode.json +0 -14
  72. package/test/data/bitcoin-sv/base58_keys_invalid.json +0 -152
  73. package/test/data/bitcoin-sv/base58_keys_valid.json +0 -452
  74. package/test/data/bitcoin-sv/script_tests.json +0 -2591
  75. package/test/data/bitcoin-sv/sighash.json +0 -1003
  76. package/test/data/bitcoin-sv/tx_invalid.json +0 -285
  77. package/test/data/bitcoin-sv/tx_valid.json +0 -367
  78. package/test/data/bitcoind/base58_keys_invalid.json +0 -152
  79. package/test/data/bitcoind/base58_keys_valid.json +0 -452
  80. package/test/data/bitcoind/blocks.json +0 -27
  81. package/test/data/bitcoind/script_tests.json +0 -2244
  82. package/test/data/bitcoind/sig_canonical.json +0 -7
  83. package/test/data/bitcoind/sig_noncanonical.json +0 -22
  84. package/test/data/bitcoind/tx_invalid.json +0 -177
  85. package/test/data/bitcoind/tx_valid.json +0 -224
  86. package/test/data/blk86756-testnet.dat +0 -0
  87. package/test/data/blk86756-testnet.js +0 -12
  88. package/test/data/blk86756-testnet.json +0 -684
  89. package/test/data/ecdsa.json +0 -230
  90. package/test/data/merkleblocks.js +0 -486
  91. package/test/data/messages.json +0 -22
  92. package/test/data/sighash.json +0 -1004
  93. package/test/data/tx_creation.json +0 -85
  94. package/test/didweb/relationships.js +0 -144
  95. package/test/ecies/bitcore-ecies.js +0 -178
  96. package/test/ecies/electrum-ecies.js +0 -206
  97. package/test/encoding/base58.js +0 -131
  98. package/test/encoding/base58check.js +0 -145
  99. package/test/encoding/bufferreader.js +0 -328
  100. package/test/encoding/bufferwriter.js +0 -160
  101. package/test/encoding/varint.js +0 -104
  102. package/test/gdaf/anchor_no_key_leak.js +0 -146
  103. package/test/gdaf/anchor_spv.js +0 -163
  104. package/test/gdaf/canonicalization.js +0 -106
  105. package/test/gdaf/canonicalize.js +0 -140
  106. package/test/gdaf/zk_prover.js +0 -204
  107. package/test/hdkeys.js +0 -365
  108. package/test/hdprivatekey.js +0 -339
  109. package/test/hdpublickey.js +0 -293
  110. package/test/index.js +0 -16
  111. package/test/ltp/ids.js +0 -74
  112. package/test/ltp/right.js +0 -198
  113. package/test/ltp/verify_failclosed.js +0 -134
  114. package/test/message/message.js +0 -190
  115. package/test/mnemonic/data/fixtures.json +0 -300
  116. package/test/mnemonic/mnemonic.js +0 -277
  117. package/test/mnemonic/mocha.opts +0 -1
  118. package/test/mnemonic/pbkdf2.test.js +0 -43
  119. package/test/networks.js +0 -207
  120. package/test/notaryhash/batch_leaf.js +0 -140
  121. package/test/notaryhash/certificate.js +0 -249
  122. package/test/notaryhash/encoding.js +0 -186
  123. package/test/notaryhash/interop.js +0 -112
  124. package/test/notaryhash/merkle.js +0 -181
  125. package/test/notaryhash/script.js +0 -270
  126. package/test/notaryhash/verify.js +0 -342
  127. package/test/opcode.js +0 -186
  128. package/test/ordinals/bsv20.js +0 -337
  129. package/test/ordinals/inscription.js +0 -319
  130. package/test/ordinals/ordlock.js +0 -613
  131. package/test/privatekey.js +0 -540
  132. package/test/publickey.js +0 -411
  133. package/test/regressions.js +0 -215
  134. package/test/script/chronicle.js +0 -543
  135. package/test/script/defaults.js +0 -160
  136. package/test/script/genesis_limits.js +0 -203
  137. package/test/script/interpreter.js +0 -776
  138. package/test/script/script.js +0 -1259
  139. package/test/script/string_ops.js +0 -88
  140. package/test/security/fail_closed_contracts.js +0 -104
  141. package/test/security/threat_model_coverage.js +0 -31
  142. package/test/smart_contract/covenants.js +0 -245
  143. package/test/smart_contract/dsl_debugger.js +0 -101
  144. package/test/smart_contract/extract_field.js +0 -61
  145. package/test/smart_contract/nonenforcing_guard.js +0 -44
  146. package/test/smart_contract/ordinal_transfer.js +0 -81
  147. package/test/smart_contract/preimage.js +0 -98
  148. package/test/smart_contract/sighash_marketplace.js +0 -108
  149. package/test/smart_contract/token_generalized.js +0 -185
  150. package/test/spv/headerchain.js +0 -86
  151. package/test/spv/merkleproof.js +0 -133
  152. package/test/statuslist/failclosed.js +0 -78
  153. package/test/transaction/deserialize.js +0 -33
  154. package/test/transaction/input/input.js +0 -92
  155. package/test/transaction/input/multisig.js +0 -174
  156. package/test/transaction/input/multisigscripthash.js +0 -111
  157. package/test/transaction/input/publickey.js +0 -68
  158. package/test/transaction/input/publickeyhash.js +0 -59
  159. package/test/transaction/output.js +0 -185
  160. package/test/transaction/sighash.js +0 -91
  161. package/test/transaction/signature.js +0 -127
  162. package/test/transaction/transaction.js +0 -1299
  163. package/test/transaction/unspentoutput.js +0 -97
  164. package/test/types/dts_drift.js +0 -124
  165. package/test/types/surface_honesty.js +0 -102
  166. package/test/util/id.js +0 -72
  167. package/test/util/js.js +0 -76
  168. package/test/util/preconditions.js +0 -79
  169. package/test/vcjwt/interop.js +0 -126
@@ -1,122 +0,0 @@
1
- 'use strict'
2
-
3
- require('chai').should()
4
- var bsv = require('../..')
5
- var Hash = bsv.crypto.Hash
6
-
7
- describe('Hash', function () {
8
- var buf = Buffer.from([0, 1, 2, 3, 253, 254, 255])
9
- var str = 'test string'
10
-
11
- describe('@sha1', function () {
12
- it('calculates the hash of this buffer correctly', function () {
13
- var hash = Hash.sha1(buf)
14
- hash.toString('hex').should.equal('de69b8a4a5604d0486e6420db81e39eb464a17b2')
15
- hash = Hash.sha1(Buffer.alloc(0))
16
- hash.toString('hex').should.equal('da39a3ee5e6b4b0d3255bfef95601890afd80709')
17
- })
18
-
19
- it('throws an error when the input is not a buffer', function () {
20
- Hash.sha1.bind(Hash, str).should.throw('Invalid Argument')
21
- })
22
- })
23
-
24
- describe('#sha256', function () {
25
- it('calculates the hash of this buffer correctly', function () {
26
- var hash = Hash.sha256(buf)
27
- hash.toString('hex').should.equal('6f2c7b22fd1626998287b3636089087961091de80311b9279c4033ec678a83e8')
28
- })
29
-
30
- it('fails when the input is not a buffer', function () {
31
- Hash.sha256.bind(Hash, str).should.throw('Invalid Argument')
32
- })
33
- })
34
-
35
- describe('#sha256hmac', function () {
36
- it('computes this known big key correctly', function () {
37
- var key = Buffer.from('b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
38
- 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
39
- 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
40
- 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad')
41
- var data = Buffer.from('')
42
- Hash.sha256hmac(data, key).toString('hex')
43
- .should.equal('fb1f87218671f1c0c4593a88498e02b6dfe8afd814c1729e89a1f1f6600faa23')
44
- })
45
-
46
- it('computes this known empty test vector correctly', function () {
47
- var key = Buffer.from('')
48
- var data = Buffer.from('')
49
- Hash.sha256hmac(data, key).toString('hex')
50
- .should.equal('b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad')
51
- })
52
-
53
- it('computes this known non-empty test vector correctly', function () {
54
- var key = Buffer.from('key')
55
- var data = Buffer.from('The quick brown fox jumps over the lazy dog')
56
- Hash.sha256hmac(data, key).toString('hex')
57
- .should.equal('f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8')
58
- })
59
- })
60
-
61
- describe('#sha256sha256', function () {
62
- it('calculates the hash of this buffer correctly', function () {
63
- var hash = Hash.sha256sha256(buf)
64
- hash.toString('hex').should.equal('be586c8b20dee549bdd66018c7a79e2b67bb88b7c7d428fa4c970976d2bec5ba')
65
- })
66
-
67
- it('fails when the input is not a buffer', function () {
68
- Hash.sha256sha256.bind(Hash, str).should.throw('Invalid Argument')
69
- })
70
- })
71
-
72
- describe('#sha256ripemd160', function () {
73
- it('calculates the hash of this buffer correctly', function () {
74
- var hash = Hash.sha256ripemd160(buf)
75
- hash.toString('hex').should.equal('7322e2bd8535e476c092934e16a6169ca9b707ec')
76
- })
77
-
78
- it('fails when the input is not a buffer', function () {
79
- Hash.sha256ripemd160.bind(Hash, str).should.throw('Invalid Argument')
80
- })
81
- })
82
-
83
- describe('#ripemd160', function () {
84
- it('calculates the hash of this buffer correctly', function () {
85
- var hash = Hash.ripemd160(buf)
86
- hash.toString('hex').should.equal('fa0f4565ff776fee0034c713cbf48b5ec06b7f5c')
87
- })
88
-
89
- it('fails when the input is not a buffer', function () {
90
- Hash.ripemd160.bind(Hash, str).should.throw('Invalid Argument')
91
- })
92
- })
93
-
94
- describe('#sha512', function () {
95
- it('calculates the hash of this buffer correctly', function () {
96
- var hash = Hash.sha512(buf)
97
- hash.toString('hex')
98
- .should.equal('c0530aa32048f4904ae162bc14b9eb535eab6c465e960130005fedd' +
99
- 'b71613e7d62aea75f7d3333ba06e805fc8e45681454524e3f8050969fe5a5f7f2392e31d0')
100
- })
101
-
102
- it('fails when the input is not a buffer', function () {
103
- Hash.sha512.bind(Hash, str).should.throw('Invalid Argument')
104
- })
105
- })
106
-
107
- describe('#sha512hmac', function () {
108
- it('calculates this known empty test vector correctly', function () {
109
- var hex = 'b936cee86c9f87aa5d3c6f2e84cb5a4239a5fe50480a6ec66b70ab5b1f4a' +
110
- 'c6730c6c515421b327ec1d69402e53dfb49ad7381eb067b338fd7b0cb22247225d47'
111
- Hash.sha512hmac(Buffer.from([]), Buffer.from([])).toString('hex').should.equal(hex)
112
- })
113
-
114
- it('calculates this known non-empty test vector correctly', function () {
115
- var hex = 'c40bd7c15aa493b309c940e08a73ffbd28b2e4cb729eb94480d727e4df577' +
116
- 'b13cc403a78e6150d83595f3b17c4cc331f12ca5952691de3735a63c1d4c69a2bac'
117
- var data = Buffer.from('test1')
118
- var key = Buffer.from('test2')
119
- Hash.sha512hmac(data, key).toString('hex').should.equal(hex)
120
- })
121
- })
122
- })
@@ -1,193 +0,0 @@
1
- 'use strict'
2
-
3
- var should = require('chai').should()
4
- var bsv = require('../..')
5
- var Point = bsv.crypto.Point
6
- var BN = bsv.crypto.BN
7
-
8
- describe('Point', function () {
9
- var valid = {
10
- x: 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2',
11
- y: '4836ab292c105a711ed10fcfd30999c31ff7c02456147747e03e739ad527c380'
12
- }
13
-
14
- it('should create a point', function () {
15
- var p = Point(valid.x, valid.y)
16
- should.exist(p)
17
- })
18
-
19
- it('should create a point when called with "new"', function () {
20
- var p = new Point(valid.x, valid.y)
21
- should.exist(p)
22
- })
23
-
24
- describe('#getX', function () {
25
- it('should return x', function () {
26
- var p = Point(valid.x, valid.y)
27
- var x = p.getX()
28
- x.toString('hex', 64).should.equal(valid.x)
29
- })
30
-
31
- it('should be convertable to a buffer', function () {
32
- var p = Point(valid.x, valid.y)
33
- var a = p.getX().toBuffer({ size: 32 })
34
- a.length.should.equal(32)
35
- a.should.deep.equal(Buffer.from(valid.x, 'hex'))
36
- })
37
- })
38
-
39
- describe('#getY', function () {
40
- it('should return y', function () {
41
- var p = Point(valid.x, valid.y)
42
- p.getY().toString('hex', 64).should.equal(valid.y)
43
- })
44
-
45
- it('should be convertable to a buffer', function () {
46
- var p = Point(valid.x, valid.y)
47
- var a = p.getY().toBuffer({ size: 32 })
48
- a.length.should.equal(32)
49
- a.should.deep.equal(Buffer.from(valid.y, 'hex'))
50
- })
51
- })
52
-
53
- describe('#add', function () {
54
- it('should accurately add g to itself', function () {
55
- var p1 = Point.getG()
56
- var p2 = Point.getG()
57
- var p3 = p1.add(p2)
58
- p3.getX().toString().should.equal('89565891926547004231252920425935692360644145829622209' +
59
- '833684329913297188986597')
60
- p3.getY().toString().should.equal('12158399299693830322967808612713398636155367887041628' +
61
- '176798871954788371653930')
62
- })
63
- })
64
-
65
- describe('#mul', function () {
66
- it('should accurately multiply g by 2', function () {
67
- var g = Point.getG()
68
- var b = g.mul(new BN(2))
69
- b.getX().toString().should.equal('8956589192654700423125292042593569236064414582962220983' +
70
- '3684329913297188986597')
71
- b.getY().toString().should.equal('1215839929969383032296780861271339863615536788704162817' +
72
- '6798871954788371653930')
73
- })
74
-
75
- it('should accurately multiply g by n-1', function () {
76
- var g = Point.getG()
77
- var n = Point.getN()
78
- var b = g.mul(n.sub(new BN(1)))
79
- b.getX().toString().should.equal('55066263022277343669578718895168534326250603453777594175' +
80
- '500187360389116729240')
81
- b.getY().toString().should.equal('83121579216557378445487899878180864668798711284981320763' +
82
- '518679672151497189239')
83
- })
84
-
85
- // not sure if this is technically accurate or not...
86
- // normally, you should always multiply g by something less than n
87
- // but it is the same result in OpenSSL
88
- it('should accurately multiply g by n+1', function () {
89
- var g = Point.getG()
90
- var n = Point.getN()
91
- var b = g.mul(n.add(new BN(1)))
92
- b.getX().toString().should.equal('550662630222773436695787188951685343262506034537775941755' +
93
- '00187360389116729240')
94
- b.getY().toString().should.equal('326705100207588169780830851305070431844712733806592432759' +
95
- '38904335757337482424')
96
- })
97
- })
98
-
99
- describe('@fromX', function () {
100
- it('should return g', function () {
101
- var g = Point.getG()
102
- var p = Point.fromX(false, g.getX())
103
- g.eq(p).should.equal(true)
104
- })
105
- })
106
-
107
- describe('@pointToCompressed', function () {
108
- it('should return g', function () {
109
- let g = Point.getG()
110
- let pbuf = Point.pointToCompressed(g)
111
- pbuf.length.should.equal(33)
112
- pbuf.toString('hex').should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
113
- })
114
- })
115
-
116
- describe('#toBuffer', function () {
117
- it('should return g', function () {
118
- let g = Point.getG()
119
- let pbuf = g.toBuffer()
120
- pbuf.length.should.equal(33)
121
- pbuf.toString('hex').should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
122
- })
123
- })
124
-
125
- describe('@fromBuffer', function () {
126
- it('should return g', function () {
127
- let buf = Buffer.from('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 'hex')
128
- let p = Point.fromBuffer(buf)
129
- p.toBuffer().toString('hex').should.equal(buf.toString('hex'))
130
- })
131
- })
132
-
133
- describe('#toHex', function () {
134
- it('should return g', function () {
135
- let g = Point.getG()
136
- let phex = g.toHex()
137
- phex.length.should.equal(33 * 2)
138
- phex.should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
139
- })
140
- })
141
-
142
- describe('@fromHex', function () {
143
- it('should return g', function () {
144
- let hex = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
145
- let p = Point.fromHex(hex)
146
- p.toHex().should.equal(hex)
147
- })
148
- })
149
-
150
- describe('#validate', function () {
151
- it('should describe this point as valid', function () {
152
- var p = Point(valid.x, valid.y)
153
- should.exist(p.validate())
154
- })
155
-
156
- it('should describe this point as invalid because of zero y', function () {
157
- var x = 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2'
158
- var y = '0000000000000000000000000000000000000000000000000000000000000000';
159
- (function () {
160
- Point(x, y)
161
- }).should.throw('Invalid y value for curve.')
162
- })
163
-
164
- it('should describe this point as invalid because of invalid y', function () {
165
- var x = 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2'
166
- var y = '00000000000000000000000000000000000000000000000000000000000000FF';
167
- (function () {
168
- Point(x, y)
169
- }).should.throw('Invalid y value for curve.')
170
- })
171
-
172
- it('should describe this point as invalid because out of curve bounds', function () {
173
- // point larger than max
174
- var x = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEDCE6AF48A03BBFD25E8CD0364141'
175
- // calculated y of x
176
- var y = 'ed3970f129bc2ca7c7c6cf92fa7da4de6a1dfc9c14da4bf056aa868d3dd74034';
177
-
178
- (function () {
179
- // set the point
180
- Point(x, y)
181
- }).should.throw('Point does not lie on the curve')
182
- })
183
-
184
- it('should describe this point as invalid because out of curve bounds', function () {
185
- var x = '0000000000000000000000000000000000000000000000000000000000000000';
186
-
187
- (function () {
188
- // set the point
189
- Point.fromX(false, x)
190
- }).should.throw('Invalid X')
191
- })
192
- })
193
- })
@@ -1,105 +0,0 @@
1
- 'use strict'
2
-
3
- var bsv = require('../..')
4
- var Random = bsv.crypto.Random
5
-
6
- describe('Random', function () {
7
- describe('@getRandomBuffer', function () {
8
- it('should return a buffer', function () {
9
- var bytes = Random.getRandomBuffer(8)
10
- bytes.length.should.equal(8)
11
- Buffer.isBuffer(bytes).should.equal(true)
12
- })
13
-
14
- it('should not equate two 256 bit random buffers', function () {
15
- var bytes1 = Random.getRandomBuffer(32)
16
- var bytes2 = Random.getRandomBuffer(32)
17
- bytes1.toString('hex').should.not.equal(bytes2.toString('hex'))
18
- })
19
-
20
- it('should generate 100 8 byte buffers in a row that are not equal', function () {
21
- var hexs = []
22
- for (var i = 0; i < 100; i++) {
23
- hexs[i] = Random.getRandomBuffer(8).toString('hex')
24
- }
25
- for (i = 0; i < 100; i++) {
26
- for (var j = i + 1; j < 100; j++) {
27
- hexs[i].should.not.equal(hexs[j])
28
- }
29
- }
30
- })
31
-
32
- // WebCrypto refuses more than 65,536 bytes per call. Before chunking, a request
33
- // above that limit threw; a naive implementation that ignored the return size
34
- // instead would hand back a zero-filled tail, which is far worse than throwing.
35
- it('fills requests larger than the 65536-byte getRandomValues limit', function () {
36
- var buf = Random.getRandomBuffer(70000)
37
- buf.length.should.equal(70000)
38
- // The tail comes from a second call — assert it is real entropy, not zero padding.
39
- var tail = buf.subarray(65536)
40
- tail.some(function (b) { return b !== 0 }).should.equal(true)
41
- buf.subarray(0, 32).toString('hex').should.not.equal(tail.subarray(0, 32).toString('hex'))
42
- })
43
-
44
- it('handles the exact limit and one past it', function () {
45
- Random.getRandomBuffer(65536).length.should.equal(65536)
46
- Random.getRandomBuffer(65537).length.should.equal(65537)
47
- })
48
-
49
- // The backend is chosen by feature detection. This used to branch on
50
- // `process.browser`, which is undefined in React Native, Deno, Workers and Bun —
51
- // all of which then fell through to require('crypto').randomBytes. Where a partial
52
- // crypto shim supplies a weak randomBytes, that produced guessable keys silently.
53
- it('does not depend on process.browser', function () {
54
- var saved = process.browser
55
- try {
56
- process.browser = undefined
57
- Random.getRandomBuffer(16).length.should.equal(16)
58
- process.browser = true
59
- Random.getRandomBuffer(16).length.should.equal(16)
60
- } finally {
61
- process.browser = saved
62
- }
63
- })
64
-
65
- it('prefers globalThis.crypto.getRandomValues when present', function () {
66
- var calls = 0
67
- var real = Object.getOwnPropertyDescriptor(globalThis, 'crypto')
68
- try {
69
- Object.defineProperty(globalThis, 'crypto', {
70
- configurable: true,
71
- value: {
72
- getRandomValues: function (arr) {
73
- calls++
74
- for (var i = 0; i < arr.length; i++) arr[i] = (i * 7 + 3) & 0xff
75
- return arr
76
- }
77
- }
78
- })
79
- var buf = Random.getRandomBuffer(4)
80
- calls.should.equal(1)
81
- buf.toString('hex').should.equal('030a1118')
82
- } finally {
83
- if (real) Object.defineProperty(globalThis, 'crypto', real)
84
- }
85
- })
86
-
87
- // The throw matters as much as the detection: a key library must never return bytes
88
- // it cannot vouch for. Verified in a child process because it has to remove both
89
- // backends, which cannot be undone safely in-process.
90
- it('throws rather than returning bytes when no CSPRNG exists', function () {
91
- var out = require('child_process').spawnSync(process.execPath, ['-e', [
92
- 'var Module = require("module"), orig = Module._load',
93
- 'delete globalThis.crypto',
94
- 'Module._load = function (r) {',
95
- ' if (r === "crypto") { var e = new Error("no crypto"); e.code = "MODULE_NOT_FOUND"; throw e }',
96
- ' return orig.apply(this, arguments)',
97
- '}',
98
- 'var R = require(' + JSON.stringify(require.resolve('../../lib/crypto/random.js')) + ')',
99
- 'try { R.getRandomBuffer(32); console.log("RETURNED") }',
100
- 'catch (e) { console.log("THREW") }'
101
- ].join('\n')], { encoding: 'utf8' })
102
- out.stdout.trim().should.equal('THREW')
103
- })
104
- })
105
- })
@@ -1,176 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it, before */
4
-
5
- require('chai').should()
6
- var expect = require('chai').expect
7
-
8
- var bsv = require('../../index.js')
9
- var BN = bsv.crypto.BN
10
- var ECDSA = bsv.crypto.ECDSA
11
- var Hash = bsv.crypto.Hash
12
- var Point = bsv.crypto.Point
13
- var Signature = bsv.crypto.Signature
14
- var SmartVerify = bsv.SmartVerify
15
-
16
- describe('SmartLedger Security Patches', function () {
17
- var privateKey, publicKey, message, hash
18
-
19
- before(function () {
20
- privateKey = new bsv.PrivateKey()
21
- publicKey = privateKey.toPublicKey()
22
- message = 'SmartLedger security test message'
23
- hash = Hash.sha256(Buffer.from(message))
24
- })
25
-
26
- describe('Zero Parameter Attack Protection', function () {
27
- it('Signature.validate() throws when r = 0', function () {
28
- var sig = new Signature({ r: new BN(0), s: new BN(1) })
29
- expect(function () { sig.validate() }).to.throw(/r component is zero/)
30
- })
31
-
32
- it('Signature.validate() throws when s = 0', function () {
33
- var sig = new Signature({ r: new BN(1), s: new BN(0) })
34
- expect(function () { sig.validate() }).to.throw(/s component is zero/)
35
- })
36
-
37
- it('smartVerify rejects (without throwing) a zero-s signature', function () {
38
- var sig = new Signature({ r: new BN(1), s: new BN(0) })
39
- SmartVerify.smartVerify(hash, sig, publicKey).should.equal(false)
40
- })
41
- })
42
-
43
- describe('Canonical Signature Enforcement', function () {
44
- it('freshly produced signatures are canonical (low-S)', function () {
45
- var sig = ECDSA.sign(hash, privateKey)
46
- sig.isCanonical().should.equal(true)
47
- SmartVerify.isCanonical(sig).should.equal(true)
48
- })
49
-
50
- it('detects a non-canonical (high-S) signature', function () {
51
- var sig = ECDSA.sign(hash, privateKey)
52
- var n = Point.getN()
53
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
54
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
55
-
56
- highS.isCanonical().should.equal(false)
57
- SmartVerify.isCanonical(highS).should.equal(false)
58
- })
59
-
60
- it('toCanonical() converts a high-S signature to canonical form', function () {
61
- var sig = ECDSA.sign(hash, privateKey)
62
- var n = Point.getN()
63
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
64
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
65
-
66
- var canonical = highS.toCanonical()
67
- canonical.isCanonical().should.equal(true)
68
- // Both forms verify (ECDSA is malleable in s); canonicalization does not
69
- // change which key/message the signature is valid for.
70
- canonical.r.cmp(highS.r).should.equal(0)
71
- })
72
-
73
- it('toCanonical() returns a new signature and leaves the original alone', function () {
74
- var sig = ECDSA.sign(hash, privateKey)
75
- var n = Point.getN()
76
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
77
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
78
- var before = highS.s.toString()
79
-
80
- var canonical = highS.toCanonical()
81
- canonical.should.not.equal(highS)
82
- highS.s.toString().should.equal(before)
83
- })
84
- })
85
-
86
- describe('applySecurityPatches', function () {
87
- var highSig = function () {
88
- var sig = ECDSA.sign(hash, privateKey)
89
- var n = Point.getN()
90
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
91
- return new Signature({ r: sig.r, s: n.sub(lowS) })
92
- }
93
-
94
- it('accepts a canonical signature and returns it for chaining', function () {
95
- var sig = ECDSA.sign(hash, privateKey)
96
- sig.applySecurityPatches().should.equal(sig)
97
- })
98
-
99
- it('rejects a non-canonical (high-S) signature rather than rewriting it', function () {
100
- // Rewriting s to n-s cannot protect against malleability: the rewritten
101
- // signature verifies exactly as the original, so silently normalizing only
102
- // hides from the caller that the signature was malleated.
103
- var highS = highSig()
104
- var before = highS.s.toString()
105
-
106
- expect(function () { highS.applySecurityPatches() }).to.throw(/non-canonical/)
107
- highS.s.toString().should.equal(before)
108
- })
109
-
110
- it('rejects zero and out-of-range components', function () {
111
- expect(function () {
112
- new Signature({ r: new BN(0), s: new BN(1) }).applySecurityPatches()
113
- }).to.throw(/zero r or s/)
114
- expect(function () {
115
- new Signature({ r: new BN(1), s: Point.getN() }).applySecurityPatches()
116
- }).to.throw(/out of range/)
117
- })
118
- })
119
-
120
- describe('SmartVerify Enhanced Validation', function () {
121
- it('accepts a valid signature', function () {
122
- var sig = ECDSA.sign(hash, privateKey)
123
- SmartVerify.smartVerify(hash, sig, publicKey).should.equal(true)
124
- })
125
-
126
- it('rejects a malleated (high-S) signature', function () {
127
- var sig = ECDSA.sign(hash, privateKey)
128
- var n = Point.getN()
129
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
130
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
131
- SmartVerify.isCanonical(highS).should.equal(false)
132
- SmartVerify.smartVerify(hash, highS, publicKey).should.equal(false)
133
- // ...while the canonical form of the same signature still verifies.
134
- SmartVerify.smartVerify(hash, new Signature({ r: sig.r, s: lowS }), publicKey).should.equal(true)
135
- })
136
-
137
- it('throws on an invalid (non-32-byte) message hash', function () {
138
- var sig = ECDSA.sign(hash, privateKey)
139
- var shortHash = Buffer.alloc(16)
140
- expect(function () {
141
- SmartVerify.smartVerify(shortHash, sig, publicKey)
142
- }).to.throw(/32-byte/)
143
- })
144
-
145
- it('rejects a signature from the wrong key', function () {
146
- var sig = ECDSA.sign(hash, privateKey)
147
- var otherPub = new bsv.PrivateKey().toPublicKey()
148
- SmartVerify.smartVerify(hash, sig, otherPub).should.equal(false)
149
- })
150
- })
151
-
152
- describe('Integration with Original BSV', function () {
153
- it('round-trips a Bitcoin message signature', function () {
154
- var sig = new bsv.Message(message).sign(privateKey)
155
- var verified = new bsv.Message(message).verify(publicKey.toAddress().toString(), sig)
156
- verified.should.equal(true)
157
- })
158
-
159
- it('signs a transaction to completion', function () {
160
- var utxo = {
161
- txId: 'a'.repeat(64),
162
- outputIndex: 0,
163
- address: privateKey.toAddress().toString(),
164
- script: bsv.Script.buildPublicKeyHashOut(privateKey.toAddress()).toHex(),
165
- satoshis: 100000
166
- }
167
-
168
- var transaction = new bsv.Transaction()
169
- .from(utxo)
170
- .to(privateKey.toAddress(), 50000)
171
- .sign(privateKey)
172
-
173
- transaction.isFullySigned().should.equal(true)
174
- })
175
- })
176
- })