smartledger-bsv 3.2.2 → 3.3.1

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 (41) hide show
  1. package/CHANGELOG.md +147 -0
  2. package/architecture_demo.js +247 -0
  3. package/bsv-gdaf.min.js +37 -0
  4. package/bsv-ltp.min.js +37 -0
  5. package/bsv-shamir.min.js +12 -0
  6. package/bsv.bundle.js +9 -9
  7. package/build/bsv-smartcontract.min.js +10 -8
  8. package/build/bsv.bundle.js +9 -9
  9. package/build/bsv.min.js +10 -8
  10. package/build/webpack.gdaf.config.js +54 -0
  11. package/build/webpack.ltp.config.js +17 -0
  12. package/bundle-entry.js +77 -1
  13. package/complete_ltp_demo.js +511 -0
  14. package/gdaf-entry.js +54 -0
  15. package/index.js +259 -0
  16. package/lib/crypto/shamir.js +360 -0
  17. package/lib/gdaf/attestation-signer.js +461 -0
  18. package/lib/gdaf/attestation-verifier.js +600 -0
  19. package/lib/gdaf/did-resolver.js +382 -0
  20. package/lib/gdaf/index.js +471 -0
  21. package/lib/gdaf/schema-validator.js +682 -0
  22. package/lib/gdaf/smartledger-anchor.js +486 -0
  23. package/lib/gdaf/zk-prover.js +507 -0
  24. package/lib/ltp/anchor.js +438 -0
  25. package/lib/ltp/claim.js +1026 -0
  26. package/lib/ltp/index.js +470 -0
  27. package/lib/ltp/obligation.js +945 -0
  28. package/lib/ltp/proof.js +828 -0
  29. package/lib/ltp/registry.js +702 -0
  30. package/lib/ltp/right.js +765 -0
  31. package/lib/smart_contract/API_REFERENCE.md +1 -1
  32. package/lib/smart_contract/EXAMPLES.md +2 -2
  33. package/lib/smart_contract/QUICK_START.md +2 -2
  34. package/lib/smart_contract/README.md +1 -1
  35. package/ltp-entry.js +92 -0
  36. package/package.json +44 -4
  37. package/shamir-entry.js +173 -0
  38. package/shamir_demo.js +121 -0
  39. package/simple_demo.js +204 -0
  40. package/test_shamir.js +221 -0
  41. package/test_standalone_shamir.html +83 -0
