@bsv/overlay 2.3.0 → 2.6.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.
- package/LICENSES/Open-BSV-License-4-standard-pre-2026.txt +28 -0
- package/README.md +171 -1
- package/THIRD_PARTY_NOTICES.md +49 -0
- package/dist/cjs/mod.d.ts +4 -1
- package/dist/cjs/mod.d.ts.map +1 -1
- package/dist/cjs/mod.js +8 -1
- package/dist/cjs/mod.js.map +1 -1
- package/dist/cjs/package.json +13 -5
- package/dist/cjs/src/BASM.d.ts +6 -0
- package/dist/cjs/src/BASM.d.ts.map +1 -1
- package/dist/cjs/src/BASM.js +21 -8
- package/dist/cjs/src/BASM.js.map +1 -1
- package/dist/cjs/src/BASMRemote.d.ts +8 -1
- package/dist/cjs/src/BASMRemote.d.ts.map +1 -1
- package/dist/cjs/src/BASMRemote.js +179 -13
- package/dist/cjs/src/BASMRemote.js.map +1 -1
- package/dist/cjs/src/BASMValidation.d.ts +27 -0
- package/dist/cjs/src/BASMValidation.d.ts.map +1 -0
- package/dist/cjs/src/BASMValidation.js +108 -0
- package/dist/cjs/src/BASMValidation.js.map +1 -0
- package/dist/cjs/src/DiscoveryAdvertisementValidation.d.ts +11 -0
- package/dist/cjs/src/DiscoveryAdvertisementValidation.d.ts.map +1 -0
- package/dist/cjs/src/DiscoveryAdvertisementValidation.js +60 -0
- package/dist/cjs/src/DiscoveryAdvertisementValidation.js.map +1 -0
- package/dist/cjs/src/Engine.d.ts +38 -13
- package/dist/cjs/src/Engine.d.ts.map +1 -1
- package/dist/cjs/src/Engine.js +1735 -336
- package/dist/cjs/src/Engine.js.map +1 -1
- package/dist/cjs/src/EngineAdmission.d.ts +70 -0
- package/dist/cjs/src/EngineAdmission.d.ts.map +1 -0
- package/dist/cjs/src/EngineAdmission.js +297 -0
- package/dist/cjs/src/EngineAdmission.js.map +1 -0
- package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts +4 -3
- package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
- package/dist/cjs/src/GASP/OverlayGASPRemote.js +27 -43
- package/dist/cjs/src/GASP/OverlayGASPRemote.js.map +1 -1
- package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts +22 -16
- package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
- package/dist/cjs/src/GASP/OverlayGASPStorage.js +206 -57
- package/dist/cjs/src/GASP/OverlayGASPStorage.js.map +1 -1
- package/dist/cjs/src/RemoteSecurity.d.ts +50 -0
- package/dist/cjs/src/RemoteSecurity.d.ts.map +1 -0
- package/dist/cjs/src/RemoteSecurity.js +301 -0
- package/dist/cjs/src/RemoteSecurity.js.map +1 -0
- package/dist/cjs/src/TopicManager.d.ts +13 -3
- package/dist/cjs/src/TopicManager.d.ts.map +1 -1
- package/dist/cjs/src/storage/AdmissionStorage.d.ts +185 -0
- package/dist/cjs/src/storage/AdmissionStorage.d.ts.map +1 -0
- package/dist/cjs/src/storage/AdmissionStorage.js +93 -0
- package/dist/cjs/src/storage/AdmissionStorage.js.map +1 -0
- package/dist/cjs/src/storage/RecoveryContract.d.ts +50 -0
- package/dist/cjs/src/storage/RecoveryContract.d.ts.map +1 -0
- package/dist/cjs/src/storage/RecoveryContract.js +35 -0
- package/dist/cjs/src/storage/RecoveryContract.js.map +1 -0
- package/dist/cjs/src/storage/Storage.d.ts +32 -19
- package/dist/cjs/src/storage/Storage.d.ts.map +1 -1
- package/dist/cjs/src/storage/Storage.js +5 -0
- package/dist/cjs/src/storage/Storage.js.map +1 -1
- package/dist/cjs/src/storage/knex/KnexStorage.d.ts +8 -8
- package/dist/cjs/src/storage/knex/KnexStorage.d.ts.map +1 -1
- package/dist/cjs/src/storage/knex/KnexStorage.js +98 -61
- package/dist/cjs/src/storage/knex/KnexStorage.js.map +1 -1
- package/dist/cjs/src/storage/knex/all-migrations.d.ts.map +1 -1
- package/dist/cjs/src/storage/knex/all-migrations.js +5 -1
- package/dist/cjs/src/storage/knex/all-migrations.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js +36 -0
- package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts +5 -0
- package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.js +16 -0
- package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.js.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.d.ts +18 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.js +229 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.js.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.d.ts +112 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.js +675 -0
- package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.js.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoOverlayStorage.d.ts +71 -0
- package/dist/cjs/src/storage/mongo/MongoOverlayStorage.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoOverlayStorage.js +453 -0
- package/dist/cjs/src/storage/mongo/MongoOverlayStorage.js.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoPayloadStore.d.ts +134 -0
- package/dist/cjs/src/storage/mongo/MongoPayloadStore.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoPayloadStore.js +756 -0
- package/dist/cjs/src/storage/mongo/MongoPayloadStore.js.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoReadGuards.d.ts +44 -0
- package/dist/cjs/src/storage/mongo/MongoReadGuards.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoReadGuards.js +135 -0
- package/dist/cjs/src/storage/mongo/MongoReadGuards.js.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoSchema.d.ts +67 -0
- package/dist/cjs/src/storage/mongo/MongoSchema.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoSchema.js +743 -0
- package/dist/cjs/src/storage/mongo/MongoSchema.js.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoTransactionRunner.d.ts +69 -0
- package/dist/cjs/src/storage/mongo/MongoTransactionRunner.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo/MongoTransactionRunner.js +368 -0
- package/dist/cjs/src/storage/mongo/MongoTransactionRunner.js.map +1 -0
- package/dist/cjs/src/storage/mongo.d.ts +9 -0
- package/dist/cjs/src/storage/mongo.d.ts.map +1 -0
- package/dist/cjs/src/storage/mongo.js +25 -0
- package/dist/cjs/src/storage/mongo.js.map +1 -0
- package/dist/esm/mod.js +3 -0
- package/dist/esm/mod.js.map +1 -1
- package/dist/esm/src/BASM.js +21 -8
- package/dist/esm/src/BASM.js.map +1 -1
- package/dist/esm/src/BASMRemote.js +176 -12
- package/dist/esm/src/BASMRemote.js.map +1 -1
- package/dist/esm/src/BASMValidation.js +95 -0
- package/dist/esm/src/BASMValidation.js.map +1 -0
- package/dist/esm/src/DiscoveryAdvertisementValidation.js +57 -0
- package/dist/esm/src/DiscoveryAdvertisementValidation.js.map +1 -0
- package/dist/esm/src/Engine.js +1720 -326
- package/dist/esm/src/Engine.js.map +1 -1
- package/dist/esm/src/EngineAdmission.js +280 -0
- package/dist/esm/src/EngineAdmission.js.map +1 -0
- package/dist/esm/src/GASP/OverlayGASPRemote.js +27 -43
- package/dist/esm/src/GASP/OverlayGASPRemote.js.map +1 -1
- package/dist/esm/src/GASP/OverlayGASPStorage.js +200 -56
- package/dist/esm/src/GASP/OverlayGASPStorage.js.map +1 -1
- package/dist/esm/src/RemoteSecurity.js +279 -0
- package/dist/esm/src/RemoteSecurity.js.map +1 -0
- package/dist/esm/src/storage/AdmissionStorage.js +85 -0
- package/dist/esm/src/storage/AdmissionStorage.js.map +1 -0
- package/dist/esm/src/storage/RecoveryContract.js +31 -0
- package/dist/esm/src/storage/RecoveryContract.js.map +1 -0
- package/dist/esm/src/storage/Storage.js +4 -1
- package/dist/esm/src/storage/Storage.js.map +1 -1
- package/dist/esm/src/storage/knex/KnexStorage.js +98 -61
- package/dist/esm/src/storage/knex/KnexStorage.js.map +1 -1
- package/dist/esm/src/storage/knex/all-migrations.js +5 -1
- package/dist/esm/src/storage/knex/all-migrations.js.map +1 -1
- package/dist/esm/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js +32 -0
- package/dist/esm/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js.map +1 -0
- package/dist/esm/src/storage/knex/migrations/2026-09-20-001-spent-by.js +12 -0
- package/dist/esm/src/storage/knex/migrations/2026-09-20-001-spent-by.js.map +1 -0
- package/dist/esm/src/storage/mongo/MongoAdmissionPlan.js +217 -0
- package/dist/esm/src/storage/mongo/MongoAdmissionPlan.js.map +1 -0
- package/dist/esm/src/storage/mongo/MongoAdmissionStorage.js +673 -0
- package/dist/esm/src/storage/mongo/MongoAdmissionStorage.js.map +1 -0
- package/dist/esm/src/storage/mongo/MongoOverlayStorage.js +451 -0
- package/dist/esm/src/storage/mongo/MongoOverlayStorage.js.map +1 -0
- package/dist/esm/src/storage/mongo/MongoPayloadStore.js +747 -0
- package/dist/esm/src/storage/mongo/MongoPayloadStore.js.map +1 -0
- package/dist/esm/src/storage/mongo/MongoReadGuards.js +129 -0
- package/dist/esm/src/storage/mongo/MongoReadGuards.js.map +1 -0
- package/dist/esm/src/storage/mongo/MongoSchema.js +730 -0
- package/dist/esm/src/storage/mongo/MongoSchema.js.map +1 -0
- package/dist/esm/src/storage/mongo/MongoTransactionRunner.js +371 -0
- package/dist/esm/src/storage/mongo/MongoTransactionRunner.js.map +1 -0
- package/dist/esm/src/storage/mongo.js +9 -0
- package/dist/esm/src/storage/mongo.js.map +1 -0
- package/dist/types/mod.d.ts +4 -1
- package/dist/types/mod.d.ts.map +1 -1
- package/dist/types/src/BASM.d.ts +6 -0
- package/dist/types/src/BASM.d.ts.map +1 -1
- package/dist/types/src/BASMRemote.d.ts +8 -1
- package/dist/types/src/BASMRemote.d.ts.map +1 -1
- package/dist/types/src/BASMValidation.d.ts +27 -0
- package/dist/types/src/BASMValidation.d.ts.map +1 -0
- package/dist/types/src/DiscoveryAdvertisementValidation.d.ts +11 -0
- package/dist/types/src/DiscoveryAdvertisementValidation.d.ts.map +1 -0
- package/dist/types/src/Engine.d.ts +38 -13
- package/dist/types/src/Engine.d.ts.map +1 -1
- package/dist/types/src/EngineAdmission.d.ts +70 -0
- package/dist/types/src/EngineAdmission.d.ts.map +1 -0
- package/dist/types/src/GASP/OverlayGASPRemote.d.ts +4 -3
- package/dist/types/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
- package/dist/types/src/GASP/OverlayGASPStorage.d.ts +22 -16
- package/dist/types/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
- package/dist/types/src/RemoteSecurity.d.ts +50 -0
- package/dist/types/src/RemoteSecurity.d.ts.map +1 -0
- package/dist/types/src/TopicManager.d.ts +13 -3
- package/dist/types/src/TopicManager.d.ts.map +1 -1
- package/dist/types/src/storage/AdmissionStorage.d.ts +185 -0
- package/dist/types/src/storage/AdmissionStorage.d.ts.map +1 -0
- package/dist/types/src/storage/RecoveryContract.d.ts +50 -0
- package/dist/types/src/storage/RecoveryContract.d.ts.map +1 -0
- package/dist/types/src/storage/Storage.d.ts +32 -19
- package/dist/types/src/storage/Storage.d.ts.map +1 -1
- package/dist/types/src/storage/knex/KnexStorage.d.ts +8 -8
- package/dist/types/src/storage/knex/KnexStorage.d.ts.map +1 -1
- package/dist/types/src/storage/knex/all-migrations.d.ts.map +1 -1
- package/dist/types/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts +4 -0
- package/dist/types/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts.map +1 -0
- package/dist/types/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts +5 -0
- package/dist/types/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts.map +1 -0
- package/dist/types/src/storage/mongo/MongoAdmissionPlan.d.ts +18 -0
- package/dist/types/src/storage/mongo/MongoAdmissionPlan.d.ts.map +1 -0
- package/dist/types/src/storage/mongo/MongoAdmissionStorage.d.ts +112 -0
- package/dist/types/src/storage/mongo/MongoAdmissionStorage.d.ts.map +1 -0
- package/dist/types/src/storage/mongo/MongoOverlayStorage.d.ts +71 -0
- package/dist/types/src/storage/mongo/MongoOverlayStorage.d.ts.map +1 -0
- package/dist/types/src/storage/mongo/MongoPayloadStore.d.ts +134 -0
- package/dist/types/src/storage/mongo/MongoPayloadStore.d.ts.map +1 -0
- package/dist/types/src/storage/mongo/MongoReadGuards.d.ts +44 -0
- package/dist/types/src/storage/mongo/MongoReadGuards.d.ts.map +1 -0
- package/dist/types/src/storage/mongo/MongoSchema.d.ts +67 -0
- package/dist/types/src/storage/mongo/MongoSchema.d.ts.map +1 -0
- package/dist/types/src/storage/mongo/MongoTransactionRunner.d.ts +69 -0
- package/dist/types/src/storage/mongo/MongoTransactionRunner.d.ts.map +1 -0
- package/dist/types/src/storage/mongo.d.ts +9 -0
- package/dist/types/src/storage/mongo.d.ts.map +1 -0
- package/package.json +14 -6
|
@@ -1,28 +1,169 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BASMRemote = void 0;
|
|
3
|
+
exports.BASMRemote = exports.BASMProtocolError = void 0;
|
|
4
|
+
const BASMValidation_js_1 = require("./BASMValidation.js");
|
|
5
|
+
const RemoteSecurity_js_1 = require("./RemoteSecurity.js");
|
|
6
|
+
var BASMValidation_js_2 = require("./BASMValidation.js");
|
|
7
|
+
Object.defineProperty(exports, "BASMProtocolError", { enumerable: true, get: function () { return BASMValidation_js_2.BASMProtocolError; } });
|
|
4
8
|
class BASMRemote {
|
|
5
|
-
constructor(endpoint, topic, fetchImpl =
|
|
6
|
-
|
|
9
|
+
constructor(endpoint, topic, fetchImpl, limits = {}) {
|
|
10
|
+
(0, RemoteSecurity_js_1.assertTopic)(topic);
|
|
11
|
+
const secured = (0, RemoteSecurity_js_1.securePeerFetch)(endpoint, fetchImpl);
|
|
12
|
+
this.endpoint = secured.endpoint;
|
|
7
13
|
this.topic = topic;
|
|
8
|
-
this.fetchImpl = fetchImpl;
|
|
14
|
+
this.fetchImpl = secured.fetchImpl;
|
|
15
|
+
this.limits = Object.freeze({ ...BASMValidation_js_1.DEFAULT_BASM_REMOTE_LIMITS, ...limits });
|
|
16
|
+
for (const [key, value] of Object.entries(this.limits)) {
|
|
17
|
+
if (!Number.isSafeInteger(value) || value <= 0)
|
|
18
|
+
throw new TypeError(`Invalid BASM limit: ${key}`);
|
|
19
|
+
}
|
|
20
|
+
if (this.limits.timeoutMs > 2147483647)
|
|
21
|
+
throw new TypeError('BASM timeout exceeds timer range');
|
|
9
22
|
}
|
|
10
23
|
async requestTopicAnchorTip() {
|
|
11
|
-
return await this.post('/requestTopicAnchorTip', {});
|
|
24
|
+
return (0, BASMValidation_js_1.basmTip)(await this.post('/requestTopicAnchorTip', {}), this.topic);
|
|
12
25
|
}
|
|
13
26
|
async requestTopicAnchorRange(fromHeight, toHeight) {
|
|
14
|
-
|
|
27
|
+
(0, BASMValidation_js_1.basmInteger)(fromHeight, 'range start');
|
|
28
|
+
(0, BASMValidation_js_1.basmInteger)(toHeight, 'range end', fromHeight);
|
|
29
|
+
(0, BASMValidation_js_1.requireBASMLimit)(toHeight - fromHeight < this.limits.maxAnchorRange, 'BASM anchor range exceeds limit');
|
|
30
|
+
const obj = (0, BASMValidation_js_1.basmObject)(await this.post('/requestTopicAnchorRange', { fromHeight, toHeight }));
|
|
31
|
+
(0, BASMValidation_js_1.requireBASM)(obj.topic === this.topic && Array.isArray(obj.anchors), 'Invalid BASM anchor range');
|
|
32
|
+
(0, BASMValidation_js_1.requireBASMLimit)(obj.anchors.length <= toHeight - fromHeight + 1, 'BASM anchor count exceeds requested range');
|
|
33
|
+
const anchors = obj.anchors.map(value => (0, BASMValidation_js_1.basmAnchor)(value, this.topic));
|
|
34
|
+
let previousHeight;
|
|
35
|
+
for (const anchor of anchors) {
|
|
36
|
+
(0, BASMValidation_js_1.requireBASM)(anchor.blockHeight >= fromHeight && anchor.blockHeight <= toHeight, 'BASM anchor outside requested range');
|
|
37
|
+
(0, BASMValidation_js_1.requireBASM)(previousHeight === undefined || anchor.blockHeight === previousHeight + 1, 'BASM anchor range has a gap or is unordered');
|
|
38
|
+
previousHeight = anchor.blockHeight;
|
|
39
|
+
}
|
|
40
|
+
return { topic: this.topic, anchors };
|
|
15
41
|
}
|
|
16
42
|
async requestAdmittedList(blockHeight, blockHash) {
|
|
17
|
-
|
|
43
|
+
(0, BASMValidation_js_1.basmInteger)(blockHeight, 'height');
|
|
44
|
+
if (blockHash !== undefined)
|
|
45
|
+
(0, BASMValidation_js_1.basmHash)(blockHash, 'block hash');
|
|
46
|
+
const obj = (0, BASMValidation_js_1.basmObject)(await this.post('/requestAdmittedList', { blockHeight, blockHash }));
|
|
47
|
+
this.requireCoordinate(obj, blockHeight);
|
|
48
|
+
const responseHash = obj.blockHash === undefined ? undefined : (0, BASMValidation_js_1.basmHash)(obj.blockHash, 'block hash');
|
|
49
|
+
(0, BASMValidation_js_1.requireBASM)(blockHash === undefined || responseHash === undefined || responseHash === blockHash, 'BASM admitted block hash mismatch');
|
|
50
|
+
return {
|
|
51
|
+
topic: this.topic,
|
|
52
|
+
blockHeight,
|
|
53
|
+
...(responseHash === undefined ? {} : { blockHash: responseHash }),
|
|
54
|
+
admitted: (0, BASMValidation_js_1.basmAdmitted)(obj.admitted, this.limits.maxAdmittedTxids)
|
|
55
|
+
};
|
|
18
56
|
}
|
|
19
57
|
async requestCompoundMerklePath(blockHeight, txids) {
|
|
20
|
-
|
|
58
|
+
(0, BASMValidation_js_1.basmInteger)(blockHeight, 'height');
|
|
59
|
+
const requested = (0, BASMValidation_js_1.basmTxids)(txids, this.limits.maxRequestedTxids);
|
|
60
|
+
(0, BASMValidation_js_1.requireBASM)(requested.length > 0, 'At least one BASM proof txid is required');
|
|
61
|
+
const obj = (0, BASMValidation_js_1.basmObject)(await this.post('/requestCompoundMerklePath', { blockHeight, txids: requested }));
|
|
62
|
+
this.requireCoordinate(obj, blockHeight);
|
|
63
|
+
const returned = (0, BASMValidation_js_1.basmTxids)(obj.txids, requested.length);
|
|
64
|
+
const requestedSet = new Set(requested);
|
|
65
|
+
(0, BASMValidation_js_1.requireBASM)(returned.length === requested.length && returned.every(txid => requestedSet.has(txid)), 'BASM proof txids do not match request');
|
|
66
|
+
return {
|
|
67
|
+
topic: this.topic,
|
|
68
|
+
blockHeight,
|
|
69
|
+
txids: returned,
|
|
70
|
+
merklePath: (0, BASMValidation_js_1.basmHex)(obj.merklePath, 'Merkle path', this.limits.maxProofBytes)
|
|
71
|
+
};
|
|
21
72
|
}
|
|
22
73
|
async requestRawTransactions(txids) {
|
|
23
|
-
|
|
74
|
+
const requested = new Set((0, BASMValidation_js_1.basmTxids)(txids, this.limits.maxRequestedTxids));
|
|
75
|
+
const obj = (0, BASMValidation_js_1.basmObject)(await this.post('/requestRawTransactions', { txids: [...requested] }));
|
|
76
|
+
(0, BASMValidation_js_1.requireBASM)(Array.isArray(obj.transactions), 'Invalid BASM raw transactions');
|
|
77
|
+
(0, BASMValidation_js_1.requireBASMLimit)(obj.transactions.length <= requested.size, 'BASM raw transaction count exceeds request');
|
|
78
|
+
const seen = new Set();
|
|
79
|
+
const transactions = obj.transactions.map(value => {
|
|
80
|
+
const record = (0, BASMValidation_js_1.basmObject)(value);
|
|
81
|
+
const txid = (0, BASMValidation_js_1.basmHash)(record.txid, 'txid');
|
|
82
|
+
(0, BASMValidation_js_1.requireBASM)(requested.has(txid) && !seen.has(txid), 'Unexpected or duplicate BASM raw transaction');
|
|
83
|
+
seen.add(txid);
|
|
84
|
+
const rawTx = (0, BASMValidation_js_1.basmHex)(record.rawTx, 'raw transaction', this.limits.maxRawTransactionBytes);
|
|
85
|
+
(0, RemoteSecurity_js_1.assertRawTransactionMatches)(txid, rawTx);
|
|
86
|
+
return {
|
|
87
|
+
txid,
|
|
88
|
+
rawTx
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
const missing = (0, BASMValidation_js_1.basmTxids)(obj.missing, requested.size);
|
|
92
|
+
for (const txid of missing) {
|
|
93
|
+
(0, BASMValidation_js_1.requireBASM)(requested.has(txid) && !seen.has(txid), 'Unexpected or conflicting BASM missing txid');
|
|
94
|
+
seen.add(txid);
|
|
95
|
+
}
|
|
96
|
+
(0, BASMValidation_js_1.requireBASM)(seen.size === requested.size, 'BASM raw response omits requested txids');
|
|
97
|
+
return { transactions, missing };
|
|
98
|
+
}
|
|
99
|
+
requireCoordinate(obj, blockHeight) {
|
|
100
|
+
(0, BASMValidation_js_1.requireBASM)(obj.topic === this.topic && obj.blockHeight === blockHeight, 'BASM response topic or height mismatch');
|
|
101
|
+
}
|
|
102
|
+
async readResponse(response, signal) {
|
|
103
|
+
var _a, _b;
|
|
104
|
+
const advertisedLength = (_a = response.headers) === null || _a === void 0 ? void 0 : _a.get('content-length');
|
|
105
|
+
if (advertisedLength !== null && advertisedLength !== undefined) {
|
|
106
|
+
if (Number(advertisedLength) > this.limits.maxResponseBytes) {
|
|
107
|
+
void ((_b = response.body) === null || _b === void 0 ? void 0 : _b.cancel().catch(() => { }));
|
|
108
|
+
(0, BASMValidation_js_1.requireBASMLimit)(false, 'BASM response exceeds byte limit');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Preserve injected fetch implementations that expose only text(). Real HTTP
|
|
112
|
+
// responses are bounded while streaming, including decoded chunked bodies.
|
|
113
|
+
if (response.body === undefined || response.body === null) {
|
|
114
|
+
const text = await response.text();
|
|
115
|
+
(0, BASMValidation_js_1.requireBASMLimit)(Buffer.byteLength(text) <= this.limits.maxResponseBytes, 'BASM response exceeds byte limit');
|
|
116
|
+
return text;
|
|
117
|
+
}
|
|
118
|
+
const reader = response.body.getReader();
|
|
119
|
+
const chunks = [];
|
|
120
|
+
let size = 0;
|
|
121
|
+
const cancel = () => {
|
|
122
|
+
void reader.cancel().catch(() => { });
|
|
123
|
+
};
|
|
124
|
+
signal.addEventListener('abort', cancel, { once: true });
|
|
125
|
+
try {
|
|
126
|
+
while (true) {
|
|
127
|
+
signal.throwIfAborted();
|
|
128
|
+
const { done, value } = await reader.read();
|
|
129
|
+
if (done)
|
|
130
|
+
break;
|
|
131
|
+
size += value.byteLength;
|
|
132
|
+
(0, BASMValidation_js_1.requireBASMLimit)(size <= this.limits.maxResponseBytes, 'BASM response exceeds byte limit');
|
|
133
|
+
chunks.push(value);
|
|
134
|
+
}
|
|
135
|
+
signal.throwIfAborted();
|
|
136
|
+
return Buffer.concat(chunks, size).toString('utf8');
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
cancel();
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
signal.removeEventListener('abort', cancel);
|
|
144
|
+
reader.releaseLock();
|
|
145
|
+
}
|
|
24
146
|
}
|
|
25
147
|
async post(path, body) {
|
|
148
|
+
const controller = new AbortController();
|
|
149
|
+
let timer;
|
|
150
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
151
|
+
timer = setTimeout(() => {
|
|
152
|
+
const error = new BASMValidation_js_1.BASMProtocolError('BASM_TIMEOUT', 'BASM request timed out');
|
|
153
|
+
controller.abort(error);
|
|
154
|
+
reject(error);
|
|
155
|
+
}, this.limits.timeoutMs);
|
|
156
|
+
});
|
|
157
|
+
try {
|
|
158
|
+
return await Promise.race([this.postResponse(path, body, controller.signal), deadline]);
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
clearTimeout(timer);
|
|
162
|
+
controller.abort();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async postResponse(path, body, signal) {
|
|
166
|
+
var _a, _b, _c, _d;
|
|
26
167
|
const response = await this.fetchImpl(new URL(path, this.endpoint).toString(), {
|
|
27
168
|
method: 'POST',
|
|
28
169
|
headers: {
|
|
@@ -30,13 +171,38 @@ class BASMRemote {
|
|
|
30
171
|
'Content-Type': 'application/json',
|
|
31
172
|
'x-bsv-topic': this.topic
|
|
32
173
|
},
|
|
33
|
-
body: JSON.stringify(body)
|
|
174
|
+
body: JSON.stringify(body),
|
|
175
|
+
signal
|
|
34
176
|
});
|
|
35
|
-
|
|
177
|
+
if (signal.aborted) {
|
|
178
|
+
void ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel().catch(() => { }));
|
|
179
|
+
signal.throwIfAborted();
|
|
180
|
+
}
|
|
181
|
+
const contentType = (_c = (_b = response.headers) === null || _b === void 0 ? void 0 : _b.get) === null || _c === void 0 ? void 0 : _c.call(_b, 'content-type');
|
|
182
|
+
if (contentType !== null &&
|
|
183
|
+
contentType !== undefined &&
|
|
184
|
+
contentType.includes('/') &&
|
|
185
|
+
!/^application\/(?:[\w.-]+\+)?json(?:\s*;|$)/i.test(contentType)) {
|
|
186
|
+
void ((_d = response.body) === null || _d === void 0 ? void 0 : _d.cancel().catch(() => { }));
|
|
187
|
+
throw new TypeError('Overlay peer response is not JSON');
|
|
188
|
+
}
|
|
189
|
+
const text = await this.readResponse(response, signal);
|
|
190
|
+
let value;
|
|
191
|
+
try {
|
|
192
|
+
value = JSON.parse(text);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
if (response.ok)
|
|
196
|
+
throw new BASMValidation_js_1.BASMProtocolError('BASM_INVALID_RESPONSE', 'Invalid BASM JSON response');
|
|
197
|
+
}
|
|
36
198
|
if (!response.ok) {
|
|
37
|
-
|
|
199
|
+
const code = typeof value === 'object' && value !== null && 'code' in value ? value.code : undefined;
|
|
200
|
+
if (response.status === 501 || code === 'BASM_UNSUPPORTED') {
|
|
201
|
+
throw new BASMValidation_js_1.BASMProtocolError('BASM_UNSUPPORTED', `BASM peer returned HTTP ${response.status}: unsupported BASM capability`);
|
|
202
|
+
}
|
|
203
|
+
throw new BASMValidation_js_1.BASMProtocolError('BASM_HTTP_ERROR', `BASM peer returned HTTP ${response.status}`);
|
|
38
204
|
}
|
|
39
|
-
return
|
|
205
|
+
return value;
|
|
40
206
|
}
|
|
41
207
|
}
|
|
42
208
|
exports.BASMRemote = BASMRemote;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BASMRemote.js","sourceRoot":"","sources":["../../../src/BASMRemote.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"BASMRemote.js","sourceRoot":"","sources":["../../../src/BASMRemote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AdmittedTxRef, TopicAnchorTip, TopicBlockAnchor } from './BASM.js';
|
|
2
|
+
/** Local acceptance limits, not Bitcoin consensus limits. */
|
|
3
|
+
export interface BASMRemoteLimits {
|
|
4
|
+
maxResponseBytes: number;
|
|
5
|
+
maxProofBytes: number;
|
|
6
|
+
maxRawTransactionBytes: number;
|
|
7
|
+
maxAdmittedTxids: number;
|
|
8
|
+
maxRequestedTxids: number;
|
|
9
|
+
maxAnchorRange: number;
|
|
10
|
+
timeoutMs: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_BASM_REMOTE_LIMITS: Readonly<BASMRemoteLimits>;
|
|
13
|
+
export declare class BASMProtocolError extends Error {
|
|
14
|
+
readonly code: 'BASM_INVALID_RESPONSE' | 'BASM_RESOURCE_LIMIT' | 'BASM_UNSUPPORTED' | 'BASM_TIMEOUT' | 'BASM_HTTP_ERROR';
|
|
15
|
+
constructor(code: 'BASM_INVALID_RESPONSE' | 'BASM_RESOURCE_LIMIT' | 'BASM_UNSUPPORTED' | 'BASM_TIMEOUT' | 'BASM_HTTP_ERROR', message: string);
|
|
16
|
+
}
|
|
17
|
+
export declare function requireBASM(condition: boolean, message: string): asserts condition;
|
|
18
|
+
export declare function requireBASMLimit(condition: boolean, message: string): void;
|
|
19
|
+
export declare function basmObject(value: unknown): Record<string, unknown>;
|
|
20
|
+
export declare function basmInteger(value: unknown, label: string, minimum?: number): number;
|
|
21
|
+
export declare function basmHash(value: unknown, label: string): string;
|
|
22
|
+
export declare function basmHex(value: unknown, label: string, maxBytes: number): string;
|
|
23
|
+
export declare function basmTxids(value: unknown, maximum: number): string[];
|
|
24
|
+
export declare function basmTip(value: unknown, topic: string): TopicAnchorTip;
|
|
25
|
+
export declare function basmAnchor(value: unknown, topic: string): TopicBlockAnchor;
|
|
26
|
+
export declare function basmAdmitted(value: unknown, maximum: number): AdmittedTxRef[];
|
|
27
|
+
//# sourceMappingURL=BASMValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BASMValidation.d.ts","sourceRoot":"","sources":["../../../src/BASMValidation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAEhF,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,gBAAgB,CAQhE,CAAA;AAEF,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,IAAI,EAChB,uBAAuB,GACvB,qBAAqB,GACrB,kBAAkB,GAClB,cAAc,GACd,iBAAiB;IANvB,YACkB,IAAI,EAChB,uBAAuB,GACvB,qBAAqB,GACrB,kBAAkB,GAClB,cAAc,GACd,iBAAiB,EACrB,OAAO,EAAE,MAAM,EAIhB;CACF;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAElF;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1E;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMlE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,MAAM,CAM9E;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ/E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAYrE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAW1E;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAiB7E"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BASMProtocolError = exports.DEFAULT_BASM_REMOTE_LIMITS = void 0;
|
|
4
|
+
exports.requireBASM = requireBASM;
|
|
5
|
+
exports.requireBASMLimit = requireBASMLimit;
|
|
6
|
+
exports.basmObject = basmObject;
|
|
7
|
+
exports.basmInteger = basmInteger;
|
|
8
|
+
exports.basmHash = basmHash;
|
|
9
|
+
exports.basmHex = basmHex;
|
|
10
|
+
exports.basmTxids = basmTxids;
|
|
11
|
+
exports.basmTip = basmTip;
|
|
12
|
+
exports.basmAnchor = basmAnchor;
|
|
13
|
+
exports.basmAdmitted = basmAdmitted;
|
|
14
|
+
const BASM_js_1 = require("./BASM.js");
|
|
15
|
+
exports.DEFAULT_BASM_REMOTE_LIMITS = Object.freeze({
|
|
16
|
+
maxResponseBytes: 64 * 1024 * 1024,
|
|
17
|
+
maxProofBytes: 8 * 1024 * 1024,
|
|
18
|
+
maxRawTransactionBytes: 32 * 1024 * 1024,
|
|
19
|
+
maxAdmittedTxids: 100000,
|
|
20
|
+
maxRequestedTxids: 1000,
|
|
21
|
+
maxAnchorRange: 1024,
|
|
22
|
+
timeoutMs: 30000
|
|
23
|
+
});
|
|
24
|
+
class BASMProtocolError extends Error {
|
|
25
|
+
constructor(code, message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.name = 'BASMProtocolError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.BASMProtocolError = BASMProtocolError;
|
|
32
|
+
function requireBASM(condition, message) {
|
|
33
|
+
if (!condition)
|
|
34
|
+
throw new BASMProtocolError('BASM_INVALID_RESPONSE', message);
|
|
35
|
+
}
|
|
36
|
+
function requireBASMLimit(condition, message) {
|
|
37
|
+
if (!condition)
|
|
38
|
+
throw new BASMProtocolError('BASM_RESOURCE_LIMIT', message);
|
|
39
|
+
}
|
|
40
|
+
function basmObject(value) {
|
|
41
|
+
requireBASM(typeof value === 'object' && value !== null && !Array.isArray(value), 'Expected a BASM JSON object');
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
function basmInteger(value, label, minimum = 0) {
|
|
45
|
+
requireBASM(typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum, `Invalid BASM ${label}`);
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function basmHash(value, label) {
|
|
49
|
+
requireBASM(typeof value === 'string' && /^[0-9a-f]{64}$/.test(value), `Invalid BASM ${label}`);
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
function basmHex(value, label, maxBytes) {
|
|
53
|
+
requireBASM(typeof value === 'string', `Invalid BASM ${label}`);
|
|
54
|
+
requireBASMLimit(value.length <= maxBytes * 2, `BASM ${label} exceeds byte limit`);
|
|
55
|
+
requireBASM(value.length > 0 && value.length % 2 === 0 && /^[0-9a-fA-F]+$/.test(value), `Invalid BASM ${label}`);
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
function basmTxids(value, maximum) {
|
|
59
|
+
requireBASM(Array.isArray(value), 'Invalid BASM txids');
|
|
60
|
+
requireBASMLimit(value.length <= maximum, 'BASM txid count exceeds limit');
|
|
61
|
+
const txids = value.map(txid => basmHash(txid, 'txid'));
|
|
62
|
+
requireBASM(new Set(txids).size === txids.length, 'Duplicate BASM txid');
|
|
63
|
+
return txids;
|
|
64
|
+
}
|
|
65
|
+
function basmTip(value, topic) {
|
|
66
|
+
const obj = basmObject(value);
|
|
67
|
+
requireBASM(obj.topic === topic, 'BASM topic mismatch');
|
|
68
|
+
const blockHeight = basmInteger(obj.blockHeight, 'tip height', -1);
|
|
69
|
+
const tac = basmHash(obj.tac, 'TAC');
|
|
70
|
+
const tip = { topic, blockHeight, tac };
|
|
71
|
+
if (obj.blockHash !== undefined)
|
|
72
|
+
tip.blockHash = basmHash(obj.blockHash, 'block hash');
|
|
73
|
+
if (obj.basmRoot !== undefined)
|
|
74
|
+
tip.basmRoot = basmHash(obj.basmRoot, 'root');
|
|
75
|
+
if (obj.admittedCount !== undefined)
|
|
76
|
+
tip.admittedCount = basmInteger(obj.admittedCount, 'admitted count');
|
|
77
|
+
if (blockHeight === -1)
|
|
78
|
+
requireBASM(tac === BASM_js_1.BASM_ZERO_HASH, 'Empty BASM tip must have zero TAC');
|
|
79
|
+
return tip;
|
|
80
|
+
}
|
|
81
|
+
function basmAnchor(value, topic) {
|
|
82
|
+
const obj = basmObject(value);
|
|
83
|
+
const tip = basmTip(value, topic);
|
|
84
|
+
return {
|
|
85
|
+
topic,
|
|
86
|
+
blockHeight: basmInteger(tip.blockHeight, 'anchor height'),
|
|
87
|
+
blockHash: basmHash(obj.blockHash, 'block hash'),
|
|
88
|
+
basmRoot: basmHash(obj.basmRoot, 'root'),
|
|
89
|
+
admittedCount: basmInteger(obj.admittedCount, 'admitted count'),
|
|
90
|
+
tac: tip.tac
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function basmAdmitted(value, maximum) {
|
|
94
|
+
requireBASM(Array.isArray(value), 'Invalid BASM admitted list');
|
|
95
|
+
requireBASMLimit(value.length <= maximum, 'BASM admitted count exceeds limit');
|
|
96
|
+
let previousIndex = -1;
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
return value.map(item => {
|
|
99
|
+
const obj = basmObject(item);
|
|
100
|
+
const txid = basmHash(obj.txid, 'txid');
|
|
101
|
+
const blockIndex = basmInteger(obj.blockIndex, 'block index');
|
|
102
|
+
requireBASM(blockIndex > previousIndex && !seen.has(txid), 'BASM admitted list must have unique txids in increasing block order');
|
|
103
|
+
previousIndex = blockIndex;
|
|
104
|
+
seen.add(txid);
|
|
105
|
+
return { txid, blockIndex };
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=BASMValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BASMValidation.js","sourceRoot":"","sources":["../../../src/BASMValidation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LockingScript } from '@bsv/sdk';
|
|
2
|
+
export type DiscoveryProtocol = 'SHIP' | 'SLAP';
|
|
3
|
+
export interface VerifiedDiscoveryAdvertisement {
|
|
4
|
+
protocol: DiscoveryProtocol;
|
|
5
|
+
identityKey: string;
|
|
6
|
+
domain: string;
|
|
7
|
+
topicOrService: string;
|
|
8
|
+
}
|
|
9
|
+
/** Decode and authenticate one canonical SHIP or SLAP PushDrop advertisement. */
|
|
10
|
+
export declare function decodeAndVerifyDiscoveryAdvertisement(lockingScript: LockingScript, expectedProtocol: DiscoveryProtocol): Promise<VerifiedDiscoveryAdvertisement>;
|
|
11
|
+
//# sourceMappingURL=DiscoveryAdvertisementValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscoveryAdvertisementValidation.d.ts","sourceRoot":"","sources":["../../../src/DiscoveryAdvertisementValidation.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,aAAa,EAId,MAAM,UAAU,CAAA;AACjB,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAA;AAE/C,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;CACvB;AAaD,iFAAiF;AACjF,wBAAsB,qCAAqC,CACzD,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,iBAAiB,GAClC,OAAO,CAAC,8BAA8B,CAAC,CA+CzC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeAndVerifyDiscoveryAdvertisement = decodeAndVerifyDiscoveryAdvertisement;
|
|
4
|
+
const utils_1 = require("@bsv/sdk/primitives/utils");
|
|
5
|
+
const sdk_1 = require("@bsv/sdk");
|
|
6
|
+
const MAX_DISCOVERY_FIELD_BYTES = 4096;
|
|
7
|
+
const MAX_DISCOVERY_PAYLOAD_BYTES = 8192;
|
|
8
|
+
const namePattern = {
|
|
9
|
+
SHIP: /^(?=.{1,50}$)tm_[a-z]+(?:_[a-z]+)*$/,
|
|
10
|
+
SLAP: /^(?=.{1,50}$)ls_[a-z]+(?:_[a-z]+)*$/
|
|
11
|
+
};
|
|
12
|
+
function walletProtocol(protocol) {
|
|
13
|
+
return [2, protocol === 'SHIP' ? 'service host interconnect' : 'service lookup availability'];
|
|
14
|
+
}
|
|
15
|
+
/** Decode and authenticate one canonical SHIP or SLAP PushDrop advertisement. */
|
|
16
|
+
async function decodeAndVerifyDiscoveryAdvertisement(lockingScript, expectedProtocol) {
|
|
17
|
+
const decoded = (0, sdk_1.decodeCanonicalPushDrop)(lockingScript, {
|
|
18
|
+
fieldCount: 5,
|
|
19
|
+
maximumFieldBytes: MAX_DISCOVERY_FIELD_BYTES,
|
|
20
|
+
maximumPayloadBytes: MAX_DISCOVERY_PAYLOAD_BYTES
|
|
21
|
+
});
|
|
22
|
+
const protocol = (0, utils_1.toUTF8Strict)(decoded.fields[0]);
|
|
23
|
+
if (protocol !== expectedProtocol)
|
|
24
|
+
throw new Error('Discovery advertisement protocol mismatch');
|
|
25
|
+
const identityKey = (0, utils_1.toHex)(decoded.fields[1]);
|
|
26
|
+
if (!/^(?:02|03)[0-9a-f]{64}$/.test(identityKey) ||
|
|
27
|
+
sdk_1.PublicKey.fromString(identityKey).toString() !== identityKey) {
|
|
28
|
+
throw new Error('Discovery advertisement identity key is invalid');
|
|
29
|
+
}
|
|
30
|
+
const domain = (0, utils_1.toUTF8Strict)(decoded.fields[2]);
|
|
31
|
+
if (new TextEncoder().encode(domain).byteLength < 1 ||
|
|
32
|
+
new TextEncoder().encode(domain).byteLength > 4096) {
|
|
33
|
+
throw new Error('Discovery advertisement domain is invalid');
|
|
34
|
+
}
|
|
35
|
+
const topicOrService = (0, utils_1.toUTF8Strict)(decoded.fields[3]);
|
|
36
|
+
if (!namePattern[expectedProtocol].test(topicOrService)) {
|
|
37
|
+
throw new Error('Discovery advertisement name is invalid');
|
|
38
|
+
}
|
|
39
|
+
const protocolID = walletProtocol(expectedProtocol);
|
|
40
|
+
const wallet = new sdk_1.ProtoWallet('anyone');
|
|
41
|
+
const { valid } = await wallet.verifySignature({
|
|
42
|
+
data: decoded.fields.slice(0, -1).flat(),
|
|
43
|
+
signature: decoded.fields.at(-1),
|
|
44
|
+
counterparty: identityKey,
|
|
45
|
+
protocolID,
|
|
46
|
+
keyID: '1'
|
|
47
|
+
});
|
|
48
|
+
if (valid !== true)
|
|
49
|
+
throw new Error('Discovery advertisement signature is invalid');
|
|
50
|
+
const { publicKey: expectedLockingKey } = await wallet.getPublicKey({
|
|
51
|
+
counterparty: identityKey,
|
|
52
|
+
protocolID,
|
|
53
|
+
keyID: '1'
|
|
54
|
+
});
|
|
55
|
+
if (expectedLockingKey !== decoded.lockingPublicKey.toString()) {
|
|
56
|
+
throw new Error('Discovery advertisement locking key is not linked to its identity');
|
|
57
|
+
}
|
|
58
|
+
return { protocol: expectedProtocol, identityKey, domain, topicOrService };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=DiscoveryAdvertisementValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscoveryAdvertisementValidation.js","sourceRoot":"","sources":["../../../src/DiscoveryAdvertisementValidation.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/src/Engine.d.ts
CHANGED
|
@@ -9,7 +9,12 @@ import { SyncConfiguration } from './SyncConfiguration.js';
|
|
|
9
9
|
import { type AdmittedListResponse, type BASMPeerSyncReport, type CompoundMerklePathResponse, type RawTransactionResponse, type ReorgReport, type TopicAnchorHeaderResolver, type TopicAnchorRangeResponse, type TopicAnchorTip } from './BASM.js';
|
|
10
10
|
type UTXOHistoryHydrationContext = {
|
|
11
11
|
outputCache: Map<string, Promise<Output | null>>;
|
|
12
|
+
budgetedOutputs: Set<string>;
|
|
13
|
+
hydratedNodes: number;
|
|
14
|
+
relationCount: number;
|
|
15
|
+
totalBeefBytes: number;
|
|
12
16
|
};
|
|
17
|
+
type SubmissionMode = 'historical-tx' | 'current-tx' | 'historical-tx-no-spv';
|
|
13
18
|
/**
|
|
14
19
|
* An engine for running BSV Overlay Services (topic managers and lookup services).
|
|
15
20
|
*/
|
|
@@ -38,6 +43,8 @@ export declare class Engine {
|
|
|
38
43
|
basmSyncEnabled: boolean;
|
|
39
44
|
unprovenEvictionBlocks: number;
|
|
40
45
|
maxLookupResults: number;
|
|
46
|
+
private submissionTail;
|
|
47
|
+
private basmFetchImpl?;
|
|
41
48
|
/**
|
|
42
49
|
* Creates a new Overlay Services Engine
|
|
43
50
|
* @param {[key: string]: TopicManager} managers - manages topic admittance
|
|
@@ -108,6 +115,7 @@ export declare class Engine {
|
|
|
108
115
|
rebuildFromHeight: number;
|
|
109
116
|
newTipHeight: number;
|
|
110
117
|
}): Promise<ReorgReport>;
|
|
118
|
+
private reconcileReorg;
|
|
111
119
|
/**
|
|
112
120
|
* Revalidation sweep: the reorg fallback for chain trackers without a reorg
|
|
113
121
|
* event stream, and the catch-up step on every reorg-SSE (re)connect (the
|
|
@@ -122,6 +130,7 @@ export declare class Engine {
|
|
|
122
130
|
private validateTopicSubmission;
|
|
123
131
|
private isTopicSubmissionAccepted;
|
|
124
132
|
private broadcastAcceptedSubmission;
|
|
133
|
+
private abortProvisionalAdmissions;
|
|
125
134
|
private notifyOutputSpent;
|
|
126
135
|
private markPreviousOutputSpent;
|
|
127
136
|
private markPreviousOutputsSpent;
|
|
@@ -133,6 +142,10 @@ export declare class Engine {
|
|
|
133
142
|
private applyTopicStorageMutation;
|
|
134
143
|
private applyStorageMutations;
|
|
135
144
|
private propagateSubmission;
|
|
145
|
+
private assertSupportedTopics;
|
|
146
|
+
private shouldSkipPropagation;
|
|
147
|
+
private notifySteakReady;
|
|
148
|
+
private acknowledgeOverlayAdmission;
|
|
136
149
|
/**
|
|
137
150
|
* Submits a transaction for processing by Overlay Services.
|
|
138
151
|
* @param {TaggedBEEF} taggedBEEF - The transaction to process
|
|
@@ -140,11 +153,13 @@ export declare class Engine {
|
|
|
140
153
|
* @param {string} mode — Indicates the submission behavior, whether historical or current. Historical transactions are not broadcast or propagated.
|
|
141
154
|
* @param {number[]} offChainValues — Values necessary to evaluate topical admittance that are not stored on-chain.
|
|
142
155
|
*
|
|
143
|
-
* The optional callback
|
|
156
|
+
* The optional callback is invoked after any required transaction broadcast and
|
|
157
|
+
* local storage mutations have completed, but before peer-to-peer propagation.
|
|
144
158
|
*
|
|
145
159
|
* @returns {Promise<STEAK>} The submitted transaction execution acknowledgement
|
|
146
160
|
*/
|
|
147
|
-
submit(taggedBEEF: TaggedBEEF, onSteakReady?: (steak: STEAK) => void, mode?:
|
|
161
|
+
submit(taggedBEEF: TaggedBEEF, onSteakReady?: (steak: STEAK) => void, mode?: SubmissionMode, offChainValues?: number[]): Promise<STEAK>;
|
|
162
|
+
private submitUnlocked;
|
|
148
163
|
/**
|
|
149
164
|
* Submit a lookup question to the Overlay Services Engine, and receive back a Lookup Answer
|
|
150
165
|
* @param LookupQuestion — The question to ask the Overlay Services Engine
|
|
@@ -153,6 +168,8 @@ export declare class Engine {
|
|
|
153
168
|
lookup(lookupQuestion: LookupQuestion): Promise<LookupAnswer>;
|
|
154
169
|
private createUTXOHistoryHydrationContext;
|
|
155
170
|
private toOutputCacheKey;
|
|
171
|
+
private assertLookupFormula;
|
|
172
|
+
private validateLookupOutput;
|
|
156
173
|
private preloadOutputsWithBEEF;
|
|
157
174
|
private loadOutputWithBEEF;
|
|
158
175
|
private hydrateUTXOHistoryNode;
|
|
@@ -175,6 +192,7 @@ export declare class Engine {
|
|
|
175
192
|
* @throws Will throw an error if there are issues during the advertisement synchronization process.
|
|
176
193
|
* @returns {Promise<void>} A promise that resolves when the synchronization process is complete.
|
|
177
194
|
*/
|
|
195
|
+
private validateCurrentAdvertisements;
|
|
178
196
|
syncAdvertisements(): Promise<void>;
|
|
179
197
|
/**
|
|
180
198
|
* This method goes through each topic that we support syncing and attempts to sync with each endpoint
|
|
@@ -186,13 +204,23 @@ export declare class Engine {
|
|
|
186
204
|
startGASPSync(): Promise<void>;
|
|
187
205
|
private syncGASPWithPeer;
|
|
188
206
|
private resolveSyncEndpointsForTopic;
|
|
207
|
+
private assertSupportedBASMTopic;
|
|
208
|
+
private assertTopicAnchorTip;
|
|
209
|
+
private assertTopicBlockAnchor;
|
|
189
210
|
provideTopicAnchorTip(topic: string): Promise<TopicAnchorTip>;
|
|
190
211
|
provideTopicAnchorRange(topic: string, fromHeight: number, toHeight: number): Promise<TopicAnchorRangeResponse>;
|
|
191
212
|
provideAdmittedList(topic: string, blockHeight: number, blockHash?: string): Promise<AdmittedListResponse>;
|
|
192
213
|
provideCompoundMerklePath(topic: string, blockHeight: number, txids: string[]): Promise<CompoundMerklePathResponse>;
|
|
193
|
-
provideRawTransactions(txids: string[]): Promise<RawTransactionResponse>;
|
|
214
|
+
provideRawTransactions(txids: string[], topic?: string): Promise<RawTransactionResponse>;
|
|
194
215
|
startBASMSync(): Promise<BASMPeerSyncReport[]>;
|
|
195
216
|
private reconcileBASMWithPeer;
|
|
217
|
+
private requireMatchingRemoteBASMTip;
|
|
218
|
+
private finishBASMWhenRemoteIsNotAhead;
|
|
219
|
+
private requireBASMRangePrefix;
|
|
220
|
+
private advanceBASMWithRemoteAnchors;
|
|
221
|
+
private markBASMPeerSyncError;
|
|
222
|
+
private requireCanonicalBASMAnchor;
|
|
223
|
+
private validateBASMProofPositions;
|
|
196
224
|
private reconcileRemoteAnchor;
|
|
197
225
|
private fetchBASMMissingTransactions;
|
|
198
226
|
evictUnprovenTransactions(options?: {
|
|
@@ -222,6 +250,7 @@ export declare class Engine {
|
|
|
222
250
|
error: string;
|
|
223
251
|
}>;
|
|
224
252
|
}>;
|
|
253
|
+
private validateUnprovenCandidates;
|
|
225
254
|
maintainUnprovenTransactions(options: {
|
|
226
255
|
topic?: string;
|
|
227
256
|
thresholdBlocks?: number;
|
|
@@ -278,7 +307,7 @@ export declare class Engine {
|
|
|
278
307
|
* @returns A promise that resolves to a GASPNode containing the raw transaction and other optional data.
|
|
279
308
|
* @throws An error if no output is found for the given transaction ID and output index.
|
|
280
309
|
*/
|
|
281
|
-
provideForeignGASPNode(graphID: string, txid: string, outputIndex: number): Promise<GASPNode>;
|
|
310
|
+
provideForeignGASPNode(graphID: string, txid: string, outputIndex: number, topic?: string): Promise<GASPNode>;
|
|
282
311
|
/**
|
|
283
312
|
* Traverse and return the history of a UTXO.
|
|
284
313
|
*
|
|
@@ -293,7 +322,7 @@ export declare class Engine {
|
|
|
293
322
|
* @param {number} [currentDepth=0] - The current depth of the traversal relative to the top-level UTXO.
|
|
294
323
|
*
|
|
295
324
|
* @returns {Promise<Output | undefined>} - A promise that resolves to the output history if found, or undefined if not.
|
|
296
|
-
|
|
325
|
+
*/
|
|
297
326
|
getUTXOHistory(output: Output, historySelector?: ((beef: number[], outputIndex: number, currentDepth: number) => Promise<boolean>) | number, currentDepth?: number, context?: UTXOHistoryHydrationContext): Promise<Output | undefined>;
|
|
298
327
|
/**
|
|
299
328
|
* Delete a UTXO and all stale consumed inputs.
|
|
@@ -301,6 +330,8 @@ export declare class Engine {
|
|
|
301
330
|
* @returns {Promise<void>} - A promise that resolves when the deletion process is complete.
|
|
302
331
|
*/
|
|
303
332
|
private deleteUTXODeep;
|
|
333
|
+
private assertStoredOutputRelations;
|
|
334
|
+
private assertStoredOutputMatches;
|
|
304
335
|
/**
|
|
305
336
|
* Given a new transaction proof (txid, proof),
|
|
306
337
|
* update tx.merklePath if appropriate,
|
|
@@ -311,14 +342,8 @@ export declare class Engine {
|
|
|
311
342
|
* @param proof for txid
|
|
312
343
|
*/
|
|
313
344
|
private updateInputProofs;
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
*
|
|
317
|
-
* @param output - An output derived from txid which may benefit from new proof.
|
|
318
|
-
* @param txid - The txid for which proof is a valid merkle path.
|
|
319
|
-
* @param proof - The merklePath proving txid is a mined transaction hash
|
|
320
|
-
*/
|
|
321
|
-
private updateMerkleProof;
|
|
345
|
+
private prepareMerkleProofUpdate;
|
|
346
|
+
private collectMerkleProofOutputs;
|
|
322
347
|
/**
|
|
323
348
|
* Recursively prune UTXOs when an incoming Merkle Proof is received.
|
|
324
349
|
*
|