@smartledger/bsv 8.3.1 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +228 -0
- package/README.md +152 -1031
- package/STABILITY.md +134 -0
- package/bsv-gdaf.min.js +58 -53
- package/bsv-ltp.min.js +23 -18
- package/bsv-script-helper.min.js +1 -1
- package/bsv-smartcontract.min.js +21 -21
- package/bsv.bundle.js +58 -53
- package/bsv.d.ts +0 -4
- package/bsv.min.js +58 -53
- package/docs/BRC220_BATCH_LEAF_AMENDMENT.md +82 -7
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- package/docs/README.md +2 -1
- package/docs/THREAT_MODEL.md +10 -2
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/getting-started/INSTALLATION.md +23 -23
- package/docs/getting-started/QUICK_START.md +7 -7
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/docs/proposals/10.0.0-package-split.md +131 -0
- package/index.js +15 -26
- package/lib/block/merkleblock.js +19 -5
- package/lib/covenant/helpers.js +34 -35
- package/lib/covenant/pushtx.js +2 -2
- package/lib/custom-script-helper.js +0 -16
- package/lib/hdprivatekey.js +15 -0
- package/lib/ordinals/ordlock.js +1 -1
- package/lib/script/interpreter.js +109 -1
- package/lib/smart_contract/builder.js +14 -0
- package/lib/smart_contract/debugger.js +2 -2
- package/lib/smart_contract/dsl.js +2 -2
- package/lib/smart_contract/index.js +0 -3
- package/lib/smart_contract/locks.js +1 -41
- package/lib/smart_contract/pels.js +1 -1
- package/lib/smart_contract/token.js +1 -1
- package/lib/util/deprecate.js +159 -0
- package/package.json +19 -82
- package/tools/gen-brc220-batch-vector.js +205 -0
- package/version.js +1 -1
- package/.mocharc.json +0 -5
- package/test/address.js +0 -629
- package/test/block/block.js +0 -239
- package/test/block/blockheader.js +0 -270
- package/test/block/merkleblock.js +0 -207
- package/test/build/bundle_crypto_shim.js +0 -104
- package/test/build/bundle_externals.js +0 -125
- package/test/build/bundle_smoke.js +0 -55
- package/test/build/esbuild_main.js +0 -65
- package/test/build/esm_wrapper.js +0 -73
- package/test/build/exports_resolution.js +0 -84
- package/test/build/version_sync.js +0 -14
- package/test/cli/smoke.js +0 -261
- package/test/consensus/base58-vectors.js +0 -120
- package/test/consensus/sv-script-vectors.js +0 -81
- package/test/consensus/sv-sighash-vectors.js +0 -51
- package/test/consensus/sv-tx-vectors.js +0 -48
- package/test/credentials-test.js +0 -332
- package/test/crypto/backend_selection.js +0 -126
- package/test/crypto/bn.js +0 -168
- package/test/crypto/ecdsa.js +0 -426
- package/test/crypto/elliptic-fixed.js +0 -61
- package/test/crypto/hash.browser.js +0 -121
- package/test/crypto/hash.js +0 -122
- package/test/crypto/point.js +0 -193
- package/test/crypto/random.js +0 -105
- package/test/crypto/security.js +0 -176
- package/test/crypto/shamir.js +0 -177
- package/test/crypto/shamir_rngcap.js +0 -29
- package/test/crypto/signature.js +0 -399
- package/test/data/bip69.json +0 -215
- package/test/data/bitcoin-sv/README.md +0 -170
- package/test/data/bitcoin-sv/base58_encode_decode.json +0 -14
- package/test/data/bitcoin-sv/base58_keys_invalid.json +0 -152
- package/test/data/bitcoin-sv/base58_keys_valid.json +0 -452
- package/test/data/bitcoin-sv/script_tests.json +0 -2591
- package/test/data/bitcoin-sv/sighash.json +0 -1003
- package/test/data/bitcoin-sv/tx_invalid.json +0 -285
- package/test/data/bitcoin-sv/tx_valid.json +0 -367
- package/test/data/bitcoind/base58_keys_invalid.json +0 -152
- package/test/data/bitcoind/base58_keys_valid.json +0 -452
- package/test/data/bitcoind/blocks.json +0 -27
- package/test/data/bitcoind/script_tests.json +0 -2244
- package/test/data/bitcoind/sig_canonical.json +0 -7
- package/test/data/bitcoind/sig_noncanonical.json +0 -22
- package/test/data/bitcoind/tx_invalid.json +0 -177
- package/test/data/bitcoind/tx_valid.json +0 -224
- package/test/data/blk86756-testnet.dat +0 -0
- package/test/data/blk86756-testnet.js +0 -12
- package/test/data/blk86756-testnet.json +0 -684
- package/test/data/ecdsa.json +0 -230
- package/test/data/merkleblocks.js +0 -486
- package/test/data/messages.json +0 -22
- package/test/data/sighash.json +0 -1004
- package/test/data/tx_creation.json +0 -85
- package/test/didweb/relationships.js +0 -144
- package/test/ecies/bitcore-ecies.js +0 -178
- package/test/ecies/electrum-ecies.js +0 -206
- package/test/encoding/base58.js +0 -131
- package/test/encoding/base58check.js +0 -145
- package/test/encoding/bufferreader.js +0 -328
- package/test/encoding/bufferwriter.js +0 -160
- package/test/encoding/varint.js +0 -104
- package/test/gdaf/anchor_no_key_leak.js +0 -146
- package/test/gdaf/anchor_spv.js +0 -163
- package/test/gdaf/canonicalization.js +0 -106
- package/test/gdaf/canonicalize.js +0 -140
- package/test/gdaf/zk_prover.js +0 -204
- package/test/hdkeys.js +0 -365
- package/test/hdprivatekey.js +0 -339
- package/test/hdpublickey.js +0 -293
- package/test/index.js +0 -16
- package/test/ltp/ids.js +0 -74
- package/test/ltp/right.js +0 -198
- package/test/ltp/verify_failclosed.js +0 -134
- package/test/message/message.js +0 -190
- package/test/mnemonic/data/fixtures.json +0 -300
- package/test/mnemonic/mnemonic.js +0 -277
- package/test/mnemonic/mocha.opts +0 -1
- package/test/mnemonic/pbkdf2.test.js +0 -43
- package/test/networks.js +0 -207
- package/test/notaryhash/batch_leaf.js +0 -140
- package/test/notaryhash/certificate.js +0 -249
- package/test/notaryhash/encoding.js +0 -186
- package/test/notaryhash/interop.js +0 -112
- package/test/notaryhash/merkle.js +0 -181
- package/test/notaryhash/script.js +0 -270
- package/test/notaryhash/verify.js +0 -342
- package/test/opcode.js +0 -186
- package/test/ordinals/bsv20.js +0 -337
- package/test/ordinals/inscription.js +0 -319
- package/test/ordinals/ordlock.js +0 -613
- package/test/privatekey.js +0 -540
- package/test/publickey.js +0 -411
- package/test/regressions.js +0 -215
- package/test/script/chronicle.js +0 -543
- package/test/script/defaults.js +0 -160
- package/test/script/genesis_limits.js +0 -203
- package/test/script/interpreter.js +0 -776
- package/test/script/script.js +0 -1259
- package/test/script/string_ops.js +0 -88
- package/test/security/fail_closed_contracts.js +0 -104
- package/test/security/threat_model_coverage.js +0 -31
- package/test/smart_contract/covenants.js +0 -245
- package/test/smart_contract/dsl_debugger.js +0 -101
- package/test/smart_contract/extract_field.js +0 -61
- package/test/smart_contract/nonenforcing_guard.js +0 -44
- package/test/smart_contract/ordinal_transfer.js +0 -81
- package/test/smart_contract/preimage.js +0 -98
- package/test/smart_contract/sighash_marketplace.js +0 -108
- package/test/smart_contract/token_generalized.js +0 -185
- package/test/spv/headerchain.js +0 -86
- package/test/spv/merkleproof.js +0 -133
- package/test/statuslist/failclosed.js +0 -78
- package/test/transaction/deserialize.js +0 -33
- package/test/transaction/input/input.js +0 -92
- package/test/transaction/input/multisig.js +0 -174
- package/test/transaction/input/multisigscripthash.js +0 -111
- package/test/transaction/input/publickey.js +0 -68
- package/test/transaction/input/publickeyhash.js +0 -59
- package/test/transaction/output.js +0 -185
- package/test/transaction/sighash.js +0 -91
- package/test/transaction/signature.js +0 -127
- package/test/transaction/transaction.js +0 -1299
- package/test/transaction/unspentoutput.js +0 -97
- package/test/types/dts_drift.js +0 -124
- package/test/types/surface_honesty.js +0 -102
- package/test/util/id.js +0 -72
- package/test/util/js.js +0 -76
- package/test/util/preconditions.js +0 -79
- package/test/vcjwt/interop.js +0 -126
package/test/ltp/ids.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/* global describe, it */
|
|
4
|
-
|
|
5
|
-
require('chai').should()
|
|
6
|
-
var expect = require('chai').expect
|
|
7
|
-
|
|
8
|
-
var bsv = require('../../index.js')
|
|
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
|
-
// A token id is covered by the credential's signature, keys the registry's
|
|
13
|
-
// registration/revocation maps, and feeds proof material — so it must be
|
|
14
|
-
// unpredictable, not merely distinct.
|
|
15
|
-
describe('LTP identifiers', function () {
|
|
16
|
-
var generators = [
|
|
17
|
-
{ name: 'Right._generateUUID', fn: function () { return bsv.LTP.Right._generateUUID() }, format: UUID_V4 },
|
|
18
|
-
{ name: 'Obligation._generateUUID', fn: function () { return bsv.LTP.Obligation._generateUUID() }, format: UUID_V4 },
|
|
19
|
-
{ name: 'Registry._generateRegistryId', fn: function () { return bsv.LTP.Registry._generateRegistryId() }, format: /^reg_[0-9a-f]{16}$/ },
|
|
20
|
-
{ name: 'Registry._generateAuditId', fn: function () { return bsv.LTP.Registry._generateAuditId() }, format: /^audit_[0-9a-f]{32}$/ },
|
|
21
|
-
{ name: 'Claim._generateBatchId', fn: function () { return bsv.LTP.Claim._generateBatchId() }, format: /^[0-9a-f]{16}$/ }
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
var withFrozenMathRandom = function (fn) {
|
|
25
|
-
var original = Math.random
|
|
26
|
-
Math.random = function () { return 0.5 }
|
|
27
|
-
try { return fn() } finally { Math.random = original }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
generators.forEach(function (g) {
|
|
31
|
-
describe(g.name, function () {
|
|
32
|
-
it('keeps its documented format', function () {
|
|
33
|
-
g.fn().should.match(g.format)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('does not repeat', function () {
|
|
37
|
-
var seen = {}
|
|
38
|
-
for (var i = 0; i < 500; i++) {
|
|
39
|
-
var id = g.fn()
|
|
40
|
-
expect(seen[id], 'duplicate id: ' + id).to.equal(undefined)
|
|
41
|
-
seen[id] = true
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('does not draw from the engine PRNG', function () {
|
|
46
|
-
withFrozenMathRandom(function () {
|
|
47
|
-
var seen = {}
|
|
48
|
-
for (var i = 0; i < 100; i++) {
|
|
49
|
-
var id = g.fn()
|
|
50
|
-
expect(seen[id], 'id is predictable from the engine PRNG: ' + id).to.equal(undefined)
|
|
51
|
-
seen[id] = true
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('issues unpredictable ids on real tokens', function () {
|
|
59
|
-
var type = Object.values(bsv.LTP.Right.RightTypes)[0]
|
|
60
|
-
var ids = {}
|
|
61
|
-
for (var i = 0; i < 25; i++) {
|
|
62
|
-
var token = bsv.LTP.Right.create(
|
|
63
|
-
type,
|
|
64
|
-
'did:example:issuer',
|
|
65
|
-
'did:example:subject',
|
|
66
|
-
{ description: 'test right' }
|
|
67
|
-
)
|
|
68
|
-
token.id.should.match(/^urn:uuid:/)
|
|
69
|
-
token.id.replace('urn:uuid:', '').should.match(UUID_V4)
|
|
70
|
-
expect(ids[token.id], 'duplicate token id').to.equal(undefined)
|
|
71
|
-
ids[token.id] = true
|
|
72
|
-
}
|
|
73
|
-
})
|
|
74
|
-
})
|
package/test/ltp/right.js
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/* global describe, it */
|
|
4
|
-
|
|
5
|
-
// Regression tests for LTP right-token creation, signing, transfer and the
|
|
6
|
-
// instance LTP#createRightToken path. These guard three defects fixed together:
|
|
7
|
-
// 1. lib/ltp/right.js defined `_signToken` twice; the second definition
|
|
8
|
-
// shadowed the working one and referenced an undefined `hash` — every
|
|
9
|
-
// prepareRightToken / transfer / reissue / obligation signing threw
|
|
10
|
-
// "hash is not defined". The second definition is the detached-JWS builder
|
|
11
|
-
// and is now `_createJWS(hash, signature)`.
|
|
12
|
-
// 2. lib/ltp/index.js#createRightToken called the non-existent
|
|
13
|
-
// `LTPRight.create(...)`. `RightToken.create` now exists (build-only).
|
|
14
|
-
// 3. lib/ltp/index.js#createRightToken signed via the non-existent
|
|
15
|
-
// `LTPProof.createSignature`; it now signs via `RightToken._signToken`.
|
|
16
|
-
|
|
17
|
-
var expect = require('chai').expect
|
|
18
|
-
var bsv = require('../../')
|
|
19
|
-
|
|
20
|
-
var LTP = bsv.LTP
|
|
21
|
-
var RightToken = LTP.Right
|
|
22
|
-
|
|
23
|
-
function newDid () {
|
|
24
|
-
var key = bsv.PrivateKey.fromRandom()
|
|
25
|
-
return { key: key, did: 'did:key:' + key.toPublicKey().toString() }
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
describe('LTP right-token signing (regression)', function () {
|
|
29
|
-
it('prepareRightToken produces a signed token with a JWS proof and tokenHash', function () {
|
|
30
|
-
var issuer = newDid()
|
|
31
|
-
var result = RightToken.prepareRightToken(
|
|
32
|
-
'EquityShare', issuer.did, issuer.did,
|
|
33
|
-
{ spv: 'spv-001', units: 1000000 }, issuer.key, { jurisdiction: 'US-DE' }
|
|
34
|
-
)
|
|
35
|
-
expect(result.success).to.equal(true)
|
|
36
|
-
expect(result.rightToken).to.be.an('object')
|
|
37
|
-
expect(result.rightToken.proof).to.be.an('object')
|
|
38
|
-
expect(result.rightToken.proof.jws).to.be.a('string').with.length.greaterThan(0)
|
|
39
|
-
expect(result.rightToken.tokenHash).to.match(/^[0-9a-f]{64}$/)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('a prepared right token passes verification (hash integrity)', function () {
|
|
43
|
-
var issuer = newDid()
|
|
44
|
-
var result = RightToken.prepareRightToken(
|
|
45
|
-
'PropertyTitle', issuer.did, issuer.did,
|
|
46
|
-
{ parcel: '123 Main St' }, issuer.key, {}
|
|
47
|
-
)
|
|
48
|
-
expect(result.success).to.equal(true)
|
|
49
|
-
var verification = RightToken.prepareRightTokenVerification(result.rightToken, {})
|
|
50
|
-
expect(verification.success).to.equal(true)
|
|
51
|
-
expect(verification.verification.valid).to.equal(true)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('RightToken.create builds an unsigned token structure', function () {
|
|
55
|
-
var issuer = newDid()
|
|
56
|
-
var token = RightToken.create(
|
|
57
|
-
'EquityShare', issuer.did, issuer.did, { spv: 'spv-001' }, issuer.key, {}
|
|
58
|
-
)
|
|
59
|
-
expect(token).to.be.an('object')
|
|
60
|
-
expect(token.credentialSubject.rightType).to.equal('EquityShare')
|
|
61
|
-
expect(token.proof).to.equal(undefined)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it('rejects an invalid right type', function () {
|
|
65
|
-
var issuer = newDid()
|
|
66
|
-
expect(function () {
|
|
67
|
-
RightToken.create('NotAType', issuer.did, issuer.did, {}, issuer.key, {})
|
|
68
|
-
}).to.throw(/Invalid right type/)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('prepareRightTokenTransfer signs a transfer to a new owner', function () {
|
|
72
|
-
var issuer = newDid()
|
|
73
|
-
var created = RightToken.prepareRightToken(
|
|
74
|
-
'EquityShare', issuer.did, issuer.did, { spv: 'spv-001', units: 1000000 }, issuer.key, {}
|
|
75
|
-
)
|
|
76
|
-
expect(created.success).to.equal(true)
|
|
77
|
-
var buyer = newDid()
|
|
78
|
-
var transfer = RightToken.prepareRightTokenTransfer(created.rightToken, buyer.did, issuer.key, {})
|
|
79
|
-
expect(transfer.success).to.equal(true)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('LTP#createRightToken (instance) returns a signed, verifiable token', function () {
|
|
83
|
-
var issuer = newDid()
|
|
84
|
-
var ltp = new LTP()
|
|
85
|
-
var res = ltp.createRightToken(
|
|
86
|
-
{ type: 'EquityShare', owner: issuer.did, spv: 'spv-001', units: 1000000 },
|
|
87
|
-
issuer.key, {}
|
|
88
|
-
)
|
|
89
|
-
expect(res.success).to.equal(true)
|
|
90
|
-
expect(res.token.proof.jws).to.be.a('string').with.length.greaterThan(0)
|
|
91
|
-
expect(res.token.tokenHash).to.match(/^[0-9a-f]{64}$/)
|
|
92
|
-
|
|
93
|
-
var verification = RightToken.prepareRightTokenVerification(res.token, {})
|
|
94
|
-
expect(verification.verification.valid).to.equal(true)
|
|
95
|
-
})
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
// Guards for the LTP.prototype wrappers that shared the prior "prepare* vs
|
|
99
|
-
// create*" naming mismatch. Before the fix verifyToken called the missing
|
|
100
|
-
// LTPProof.verifySignature, transferRight called the missing LTPRight.transfer
|
|
101
|
-
// + LTPProof.createSignature, createObligation called the missing
|
|
102
|
-
// LTPRight.createObligation, and createSelectiveDisclosure /
|
|
103
|
-
// createLegalValidityProof called missing LTPProof.create* entrypoints — all
|
|
104
|
-
// threw. RightToken.verifyToken is the new public-key signature verifier.
|
|
105
|
-
describe('LTP instance token operations (regression)', function () {
|
|
106
|
-
function signedRight () {
|
|
107
|
-
var issuer = newDid()
|
|
108
|
-
var ltp = new LTP()
|
|
109
|
-
var res = ltp.createRightToken(
|
|
110
|
-
{ type: 'EquityShare', owner: issuer.did, spv: 'spv-001', units: 1000000 },
|
|
111
|
-
issuer.key, {}
|
|
112
|
-
)
|
|
113
|
-
expect(res.success).to.equal(true)
|
|
114
|
-
return { issuer: issuer, ltp: ltp, token: res.token }
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
it('RightToken.verifyToken accepts a token signed by the matching key', function () {
|
|
118
|
-
var ctx = signedRight()
|
|
119
|
-
var result = RightToken.verifyToken(ctx.token, ctx.issuer.key.toPublicKey().toString())
|
|
120
|
-
expect(result.valid).to.equal(true)
|
|
121
|
-
expect(result.errors).to.deep.equal([])
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('RightToken.verifyToken rejects a wrong public key', function () {
|
|
125
|
-
var ctx = signedRight()
|
|
126
|
-
var stranger = newDid()
|
|
127
|
-
var result = RightToken.verifyToken(ctx.token, stranger.key.toPublicKey().toString())
|
|
128
|
-
expect(result.valid).to.equal(false)
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it('RightToken.verifyToken rejects a tampered token', function () {
|
|
132
|
-
var ctx = signedRight()
|
|
133
|
-
ctx.token.credentialSubject.units = 2
|
|
134
|
-
var result = RightToken.verifyToken(ctx.token, ctx.issuer.key.toPublicKey().toString())
|
|
135
|
-
expect(result.valid).to.equal(false)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
it('LTP#verifyToken validates an instance-created right token', function () {
|
|
139
|
-
var ctx = signedRight()
|
|
140
|
-
var result = ctx.ltp.verifyToken(ctx.token, ctx.issuer.key.toPublicKey().toString())
|
|
141
|
-
expect(result.valid).to.equal(true)
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
it('LTP#transferRight produces a signed token owned by the new owner', function () {
|
|
145
|
-
var ctx = signedRight()
|
|
146
|
-
var buyer = newDid()
|
|
147
|
-
var res = ctx.ltp.transferRight(ctx.token, buyer.did, ctx.issuer.key, {})
|
|
148
|
-
expect(res.success).to.equal(true)
|
|
149
|
-
expect(res.token.credentialSubject.id).to.equal(buyer.did)
|
|
150
|
-
expect(res.token.proof.jws).to.be.a('string').with.length.greaterThan(0)
|
|
151
|
-
expect(res.transferProof).to.be.an('object')
|
|
152
|
-
// New token is signed by the transferring (current) owner's key.
|
|
153
|
-
var check = RightToken.verifyToken(res.token, ctx.issuer.key.toPublicKey().toString())
|
|
154
|
-
expect(check.valid).to.equal(true)
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('LTP#transferRight refuses a non-transferable token', function () {
|
|
158
|
-
var issuer = newDid()
|
|
159
|
-
var ltp = new LTP()
|
|
160
|
-
var created = ltp.createRightToken(
|
|
161
|
-
{ type: 'EquityShare', owner: issuer.did, spv: 'spv-001' },
|
|
162
|
-
issuer.key, { transferable: false }
|
|
163
|
-
)
|
|
164
|
-
expect(created.success).to.equal(true)
|
|
165
|
-
var buyer = newDid()
|
|
166
|
-
var res = ltp.transferRight(created.token, buyer.did, issuer.key, {})
|
|
167
|
-
expect(res.success).to.equal(false)
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
it('LTP#createObligation produces a signed correlative obligation', function () {
|
|
171
|
-
var ctx = signedRight()
|
|
172
|
-
var obligor = newDid()
|
|
173
|
-
var res = ctx.ltp.createObligation(
|
|
174
|
-
ctx.token,
|
|
175
|
-
{ obligor: obligor.did, description: 'deliver shares', dueDate: '2030-01-01' },
|
|
176
|
-
ctx.issuer.key
|
|
177
|
-
)
|
|
178
|
-
expect(res.success).to.equal(true)
|
|
179
|
-
expect(res.obligation.proof.jws).to.be.a('string').with.length.greaterThan(0)
|
|
180
|
-
expect(res.obligation.credentialSubject.correlativeRight).to.equal(ctx.token.id)
|
|
181
|
-
expect(res.rightTokenId).to.equal(ctx.token.id)
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
it('LTP#createSelectiveDisclosure builds a disclosure proof', function () {
|
|
185
|
-
var ctx = signedRight()
|
|
186
|
-
var res = ctx.ltp.createSelectiveDisclosure(ctx.token, ['credentialSubject.rightType'], 'nonce-123')
|
|
187
|
-
expect(res.success).to.equal(true)
|
|
188
|
-
expect(res.proof).to.be.an('object')
|
|
189
|
-
expect(res.proof.type).to.equal('LegalTokenSelectiveDisclosure')
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('LTP#createLegalValidityProof builds a validity proof', function () {
|
|
193
|
-
var ctx = signedRight()
|
|
194
|
-
var res = ctx.ltp.createLegalValidityProof(ctx.token, { name: 'US-DE', requirements: [] }, 'nonce-456')
|
|
195
|
-
expect(res.success).to.equal(true)
|
|
196
|
-
expect(res.proof).to.be.an('object')
|
|
197
|
-
})
|
|
198
|
-
})
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/* global describe, it */
|
|
4
|
-
|
|
5
|
-
// Regression guard for the C1–C4 fail-open verification bugs. Before the fix,
|
|
6
|
-
// LTP signature verification returned the ECDSA instance (always truthy) or
|
|
7
|
-
// skipped the JWS check entirely (a `// TODO`), so a forged token verified as
|
|
8
|
-
// valid. These tests feed known-bad signatures/issuers and assert valid===false.
|
|
9
|
-
|
|
10
|
-
var expect = require('chai').expect
|
|
11
|
-
var bsv = require('../../')
|
|
12
|
-
|
|
13
|
-
var LTP = bsv.LTP
|
|
14
|
-
var RightToken = LTP.Right
|
|
15
|
-
var Obligation = LTP.Obligation
|
|
16
|
-
|
|
17
|
-
function newDid () {
|
|
18
|
-
var key = bsv.PrivateKey.fromRandom()
|
|
19
|
-
return { key: key, did: 'did:key:' + key.toPublicKey().toString() }
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
describe('LTP verification fails closed (C1–C4 regression)', function () {
|
|
23
|
-
it('a genuinely signed right token still verifies as valid', function () {
|
|
24
|
-
var issuer = newDid()
|
|
25
|
-
var result = RightToken.prepareRightToken(
|
|
26
|
-
'EquityShare', issuer.did, issuer.did,
|
|
27
|
-
{ spv: 'spv-001', units: 1000 }, issuer.key, {}
|
|
28
|
-
)
|
|
29
|
-
expect(result.success).to.equal(true)
|
|
30
|
-
var v = RightToken.prepareRightTokenVerification(result.rightToken, {})
|
|
31
|
-
expect(v.verification.valid, JSON.stringify(v.verification.errors)).to.equal(true)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('a tampered JWS signature is rejected (C4)', function () {
|
|
35
|
-
var issuer = newDid()
|
|
36
|
-
var result = RightToken.prepareRightToken(
|
|
37
|
-
'EquityShare', issuer.did, issuer.did, { spv: 'x' }, issuer.key, {}
|
|
38
|
-
)
|
|
39
|
-
var token = result.rightToken
|
|
40
|
-
// Flip the signature: replace it with a signature over different data by a
|
|
41
|
-
// different key, re-encoded as a valid-looking JWS.
|
|
42
|
-
var attacker = newDid()
|
|
43
|
-
var parts = token.proof.jws.split('.')
|
|
44
|
-
var bogusSig = bsv.crypto.ECDSA.sign(
|
|
45
|
-
bsv.crypto.Hash.sha256(Buffer.from('not the token')), attacker.key
|
|
46
|
-
)
|
|
47
|
-
token.proof.jws = parts[0] + '.' + parts[1] + '.' + bogusSig.toDER().toString('base64url')
|
|
48
|
-
|
|
49
|
-
var v = RightToken.prepareRightTokenVerification(token, {})
|
|
50
|
-
expect(v.verification.valid).to.equal(false)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('a token re-signed by an attacker but attributed to the victim issuer is rejected (C4 binding)', function () {
|
|
54
|
-
var victim = newDid()
|
|
55
|
-
var attacker = newDid()
|
|
56
|
-
var result = RightToken.prepareRightToken(
|
|
57
|
-
'PropertyTitle', victim.did, victim.did, { parcel: '1 Main' }, victim.key, {}
|
|
58
|
-
)
|
|
59
|
-
var token = result.rightToken
|
|
60
|
-
// Attacker re-signs the exact token hash with THEIR key, but leaves issuer =
|
|
61
|
-
// victim. Verification must bind to the victim issuer key and reject.
|
|
62
|
-
var sig = bsv.crypto.ECDSA.sign(
|
|
63
|
-
bsv.crypto.Hash.sha256(Buffer.from(RightToken._canonicalizeToken(token))), attacker.key
|
|
64
|
-
)
|
|
65
|
-
var parts = token.proof.jws.split('.')
|
|
66
|
-
token.proof.jws = parts[0] + '.' + parts[1] + '.' + sig.toDER().toString('base64url')
|
|
67
|
-
|
|
68
|
-
var v = RightToken.prepareRightTokenVerification(token, {})
|
|
69
|
-
expect(v.verification.valid).to.equal(false)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('prepareRightTokenTransfer rejects a transfer signed by a non-owner (ownership binding)', function () {
|
|
73
|
-
var owner = newDid()
|
|
74
|
-
var attacker = newDid()
|
|
75
|
-
var res = RightToken.prepareRightToken(
|
|
76
|
-
'EquityShare', owner.did, owner.did, { spv: 't-1' }, owner.key, {}
|
|
77
|
-
)
|
|
78
|
-
var token = res.rightToken
|
|
79
|
-
// Attacker tries to transfer a token they do not own → must be refused.
|
|
80
|
-
var bad = RightToken.prepareRightTokenTransfer(token, attacker.did, attacker.key, {})
|
|
81
|
-
expect(bad.success).to.equal(false)
|
|
82
|
-
// The genuine owner can transfer.
|
|
83
|
-
var good = RightToken.prepareRightTokenTransfer(token, attacker.did, owner.key, {})
|
|
84
|
-
expect(good.success, JSON.stringify(good.error)).to.equal(true)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('verifyOwnership rejects a signature by the wrong key (C2)', function () {
|
|
88
|
-
var owner = newDid()
|
|
89
|
-
var attacker = newDid()
|
|
90
|
-
var Resolver = require('../../lib/gdaf/did-resolver')
|
|
91
|
-
var did = 'did:smartledger:' + owner.key.toPublicKey().toString()
|
|
92
|
-
var msg = 'transfer authorization'
|
|
93
|
-
// Signature by attacker, checked against owner's DID → must be false.
|
|
94
|
-
var badSig = bsv.crypto.ECDSA.sign(bsv.crypto.Hash.sha256(Buffer.from(msg)), attacker.key)
|
|
95
|
-
expect(Resolver.verifyOwnership(did, badSig.toString(), msg)).to.equal(false)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('verifyAnchor refuses to fabricate success without a chain provider (C3)', async function () {
|
|
99
|
-
var Anchor = require('../../lib/gdaf/smartledger-anchor')
|
|
100
|
-
var threw = false
|
|
101
|
-
try {
|
|
102
|
-
await Anchor.verifyAnchor('deadbeef', 'cafe')
|
|
103
|
-
} catch (e) {
|
|
104
|
-
threw = true
|
|
105
|
-
}
|
|
106
|
-
expect(threw).to.equal(true)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('a genuinely signed obligation token still verifies as valid', function () {
|
|
110
|
-
var issuer = newDid()
|
|
111
|
-
var ob = Obligation.prepareObligationToken(
|
|
112
|
-
'PaymentObligation', issuer.did, issuer.did, { amount: 1 }, issuer.key, {}
|
|
113
|
-
)
|
|
114
|
-
expect(ob.success).to.equal(true)
|
|
115
|
-
var v = Obligation.prepareObligationVerification(ob.obligationToken, {})
|
|
116
|
-
expect(v.verification.valid, JSON.stringify(v.verification && v.verification.errors)).to.equal(true)
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
it('a tampered obligation signature is rejected (C4)', function () {
|
|
120
|
-
var issuer = newDid()
|
|
121
|
-
var attacker = newDid()
|
|
122
|
-
var ob = Obligation.prepareObligationToken(
|
|
123
|
-
'PaymentObligation', issuer.did, issuer.did, { amount: 1 }, issuer.key, {}
|
|
124
|
-
)
|
|
125
|
-
var tok = ob.obligationToken
|
|
126
|
-
var sig = bsv.crypto.ECDSA.sign(
|
|
127
|
-
bsv.crypto.Hash.sha256(Buffer.from('forged')), attacker.key
|
|
128
|
-
)
|
|
129
|
-
var parts = tok.proof.jws.split('.')
|
|
130
|
-
tok.proof.jws = parts[0] + '.' + parts[1] + '.' + sig.toDER().toString('base64url')
|
|
131
|
-
var v = Obligation.prepareObligationVerification(tok, {})
|
|
132
|
-
expect(v.verification.valid).to.equal(false)
|
|
133
|
-
})
|
|
134
|
-
})
|
package/test/message/message.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
var chai = require('chai')
|
|
4
|
-
var expect = chai.expect
|
|
5
|
-
var should = chai.should()
|
|
6
|
-
|
|
7
|
-
var bsv = require('../../')
|
|
8
|
-
var Address = bsv.Address
|
|
9
|
-
var Signature = bsv.crypto.Signature
|
|
10
|
-
var PrivateKey = bsv.PrivateKey
|
|
11
|
-
var Message = require('../../lib/message')
|
|
12
|
-
|
|
13
|
-
describe('Message', function () {
|
|
14
|
-
var address = 'n1ZCYg9YXtB5XCZazLxSmPDa8iwJRZHhGx'
|
|
15
|
-
var badAddress = 'mmRcrB5fTwgxaFJmVLNtaG8SV454y1E3kC'
|
|
16
|
-
var privateKey = bsv.PrivateKey.fromWIF('cPBn5A4ikZvBTQ8D7NnvHZYCAxzDZ5Z2TSGW2LkyPiLxqYaJPBW4')
|
|
17
|
-
var text = 'hello, world'
|
|
18
|
-
var textBuffer = Buffer.from('hello, world')
|
|
19
|
-
var bufferData = Buffer.from('H/DIn8uA1scAuKLlCx+/9LnAcJtwQQ0PmcPrJUq90aboLv3fH5fFvY+vmbfOSFEtGarznYli6ShPr9RXwY9UrIY=', 'base64')
|
|
20
|
-
var signatureString = 'H/DIn8uA1scAuKLlCx+/9LnAcJtwQQ0PmcPrJUq90aboLv3fH5fFvY+vmbfOSFEtGarznYli6ShPr9RXwY9UrIY='
|
|
21
|
-
|
|
22
|
-
var badSignatureString = 'H69qZ4mbZCcvXk7CWjptD5ypnYVLvQ3eMXLM8+1gX21SLH/GaFnAjQrDn37+TDw79i9zHhbiMMwhtvTwnPigZ6k='
|
|
23
|
-
|
|
24
|
-
var signature = Signature.fromCompact(Buffer.from(signatureString, 'base64'))
|
|
25
|
-
var badSignature = Signature.fromCompact(Buffer.from(badSignatureString, 'base64'))
|
|
26
|
-
|
|
27
|
-
var publicKey = privateKey.toPublicKey()
|
|
28
|
-
|
|
29
|
-
it('will error with incorrect message type', function () {
|
|
30
|
-
expect(function () {
|
|
31
|
-
return new Message(new Date())
|
|
32
|
-
}).to.throw('First argument should be a string')
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it('will instantiate without "new"', function () {
|
|
36
|
-
var message = Message(text)
|
|
37
|
-
should.exist(message)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
var signature2
|
|
41
|
-
var signature3
|
|
42
|
-
|
|
43
|
-
it('can sign a message', function () {
|
|
44
|
-
var message2 = new Message(text)
|
|
45
|
-
signature2 = message2._sign(privateKey)
|
|
46
|
-
signature3 = Message(text).sign(privateKey)
|
|
47
|
-
should.exist(signature2)
|
|
48
|
-
should.exist(signature3)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('can sign a message (buffer representation of utf-8 string)', function () {
|
|
52
|
-
var messageBuf = new Message(textBuffer)
|
|
53
|
-
var signatureBuffer1 = messageBuf.sign(privateKey)
|
|
54
|
-
var signatureBuffer2 = Message(textBuffer).sign(privateKey)
|
|
55
|
-
should.exist(signatureBuffer1)
|
|
56
|
-
should.exist(signatureBuffer2)
|
|
57
|
-
var verified = messageBuf.verify(address, signatureBuffer1.toString()) && messageBuf.verify(address, signatureBuffer2.toString())
|
|
58
|
-
verified.should.equal(true)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('can sign a message (buffer representation of arbitrary data)', function () {
|
|
62
|
-
var messageBuf = new Message(bufferData)
|
|
63
|
-
var signatureBuffer1 = messageBuf.sign(privateKey)
|
|
64
|
-
var signatureBuffer2 = Message(bufferData).sign(privateKey)
|
|
65
|
-
should.exist(signatureBuffer1)
|
|
66
|
-
should.exist(signatureBuffer2)
|
|
67
|
-
var verified = messageBuf.verify(address, signatureBuffer1.toString()) && messageBuf.verify(address, signatureBuffer2.toString())
|
|
68
|
-
verified.should.equal(true)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('sign will error with incorrect private key argument', function () {
|
|
72
|
-
expect(function () {
|
|
73
|
-
var message3 = new Message(text)
|
|
74
|
-
return message3.sign('not a private key')
|
|
75
|
-
}).to.throw('First argument should be an instance of PrivateKey')
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
it('can verify a message with signature', function () {
|
|
79
|
-
var message4 = new Message(text)
|
|
80
|
-
var verified = message4._verify(publicKey, signature2)
|
|
81
|
-
verified.should.equal(true)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('can verify a message with existing signature', function () {
|
|
85
|
-
var message5 = new Message(text)
|
|
86
|
-
var verified = message5._verify(publicKey, signature)
|
|
87
|
-
verified.should.equal(true)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
it('verify will error with incorrect public key argument', function () {
|
|
91
|
-
expect(function () {
|
|
92
|
-
var message6 = new Message(text)
|
|
93
|
-
return message6._verify('not a public key', signature)
|
|
94
|
-
}).to.throw('First argument should be an instance of PublicKey')
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('verify will error with incorrect signature argument', function () {
|
|
98
|
-
expect(function () {
|
|
99
|
-
var message7 = new Message(text)
|
|
100
|
-
return message7._verify(publicKey, 'not a signature')
|
|
101
|
-
}).to.throw('Second argument should be an instance of Signature')
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('verify will correctly identify a bad signature', function () {
|
|
105
|
-
var message8 = new Message(text)
|
|
106
|
-
var verified = message8._verify(publicKey, badSignature)
|
|
107
|
-
should.exist(message8.error)
|
|
108
|
-
verified.should.equal(false)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
it('can verify a message with address and generated signature string', function () {
|
|
112
|
-
var message9 = new Message(text)
|
|
113
|
-
var verified = message9.verify(address, signature3)
|
|
114
|
-
should.not.exist(message9.error)
|
|
115
|
-
verified.should.equal(true)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('will not verify with address mismatch', function () {
|
|
119
|
-
var message10 = new Message(text)
|
|
120
|
-
var verified = message10.verify(badAddress, signatureString)
|
|
121
|
-
should.exist(message10.error)
|
|
122
|
-
verified.should.equal(false)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
it('will verify with an uncompressed pubkey', function () {
|
|
126
|
-
var privateKey = new bsv.PrivateKey('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss')
|
|
127
|
-
var message = new Message('This is an example of a signed message.')
|
|
128
|
-
var signature = message.sign(privateKey)
|
|
129
|
-
var verified = message.verify(privateKey.toAddress(), signature)
|
|
130
|
-
verified.should.equal(true)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('can chain methods', function () {
|
|
134
|
-
var verified = Message(text).verify(address, signatureString)
|
|
135
|
-
verified.should.equal(true)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
describe('@sign', function () {
|
|
139
|
-
it('should sign and verify', function () {
|
|
140
|
-
var privateKey = PrivateKey.fromString('L3nrwRssVKMkScjejmmu6kmq4hSuUApJnFdW1hGvBP69jnQuKYCh')
|
|
141
|
-
var address = privateKey.toAddress()
|
|
142
|
-
var message = 'this is the message that I want to sign'
|
|
143
|
-
var sig = Message.sign(message, privateKey)
|
|
144
|
-
sig.toString().should.equal('II5uoh3m0yQ+/5va+1acFQhPaEdTnFFiG/PiKpoC+kpgHbmIk3aWHQ6tyPGgNCUmKlSfwzcP6qVAxuUt0PwDzpg=')
|
|
145
|
-
var verify = Message.verify(message, address, sig)
|
|
146
|
-
verify.should.equal(true)
|
|
147
|
-
})
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
describe('#json', function () {
|
|
151
|
-
it('roundtrip to-from-to', function () {
|
|
152
|
-
var json = new Message(text).toJSON()
|
|
153
|
-
var message = Message.fromJSON(json)
|
|
154
|
-
message.toString().should.equal(Buffer.from(text).toString())
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('checks that the string parameter is valid JSON', function () {
|
|
158
|
-
expect(function () {
|
|
159
|
-
return Message.fromJSON('¹')
|
|
160
|
-
}).to.throw()
|
|
161
|
-
})
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
describe('#toString', function () {
|
|
165
|
-
it('message string', function () {
|
|
166
|
-
var message = new Message(text)
|
|
167
|
-
message.toString().should.equal(text)
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
it('roundtrip to-from-to', function () {
|
|
171
|
-
var str = new Message(text).toString()
|
|
172
|
-
var message = Message.fromString(str)
|
|
173
|
-
message.toString().should.equal(text)
|
|
174
|
-
})
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
describe('#inspect', function () {
|
|
178
|
-
it('should output formatted output correctly', function () {
|
|
179
|
-
var message = new Message(text)
|
|
180
|
-
var output = '<Message: ' + text + '>'
|
|
181
|
-
message.inspect().should.equal(output)
|
|
182
|
-
})
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
it('accepts Address for verification', function () {
|
|
186
|
-
var verified = Message(text)
|
|
187
|
-
.verify(new Address(address), signatureString)
|
|
188
|
-
verified.should.equal(true)
|
|
189
|
-
})
|
|
190
|
-
})
|