@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,97 +0,0 @@
1
- 'use strict'
2
-
3
- var chai = require('chai')
4
- var expect = chai.expect
5
- /* global structuredClone */
6
- // structuredClone, not the former clone-deep dependency: the fixture below is plain
7
- // JSON (strings and numbers), where the two are equivalent. The interpreter's stack
8
- // clone is NOT — it holds Buffers, which structuredClone would return as Uint8Array.
9
- // The global comment is for standard@12's eslint, which predates the API.
10
- var cloneDeep = structuredClone
11
-
12
- var bsv = require('../..')
13
- var UnspentOutput = bsv.Transaction.UnspentOutput
14
-
15
- describe('UnspentOutput', function () {
16
- var sampleData1 = {
17
- 'address': 'mszYqVnqKoQx4jcTdJXxwKAissE3Jbrrc1',
18
- 'txId': 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
19
- 'outputIndex': 0,
20
- 'script': 'OP_DUP OP_HASH160 20 0x88d9931ea73d60eaf7e5671efc0552b912911f2a OP_EQUALVERIFY OP_CHECKSIG',
21
- 'satoshis': 1020000
22
- }
23
- var sampleData2 = {
24
- 'txid': 'e42447187db5a29d6db161661e4bc66d61c3e499690fe5ea47f87b79ca573986',
25
- 'vout': 1,
26
- 'address': 'mgBCJAsvzgT2qNNeXsoECg2uPKrUsZ76up',
27
- 'scriptPubKey': '76a914073b7eae2823efa349e3b9155b8a735526463a0f88ac',
28
- 'amount': 0.01080000
29
- }
30
-
31
- it('roundtrip from raw data', function () {
32
- expect(UnspentOutput(sampleData2).toObject()).to.deep.equal(sampleData2)
33
- })
34
-
35
- it('can be created without "new" operand', function () {
36
- expect(UnspentOutput(sampleData1) instanceof UnspentOutput).to.equal(true)
37
- })
38
-
39
- it('fails if no tx id is provided', function () {
40
- expect(function () {
41
- return new UnspentOutput({})
42
- }).to.throw()
43
- })
44
-
45
- it('fails if vout is not a number', function () {
46
- var sample = cloneDeep(sampleData2)
47
- sample.vout = '1'
48
- expect(function () {
49
- return new UnspentOutput(sample)
50
- }).to.throw()
51
- })
52
-
53
- it('displays nicely on the console', function () {
54
- var expected = '<UnspentOutput: a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458:0' +
55
- ', satoshis: 1020000, address: mszYqVnqKoQx4jcTdJXxwKAissE3Jbrrc1>'
56
- expect(new UnspentOutput(sampleData1).inspect()).to.equal(expected)
57
- })
58
-
59
- describe('checking the constructor parameters', function () {
60
- var notDefined = {
61
- 'txId': 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
62
- 'outputIndex': 0,
63
- 'script': 'OP_DUP OP_HASH160 20 0x88d9931ea73d60eaf7e5671efc0552b912911f2a OP_EQUALVERIFY OP_CHECKSIG'
64
- }
65
- var zero = {
66
- 'txId': 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
67
- 'outputIndex': 0,
68
- 'script': 'OP_DUP OP_HASH160 20 0x88d9931ea73d60eaf7e5671efc0552b912911f2a OP_EQUALVERIFY OP_CHECKSIG',
69
- 'amount': 0
70
- }
71
- it('fails when no amount is defined', function () {
72
- expect(function () {
73
- return new UnspentOutput(notDefined)
74
- }).to.throw('Must provide an amount for the output')
75
- })
76
- it('does not fail when amount is zero', function () {
77
- expect(function () {
78
- return new UnspentOutput(zero)
79
- }).to.not.throw()
80
- })
81
- })
82
-
83
- it('toString returns txid:vout', function () {
84
- var expected = 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458:0'
85
- expect(new UnspentOutput(sampleData1).toString()).to.equal(expected)
86
- })
87
-
88
- it('to/from JSON roundtrip', function () {
89
- var utxo = new UnspentOutput(sampleData2)
90
- var obj = UnspentOutput.fromObject(utxo.toJSON()).toObject()
91
- expect(obj).to.deep.equal(sampleData2)
92
- var str = JSON.stringify(UnspentOutput.fromObject(obj))
93
- expect(JSON.parse(str)).to.deep.equal(sampleData2)
94
- var str2 = JSON.stringify(new UnspentOutput(JSON.parse(str)))
95
- expect(JSON.parse(str2)).to.deep.equal(sampleData2)
96
- })
97
- })
@@ -1,124 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it, before */
4
-
5
- // TYPE-DRIFT GATE — mechanically proves the hand-maintained `bsv.d.ts` does not lie
6
- // about the runtime. `bsv.d.ts` is a curated public-API surface (better than anything
7
- // auto-generated from the spotty JSDoc), but nothing stopped it drifting — its own
8
- // header said "3.4.x" on a 6.x package. This test parses the .d.ts with the real
9
- // TypeScript AST and asserts:
10
- // (1) every declared value symbol (class / function / const, at any nesting) EXISTS
11
- // at runtime — no phantom APIs that the types promise but the code doesn't have;
12
- // (2) for the audited namespaces (Ordinals, Ordinals.BSV20, SPV) every runtime
13
- // function is DECLARED — so new APIs there can't ship untyped.
14
- // Interfaces and type aliases are compile-time only and are ignored.
15
-
16
- require('chai').should()
17
- var path = require('path')
18
- var fs = require('fs')
19
- var ts = require('typescript')
20
- var bsv = require('../..')
21
-
22
- var DTS_PATH = path.join(__dirname, '../../bsv.d.ts')
23
- var MODULE_NAME = '@smartledger/bsv'
24
-
25
- // Walk the `declare module '@smartledger/bsv'` block and collect the dotted path of
26
- // every value declaration (class / function / const), recursing into namespaces.
27
- function collectDeclaredPaths (source) {
28
- var sf = ts.createSourceFile('bsv.d.ts', source, ts.ScriptTarget.Latest, true)
29
- var paths = []
30
- var moduleBody = null
31
-
32
- sf.forEachChild(function (node) {
33
- if (ts.isModuleDeclaration(node) && node.name && ts.isStringLiteral(node.name) &&
34
- node.name.text === MODULE_NAME && node.body && ts.isModuleBlock(node.body)) {
35
- moduleBody = node.body
36
- }
37
- })
38
- if (!moduleBody) throw new Error('could not find `declare module "' + MODULE_NAME + '"` in bsv.d.ts')
39
-
40
- function walk (statements, prefix) {
41
- statements.forEach(function (node) {
42
- if (ts.isModuleDeclaration(node) && node.name && node.body && ts.isModuleBlock(node.body)) {
43
- // A namespace: recurse (the namespace itself is checked via its members' paths).
44
- walk(node.body.statements, prefix.concat(node.name.text))
45
- } else if (ts.isClassDeclaration(node) && node.name) {
46
- paths.push(prefix.concat(node.name.text))
47
- } else if (ts.isFunctionDeclaration(node) && node.name) {
48
- var p = prefix.concat(node.name.text)
49
- p.returnType = node.type ? node.type.getText() : null
50
- paths.push(p)
51
- } else if (ts.isVariableStatement(node)) {
52
- node.declarationList.declarations.forEach(function (d) {
53
- if (ts.isIdentifier(d.name)) paths.push(prefix.concat(d.name.text))
54
- })
55
- }
56
- // InterfaceDeclaration / TypeAliasDeclaration: compile-time only — ignored.
57
- })
58
- }
59
- walk(moduleBody.statements, [])
60
- return paths
61
- }
62
-
63
- // Resolve a dotted path on the runtime object; returns undefined if any segment is missing.
64
- function resolve (root, segments) {
65
- return segments.reduce(function (o, k) { return (o == null) ? undefined : o[k] }, root)
66
- }
67
-
68
- describe('types: bsv.d.ts does not drift from runtime', function () {
69
- var declaredPaths
70
-
71
- before(function () {
72
- declaredPaths = collectDeclaredPaths(fs.readFileSync(DTS_PATH, 'utf8'))
73
- })
74
-
75
- it('parses a non-trivial number of declared symbols', function () {
76
- // Sanity: if the parse silently produced nothing, the whole gate would be a no-op.
77
- declaredPaths.length.should.be.above(50)
78
- })
79
-
80
- it('every declared class / function / const exists at runtime (no phantom API)', function () {
81
- var missing = declaredPaths
82
- .filter(function (segs) { return resolve(bsv, segs) === undefined })
83
- .map(function (segs) { return segs.join('.') })
84
- missing.should.deep.equal([], 'bsv.d.ts declares these but runtime does not expose them:\n ' + missing.join('\n '))
85
- })
86
-
87
- // Reverse direction where it matters most: the modules added in 6.x must stay fully typed.
88
- var AUDITED = [
89
- { label: 'Ordinals', obj: bsv.Ordinals, decl: 'Ordinals' },
90
- { label: 'Ordinals.BSV20', obj: bsv.Ordinals && bsv.Ordinals.BSV20, decl: 'Ordinals.BSV20' },
91
- { label: 'SPV', obj: bsv.SPV, decl: 'SPV' }
92
- ]
93
-
94
- // An `async` runtime function declared with a non-Promise return type is the most
95
- // dangerous kind of drift, because the type checker actively hides the bug rather than
96
- // merely failing to catch it: `StatusList.getCredentialStatusEntry` was declared
97
- // `: CredentialStatus` while being async, so `if (fn(...) === 'revoked')` compiled clean
98
- // and was ALWAYS false — every revoked credential passed as valid.
99
- it('no async runtime function is declared with a synchronous return type', function () {
100
- var lies = []
101
- declaredPaths.forEach(function (segs) {
102
- if (!segs.returnType) return
103
- var fn = resolve(bsv, segs)
104
- if (typeof fn !== 'function') return
105
- var isAsync = fn.constructor && fn.constructor.name === 'AsyncFunction'
106
- var declaresPromise = /\bPromise\s*</.test(segs.returnType)
107
- if (isAsync && !declaresPromise) {
108
- lies.push(segs.join('.') + ' is async but is declared `: ' + segs.returnType + '`')
109
- }
110
- })
111
- lies.should.deep.equal([], 'these declarations hide a Promise:\n ' + lies.join('\n '))
112
- })
113
-
114
- AUDITED.forEach(function (ns) {
115
- it('every runtime function on ' + ns.label + ' is declared in bsv.d.ts', function () {
116
- ns.obj.should.be.an('object')
117
- var declaredSet = {}
118
- declaredPaths.forEach(function (segs) { declaredSet[segs.join('.')] = true })
119
- var runtimeFns = Object.keys(ns.obj).filter(function (k) { return typeof ns.obj[k] === 'function' })
120
- var untyped = runtimeFns.filter(function (k) { return !declaredSet[ns.decl + '.' + k] })
121
- untyped.should.deep.equal([], ns.label + ' exposes these functions but bsv.d.ts does not declare them:\n ' + untyped.join('\n '))
122
- })
123
- })
124
- })
@@ -1,102 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it */
4
-
5
- // Runtime half of a field review that found declarations disagreeing with the code.
6
- // The declarations themselves are gated by dts_drift.js and by the tsc check in CI; the
7
- // cases below are the ones where the RUNTIME also had to change, because a declaration
8
- // that merely matched the old behaviour would have been documenting a bug.
9
-
10
- var should = require('chai').should()
11
- var bsv = require('../..')
12
- var SC = bsv.SmartContract
13
-
14
- describe('public surface tells the truth about itself', function () {
15
- describe('SmartContract.ownershipToken forwards its authorizer', function () {
16
- it('is not a two-argument alias that drops the third', function () {
17
- // The top-level alias took (fee, ownerPubKeyHash) and called through with only
18
- // those two, so a co-signed token built via this path came out single-key — the
19
- // authorizer was accepted and silently discarded.
20
- var auth = SC.Authorizers.multisig(2, 3)
21
- var withAuth = SC.ownershipToken(1, Buffer.alloc(20), auth).toHex()
22
- var without = SC.ownershipToken(1, Buffer.alloc(20)).toHex()
23
- withAuth.should.not.equal(without)
24
- })
25
-
26
- it('agrees with SmartContract.Token.ownershipToken', function () {
27
- var auth = SC.Authorizers.multisig(2, 3)
28
- SC.ownershipToken(1, Buffer.alloc(20), auth).toHex()
29
- .should.equal(SC.Token.ownershipToken(1, Buffer.alloc(20), auth).toHex())
30
- })
31
- })
32
-
33
- describe('Authorizers.multisig takes a key COUNT', function () {
34
- it('rejects an array of keys instead of silently building a broken authorizer', function () {
35
- // `m > nKeys` compared a number to an array, which coerces to NaN, so the guard
36
- // passed and the array was interpolated into the authorizer's name.
37
- var keys = [1, 2, 3].map(function () {
38
- return bsv.PrivateKey.fromRandom().toPublicKey().toBuffer()
39
- })
40
- ;(function () { SC.Authorizers.multisig(2, keys) }).should.throw(/NUMBER of keys/)
41
- // The message names the fix.
42
- ;(function () { SC.Authorizers.multisig(2, keys) }).should.throw(/pass 3 instead/)
43
- })
44
-
45
- it('still accepts the documented count form', function () {
46
- SC.Authorizers.multisig(2, 3).n.should.equal(3)
47
- SC.Authorizers.multisig(2, 3).m.should.equal(2)
48
- })
49
-
50
- it('rejects non-integer m', function () {
51
- (function () { SC.Authorizers.multisig('2', 3) }).should.throw(/m must be an integer/)
52
- })
53
- })
54
-
55
- describe('StatusList refuses to record a suspension as a revocation', function () {
56
- it('throws on status: suspended rather than setting the revocation bit', function () {
57
- // Both statuses set the SAME bit and read back as 'revoked', so a suspension was
58
- // silently recorded — and later reported — as a permanent revocation.
59
- return bsv.StatusList.updateStatusList({
60
- listVcJwt: 'x', index: 1, status: 'suspended', privateJwk: {}
61
- }).then(
62
- function () { throw new Error('should not have accepted suspended') },
63
- function (err) { err.message.should.match(/'suspended' is not supported/) }
64
- )
65
- })
66
- })
67
-
68
- describe('securityFeatures describes what is actually shipped', function () {
69
- it('no longer claims elliptic patches, since elliptic is not a dependency', function () {
70
- var pkg = require('../../package.json')
71
- var deps = Object.keys(pkg.dependencies || {})
72
- deps.indexOf('elliptic').should.equal(-1)
73
- bsv.securityFeatures.indexOf('elliptic-patches').should.equal(-1)
74
- bsv.securityFeatures.should.be.an('array')
75
- bsv.securityFeatures.length.should.be.above(0)
76
- })
77
- })
78
-
79
- describe('documented sub-path entry points resolve', function () {
80
- // Every one of these was MODULE_NOT_FOUND: the package `exports` map had no aliases
81
- // for the *-entry.js files, so a documented deep import could not be loaded at all.
82
- var SUBPATHS = ['didweb', 'vcjwt', 'gdaf', 'ltp', 'statuslist', 'shamir',
83
- 'anchor', 'covenant', 'security', 'smartcontract', 'script-helper']
84
-
85
- SUBPATHS.forEach(function (name) {
86
- it('@smartledger/bsv/' + name, function () {
87
- var mod = require('@smartledger/bsv/' + name)
88
- // Some entry points export a class (a function), others a namespace object.
89
- var t = typeof mod
90
- t.should.be.oneOf(['object', 'function'])
91
- should.exist(mod)
92
- })
93
- })
94
-
95
- it('still resolves the package root and lib deep imports', function () {
96
- require('@smartledger/bsv').should.be.an('object')
97
- require('@smartledger/bsv/version').should.be.a('string')
98
- // Directory deep-imports need the explicit file — a documented 7.0 exports break.
99
- require('@smartledger/bsv/lib/ordinals/index.js').should.be.an('object')
100
- })
101
- })
102
- })
package/test/util/id.js DELETED
@@ -1,72 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it */
4
-
5
- require('chai').should()
6
- var expect = require('chai').expect
7
-
8
- var Id = require('../../lib/util/id')
9
-
10
- var UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
11
-
12
- describe('util/id', function () {
13
- describe('#uuid4', function () {
14
- it('produces a well-formed RFC 4122 v4 uuid', function () {
15
- Id.uuid4().should.match(UUID_V4)
16
- })
17
-
18
- it('sets the version and variant bits on every draw', function () {
19
- for (var i = 0; i < 200; i++) {
20
- Id.uuid4().should.match(UUID_V4)
21
- }
22
- })
23
-
24
- it('does not repeat', function () {
25
- var seen = {}
26
- for (var i = 0; i < 2000; i++) {
27
- var id = Id.uuid4()
28
- expect(seen[id], 'duplicate uuid: ' + id).to.equal(undefined)
29
- seen[id] = true
30
- }
31
- })
32
- })
33
-
34
- describe('#randomHex', function () {
35
- it('returns the requested number of hex characters', function () {
36
- Id.randomHex(16).should.match(/^[0-9a-f]{16}$/)
37
- Id.randomHex(12).should.match(/^[0-9a-f]{12}$/)
38
- Id.randomHex(1).should.match(/^[0-9a-f]$/)
39
- })
40
-
41
- it('does not repeat', function () {
42
- var seen = {}
43
- for (var i = 0; i < 2000; i++) {
44
- var id = Id.randomHex(16)
45
- expect(seen[id], 'duplicate id: ' + id).to.equal(undefined)
46
- seen[id] = true
47
- }
48
- })
49
- })
50
-
51
- describe('entropy source', function () {
52
- // Identifiers must come from the CSPRNG. Freezing the engine PRNG must not
53
- // affect them; if it does, they are predictable from observed output.
54
- var withFrozenMathRandom = function (fn) {
55
- var original = Math.random
56
- Math.random = function () { return 0.5 }
57
- try { return fn() } finally { Math.random = original }
58
- }
59
-
60
- it('uuid4 is unaffected by the engine PRNG', function () {
61
- withFrozenMathRandom(function () {
62
- Id.uuid4().should.not.equal(Id.uuid4())
63
- })
64
- })
65
-
66
- it('randomHex is unaffected by the engine PRNG', function () {
67
- withFrozenMathRandom(function () {
68
- Id.randomHex(16).should.not.equal(Id.randomHex(16))
69
- })
70
- })
71
- })
72
- })
package/test/util/js.js DELETED
@@ -1,76 +0,0 @@
1
- 'use strict'
2
-
3
- require('chai').should()
4
-
5
- var bsv = require('../..')
6
- var JSUtil = bsv.util.js
7
-
8
- describe('js utils', function () {
9
- describe('isValidJSON', function () {
10
- var hexa = '8080808080808080808080808080808080808080808080808080808080808080'
11
- var json = '{"key": ["value", "value2"]}'
12
- var json2 = '["value", "value2", {"key": "value"}]'
13
-
14
- it('does not mistake an integer as valid json object', function () {
15
- var valid = JSUtil.isValidJSON(hexa)
16
- valid.should.equal(false)
17
- })
18
-
19
- it('correctly validates a json object', function () {
20
- var valid = JSUtil.isValidJSON(json)
21
- valid.should.equal(true)
22
- })
23
-
24
- it('correctly validates an array json object', function () {
25
- var valid = JSUtil.isValidJSON(json2)
26
- valid.should.equal(true)
27
- })
28
- })
29
-
30
- describe('isNaturalNumber', function () {
31
- it('false for float', function () {
32
- var a = JSUtil.isNaturalNumber(0.1)
33
- a.should.equal(false)
34
- })
35
-
36
- it('false for string float', function () {
37
- var a = JSUtil.isNaturalNumber('0.1')
38
- a.should.equal(false)
39
- })
40
-
41
- it('false for string integer', function () {
42
- var a = JSUtil.isNaturalNumber('1')
43
- a.should.equal(false)
44
- })
45
-
46
- it('false for negative integer', function () {
47
- var a = JSUtil.isNaturalNumber(-1)
48
- a.should.equal(false)
49
- })
50
-
51
- it('false for negative integer string', function () {
52
- var a = JSUtil.isNaturalNumber('-1')
53
- a.should.equal(false)
54
- })
55
-
56
- it('false for infinity', function () {
57
- var a = JSUtil.isNaturalNumber(Infinity)
58
- a.should.equal(false)
59
- })
60
-
61
- it('false for NaN', function () {
62
- var a = JSUtil.isNaturalNumber(NaN)
63
- a.should.equal(false)
64
- })
65
-
66
- it('true for zero', function () {
67
- var a = JSUtil.isNaturalNumber(0)
68
- a.should.equal(true)
69
- })
70
-
71
- it('true for positive integer', function () {
72
- var a = JSUtil.isNaturalNumber(1000)
73
- a.should.equal(true)
74
- })
75
- })
76
- })
@@ -1,79 +0,0 @@
1
- 'use strict'
2
-
3
- var should = require('chai').should()
4
-
5
- var bsv = require('../..')
6
- var errors = bsv.errors
7
- var $ = bsv.util.preconditions
8
- var PrivateKey = bsv.PrivateKey
9
-
10
- describe('preconditions', function () {
11
- it('can be used to assert state', function () {
12
- (function () {
13
- $.checkState(false, 'testing')
14
- }).should.throw(errors.InvalidState)
15
- })
16
- it('throws no false negative', function () {
17
- (function () {
18
- $.checkState(true, 'testing')
19
- }).should.not.throw()
20
- })
21
-
22
- it('can be used to check an argument', function () {
23
- (function () {
24
- $.checkArgument(false, 'testing')
25
- }).should.throw(errors.InvalidArgument);
26
-
27
- (function () {
28
- $.checkArgument(true, 'testing')
29
- }).should.not.throw(errors.InvalidArgument)
30
- })
31
-
32
- it('can be used to check an argument type', function () {
33
- var error
34
- try {
35
- $.checkArgumentType(1, 'string', 'argumentName')
36
- } catch (e) {
37
- error = e
38
- e.message.should.equal('Invalid Argument for argumentName, expected string but got number')
39
- }
40
- should.exist(error)
41
- })
42
- it('has no false negatives when used to check an argument type', function () {
43
- (function () {
44
- $.checkArgumentType('a String', 'string', 'argumentName')
45
- }).should.not.throw()
46
- })
47
-
48
- it('can be used to check an argument type for a class', function () {
49
- var error
50
- try {
51
- $.checkArgumentType(1, PrivateKey)
52
- } catch (e) {
53
- error = e
54
- var fail = !(~e.message.indexOf('Invalid Argument for (unknown name)'))
55
- fail.should.equal(false)
56
- }
57
- should.exist(error)
58
- })
59
- it('has no false negatives when checking a type for a class', function () {
60
- (function () {
61
- $.checkArgumentType(new PrivateKey(), PrivateKey)
62
- }).should.not.throw()
63
- })
64
-
65
- it('formats correctly a message on InvalidArgument()', function () {
66
- var error = new errors.InvalidArgument()
67
- error.message.should.equal('Invalid Argument')
68
- })
69
-
70
- it('formats correctly a message on checkArgument', function () {
71
- var error
72
- try {
73
- $.checkArgument(null, 'parameter must be provided')
74
- } catch (e) {
75
- error = e
76
- }
77
- error.message.should.equal('Invalid Argument: parameter must be provided')
78
- })
79
- })
@@ -1,126 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it */
4
-
5
- // Proves the VC-JWT module is interoperable with the standards-compliant
6
- // `jose` library in BOTH directions, for ES256 (P-256) and ES256K (secp256k1),
7
- // and that algorithm pinning / curve binding reject substitution attacks.
8
-
9
- var assert = require('assert')
10
- var crypto = require('crypto')
11
- var jose = require('jose')
12
- var vcjwt = require('../../lib/vcjwt')
13
-
14
- function genKeys (alg, namedCurve) {
15
- var pair = crypto.generateKeyPairSync('ec', { namedCurve: namedCurve })
16
- var privateJwk = pair.privateKey.export({ format: 'jwk' })
17
- var publicJwk = pair.publicKey.export({ format: 'jwk' })
18
- privateJwk.kid = publicJwk.kid = 'test-key-1'
19
- privateJwk.alg = publicJwk.alg = alg
20
- return { privateJwk: privateJwk, publicJwk: publicJwk }
21
- }
22
-
23
- function resolverFor (publicJwk) {
24
- return function () {
25
- return Promise.resolve({ jwks: { keys: [publicJwk] } })
26
- }
27
- }
28
-
29
- var CASES = [
30
- { alg: 'ES256', curve: 'prime256v1' },
31
- { alg: 'ES256K', curve: 'secp256k1' }
32
- ]
33
-
34
- describe('vcjwt JOSE interop', function () {
35
- CASES.forEach(function (c) {
36
- it('issues a token that ' + c.alg + ' jose can verify (P1363 encoding)', async function () {
37
- var keys = genKeys(c.alg, c.curve)
38
- var issued = await vcjwt.issueVcJwt({
39
- issuerDid: 'did:web:example.com',
40
- subjectId: 'did:web:subject.example',
41
- credentialSubject: { name: 'Alice' },
42
- privateJwk: keys.privateJwk,
43
- alg: c.alg
44
- })
45
- var joseKey = await jose.importJWK(keys.publicJwk, c.alg)
46
- var result = await jose.jwtVerify(issued.jwt, joseKey) // throws if non-compliant
47
- assert.strictEqual(result.payload.iss, 'did:web:example.com')
48
- })
49
-
50
- it('verifies a ' + c.alg + ' token issued by jose', async function () {
51
- var keys = genKeys(c.alg, c.curve)
52
- var josePriv = await jose.importJWK(keys.privateJwk, c.alg)
53
- var joseJwt = await new jose.SignJWT({ vc: { type: ['VerifiableCredential'] } })
54
- .setProtectedHeader({ alg: c.alg, typ: 'JWT', kid: keys.publicJwk.kid })
55
- .setIssuer('did:web:example.com')
56
- .setSubject('did:web:subject.example')
57
- .setIssuedAt()
58
- .setExpirationTime('1y')
59
- .sign(josePriv)
60
- var res = await vcjwt.verifyVcJwt(joseJwt, { didResolver: resolverFor(keys.publicJwk) })
61
- assert.strictEqual(res.valid, true, res.error)
62
- })
63
- })
64
-
65
- it('rejects a token whose alg is not in the allowlist', async function () {
66
- var keys = genKeys('ES256', 'prime256v1')
67
- var issued = await vcjwt.issueVcJwt({
68
- issuerDid: 'did:web:example.com', subjectId: 's', credentialSubject: {}, privateJwk: keys.privateJwk, alg: 'ES256'
69
- })
70
- var res = await vcjwt.verifyVcJwt(issued.jwt, {
71
- allowedAlgs: ['ES256K'],
72
- didResolver: resolverFor(keys.publicJwk)
73
- })
74
- assert.strictEqual(res.valid, false)
75
- assert.ok(/Algorithm not allowed/.test(res.error), res.error)
76
- })
77
-
78
- it('rejects when the resolved key curve does not match the algorithm', async function () {
79
- // ES256 token, but the JWKS serves a secp256k1 key under the same kid.
80
- var p256 = genKeys('ES256', 'prime256v1')
81
- var k1 = genKeys('ES256K', 'secp256k1')
82
- var issued = await vcjwt.issueVcJwt({
83
- issuerDid: 'did:web:example.com', subjectId: 's', credentialSubject: {}, privateJwk: p256.privateJwk, alg: 'ES256'
84
- })
85
- var res = await vcjwt.verifyVcJwt(issued.jwt, { didResolver: resolverFor(k1.publicJwk) })
86
- assert.strictEqual(res.valid, false)
87
- assert.ok(/curve does not match/.test(res.error), res.error)
88
- })
89
-
90
- it('refuses to sign when the key curve does not match the algorithm', async function () {
91
- var k1 = genKeys('ES256K', 'secp256k1')
92
- var threw = false
93
- try {
94
- await vcjwt.issueVcJwt({
95
- issuerDid: 'did:web:example.com', subjectId: 's', credentialSubject: {}, privateJwk: k1.privateJwk, alg: 'ES256'
96
- })
97
- } catch (e) {
98
- threw = /does not match alg/.test(e.message)
99
- }
100
- assert.ok(threw, 'expected curve/alg mismatch to throw')
101
- })
102
-
103
- it('accepts a legacy DER-encoded token only when allowLegacyDER is set', async function () {
104
- // Simulate a <=4.6.0 token: same signing input, but DER-encoded signature.
105
- var keys = genKeys('ES256', 'prime256v1')
106
- var header = { alg: 'ES256', typ: 'JWT', kid: keys.publicJwk.kid }
107
- var payload = { iss: 'did:web:example.com', sub: 's', iat: 1700000000, exp: 4102444800, vc: {} }
108
- var headerB64 = vcjwt.base64UrlEncode(Buffer.from(JSON.stringify(header)))
109
- var payloadB64 = vcjwt.base64UrlEncode(Buffer.from(JSON.stringify(payload)))
110
- var signingInput = headerB64 + '.' + payloadB64
111
- var derSig = crypto.sign('sha256', Buffer.from(signingInput), {
112
- key: crypto.createPrivateKey({ key: keys.privateJwk, format: 'jwk' }),
113
- dsaEncoding: 'der'
114
- })
115
- var legacyJwt = signingInput + '.' + vcjwt.base64UrlEncode(derSig)
116
-
117
- var rejected = await vcjwt.verifyVcJwt(legacyJwt, { didResolver: resolverFor(keys.publicJwk) })
118
- assert.strictEqual(rejected.valid, false, 'legacy DER token must fail by default')
119
-
120
- var accepted = await vcjwt.verifyVcJwt(legacyJwt, {
121
- allowLegacyDER: true,
122
- didResolver: resolverFor(keys.publicJwk)
123
- })
124
- assert.strictEqual(accepted.valid, true, accepted.error)
125
- })
126
- })