@@ -0,0 +1,438 @@
1
+ 'use strict'
2
+
3
+ var bsv = require('../../')
4
+ var Hash = bsv.crypto.Hash
5
+ var $ = bsv.util.preconditions
6
+
7
+ /**
8
+ * Legal Token Protocol - Blockchain Anchoring Primitives
9
+ *
10
+ * Provides primitives for preparing legal tokens for blockchain anchoring
11
+ * without directly publishing to blockchain. External services handle
12
+ * the actual transaction broadcasting and confirmation.
13
+ */
14
+
15
+ var LTPAnchor = {
16
+
17
+ /**
18
+ * Prepare token commitment for blockchain anchoring
19
+ * @param {Object} token - Token to prepare for anchoring
20
+ * @param {Object} options - Anchoring options
21
+ * @returns {Object} Prepared anchor data
22
+ */
23
+ prepareTokenCommitment: function(token, options) {
24
+ options = options || {}
25
+
26
+ $.checkArgument(token && typeof token === 'object', 'Invalid token')
27
+
28
+ try {
29
+ // Create commitment hash
30
+ var commitment = this._createCommitment(token, options)
31
+
32
+ // Prepare OP_RETURN data
33
+ var opReturnData = this._formatOpReturn(commitment, options)
34
+
35
+ // Create transaction template
36
+ var txTemplate = this._createTxTemplate(opReturnData, options)
37
+
38
+ return {
39
+ success: true,
40
+ commitment: commitment,
41
+ opReturnData: opReturnData,
42
+ txTemplate: txTemplate,
43
+ preparedAt: new Date().toISOString(),
44
+ metadata: {
45
+ tokenId: token.id,
46
+ purpose: options.purpose || 'legal_token_anchor',
47
+ version: 'LTP.v1'
48
+ }
49
+ }
50
+
51
+ } catch (error) {
52
+ return {
53
+ success: false,
54
+ error: error.message
55
+ }
56
+ }
57
+ },
58
+
59
+ /**
60
+ * Prepare batch of tokens for anchoring
61
+ * @param {Array} tokens - Tokens to prepare for anchoring
62
+ * @param {Object} options - Anchoring options
63
+ * @returns {Object} Prepared batch anchor data
64
+ */
65
+ prepareBatchCommitment: function(tokens, options) {
66
+ options = options || {}
67
+
68
+ $.checkArgument(Array.isArray(tokens), 'Tokens must be array')
69
+
70
+ try {
71
+ // Create batch commitment
72
+ var batchCommitment = this._createBatchCommitment(tokens, options)
73
+
74
+ // Prepare OP_RETURN data for batch
75
+ var opReturnData = this._formatOpReturn(batchCommitment, options)
76
+
77
+ // Create transaction template
78
+ var txTemplate = this._createTxTemplate(opReturnData, options)
79
+
80
+ return {
81
+ success: true,
82
+ batchCommitment: batchCommitment,
83
+ opReturnData: opReturnData,
84
+ txTemplate: txTemplate,
85
+ tokenCount: tokens.length,
86
+ preparedAt: new Date().toISOString(),
87
+ metadata: {
88
+ purpose: options.purpose || 'legal_token_batch_anchor',
89
+ version: 'LTP.v1'
90
+ }
91
+ }
92
+
93
+ } catch (error) {
94
+ return {
95
+ success: false,
96
+ error: error.message
97
+ }
98
+ }
99
+ },
100
+
101
+ /**
102
+ * Verify token anchor using external transaction data
103
+ * @param {Object} token - Token to verify
104
+ * @param {String} txid - Transaction ID from external anchor
105
+ * @param {Object} txData - Transaction data from blockchain
106
+ * @returns {Object} Verification result
107
+ */
108
+ verifyTokenAnchor: function(token, txid, txData) {
109
+ $.checkArgument(token && typeof token === 'object', 'Invalid token')
110
+ $.checkArgument(typeof txid === 'string', 'Transaction ID must be string')
111
+
112
+ try {
113
+ // Recreate expected commitment
114
+ var expectedCommitment = this._createCommitment(token, {})
115
+
116
+ // Extract OP_RETURN data from transaction
117
+ var opReturnData = this._extractOpReturn(txData)
118
+
119
+ if (!opReturnData) {
120
+ return {
121
+ valid: false,
122
+ error: 'No OP_RETURN data found in transaction'
123
+ }
124
+ }
125
+
126
+ // Verify commitment matches
127
+ var commitmentValid = this._verifyCommitment(expectedCommitment, opReturnData)
128
+
129
+ return {
130
+ valid: commitmentValid,
131
+ txid: txid,
132
+ commitment: expectedCommitment,
133
+ anchorData: opReturnData,
134
+ verifiedAt: new Date().toISOString()
135
+ }
136
+
137
+ } catch (error) {
138
+ return {
139
+ valid: false,
140
+ error: error.message
141
+ }
142
+ }
143
+ },
144
+
145
+ /**
146
+ * Format revocation data for external registry
147
+ * @param {String} tokenId - Token ID to revoke
148
+ * @param {Object} revocationData - Revocation details
149
+ * @returns {Object} Formatted revocation data
150
+ */
151
+ formatRevocation: function(tokenId, revocationData) {
152
+ $.checkArgument(typeof tokenId === 'string', 'Token ID must be string')
153
+ $.checkArgument(revocationData && typeof revocationData === 'object', 'Invalid revocation data')
154
+
155
+ try {
156
+ var revocation = {
157
+ type: 'LTP_REVOCATION',
158
+ tokenId: tokenId,
159
+ reason: revocationData.reason || 'UNSPECIFIED',
160
+ revokedBy: revocationData.revokedBy || 'UNKNOWN',
161
+ revokedAt: new Date().toISOString(),
162
+ effectiveDate: revocationData.effectiveDate || new Date().toISOString(),
163
+ legalBasis: revocationData.legalBasis || null,
164
+ evidence: revocationData.evidence || null
165
+ }
166
+
167
+ // Create revocation hash
168
+ var revocationHash = Hash.sha256(Buffer.from(JSON.stringify(revocation))).toString('hex')
169
+
170
+ return {
171
+ success: true,
172
+ revocation: revocation,
173
+ revocationHash: revocationHash,
174
+ opReturnData: this._formatOpReturn({ hash: revocationHash, type: 'REVOCATION' }, {})
175
+ }
176
+
177
+ } catch (error) {
178
+ return {
179
+ success: false,
180
+ error: error.message
181
+ }
182
+ }
183
+ },
184
+
185
+ /**
186
+ * Create commitment hash from token
187
+ * @private
188
+ */
189
+ _createCommitment: function(token, options) {
190
+ // Create canonical representation
191
+ var canonical = this._canonicalizeToken(token)
192
+
193
+ // Create commitment object
194
+ var commitment = {
195
+ type: 'LTP_TOKEN',
196
+ tokenHash: Hash.sha256(Buffer.from(canonical)).toString('hex'),
197
+ tokenId: token.id,
198
+ timestamp: new Date().toISOString(),
199
+ purpose: options.purpose || 'legal_token'
200
+ }
201
+
202
+ // Hash the commitment
203
+ var commitmentHash = Hash.sha256(Buffer.from(JSON.stringify(commitment))).toString('hex')
204
+
205
+ return {
206
+ hash: commitmentHash,
207
+ data: commitment,
208
+ canonical: canonical
209
+ }
210
+ },
211
+
212
+ /**
213
+ * Create batch commitment from multiple tokens
214
+ * @private
215
+ */
216
+ _createBatchCommitment: function(tokens, options) {
217
+ var tokenHashes = []
218
+ var tokenIds = []
219
+
220
+ tokens.forEach(function(token) {
221
+ var commitment = this._createCommitment(token, options)
222
+ tokenHashes.push(commitment.hash)
223
+ tokenIds.push(token.id)
224
+ }.bind(this))
225
+
226
+ // Create Merkle tree
227
+ var merkleRoot = this._createMerkleRoot(tokenHashes)
228
+
229
+ var batchCommitment = {
230
+ type: 'LTP_BATCH',
231
+ merkleRoot: merkleRoot,
232
+ tokenCount: tokens.length,
233
+ tokenIds: tokenIds,
234
+ timestamp: new Date().toISOString(),
235
+ purpose: options.purpose || 'batch_anchor'
236
+ }
237
+
238
+ var batchHash = Hash.sha256(Buffer.from(JSON.stringify(batchCommitment))).toString('hex')
239
+
240
+ return {
241
+ hash: batchHash,
242
+ data: batchCommitment,
243
+ merkleRoot: merkleRoot,
244
+ tokenHashes: tokenHashes
245
+ }
246
+ },
247
+
248
+ /**
249
+ * Format OP_RETURN data
250
+ * @private
251
+ */
252
+ _formatOpReturn: function(commitment, options) {
253
+ var prefix = options.prefix || 'LTP.v1'
254
+ var data = commitment.hash
255
+
256
+ return {
257
+ prefix: prefix,
258
+ data: data,
259
+ full: prefix + '.' + data,
260
+ bytes: Buffer.from(prefix + '.' + data, 'utf8'),
261
+ size: Buffer.from(prefix + '.' + data, 'utf8').length
262
+ }
263
+ },
264
+
265
+ /**
266
+ * Create transaction template
267
+ * @private
268
+ */
269
+ _createTxTemplate: function(opReturnData, options) {
270
+ try {
271
+ // Create basic transaction structure
272
+ var tx = {
273
+ version: 1,
274
+ inputs: [], // To be filled by implementing application
275
+ outputs: [
276
+ {
277
+ satoshis: 0,
278
+ script: 'OP_RETURN ' + opReturnData.data
279
+ }
280
+ ],
281
+ locktime: 0
282
+ }
283
+
284
+ // Add fee output if specified
285
+ if (options.feeOutput) {
286
+ tx.outputs.push(options.feeOutput)
287
+ }
288
+
289
+ return {
290
+ template: tx,
291
+ opReturn: opReturnData,
292
+ estimatedSize: this._estimateSize(tx),
293
+ instructions: {
294
+ step1: 'Add input UTXOs to cover fees',
295
+ step2: 'Add change output if needed',
296
+ step3: 'Sign transaction with appropriate keys',
297
+ step4: 'Broadcast to BSV network'
298
+ }
299
+ }
300
+
301
+ } catch (error) {
302
+ throw new Error('Failed to create transaction template: ' + error.message)
303
+ }
304
+ },
305
+
306
+ /**
307
+ * Extract OP_RETURN data from transaction
308
+ * @private
309
+ */
310
+ _extractOpReturn: function(txData) {
311
+ try {
312
+ if (!txData || !txData.outputs) {
313
+ return null
314
+ }
315
+
316
+ for (var i = 0; i < txData.outputs.length; i++) {
317
+ var output = txData.outputs[i]
318
+ if (output.script && output.script.startsWith('OP_RETURN')) {
319
+ var data = output.script.replace('OP_RETURN ', '')
320
+ return {
321
+ raw: data,
322
+ decoded: Buffer.from(data, 'hex').toString('utf8')
323
+ }
324
+ }
325
+ }
326
+
327
+ return null
328
+ } catch (error) {
329
+ return null
330
+ }
331
+ },
332
+
333
+ /**
334
+ * Verify commitment matches OP_RETURN data
335
+ * @private
336
+ */
337
+ _verifyCommitment: function(commitment, opReturnData) {
338
+ try {
339
+ if (!opReturnData || !opReturnData.decoded) {
340
+ return false
341
+ }
342
+
343
+ // Check if our commitment hash appears in the OP_RETURN
344
+ return opReturnData.decoded.includes(commitment.hash)
345
+ } catch (error) {
346
+ return false
347
+ }
348
+ },
349
+
350
+ /**
351
+ * Canonicalize token for hashing
352
+ * @private
353
+ */
354
+ _canonicalizeToken: function(token) {
355
+ // Remove dynamic fields
356
+ var canonical = JSON.parse(JSON.stringify(token))
357
+ delete canonical.proof
358
+ delete canonical.tokenHash
359
+ delete canonical.anchorTx
360
+ delete canonical.anchorBlock
361
+
362
+ // Sort keys recursively
363
+ return JSON.stringify(this._sortObjectKeys(canonical))
364
+ },
365
+
366
+ /**
367
+ * Create Merkle root from array of hashes
368
+ * @private
369
+ */
370
+ _createMerkleRoot: function(hashes) {
371
+ if (hashes.length === 0) {
372
+ return null
373
+ }
374
+
375
+ if (hashes.length === 1) {
376
+ return hashes[0]
377
+ }
378
+
379
+ var level = hashes.slice()
380
+
381
+ while (level.length > 1) {
382
+ var nextLevel = []
383
+
384
+ for (var i = 0; i < level.length; i += 2) {
385
+ var left = level[i]
386
+ var right = level[i + 1] || left
387
+
388
+ var combined = Buffer.concat([
389
+ Buffer.from(left, 'hex'),
390
+ Buffer.from(right, 'hex')
391
+ ])
392
+
393
+ var hash = Hash.sha256(combined).toString('hex')
394
+ nextLevel.push(hash)
395
+ }
396
+
397
+ level = nextLevel
398
+ }
399
+
400
+ return level[0]
401
+ },
402
+
403
+ /**
404
+ * Estimate transaction size
405
+ * @private
406
+ */
407
+ _estimateSize: function(tx) {
408
+ // Basic estimation - actual size depends on inputs
409
+ var baseSize = 10 // version + locktime + input/output counts
410
+ var outputSize = tx.outputs.length * 34 // approximate output size
411
+ var estimatedInputSize = 148 // approximate input size with signature
412
+
413
+ return {
414
+ base: baseSize + outputSize,
415
+ withOneInput: baseSize + outputSize + estimatedInputSize,
416
+ bytesPerInput: estimatedInputSize
417
+ }
418
+ },
419
+
420
+ /**
421
+ * Sort object keys recursively
422
+ * @private
423
+ */
424
+ _sortObjectKeys: function(obj) {
425
+ if (Array.isArray(obj)) {
426
+ return obj.map(this._sortObjectKeys.bind(this))
427
+ } else if (obj !== null && typeof obj === 'object') {
428
+ var sorted = {}
429
+ Object.keys(obj).sort().forEach(function(key) {
430
+ sorted[key] = this._sortObjectKeys(obj[key])
431
+ }.bind(this))
432
+ return sorted
433
+ }
434
+ return obj
435
+ }
436
+ }
437
+
438
+ module.exports = LTPAnchor