@smartledger/bsv 9.0.0 → 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 (155) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/README.md +152 -1041
  3. package/STABILITY.md +134 -0
  4. package/bsv-gdaf.min.js +53 -48
  5. package/bsv-ltp.min.js +23 -18
  6. package/bsv-smartcontract.min.js +18 -18
  7. package/bsv.bundle.js +53 -48
  8. package/bsv.min.js +53 -48
  9. package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
  10. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  11. package/docs/getting-started/INSTALLATION.md +23 -23
  12. package/docs/getting-started/QUICK_START.md +7 -7
  13. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  14. package/docs/proposals/10.0.0-package-split.md +131 -0
  15. package/index.js +5 -0
  16. package/lib/block/merkleblock.js +19 -5
  17. package/lib/hdprivatekey.js +15 -0
  18. package/lib/script/interpreter.js +109 -1
  19. package/lib/smart_contract/builder.js +14 -0
  20. package/lib/util/deprecate.js +159 -0
  21. package/package.json +19 -82
  22. package/version.js +1 -1
  23. package/.mocharc.json +0 -5
  24. package/test/address.js +0 -629
  25. package/test/block/block.js +0 -239
  26. package/test/block/blockheader.js +0 -270
  27. package/test/block/merkleblock.js +0 -207
  28. package/test/build/bundle_crypto_shim.js +0 -104
  29. package/test/build/bundle_externals.js +0 -125
  30. package/test/build/bundle_smoke.js +0 -55
  31. package/test/build/esbuild_main.js +0 -65
  32. package/test/build/esm_wrapper.js +0 -97
  33. package/test/build/exports_resolution.js +0 -84
  34. package/test/build/version_sync.js +0 -14
  35. package/test/cli/smoke.js +0 -261
  36. package/test/consensus/base58-vectors.js +0 -120
  37. package/test/consensus/sv-script-vectors.js +0 -81
  38. package/test/consensus/sv-sighash-vectors.js +0 -51
  39. package/test/consensus/sv-tx-vectors.js +0 -48
  40. package/test/credentials-test.js +0 -332
  41. package/test/crypto/backend_selection.js +0 -126
  42. package/test/crypto/bn.js +0 -168
  43. package/test/crypto/ecdsa.js +0 -426
  44. package/test/crypto/elliptic-fixed.js +0 -61
  45. package/test/crypto/hash.browser.js +0 -121
  46. package/test/crypto/hash.js +0 -122
  47. package/test/crypto/point.js +0 -193
  48. package/test/crypto/random.js +0 -105
  49. package/test/crypto/security.js +0 -176
  50. package/test/crypto/shamir.js +0 -177
  51. package/test/crypto/shamir_rngcap.js +0 -29
  52. package/test/crypto/signature.js +0 -399
  53. package/test/data/bip69.json +0 -215
  54. package/test/data/bitcoin-sv/README.md +0 -170
  55. package/test/data/bitcoin-sv/base58_encode_decode.json +0 -14
  56. package/test/data/bitcoin-sv/base58_keys_invalid.json +0 -152
  57. package/test/data/bitcoin-sv/base58_keys_valid.json +0 -452
  58. package/test/data/bitcoin-sv/script_tests.json +0 -2591
  59. package/test/data/bitcoin-sv/sighash.json +0 -1003
  60. package/test/data/bitcoin-sv/tx_invalid.json +0 -285
  61. package/test/data/bitcoin-sv/tx_valid.json +0 -367
  62. package/test/data/bitcoind/base58_keys_invalid.json +0 -152
  63. package/test/data/bitcoind/base58_keys_valid.json +0 -452
  64. package/test/data/bitcoind/blocks.json +0 -27
  65. package/test/data/bitcoind/script_tests.json +0 -2244
  66. package/test/data/bitcoind/sig_canonical.json +0 -7
  67. package/test/data/bitcoind/sig_noncanonical.json +0 -22
  68. package/test/data/bitcoind/tx_invalid.json +0 -177
  69. package/test/data/bitcoind/tx_valid.json +0 -224
  70. package/test/data/blk86756-testnet.dat +0 -0
  71. package/test/data/blk86756-testnet.js +0 -12
  72. package/test/data/blk86756-testnet.json +0 -684
  73. package/test/data/brc220-batch-vector.json +0 -129
  74. package/test/data/ecdsa.json +0 -230
  75. package/test/data/merkleblocks.js +0 -486
  76. package/test/data/messages.json +0 -22
  77. package/test/data/sighash.json +0 -1004
  78. package/test/data/tx_creation.json +0 -85
  79. package/test/didweb/relationships.js +0 -144
  80. package/test/ecies/bitcore-ecies.js +0 -178
  81. package/test/ecies/electrum-ecies.js +0 -206
  82. package/test/encoding/base58.js +0 -131
  83. package/test/encoding/base58check.js +0 -145
  84. package/test/encoding/bufferreader.js +0 -328
  85. package/test/encoding/bufferwriter.js +0 -160
  86. package/test/encoding/varint.js +0 -104
  87. package/test/gdaf/anchor_no_key_leak.js +0 -146
  88. package/test/gdaf/anchor_spv.js +0 -163
  89. package/test/gdaf/canonicalization.js +0 -106
  90. package/test/gdaf/canonicalize.js +0 -140
  91. package/test/gdaf/zk_prover.js +0 -204
  92. package/test/hdkeys.js +0 -365
  93. package/test/hdprivatekey.js +0 -339
  94. package/test/hdpublickey.js +0 -293
  95. package/test/index.js +0 -16
  96. package/test/ltp/ids.js +0 -74
  97. package/test/ltp/right.js +0 -198
  98. package/test/ltp/verify_failclosed.js +0 -134
  99. package/test/message/message.js +0 -190
  100. package/test/mnemonic/data/fixtures.json +0 -300
  101. package/test/mnemonic/mnemonic.js +0 -277
  102. package/test/mnemonic/mocha.opts +0 -1
  103. package/test/mnemonic/pbkdf2.test.js +0 -43
  104. package/test/networks.js +0 -207
  105. package/test/notaryhash/batch_leaf.js +0 -140
  106. package/test/notaryhash/batch_vector.js +0 -282
  107. package/test/notaryhash/certificate.js +0 -249
  108. package/test/notaryhash/encoding.js +0 -186
  109. package/test/notaryhash/interop.js +0 -112
  110. package/test/notaryhash/merkle.js +0 -181
  111. package/test/notaryhash/script.js +0 -270
  112. package/test/notaryhash/verify.js +0 -342
  113. package/test/opcode.js +0 -186
  114. package/test/ordinals/bsv20.js +0 -337
  115. package/test/ordinals/inscription.js +0 -329
  116. package/test/ordinals/ordlock.js +0 -567
  117. package/test/privatekey.js +0 -540
  118. package/test/publickey.js +0 -411
  119. package/test/regressions.js +0 -215
  120. package/test/script/chronicle.js +0 -543
  121. package/test/script/defaults.js +0 -160
  122. package/test/script/genesis_limits.js +0 -203
  123. package/test/script/interpreter.js +0 -776
  124. package/test/script/script.js +0 -1259
  125. package/test/script/string_ops.js +0 -88
  126. package/test/security/fail_closed_contracts.js +0 -104
  127. package/test/security/threat_model_coverage.js +0 -31
  128. package/test/smart_contract/covenants.js +0 -207
  129. package/test/smart_contract/dsl_debugger.js +0 -92
  130. package/test/smart_contract/extract_field.js +0 -61
  131. package/test/smart_contract/nonenforcing_guard.js +0 -44
  132. package/test/smart_contract/ordinal_transfer.js +0 -71
  133. package/test/smart_contract/preimage.js +0 -98
  134. package/test/smart_contract/sighash_marketplace.js +0 -98
  135. package/test/smart_contract/token_generalized.js +0 -175
  136. package/test/spv/headerchain.js +0 -86
  137. package/test/spv/merkleproof.js +0 -133
  138. package/test/statuslist/failclosed.js +0 -78
  139. package/test/transaction/deserialize.js +0 -33
  140. package/test/transaction/input/input.js +0 -92
  141. package/test/transaction/input/multisig.js +0 -174
  142. package/test/transaction/input/multisigscripthash.js +0 -111
  143. package/test/transaction/input/publickey.js +0 -68
  144. package/test/transaction/input/publickeyhash.js +0 -59
  145. package/test/transaction/output.js +0 -185
  146. package/test/transaction/sighash.js +0 -91
  147. package/test/transaction/signature.js +0 -127
  148. package/test/transaction/transaction.js +0 -1299
  149. package/test/transaction/unspentoutput.js +0 -97
  150. package/test/types/dts_drift.js +0 -124
  151. package/test/types/surface_honesty.js +0 -102
  152. package/test/util/id.js +0 -72
  153. package/test/util/js.js +0 -76
  154. package/test/util/preconditions.js +0 -79
  155. 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
- })