@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,160 +0,0 @@
1
- 'use strict'
2
-
3
- var bsv = require('../..')
4
- var should = require('chai').should()
5
- var BufferWriter = bsv.encoding.BufferWriter
6
- var BufferReader = bsv.encoding.BufferReader
7
- var BN = bsv.crypto.BN
8
-
9
- describe('BufferWriter', function () {
10
- it('should create a new buffer writer', function () {
11
- var bw = new BufferWriter()
12
- should.exist(bw)
13
- })
14
-
15
- describe('#set', function () {
16
- it('set bufs', function () {
17
- var buf1 = Buffer.from([0])
18
- var buf2 = Buffer.from([1])
19
- var bw = new BufferWriter().set({ bufs: [buf1, buf2] })
20
- bw.concat().toString('hex').should.equal('0001')
21
- })
22
- })
23
-
24
- describe('#toBuffer', function () {
25
- it('should concat these two bufs', function () {
26
- var buf1 = Buffer.from([0])
27
- var buf2 = Buffer.from([1])
28
- var bw = new BufferWriter({ bufs: [buf1, buf2] })
29
- bw.toBuffer().toString('hex').should.equal('0001')
30
- })
31
- })
32
-
33
- describe('#concat', function () {
34
- it('should concat these two bufs', function () {
35
- var buf1 = Buffer.from([0])
36
- var buf2 = Buffer.from([1])
37
- var bw = new BufferWriter({ bufs: [buf1, buf2] })
38
- bw.concat().toString('hex').should.equal('0001')
39
- })
40
- })
41
-
42
- describe('#write', function () {
43
- it('should write a buffer', function () {
44
- var buf = Buffer.from([0])
45
- var bw = new BufferWriter()
46
- bw.write(buf)
47
- bw.concat().toString('hex').should.equal('00')
48
- })
49
- })
50
-
51
- describe('#writeUInt8', function () {
52
- it('should write 1', function () {
53
- var bw = new BufferWriter()
54
- bw.writeUInt8(1).concat().toString('hex').should.equal('01')
55
- })
56
- })
57
-
58
- describe('#writeUInt16BE', function () {
59
- it('should write 1', function () {
60
- var bw = new BufferWriter()
61
- bw.writeUInt16BE(1).concat().toString('hex').should.equal('0001')
62
- })
63
- })
64
-
65
- describe('#writeUInt16LE', function () {
66
- it('should write 1', function () {
67
- var bw = new BufferWriter()
68
- bw.writeUInt16LE(1).concat().toString('hex').should.equal('0100')
69
- })
70
- })
71
-
72
- describe('#writeUInt32BE', function () {
73
- it('should write 1', function () {
74
- var bw = new BufferWriter()
75
- bw.writeUInt32BE(1).concat().toString('hex').should.equal('00000001')
76
- })
77
- })
78
-
79
- describe('#writeUInt32LE', function () {
80
- it('should write 1', function () {
81
- var bw = new BufferWriter()
82
- bw.writeUInt32LE(1).concat().toString('hex').should.equal('01000000')
83
- })
84
- })
85
-
86
- describe('#writeUInt64BEBN', function () {
87
- it('should write 1', function () {
88
- var bw = new BufferWriter()
89
- bw.writeUInt64BEBN(new BN(1)).concat().toString('hex').should.equal('0000000000000001')
90
- })
91
- })
92
-
93
- describe('#writeUInt64LEBN', function () {
94
- it('should write 1', function () {
95
- var bw = new BufferWriter()
96
- bw.writeUInt64LEBN(new BN(1)).concat().toString('hex').should.equal('0100000000000000')
97
- })
98
- })
99
-
100
- describe('#writeVarint', function () {
101
- it('should write a 1 byte varint', function () {
102
- var bw = new BufferWriter()
103
- bw.writeVarintNum(1)
104
- bw.concat().length.should.equal(1)
105
- })
106
-
107
- it('should write a 3 byte varint', function () {
108
- var bw = new BufferWriter()
109
- bw.writeVarintNum(1000)
110
- bw.concat().length.should.equal(3)
111
- })
112
-
113
- it('should write a 5 byte varint', function () {
114
- var bw = new BufferWriter()
115
- bw.writeVarintNum(Math.pow(2, 16 + 1))
116
- bw.concat().length.should.equal(5)
117
- })
118
-
119
- it('should write a 9 byte varint', function () {
120
- var bw = new BufferWriter()
121
- bw.writeVarintNum(Math.pow(2, 32 + 1))
122
- bw.concat().length.should.equal(9)
123
- })
124
-
125
- it('should read back the same value it wrote for a 9 byte varint', function () {
126
- var bw = new BufferWriter()
127
- var n = Math.pow(2, 53)
128
- n.should.equal(n + 1) // javascript number precision limit
129
- bw.writeVarintNum(n)
130
- var br = new BufferReader({ buf: bw.concat() })
131
- br.readVarintBN().toNumber().should.equal(n)
132
- })
133
- })
134
-
135
- describe('#writeVarintBN', function () {
136
- it('should write a 1 byte varint', function () {
137
- var bw = new BufferWriter()
138
- bw.writeVarintBN(new BN(1))
139
- bw.concat().length.should.equal(1)
140
- })
141
-
142
- it('should write a 3 byte varint', function () {
143
- var bw = new BufferWriter()
144
- bw.writeVarintBN(new BN(1000))
145
- bw.concat().length.should.equal(3)
146
- })
147
-
148
- it('should write a 5 byte varint', function () {
149
- var bw = new BufferWriter()
150
- bw.writeVarintBN(new BN(Math.pow(2, 16 + 1)))
151
- bw.concat().length.should.equal(5)
152
- })
153
-
154
- it('should write a 9 byte varint', function () {
155
- var bw = new BufferWriter()
156
- bw.writeVarintBN(new BN(Math.pow(2, 32 + 1)))
157
- bw.concat().length.should.equal(9)
158
- })
159
- })
160
- })
@@ -1,104 +0,0 @@
1
- 'use strict'
2
-
3
- var should = require('chai').should()
4
- var bsv = require('../..')
5
- var BN = bsv.crypto.BN
6
- var BufferReader = bsv.encoding.BufferReader
7
- var BufferWriter = bsv.encoding.BufferWriter
8
- var Varint = bsv.encoding.Varint
9
-
10
- describe('Varint', function () {
11
- it('should make a new varint', function () {
12
- var buf = Buffer.from('00', 'hex')
13
- var varint = new Varint(buf)
14
- should.exist(varint)
15
- varint.buf.toString('hex').should.equal('00')
16
- varint = Varint(buf)
17
- should.exist(varint)
18
- varint.buf.toString('hex').should.equal('00')
19
-
20
- // various ways to use the constructor
21
- Varint(Varint(0).toBuffer()).toNumber().should.equal(0)
22
- Varint(0).toNumber().should.equal(0)
23
- Varint(new BN(0)).toNumber().should.equal(0)
24
- })
25
-
26
- describe('#set', function () {
27
- it('should set a buffer', function () {
28
- var buf = Buffer.from('00', 'hex')
29
- var varint = Varint().set({ buf: buf })
30
- varint.buf.toString('hex').should.equal('00')
31
- varint.set({})
32
- varint.buf.toString('hex').should.equal('00')
33
- })
34
- })
35
-
36
- describe('#fromString', function () {
37
- it('should set a buffer', function () {
38
- var buf = BufferWriter().writeVarintNum(5).concat()
39
- var varint = Varint().fromString(buf.toString('hex'))
40
- varint.toNumber().should.equal(5)
41
- })
42
- })
43
-
44
- describe('#toString', function () {
45
- it('should return a buffer', function () {
46
- var buf = BufferWriter().writeVarintNum(5).concat()
47
- var varint = Varint().fromString(buf.toString('hex'))
48
- varint.toString().should.equal('05')
49
- })
50
- })
51
-
52
- describe('#fromBuffer', function () {
53
- it('should set a buffer', function () {
54
- var buf = BufferWriter().writeVarintNum(5).concat()
55
- var varint = Varint().fromBuffer(buf)
56
- varint.toNumber().should.equal(5)
57
- })
58
- })
59
-
60
- describe('#fromBufferReader', function () {
61
- it('should set a buffer reader', function () {
62
- var buf = BufferWriter().writeVarintNum(5).concat()
63
- var br = BufferReader(buf)
64
- var varint = Varint().fromBufferReader(br)
65
- varint.toNumber().should.equal(5)
66
- })
67
- })
68
-
69
- describe('#fromBN', function () {
70
- it('should set a number', function () {
71
- var varint = Varint().fromBN(new BN(5))
72
- varint.toNumber().should.equal(5)
73
- })
74
- })
75
-
76
- describe('#fromNumber', function () {
77
- it('should set a number', function () {
78
- var varint = Varint().fromNumber(5)
79
- varint.toNumber().should.equal(5)
80
- })
81
- })
82
-
83
- describe('#toBuffer', function () {
84
- it('should return a buffer', function () {
85
- var buf = BufferWriter().writeVarintNum(5).concat()
86
- var varint = Varint(buf)
87
- varint.toBuffer().toString('hex').should.equal(buf.toString('hex'))
88
- })
89
- })
90
-
91
- describe('#toBN', function () {
92
- it('should return a buffer', function () {
93
- var varint = Varint(5)
94
- varint.toBN().toString().should.equal(new BN(5).toString())
95
- })
96
- })
97
-
98
- describe('#toNumber', function () {
99
- it('should return a buffer', function () {
100
- var varint = Varint(5)
101
- varint.toNumber().should.equal(5)
102
- })
103
- })
104
- })
@@ -1,146 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it */
4
-
5
- // The GDAF anchoring wrappers take (payload, privateKey, options) while the underlying
6
- // SmartLedgerAnchor methods take (payload, metadata, utxos). Every wrapper forwarded
7
- // `privateKey` into a slot that is not a key. For anchorCredential/anchorBatch it landed
8
- // in `metadata`, which is JSON.stringify-ed straight into the OP_RETURN — so the secret
9
- // scalar was broadcast, and the key was recoverable from chain data with an identical WIF.
10
-
11
- require('chai').should()
12
- var bsv = require('../..')
13
-
14
- describe('GDAF anchoring never publishes key material', function () {
15
- var key = bsv.PrivateKey.fromBuffer(Buffer.alloc(32, 7))
16
- var utxos = [{
17
- txId: '11'.repeat(32),
18
- outputIndex: 0,
19
- script: bsv.Script.buildPublicKeyHashOut(key.toAddress()).toHex(),
20
- satoshis: 100000
21
- }]
22
- var HASH = 'ab'.repeat(32)
23
-
24
- function gdaf () { return new bsv.GDAF() }
25
-
26
- // Pull every OP_RETURN payload out of a built transaction, as UTF-8.
27
- function payloadsOf (result) {
28
- var tx = new bsv.Transaction((result.transaction || result.tx || result).toString())
29
- return tx.outputs.map(function (o) {
30
- var asm = o.script.toASM().split(' ')
31
- return Buffer.from(asm[asm.length - 1], 'hex').toString('utf8')
32
- })
33
- }
34
-
35
- function assertNoSecret (result) {
36
- var scalarHex = key.bn.toString('hex')
37
- var raw = (result.transaction || result.tx || result).toString()
38
- raw.indexOf(Buffer.from(scalarHex, 'utf8').toString('hex')).should.equal(-1)
39
- raw.indexOf(Buffer.from('"bn"', 'utf8').toString('hex')).should.equal(-1)
40
- payloadsOf(result).forEach(function (p) {
41
- p.indexOf(scalarHex).should.equal(-1)
42
- p.indexOf('"bn"').should.equal(-1)
43
- })
44
- }
45
-
46
- it('anchorCredential does not put the key in the OP_RETURN', function () {
47
- return gdaf().anchorCredential(HASH, key, utxos).then(assertNoSecret)
48
- })
49
-
50
- it('anchorBatch does not put the key in the OP_RETURN', function () {
51
- return gdaf().anchorBatch([HASH, 'cd'.repeat(32)], key, utxos).then(assertNoSecret)
52
- })
53
-
54
- it('accepts the documented { utxos, metadata } options shape', function () {
55
- return gdaf().anchorCredential(HASH, key, { utxos: utxos, metadata: { issuer: 'did:web:example' } })
56
- .then(function (r) {
57
- assertNoSecret(r)
58
- // The caller's own metadata still reaches the chain.
59
- payloadsOf(r).join('').indexOf('did:web:example').should.not.equal(-1)
60
- })
61
- })
62
-
63
- it('still accepts a bare UTXO array, the only shape that used to work', function () {
64
- return gdaf().anchorCredential(HASH, key, utxos).then(function (r) {
65
- r.should.be.an('object')
66
- })
67
- })
68
-
69
- // Defence in depth: even reaching the payload builder with key material must fail
70
- // loudly rather than broadcast it.
71
- it('refuses to anchor metadata containing a PrivateKey instance', function () {
72
- return gdaf().anchorCredential(HASH, key, { utxos: utxos, metadata: { signer: key } })
73
- .then(function () { throw new Error('should not have anchored') },
74
- function (err) { err.message.should.match(/Refusing to anchor/) })
75
- })
76
-
77
- it('refuses to anchor metadata carrying a key-shaped field', function () {
78
- return gdaf().anchorCredential(HASH, key, { utxos: utxos, metadata: { wif: key.toWIF() } })
79
- .then(function () { throw new Error('should not have anchored') },
80
- function (err) { err.message.should.match(/key material/) })
81
- })
82
-
83
- it('leaves ordinary metadata alone', function () {
84
- return gdaf().anchorCredential(HASH, key, {
85
- utxos: utxos, metadata: { id: 'urn:uuid:1', nested: { note: 'fine' } }
86
- }).then(function (r) { assertNoSecret(r) })
87
- })
88
- // The guard keyed off field NAMES alone, which was wrong in both directions: it
89
- // rejected `{ d: '2026-01-01' }` as key material while publishing a real WIF stored
90
- // under `note`. Detection is now by value as well as name.
91
- describe('detects key material by value, not just by field name', function () {
92
- var Anchor = require('../../lib/gdaf/smartledger-anchor.js')
93
- var other = bsv.PrivateKey.fromBuffer(Buffer.alloc(32, 99))
94
- var HASH_BUF = bsv.crypto.Hash.sha256(Buffer.from('doc'))
95
-
96
- function build (metadata) {
97
- return new Anchor(key, {})._createAnchorPayload('CREDENTIAL', HASH_BUF, metadata)
98
- }
99
- function refuses (label, metadata) {
100
- it('refuses ' + label, function () {
101
- ;(function () { build(metadata) }).should.throw(/Refusing to anchor/)
102
- })
103
- }
104
- function accepts (label, metadata) {
105
- it('accepts ' + label, function () {
106
- var payload = Buffer.from(build(metadata)).toString('utf8')
107
- payload.indexOf(key.toWIF()).should.equal(-1)
108
- })
109
- }
110
-
111
- // Self-identifying secrets: the encoding says "private key" whatever the field is
112
- // called. Naming a WIF `note` does not make it safe to publish.
113
- refuses('a WIF under an innocuous name', { note: other.toWIF() })
114
- refuses('an xprv under an innocuous name', {
115
- ref: bsv.HDPrivateKey.fromSeed(Buffer.alloc(32, 1)).toString()
116
- })
117
- refuses('a BIP39 mnemonic under an innocuous name', {
118
- memo: 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
119
- })
120
- refuses('a secret nested in an array', { signers: [other.toWIF()] })
121
-
122
- // The anchor's OWN key, in any representation — the exact defect this guard exists
123
- // for. A bare hex scalar is otherwise indistinguishable from a hash, so knowing our
124
- // own key is what makes this catchable.
125
- refuses("the anchor's own key as a raw hex scalar", { backup: key.toString() })
126
- refuses("the anchor's own key as a WIF", { backup: key.toWIF() })
127
-
128
- // Ambiguous names are refused only when the value really is secret.
129
- refuses('d holding a private scalar', { d: other.toString() })
130
- refuses('seed holding a mnemonic', {
131
- seed: 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
132
- })
133
-
134
- // ...and left alone otherwise. Anchoring a document hash is the module's purpose,
135
- // and a 64-hex hash cannot be told apart from a scalar, so it must not be rejected.
136
- accepts('d as a date', { d: '2026-01-01' })
137
- accepts('seed as a campaign name', { seed: 'spring-campaign' })
138
- accepts('a SHA-256 document hash', { docHash: bsv.crypto.Hash.sha256(Buffer.from('x')).toString('hex') })
139
- accepts('key used as an ordinary label', { key: 'value' })
140
-
141
- // Public material is not secret and an anchor legitimately references it.
142
- accepts('an address', { payTo: key.toAddress().toString() })
143
- accepts('a public key', { pub: key.toPublicKey().toString() })
144
- accepts('an xpub', { xpub: bsv.HDPrivateKey.fromSeed(Buffer.alloc(32, 1)).hdPublicKey.toString() })
145
- })
146
- })
@@ -1,163 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it */
4
-
5
- // Trustless SPV anchor verification end-to-end: build a real anchoring tx with an
6
- // OP_RETURN commitment, place it in a block, prove its inclusion with a Merkle
7
- // branch + header, and verify through SmartLedgerAnchor.verifyAnchor with NO trusted
8
- // provider. Replaces the old {verified:true} stub / trust-the-caller-txData path.
9
-
10
- require('chai').should()
11
- var bsv = require('../..')
12
- var Anchor = require('../../lib/gdaf/smartledger-anchor')
13
- var Hash = bsv.crypto.Hash
14
-
15
- function rev (b) { return Buffer.from(b).reverse() }
16
- function buildTree (leaves) {
17
- var tree = leaves.slice(); var j = 0
18
- for (var size = leaves.length; size > 1; size = Math.floor((size + 1) / 2)) {
19
- for (var i = 0; i < size; i += 2) {
20
- var i2 = Math.min(i + 1, size - 1)
21
- tree.push(Hash.sha256sha256(Buffer.concat([tree[j + i], tree[j + i2]])))
22
- }
23
- j += size
24
- }
25
- return tree
26
- }
27
- function rootOf (l) { var t = buildTree(l); return t[t.length - 1] }
28
- function branchFor (leaves, index) {
29
- var tree = buildTree(leaves); var branch = []; var j = 0; var idx = index
30
- for (var size = leaves.length; size > 1; size = Math.floor((size + 1) / 2)) {
31
- var sib = idx ^ 1; if (sib >= size) sib = idx
32
- branch.push(rev(tree[j + sib]).toString('hex'))
33
- j += size; idx = Math.floor(idx / 2)
34
- }
35
- return branch
36
- }
37
-
38
- function anchorTxFor (hashHex) {
39
- var tx = new bsv.Transaction()
40
- tx.addOutput(new bsv.Transaction.Output({
41
- script: bsv.Script.buildDataOut(Buffer.from(hashHex, 'hex')),
42
- satoshis: 0
43
- }))
44
- return tx
45
- }
46
-
47
- function blockOf (rootInternal) {
48
- return new bsv.BlockHeader({
49
- version: 1, prevHash: Buffer.alloc(32), merkleRoot: rootInternal,
50
- time: 1231006505, bits: 0x1d00ffff, nonce: 0
51
- })
52
- }
53
-
54
- // "Mine" a regtest-difficulty header (PoW passes after trivial nonce grinding).
55
- function minedHeader (prevHashInternal, merkleInternal) {
56
- for (var nonce = 0; nonce < 100000; nonce++) {
57
- var h = new bsv.BlockHeader({
58
- version: 1, prevHash: prevHashInternal, merkleRoot: merkleInternal,
59
- time: 1231006505 + nonce, bits: 0x207fffff, nonce: nonce
60
- })
61
- if (h.validProofOfWork()) return h
62
- }
63
- throw new Error('could not mine header')
64
- }
65
-
66
- describe('SPV anchor verification (trustless)', function () {
67
- var anchorHash = Hash.sha256(Buffer.from('anchor me')).toString('hex')
68
- var atx = anchorTxFor(anchorHash)
69
- var rawTx = atx.uncheckedSerialize()
70
- var txid = atx.hash
71
- // Place the anchor tx at index 2 among 5 leaves.
72
- var leaves = [
73
- bsv.crypto.Random.getRandomBuffer(32),
74
- bsv.crypto.Random.getRandomBuffer(32),
75
- atx._getHash(),
76
- bsv.crypto.Random.getRandomBuffer(32),
77
- bsv.crypto.Random.getRandomBuffer(32)
78
- ]
79
- var header = blockOf(rootOf(leaves))
80
- var spvProof = { index: 2, nodes: branchFor(leaves, 2) }
81
-
82
- it('verifies inclusion + commitment with a valid proof', async function () {
83
- var res = await Anchor.verifyAnchor(txid, anchorHash, {
84
- spvProof: spvProof, header: header, rawTx: rawTx, requirePow: false
85
- })
86
- res.verified.should.equal(true)
87
- res.chainVerified.should.equal(true)
88
- res.committed.should.equal(true)
89
- res.txidBound.should.equal(true)
90
- res.proof.type.should.equal('spv_merkle_inclusion')
91
- })
92
-
93
- it('rejects when the tx does not commit to the expected hash', async function () {
94
- var otherHash = Hash.sha256(Buffer.from('something else')).toString('hex')
95
- var res = await Anchor.verifyAnchor(txid, otherHash, {
96
- spvProof: spvProof, header: header, rawTx: rawTx, requirePow: false
97
- })
98
- res.committed.should.equal(false)
99
- res.verified.should.equal(false)
100
- })
101
-
102
- it('rejects a tampered Merkle branch (inclusion fails)', async function () {
103
- var bad = { index: 2, nodes: branchFor(leaves, 2).slice() }
104
- bad.nodes[0] = rev(bsv.crypto.Random.getRandomBuffer(32)).toString('hex')
105
- var res = await Anchor.verifyAnchor(txid, anchorHash, {
106
- spvProof: bad, header: header, rawTx: rawTx, requirePow: false
107
- })
108
- res.chainVerified.should.equal(false)
109
- res.verified.should.equal(false)
110
- })
111
-
112
- it('rejects rawTx that does not hash to txid', async function () {
113
- var otherRaw = anchorTxFor(Hash.sha256(Buffer.from('decoy')).toString('hex')).uncheckedSerialize()
114
- var res = await Anchor.verifyAnchor(txid, anchorHash, {
115
- spvProof: spvProof, header: header, rawTx: otherRaw, requirePow: false
116
- })
117
- res.txidBound.should.equal(false)
118
- res.verified.should.equal(false)
119
- })
120
-
121
- it('still refuses to fabricate a result with neither an SPV proof nor a provider', async function () {
122
- var threw = false
123
- try { await Anchor.verifyAnchor(txid, anchorHash, {}) } catch (e) { threw = true }
124
- threw.should.equal(true)
125
- })
126
-
127
- describe('with a header chain (confirmations under real PoW)', function () {
128
- this.timeout(10000)
129
- // Block containing the tx must carry the real merkle root; then descendants.
130
- var h0 = minedHeader(Buffer.alloc(32), rootOf(leaves))
131
- var h1 = minedHeader(h0._getHash(), bsv.crypto.Random.getRandomBuffer(32))
132
- var h2 = minedHeader(h1._getHash(), bsv.crypto.Random.getRandomBuffer(32))
133
- var headerChain = [h0, h1, h2]
134
-
135
- it('verifies inclusion + 3 confirmations under real proof-of-work', async function () {
136
- var res = await Anchor.verifyAnchor(txid, anchorHash, {
137
- spvProof: spvProof, headerChain: headerChain, rawTx: rawTx, minConfirmations: 3
138
- })
139
- res.verified.should.equal(true)
140
- res.confirmations.should.equal(3)
141
- res.headerChainValid.should.equal(true)
142
- res.powValid.should.equal(true)
143
- res.tipHash.should.equal(h2.id)
144
- res.proof.type.should.equal('spv_merkle_inclusion_with_confirmations')
145
- })
146
-
147
- it('rejects when confirmations are below the required minimum', async function () {
148
- var res = await Anchor.verifyAnchor(txid, anchorHash, {
149
- spvProof: spvProof, headerChain: headerChain, rawTx: rawTx, minConfirmations: 6
150
- })
151
- res.confirmations.should.equal(3)
152
- res.verified.should.equal(false)
153
- })
154
-
155
- it('rejects a header chain with a broken link', async function () {
156
- var res = await Anchor.verifyAnchor(txid, anchorHash, {
157
- spvProof: spvProof, headerChain: [h0, h2], rawTx: rawTx, minConfirmations: 1
158
- })
159
- res.headerChainValid.should.equal(false)
160
- res.verified.should.equal(false)
161
- })
162
- })
163
- })
@@ -1,106 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it */
4
-
5
- // GDAF signs a hash of canonical JSON, so the canonicalization IS part of the signature
6
- // scheme. It was sorted-key JSON that rebuilt the object, which loses the sort: V8 orders
7
- // integer-like own properties numerically, ahead of string keys, whatever order they were
8
- // inserted in.
9
- //
10
- // Within this library that was deterministic — signing and verification agreed, and no
11
- // forgery followed. Across implementations it was a verification failure, which for
12
- // credentials that exist to be checked by other parties is the thing that matters.
13
-
14
- require('chai').should()
15
- var Signer = require('../../lib/gdaf/attestation-signer')
16
-
17
- describe('GDAF canonicalization', function () {
18
- describe('RFC 8785 conformance', function () {
19
- // The concrete divergence. JCS sorts by UTF-16 code unit, where '10' < '2'.
20
- it('sorts integer-like keys lexicographically, not numerically', function () {
21
- var o = {}
22
- o['10'] = 'ten'
23
- o['2'] = 'two'
24
- Signer._canonicalizeJCS(o).should.equal('{"10":"ten","2":"two"}')
25
- })
26
-
27
- it('is what the legacy form got wrong, which is why both exist', function () {
28
- var o = {}
29
- o['10'] = 'ten'
30
- o['2'] = 'two'
31
- Signer._canonicalizeJSON(o).should.equal('{"2":"two","10":"ten"}')
32
- Signer._canonicalizeJCS(o).should.not.equal(Signer._canonicalizeJSON(o))
33
- })
34
-
35
- it('sorts at every depth and leaves arrays in order', function () {
36
- Signer._canonicalizeJCS({ z: { b: 1, a: 2 }, a: [3, { d: 1, c: 2 }] })
37
- .should.equal('{"a":[3,{"c":2,"d":1}],"z":{"a":2,"b":1}}')
38
- })
39
-
40
- it('is insensitive to key insertion order', function () {
41
- var x = {}; x.b = 1; x.a = 2
42
- var y = {}; y.a = 2; y.b = 1
43
- Signer._canonicalizeJCS(x).should.equal(Signer._canonicalizeJCS(y))
44
- })
45
-
46
- // These are the same IEEE-754 double, so collapsing them is correct rather than a
47
- // weakness — JavaScript has one number type. Pinned so nobody "fixes" it.
48
- it('treats 1847, 1847.0 and 1.847e3 as the one number they are', function () {
49
- Signer._canonicalizeJCS({ a: 1847 }).should.equal('{"a":1847}')
50
- Signer._canonicalizeJCS({ a: 1847.0 }).should.equal('{"a":1847}')
51
- Signer._canonicalizeJCS({ a: 1.847e3 }).should.equal('{"a":1847}')
52
- })
53
-
54
- it('keeps a number distinct from its string form', function () {
55
- Signer._canonicalizeJCS({ a: 1847 }).should.not.equal(Signer._canonicalizeJCS({ a: '1847' }))
56
- })
57
-
58
- // JSON.stringify would emit `null` here, silently signing a different document.
59
- it('refuses non-finite numbers rather than emitting null', function () {
60
- ;(function () { Signer._canonicalizeJCS({ a: NaN }) }).should.throw(/non-finite/)
61
- ;(function () { Signer._canonicalizeJCS({ a: Infinity }) }).should.throw(/non-finite/)
62
- })
63
-
64
- it('emits unicode and non-BMP characters directly', function () {
65
- Signer._canonicalizeJCS({ a: 'é' }).should.equal('{"a":"é"}')
66
- Signer._canonicalizeJCS({ a: '😀' }).should.equal('{"a":"😀"}')
67
- })
68
-
69
- it('drops undefined members, which JSON cannot represent', function () {
70
- Signer._canonicalizeJCS({ a: 1, b: undefined }).should.equal('{"a":1}')
71
- })
72
-
73
- it('nulls undefined array elements, as JSON.stringify does', function () {
74
- Signer._canonicalizeJCS([1, undefined, 2]).should.equal('[1,null,2]')
75
- })
76
- })
77
-
78
- describe('hashing and migration', function () {
79
- var CRED = { id: 'urn:x', credentialSubject: { name: 'Alice', age: 41 } }
80
-
81
- it('hashes with JCS by default', function () {
82
- Signer._hashCredential(CRED).toString('hex')
83
- .should.equal(Signer._hashCredential(CRED, Signer.CANONICALIZATION.JCS).toString('hex'))
84
- })
85
-
86
- // The migration path. A credential whose keys make the two forms differ must hash
87
- // differently, or the legacy fallback in the verifier would be pointless.
88
- it('gives a different hash under the legacy form when the forms diverge', function () {
89
- var withIntKeys = { '10': 'ten', '2': 'two' }
90
- Signer._hashCredential(withIntKeys, Signer.CANONICALIZATION.JCS).toString('hex')
91
- .should.not.equal(
92
- Signer._hashCredential(withIntKeys, Signer.CANONICALIZATION.LEGACY).toString('hex')
93
- )
94
- })
95
-
96
- it('agrees between the forms when no integer-like keys are present', function () {
97
- Signer._hashCredential(CRED, Signer.CANONICALIZATION.JCS).toString('hex')
98
- .should.equal(Signer._hashCredential(CRED, Signer.CANONICALIZATION.LEGACY).toString('hex'))
99
- })
100
-
101
- it('exposes both forms by name', function () {
102
- Signer.CANONICALIZATION.JCS.should.equal('jcs')
103
- Signer.CANONICALIZATION.LEGACY.should.equal('legacy')
104
- })
105
- })
106
- })