@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,177 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it */
4
-
5
- var assert = require('assert')
6
- var crypto = require('crypto')
7
- var Shamir = require('../../lib/crypto/shamir')
8
-
9
- describe('Shamir Secret Sharing', function () {
10
- describe('split / combine round-trip', function () {
11
- it('reconstructs an ASCII secret from exactly threshold shares', function () {
12
- var shares = Shamir.split('Hello, Bitcoin SV!', 3, 5)
13
- assert.strictEqual(shares.length, 5)
14
- var out = Shamir.combine(shares.slice(0, 3))
15
- assert.strictEqual(out.toString('utf8'), 'Hello, Bitcoin SV!')
16
- })
17
-
18
- it('reconstructs from any threshold-sized subset of shares', function () {
19
- var secret = crypto.randomBytes(32)
20
- var shares = Shamir.split(secret, 3, 5)
21
- // a few different 3-of-5 subsets
22
- var subsets = [[0, 1, 2], [2, 3, 4], [0, 2, 4], [1, 3, 4]]
23
- subsets.forEach(function (idx) {
24
- var pick = idx.map(function (i) { return shares[i] })
25
- assert.ok(Shamir.combine(pick).equals(secret), 'subset ' + idx)
26
- })
27
- })
28
-
29
- it('reconstructs a 32-byte key and more shares than threshold', function () {
30
- var key = crypto.randomBytes(32)
31
- var shares = Shamir.split(key, 4, 7)
32
- assert.ok(Shamir.combine(shares.slice(0, 4)).equals(key))
33
- assert.ok(Shamir.combine(shares).equals(key)) // all 7 also works
34
- })
35
-
36
- it('preserves leading zero bytes', function () {
37
- var secret = Buffer.from('000000deadbeef', 'hex')
38
- var shares = Shamir.split(secret, 2, 3)
39
- assert.ok(Shamir.combine(shares.slice(0, 2)).equals(secret))
40
- })
41
-
42
- it('handles a single zero byte', function () {
43
- var shares = Shamir.split(Buffer.from([0]), 2, 2)
44
- assert.ok(Shamir.combine(shares).equals(Buffer.from([0])))
45
- })
46
-
47
- it('accepts a Buffer secret and returns a Buffer', function () {
48
- var secret = Buffer.from('binary\x00\xff data', 'binary')
49
- var shares = Shamir.split(secret, 2, 3)
50
- var out = Shamir.combine(shares.slice(0, 2))
51
- assert.ok(Buffer.isBuffer(out))
52
- assert.ok(out.equals(secret))
53
- })
54
- })
55
-
56
- describe('input validation', function () {
57
- it('requires a secret', function () {
58
- assert.throws(function () { Shamir.split(null, 2, 3) }, /Secret is required/)
59
- })
60
- it('requires threshold >= 2', function () {
61
- assert.throws(function () { Shamir.split('x', 1, 3) }, /at least 2/)
62
- })
63
- it('requires shares >= threshold', function () {
64
- assert.throws(function () { Shamir.split('x', 3, 2) }, /at least threshold/)
65
- })
66
- it('caps shares/threshold at 255', function () {
67
- assert.throws(function () { Shamir.split('x', 2, 256) }, /<= 255/)
68
- })
69
- it('requires a non-empty shares array to combine', function () {
70
- assert.throws(function () { Shamir.combine([]) }, /required/)
71
- })
72
- it('rejects fewer than threshold shares', function () {
73
- var shares = Shamir.split('secret', 3, 5)
74
- assert.throws(function () { Shamir.combine(shares.slice(0, 2)) }, /Insufficient/)
75
- })
76
- })
77
-
78
- describe('integrity and isolation', function () {
79
- it('detects a tampered share at combine time', function () {
80
- // checksum is opt-in (off by default to avoid leaking a hash of the secret);
81
- // this test exercises the checksum-based detection, so enable it explicitly.
82
- var shares = Shamir.split(crypto.randomBytes(16), 3, 5, { checksum: true })
83
- // flip a hex nibble in one share's data
84
- var s = shares[1]
85
- var ch = s.share[s.share.length - 1]
86
- shares[1] = Object.assign({}, s, {
87
- share: s.share.slice(0, -1) + (ch === '0' ? '1' : '0')
88
- })
89
- assert.throws(function () { Shamir.combine(shares.slice(0, 3)) },
90
- /Integrity check failed|Reconstruction failed/)
91
- })
92
-
93
- it('refuses to mix shares from different splits', function () {
94
- var secret = crypto.randomBytes(16)
95
- var a = Shamir.split(secret, 2, 3)
96
- var b = Shamir.split(secret, 2, 3)
97
- assert.throws(function () { Shamir.combine([a[0], b[1]]) }, /different splits|splitId/)
98
- })
99
-
100
- it('does not embed a secret checksum by default (no leak to sub-threshold holders)', function () {
101
- var shares = Shamir.split('low-entropy-pin-1234', 2, 3)
102
- assert.strictEqual(shares[0].checksum, null)
103
- assert.strictEqual(Shamir.combine(shares.slice(0, 2)).toString('utf8'), 'low-entropy-pin-1234')
104
- })
105
-
106
- it('checksum can be disabled', function () {
107
- var shares = Shamir.split('no-checksum', 2, 3, { checksum: false })
108
- assert.strictEqual(shares[0].checksum, null)
109
- assert.strictEqual(Shamir.combine(shares.slice(0, 2)).toString('utf8'), 'no-checksum')
110
- })
111
-
112
- it('produces a different splitId for each split', function () {
113
- var a = Shamir.split('x', 2, 3)
114
- var b = Shamir.split('x', 2, 3)
115
- assert.notStrictEqual(a[0].splitId, b[0].splitId)
116
- })
117
- })
118
-
119
- describe('verifyShare', function () {
120
- it('accepts a freshly produced share', function () {
121
- var shares = Shamir.split('verify me', 2, 3)
122
- assert.strictEqual(Shamir.verifyShare(shares[0]), true)
123
- })
124
- it('rejects non-objects and malformed shares', function () {
125
- assert.strictEqual(Shamir.verifyShare(null), false)
126
- assert.strictEqual(Shamir.verifyShare({}), false)
127
- assert.strictEqual(Shamir.verifyShare({ v: 2, share: 'nothex!!', threshold: 2, shares: 3, id: 1 }), false)
128
- })
129
- })
130
-
131
- describe('generateTestVectors', function () {
132
- it('round-trips its own vectors', function () {
133
- var tv = Shamir.generateTestVectors()
134
- assert.strictEqual(tv.valid, true)
135
- assert.strictEqual(tv.reconstructed, tv.secret)
136
- })
137
- })
138
-
139
- describe('legacy (<= 4.x) share recovery', function () {
140
- // A real 2-of-3 share set produced by the old 31-bit-prime implementation
141
- // for the secret "hi" (0x6869). Kept as a fixed vector so we know old
142
- // shares remain recoverable.
143
- function legacyShareSetForHi () {
144
- // Reconstruct deterministically using the legacy math so the vector
145
- // is self-consistent: build points for the polynomial f(x)=secretByte
146
- // with known coefficients is non-trivial; instead we exercise the legacy
147
- // path by round-tripping through the retained legacy combiner with a
148
- // hand-built linear (threshold=2) sharing over the legacy prime.
149
- var prime = 2147483647
150
- var bytes = [0x68, 0x69] // "hi"
151
- // f_b(x) = byte_b + a_b * x (a_b chosen fixed, nonzero)
152
- var a = [12345, 67890]
153
- function y (b, x) { return ((bytes[b] + a[b] * x) % prime).toString(16) }
154
- function share (id) {
155
- return {
156
- id: id,
157
- threshold: 2,
158
- shares: 3,
159
- length: 2,
160
- bytes: [{ x: id, y: y(0, id) }, { x: id, y: y(1, id) }]
161
- }
162
- }
163
- return [share(1), share(2), share(3)]
164
- }
165
-
166
- it('recovers a secret split by the old implementation', function () {
167
- var legacy = legacyShareSetForHi()
168
- var out = Shamir.combine([legacy[0], legacy[2]])
169
- assert.strictEqual(out.toString('utf8'), 'hi')
170
- })
171
-
172
- it('verifyShare accepts a legacy share', function () {
173
- var legacy = legacyShareSetForHi()
174
- assert.strictEqual(Shamir.verifyShare(legacy[0]), true)
175
- })
176
- })
177
- })
@@ -1,29 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it, afterEach */
4
-
5
- // Regression: the secrets.js RNG callback re-draws on an all-zero draw. A broken
6
- // or stubbed CSPRNG that returns all-zero bytes forever (e.g. a bundle mocking
7
- // node crypto to Buffer.alloc) previously made that loop spin forever. The bounded
8
- // loop now throws a clear error instead of hanging.
9
-
10
- var assert = require('assert')
11
- var Shamir = require('../../lib/crypto/shamir')
12
- var Random = require('../../lib/crypto/random')
13
-
14
- describe('Shamir RNG degenerate-source cap', function () {
15
- var orig = Random.getRandomBuffer
16
- afterEach(function () { Random.getRandomBuffer = orig })
17
-
18
- it('throws (does not hang) when the CSPRNG is stuck returning all zeros', function () {
19
- Random.getRandomBuffer = function (n) { return Buffer.alloc(n, 0) }
20
- assert.throws(function () {
21
- Shamir.split('secret', 2, 3)
22
- }, /all-zero|degenerate/)
23
- })
24
-
25
- it('still splits/combines normally with a healthy CSPRNG', function () {
26
- var shares = Shamir.split('round-trip', 2, 3)
27
- assert.strictEqual(Shamir.combine(shares.slice(0, 2)).toString('utf8'), 'round-trip')
28
- })
29
- })
@@ -1,399 +0,0 @@
1
- 'use strict'
2
-
3
- var _ = require('../../lib/util/_')
4
- var should = require('chai').should()
5
- var expect = require('chai').expect
6
- var bsv = require('../..')
7
- var BN = bsv.crypto.BN
8
- var Signature = bsv.crypto.Signature
9
- var ECDSA = bsv.crypto.ECDSA
10
- var Hash = bsv.crypto.Hash
11
- var PrivateKey = bsv.PrivateKey
12
- var JSUtil = bsv.util.js
13
- var Interpreter = bsv.Script.Interpreter
14
-
15
- var sigCanonical = require('../data/bitcoind/sig_canonical')
16
- var sigNonCanonical = require('../data/bitcoind/sig_noncanonical')
17
-
18
- describe('Signature', function () {
19
- it('should make a blank signature', function () {
20
- var sig = new Signature()
21
- should.exist(sig)
22
- })
23
-
24
- it('should work with conveniently setting r, s', function () {
25
- var r = new BN()
26
- var s = new BN()
27
- var sig = new Signature(r, s)
28
- should.exist(sig)
29
- sig.r.toString().should.equal(r.toString())
30
- sig.s.toString().should.equal(s.toString())
31
- })
32
-
33
- describe('#set', function () {
34
- it('should set compressed', function () {
35
- should.exist(Signature().set({
36
- compressed: true
37
- }))
38
- })
39
-
40
- it('should set nhashtype', function () {
41
- var sig = Signature().set({
42
- nhashtype: Signature.SIGHASH_ALL
43
- })
44
- sig.nhashtype.should.equal(Signature.SIGHASH_ALL)
45
- sig.set({
46
- nhashtype: Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY
47
- })
48
- sig.nhashtype.should.equal(Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY)
49
- })
50
- })
51
-
52
- describe('#fromCompact', function () {
53
- it('should create a signature from a compressed signature', function () {
54
- var blank = Buffer.alloc(32)
55
- blank.fill(0)
56
- var compressed = Buffer.concat([
57
- Buffer.from([0 + 27 + 4]),
58
- blank,
59
- blank
60
- ])
61
- var sig = Signature.fromCompact(compressed)
62
- sig.r.cmp(BN.Zero).should.equal(0)
63
- sig.s.cmp(BN.Zero).should.equal(0)
64
- sig.compressed.should.equal(true)
65
- })
66
-
67
- it('should create a signature from an uncompressed signature', function () {
68
- var sigHexaStr = '1cd5e61ab5bfd0d1450997894cb1a53e917f89d82eb43f06fa96f32c96e061aec12fc1188e8b' +
69
- '0dc553a2588be2b5b68dbbd7f092894aa3397786e9c769c5348dc6'
70
- var sig = Signature.fromCompact(Buffer.from(sigHexaStr, 'hex'))
71
- var r = 'd5e61ab5bfd0d1450997894cb1a53e917f89d82eb43f06fa96f32c96e061aec1'
72
- var s = '2fc1188e8b0dc553a2588be2b5b68dbbd7f092894aa3397786e9c769c5348dc6'
73
- sig.r.toString('hex').should.equal(r)
74
- sig.s.toString('hex').should.equal(s)
75
- sig.compressed.should.equal(false)
76
- })
77
- })
78
-
79
- describe('#fromDER', function () {
80
- var buf = Buffer.from('3044022075fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e62770220729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2', 'hex')
81
-
82
- it('should parse this DER format signature', function () {
83
- var sig = Signature.fromDER(buf)
84
- sig.r.toBuffer({
85
- size: 32
86
- }).toString('hex').should.equal('75fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e6277')
87
- sig.s.toBuffer({
88
- size: 32
89
- }).toString('hex').should.equal('729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2')
90
- })
91
- })
92
-
93
- describe('#fromString', function () {
94
- var buf = Buffer.from('3044022075fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e62770220729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2', 'hex')
95
-
96
- it('should parse this DER format signature in hex', function () {
97
- var sig = Signature.fromString(buf.toString('hex'))
98
- sig.r.toBuffer({
99
- size: 32
100
- }).toString('hex').should.equal('75fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e6277')
101
- sig.s.toBuffer({
102
- size: 32
103
- }).toString('hex').should.equal('729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2')
104
- })
105
- })
106
-
107
- describe('#toTxFormat', function () {
108
- it('should parse this known signature and rebuild it with updated zero-padded sighash types', function () {
109
- var original = '30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e7201'
110
- var buf = Buffer.from(original, 'hex')
111
- var sig = Signature.fromTxFormat(buf)
112
- sig.nhashtype.should.equal(Signature.SIGHASH_ALL)
113
- sig.set({
114
- nhashtype: Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY
115
- })
116
- sig.toTxFormat().toString('hex').should.equal(original.slice(0, -2) + '81')
117
- sig.set({
118
- nhashtype: Signature.SIGHASH_SINGLE
119
- })
120
- sig.toTxFormat().toString('hex').should.equal(original.slice(0, -2) + '03')
121
- })
122
- })
123
-
124
- describe('#fromTxFormat', function () {
125
- it('should convert from this known tx-format buffer', function () {
126
- var buf = Buffer.from('30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e7201', 'hex')
127
- var sig = Signature.fromTxFormat(buf)
128
- sig.r.toString().should.equal('63173831029936981022572627018246571655303050627048489594159321588908385378810')
129
- sig.s.toString().should.equal('4331694221846364448463828256391194279133231453999942381442030409253074198130')
130
- sig.nhashtype.should.equal(Signature.SIGHASH_ALL)
131
- })
132
-
133
- it('should parse this known signature and rebuild it', function () {
134
- var hex = '3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501'
135
- var buf = Buffer.from(hex, 'hex')
136
- var sig = Signature.fromTxFormat(buf)
137
- sig.toTxFormat().toString('hex').should.equal(hex)
138
- })
139
- })
140
-
141
- describe('#parseDER', function () {
142
- it('should parse this signature generated in node', function () {
143
- var sighex = '30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72'
144
- var sig = Buffer.from(sighex, 'hex')
145
- var parsed = Signature.parseDER(sig)
146
- parsed.header.should.equal(0x30)
147
- parsed.length.should.equal(69)
148
- parsed.rlength.should.equal(33)
149
- parsed.rneg.should.equal(true)
150
- parsed.rbuf.toString('hex').should.equal('008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa')
151
- parsed.r.toString().should.equal('63173831029936981022572627018246571655303050627048489594159321588908385378810')
152
- parsed.slength.should.equal(32)
153
- parsed.sneg.should.equal(false)
154
- parsed.sbuf.toString('hex').should.equal('0993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72')
155
- parsed.s.toString().should.equal('4331694221846364448463828256391194279133231453999942381442030409253074198130')
156
- })
157
-
158
- it('should parse this 69 byte signature', function () {
159
- var sighex = '3043021f59e4705959cc78acbfcf8bd0114e9cc1b389a4287fb33152b73a38c319b50302202f7428a27284c757e409bf41506183e9e49dfb54d5063796dfa0d403a4deccfa'
160
- var sig = Buffer.from(sighex, 'hex')
161
- var parsed = Signature.parseDER(sig)
162
- parsed.header.should.equal(0x30)
163
- parsed.length.should.equal(67)
164
- parsed.rlength.should.equal(31)
165
- parsed.rneg.should.equal(false)
166
- parsed.rbuf.toString('hex').should.equal('59e4705959cc78acbfcf8bd0114e9cc1b389a4287fb33152b73a38c319b503')
167
- parsed.r.toString().should.equal('158826015856106182499128681792325160381907915189052224498209222621383996675')
168
- parsed.slength.should.equal(32)
169
- parsed.sneg.should.equal(false)
170
- parsed.sbuf.toString('hex').should.equal('2f7428a27284c757e409bf41506183e9e49dfb54d5063796dfa0d403a4deccfa')
171
- parsed.s.toString().should.equal('21463938592353267769710297084836796652964571266930856168996063301532842380538')
172
- })
173
-
174
- it('should parse this 68 byte signature', function () {
175
- var sighex = '3042021e17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632022061bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a51'
176
- var sig = Buffer.from(sighex, 'hex')
177
- var parsed = Signature.parseDER(sig)
178
- parsed.header.should.equal(0x30)
179
- parsed.length.should.equal(66)
180
- parsed.rlength.should.equal(30)
181
- parsed.rneg.should.equal(false)
182
- parsed.rbuf.toString('hex').should.equal('17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632')
183
- parsed.r.toString().should.equal('164345250294671732127776123343329699648286106708464198588053542748255794')
184
- parsed.slength.should.equal(32)
185
- parsed.sneg.should.equal(false)
186
- parsed.sbuf.toString('hex').should.equal('61bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a51')
187
- parsed.s.toString().should.equal('44212963026209759051804639008236126356702363229859210154760104982946304432721')
188
- })
189
-
190
- it('should parse this signature from script_valid.json', function () {
191
- var sighex = '304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef051'
192
- var sig = Buffer.from(sighex, 'hex')
193
- var parsed = Signature.parseDER(sig, false)
194
- should.exist(parsed)
195
- })
196
-
197
- it('reports sneg for a padded s', function () {
198
- // 02 21 00ab.. — s carries the pad that clears its high bit.
199
- var sighex = '304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c' +
200
- '022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef0'
201
- var parsed = Signature.parseDER(Buffer.from(sighex, 'hex'))
202
- parsed.sbuf[0].should.equal(0x00)
203
- parsed.sneg.should.equal(true)
204
- parsed.rneg.should.equal(false)
205
- })
206
- })
207
-
208
- describe('#parseDER canonicality', function () {
209
- // A non-canonical INTEGER is a second encoding of the same number, i.e. a
210
- // malleable signature. Strict (the default, used by fromDER/fromString and
211
- // so by credential/proof verification) rejects them; non-strict must keep
212
- // accepting them, because signatures already on chain are not canonical and
213
- // fromTxFormat has to parse them.
214
- var cases = [
215
- { name: 'r negative (high bit set, unpadded)', hex: '3006' + '0201ff' + '020101', err: /Value of r is negative/ },
216
- { name: 's negative (high bit set, unpadded)', hex: '3006' + '020101' + '0201ff', err: /Value of s is negative/ },
217
- { name: 'r excessively padded', hex: '3007' + '02020011' + '020101', err: /Value of r is excessively padded/ },
218
- { name: 's excessively padded', hex: '3007' + '020101' + '02020011', err: /Value of s is excessively padded/ },
219
- { name: 'r zero-length', hex: '3005' + '0200' + '020101', err: /Length of r is zero/ },
220
- { name: 's zero-length', hex: '3005' + '020101' + '0200', err: /Length of s is zero/ }
221
- ]
222
-
223
- cases.forEach(function (c) {
224
- it('strict rejects ' + c.name, function () {
225
- expect(function () {
226
- Signature.parseDER(Buffer.from(c.hex, 'hex'))
227
- }).to.throw(c.err)
228
- })
229
-
230
- it('non-strict still accepts ' + c.name + ' (chain compatibility)', function () {
231
- should.exist(Signature.parseDER(Buffer.from(c.hex, 'hex'), false))
232
- })
233
- })
234
-
235
- it('strict accepts a minimally padded integer', function () {
236
- // 0x00ff is canonical: the pad is required to clear the high bit.
237
- should.exist(Signature.parseDER(Buffer.from('3008020200ff020200ff', 'hex')))
238
- })
239
-
240
- it('strict accepts a canonical zero integer', function () {
241
- should.exist(Signature.parseDER(Buffer.from('3006020100020100', 'hex')))
242
- })
243
-
244
- it('rejects a malleated re-encoding while the original still verifies', function () {
245
- var privkey = new PrivateKey()
246
- var hashbuf = Hash.sha256(Buffer.from('der canonicality'))
247
- var sig = ECDSA.sign(hashbuf, privkey)
248
- var der = sig.toDER()
249
-
250
- ECDSA.verify(hashbuf, Signature.fromDER(der), privkey.toPublicKey()).should.equal(true)
251
-
252
- // Re-encode r with one pad byte more than DER allows: same r, different
253
- // bytes. The extra zero goes on top of the canonical encoding, so this is
254
- // excess padding whether or not r needed a pad to begin with.
255
- var canonical = function (nbuf) {
256
- return (nbuf[0] & 0x80) ? Buffer.concat([Buffer.from([0x00]), nbuf]) : nbuf
257
- }
258
- var padded = Buffer.concat([Buffer.from([0x00]), canonical(sig.r.toBuffer())])
259
- var sEnc = canonical(sig.s.toBuffer())
260
- var body = Buffer.concat([
261
- Buffer.from([0x02, padded.length]), padded,
262
- Buffer.from([0x02, sEnc.length]), sEnc
263
- ])
264
- var malleated = Buffer.concat([Buffer.from([0x30, body.length]), body])
265
-
266
- malleated.toString('hex').should.not.equal(der.toString('hex'))
267
- expect(function () {
268
- Signature.fromDER(malleated)
269
- }).to.throw(/excessively padded/)
270
- // The same bytes remain parseable on the non-strict (chain) path.
271
- Signature.parseDER(malleated, false).r.eq(sig.r).should.equal(true)
272
- })
273
- })
274
-
275
- describe('#toDER', function () {
276
- it('should convert these known r and s values into a known signature', function () {
277
- var r = new BN('63173831029936981022572627018246571655303050627048489594159321588908385378810')
278
- var s = new BN('4331694221846364448463828256391194279133231453999942381442030409253074198130')
279
- var sig = new Signature({
280
- r: r,
281
- s: s
282
- })
283
- var der = sig.toDER(r, s)
284
- der.toString('hex').should.equal('30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72')
285
- })
286
- })
287
-
288
- describe('#toString', function () {
289
- it('should convert this signature in to hex DER', function () {
290
- var r = new BN('63173831029936981022572627018246571655303050627048489594159321588908385378810')
291
- var s = new BN('4331694221846364448463828256391194279133231453999942381442030409253074198130')
292
- var sig = new Signature({
293
- r: r,
294
- s: s
295
- })
296
- var hex = sig.toString()
297
- hex.should.equal('30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72')
298
- })
299
- })
300
-
301
- describe('@isTxDER', function () {
302
- it('should know this is a DER signature', function () {
303
- var sighex = '3042021e17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632022061bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a5101'
304
- var sigbuf = Buffer.from(sighex, 'hex')
305
- Signature.isTxDER(sigbuf).should.equal(true)
306
- })
307
-
308
- it('should know this is not a DER signature', function () {
309
- // for more extensive tests, see the script interpreter
310
- var sighex = '3042021e17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632022061bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a5101'
311
- var sigbuf = Buffer.from(sighex, 'hex')
312
- sigbuf[0] = 0x31
313
- Signature.isTxDER(sigbuf).should.equal(false)
314
- })
315
-
316
- describe('bitcoind fixtures', function () {
317
- var testSigs = function (set, expected) {
318
- var i = 0
319
- set.forEach(function (vector) {
320
- if (!JSUtil.isHexa(vector)) {
321
- // non-hex strings are ignored
322
- return
323
- }
324
- it('should be ' + (expected ? '' : 'in') + 'valid for fixture #' + i, function () {
325
- var sighex = vector
326
- var interp = Interpreter()
327
- interp.flags = Interpreter.SCRIPT_VERIFY_DERSIG |
328
- Interpreter.SCRIPT_VERIFY_STRICTENC
329
- var result = interp.checkSignatureEncoding(Buffer.from(sighex, 'hex'))
330
- result.should.equal(expected)
331
- })
332
- i++
333
- })
334
- }
335
- testSigs(sigCanonical, true)
336
- testSigs(sigNonCanonical, false)
337
- })
338
- })
339
- describe('#hasLowS', function () {
340
- it('should detect high and low S', function () {
341
- var r = new BN('63173831029936981022572627018246571655303050627048489594159321588908385378810')
342
-
343
- var sig = new Signature({
344
- r: r,
345
- s: new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A1', 'hex')
346
- })
347
- sig.hasLowS().should.equal(false)
348
-
349
- var sig2 = new Signature({
350
- r: r,
351
- s: new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')
352
- })
353
- sig2.hasLowS().should.equal(true)
354
-
355
- var sig3 = new Signature({
356
- r: r,
357
- s: new BN(1)
358
- })
359
- sig3.hasLowS().should.equal(true)
360
-
361
- var sig4 = new Signature({
362
- r: r,
363
- s: new BN(0)
364
- })
365
- sig4.hasLowS().should.equal(false)
366
- })
367
- })
368
-
369
- describe('#hasDefinedHashtype', function () {
370
- it('should reject invalid sighash types and accept valid ones', function () {
371
- var sig = new Signature()
372
- sig.hasDefinedHashtype().should.equal(false)
373
- var testCases = [
374
- [undefined, false],
375
- [null, false],
376
- [0, false],
377
- [1.1, false],
378
- [-1, false],
379
- [-1.1, false],
380
- ['', false],
381
- ['1', false],
382
- [Signature.SIGHASH_ANYONECANPAY, false],
383
- [Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_ALL, true],
384
- [Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_NONE, true],
385
- [Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_SINGLE, true],
386
- [Signature.SIGHASH_ALL, true],
387
- [Signature.SIGHASH_NONE, true],
388
- [Signature.SIGHASH_SINGLE, true],
389
- [Signature.SIGHASH_SINGLE + 1, false],
390
- [(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_SINGLE) + 1, false],
391
- [(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_ALL) - 1, false]
392
- ]
393
- _.each(testCases, function (testCase) {
394
- sig.nhashtype = testCase[0]
395
- sig.hasDefinedHashtype().should.equal(testCase[1])
396
- })
397
- })
398
- })
399
- })