@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
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { extractMerkleProofMetadata } from './BASM.js';
|
|
3
|
+
import { admissionSemanticDigest, asStorageUint64, getAdmissionStorage } from './storage/AdmissionStorage.js';
|
|
4
|
+
export const OVERLAY_ENGINE_POLICY_ID = 'overlay-engine-submit-v1';
|
|
5
|
+
export function getOverlayAdmissionHost(storage) {
|
|
6
|
+
const admission = getAdmissionStorage(storage);
|
|
7
|
+
if (admission === undefined || typeof storage !== 'object' || storage === null)
|
|
8
|
+
return undefined;
|
|
9
|
+
if (!('admissionScope' in storage))
|
|
10
|
+
return undefined;
|
|
11
|
+
const scope = storage.admissionScope;
|
|
12
|
+
if (scope === undefined ||
|
|
13
|
+
typeof scope.network !== 'string' ||
|
|
14
|
+
typeof scope.genesisHash !== 'string' ||
|
|
15
|
+
typeof scope.nodeId !== 'string' ||
|
|
16
|
+
!/^[0-9a-f]{64}$/.test(scope.genesisHash)) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const host = storage;
|
|
20
|
+
return {
|
|
21
|
+
admission,
|
|
22
|
+
admissionScope: { ...scope },
|
|
23
|
+
// Adapters are class instances whose methods read instance state, so each
|
|
24
|
+
// optional method stays bound to the storage it came from.
|
|
25
|
+
publishAdmissionPayload: host.publishAdmissionPayload?.bind(host),
|
|
26
|
+
enlistedIndexTargets: host.enlistedIndexTargets?.bind(host),
|
|
27
|
+
getHistoryFence: host.getHistoryFence?.bind(host)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function overlayAdmissionContextDigest(offChainValues) {
|
|
31
|
+
const hash = createHash('sha256');
|
|
32
|
+
if (offChainValues !== undefined)
|
|
33
|
+
hash.update(Buffer.from(offChainValues));
|
|
34
|
+
return hash.digest('hex');
|
|
35
|
+
}
|
|
36
|
+
export function overlayAdmissionOperationId(_mode, txid, topics) {
|
|
37
|
+
const topicKey = [...topics].sort((a, b) => a.localeCompare(b, 'en')).join('\n');
|
|
38
|
+
// Historical GASP replay and a later live retry represent the same
|
|
39
|
+
// transaction admission. Keep their id stable so the durable admission
|
|
40
|
+
// record is replayed instead of being submitted a second time.
|
|
41
|
+
const raw = `submit:${txid}:${topicKey}`;
|
|
42
|
+
if (Buffer.byteLength(raw, 'utf8') <= 512 && raw.isWellFormed())
|
|
43
|
+
return raw;
|
|
44
|
+
return `submit:${createHash('sha256').update(raw, 'utf8').digest('hex')}`;
|
|
45
|
+
}
|
|
46
|
+
export function overlayAdmissionMode(mode) {
|
|
47
|
+
return mode === 'current-tx' ? 'live' : 'historical';
|
|
48
|
+
}
|
|
49
|
+
async function localPayload(host, kind, bytes, txid) {
|
|
50
|
+
if (host.publishAdmissionPayload !== undefined) {
|
|
51
|
+
return await host.publishAdmissionPayload({ kind, bytes, txid });
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
kind,
|
|
55
|
+
digest: createHash('sha256').update(bytes).digest('hex'),
|
|
56
|
+
byteLength: asStorageUint64(String(bytes.byteLength))
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Selects the topics that require a new admission decision: topics that did
|
|
61
|
+
* not fail validation, are not already-applied dupes, and actually admit or
|
|
62
|
+
* retain something (or consume a previously-admitted coin). Already-applied
|
|
63
|
+
* (dupe) topics are excluded so that a retry — including a historical GASP
|
|
64
|
+
* replay after a live admit, or a multi-topic resubmit where only some
|
|
65
|
+
* topics were previously applied — never re-submits an admission decision
|
|
66
|
+
* for a topic that MongoAdmissionStorage.assertAppliedAvailable would reject
|
|
67
|
+
* as belonging to a different operation.
|
|
68
|
+
*/
|
|
69
|
+
export function selectNewAdmissionTopics(validations, failedTopics) {
|
|
70
|
+
return validations.filter(validation => !failedTopics.has(validation.topic) &&
|
|
71
|
+
!validation.isDupe &&
|
|
72
|
+
(validation.admissibleOutputs.outputsToAdmit.length > 0 ||
|
|
73
|
+
validation.admissibleOutputs.coinsToRetain.length > 0 ||
|
|
74
|
+
validation.previousCoins.length > 0));
|
|
75
|
+
}
|
|
76
|
+
export async function buildOverlayAdmissionPlan(input) {
|
|
77
|
+
// Only topics with a genuinely new admission get an identity/decision entry
|
|
78
|
+
// and take part in the commit. Dupe topics are still reflected in `steak`
|
|
79
|
+
// below (with their empty admissibleOutputs), matching what the classic
|
|
80
|
+
// storage path already returns for a dupe, but they must never be
|
|
81
|
+
// resubmitted to commitAdmission: MongoAdmissionStorage.assertAppliedAvailable
|
|
82
|
+
// rejects an applied row whose admissionId belongs to a different
|
|
83
|
+
// operation, which a dupe re-included here would trigger on retry.
|
|
84
|
+
const accepted = selectNewAdmissionTopics(input.validations, input.failedTopics);
|
|
85
|
+
const identityTopics = accepted.map(validation => ({
|
|
86
|
+
topic: validation.topic,
|
|
87
|
+
policyId: OVERLAY_ENGINE_POLICY_ID
|
|
88
|
+
}));
|
|
89
|
+
if (identityTopics.length === 0)
|
|
90
|
+
throw new Error('Overlay admission plan has no topics');
|
|
91
|
+
const identity = {
|
|
92
|
+
scope: input.host.admissionScope,
|
|
93
|
+
txid: input.txid,
|
|
94
|
+
mode: input.mode,
|
|
95
|
+
contextDigest: overlayAdmissionContextDigest(input.offChainValues),
|
|
96
|
+
topics: identityTopics
|
|
97
|
+
};
|
|
98
|
+
const raw = await localPayload(input.host, 'raw-transaction', Buffer.from(input.tx.toBinary()), input.txid);
|
|
99
|
+
const payloads = [raw];
|
|
100
|
+
let proof;
|
|
101
|
+
if (input.tx.merklePath !== undefined) {
|
|
102
|
+
proof = await localPayload(input.host, 'merkle-path', Buffer.from(input.tx.merklePath.toBinary()));
|
|
103
|
+
payloads.push(proof);
|
|
104
|
+
}
|
|
105
|
+
const merkle = extractMerkleProofMetadata(input.txid, input.tx.merklePath);
|
|
106
|
+
const decisions = [];
|
|
107
|
+
const steak = {};
|
|
108
|
+
for (const validation of input.validations) {
|
|
109
|
+
steak[validation.topic] = {
|
|
110
|
+
outputsToAdmit: validation.admissibleOutputs.outputsToAdmit,
|
|
111
|
+
coinsToRetain: validation.admissibleOutputs.coinsToRetain,
|
|
112
|
+
coinsRemoved: validation.admissibleOutputs.coinsRemoved ?? []
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
for (const validation of accepted) {
|
|
116
|
+
const { outputsConsumed, outputsToMarkStale } = classifyCoins(input.tx, validation);
|
|
117
|
+
const fence = input.host.getHistoryFence === undefined
|
|
118
|
+
? { chainEpoch: asStorageUint64('0'), topicHistoryGeneration: asStorageUint64('0') }
|
|
119
|
+
: await input.host.getHistoryFence(validation.topic);
|
|
120
|
+
const outputs = [];
|
|
121
|
+
for (const outputIndex of validation.admissibleOutputs.outputsToAdmit) {
|
|
122
|
+
const txOut = input.tx.outputs[outputIndex];
|
|
123
|
+
if (typeof txOut?.satoshis !== 'number' || !Number.isSafeInteger(txOut.satoshis))
|
|
124
|
+
continue;
|
|
125
|
+
const scriptBytes = Buffer.from(txOut.lockingScript.toBinary());
|
|
126
|
+
const script = await localPayload(input.host, 'locking-script', scriptBytes);
|
|
127
|
+
payloads.push(script);
|
|
128
|
+
outputs.push({
|
|
129
|
+
txid: input.txid,
|
|
130
|
+
outputIndex: asStorageUint64(String(outputIndex)),
|
|
131
|
+
satoshis: asStorageUint64(String(txOut.satoshis)),
|
|
132
|
+
score: asStorageUint64(String(Date.now())),
|
|
133
|
+
script: { payload: script, offset: asStorageUint64('0'), byteLength: script.byteLength }
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const spends = validation.previousOutputs.flatMap(output => output === null
|
|
137
|
+
? []
|
|
138
|
+
: [
|
|
139
|
+
{
|
|
140
|
+
outpoint: { txid: output.txid, outputIndex: asStorageUint64(String(output.outputIndex)) },
|
|
141
|
+
expectedVersion: '1',
|
|
142
|
+
spender: input.txid
|
|
143
|
+
}
|
|
144
|
+
]);
|
|
145
|
+
decisions.push({
|
|
146
|
+
topic: validation.topic,
|
|
147
|
+
expectedHistory: fence,
|
|
148
|
+
reads: [],
|
|
149
|
+
spends,
|
|
150
|
+
evictions: outputsToMarkStale.map(item => ({
|
|
151
|
+
txid: item.txid,
|
|
152
|
+
outputIndex: asStorageUint64(String(item.previousOutputIndex))
|
|
153
|
+
})),
|
|
154
|
+
outputs,
|
|
155
|
+
edges: outputsConsumed.flatMap(source => outputs.map(output => ({
|
|
156
|
+
source: { txid: source.txid, outputIndex: asStorageUint64(String(source.outputIndex)) },
|
|
157
|
+
consumer: { txid: output.txid, outputIndex: output.outputIndex }
|
|
158
|
+
}))),
|
|
159
|
+
applied: appliedRecord(input, proof, merkle)
|
|
160
|
+
});
|
|
161
|
+
steak[validation.topic] = {
|
|
162
|
+
outputsToAdmit: validation.admissibleOutputs.outputsToAdmit,
|
|
163
|
+
coinsToRetain: validation.admissibleOutputs.coinsToRetain,
|
|
164
|
+
coinsRemoved: outputsToMarkStale.map(item => item.inputIndex)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const enlisted = new Set(input.host.enlistedIndexTargets?.() ?? []);
|
|
168
|
+
const outbox = Object.keys(input.lookupServices)
|
|
169
|
+
.filter(target => !enlisted.has(target))
|
|
170
|
+
.map(target => ({
|
|
171
|
+
eventId: `${overlayAdmissionOperationId(input.mode, input.txid, input.topics)}:lookup:${target}`,
|
|
172
|
+
kind: 'lookup',
|
|
173
|
+
target,
|
|
174
|
+
payloads: [raw]
|
|
175
|
+
}));
|
|
176
|
+
if (input.includePropagation && input.mode === 'live') {
|
|
177
|
+
outbox.push({
|
|
178
|
+
eventId: `${overlayAdmissionOperationId(input.mode, input.txid, input.topics)}:propagate`,
|
|
179
|
+
kind: 'propagation',
|
|
180
|
+
target: 'ship',
|
|
181
|
+
payloads: [raw]
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
key: {
|
|
186
|
+
scope: input.host.admissionScope,
|
|
187
|
+
operationId: overlayAdmissionOperationId(input.mode, input.txid, input.topics),
|
|
188
|
+
semanticDigest: admissionSemanticDigest(identity)
|
|
189
|
+
},
|
|
190
|
+
identity,
|
|
191
|
+
payloads: uniquePayloads(payloads),
|
|
192
|
+
decisions,
|
|
193
|
+
outbox,
|
|
194
|
+
steak: JSON.stringify(steak)
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
export async function waitForAdmissionReceipt(admission, plan, rebuild) {
|
|
198
|
+
let current = plan;
|
|
199
|
+
for (let attempt = 0; attempt < 8; attempt += 1) {
|
|
200
|
+
const result = await admission.commitAdmission(current);
|
|
201
|
+
if (result.state === 'committed')
|
|
202
|
+
return result;
|
|
203
|
+
if (result.state === 'rejected') {
|
|
204
|
+
if (result.code === 'read-conflict' && attempt < 7) {
|
|
205
|
+
current = await rebuild();
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
throw new Error(`Overlay admission rejected: ${result.code}`);
|
|
209
|
+
}
|
|
210
|
+
const reconciled = await admission.reconcileAdmission(current.key, result.attemptId);
|
|
211
|
+
if (reconciled.state === 'committed')
|
|
212
|
+
return reconciled;
|
|
213
|
+
if (reconciled.state === 'aborted') {
|
|
214
|
+
current = await rebuild();
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (reconciled.state === 'rejected') {
|
|
218
|
+
throw new Error(`Overlay admission rejected: ${reconciled.code}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
throw new Error('Overlay admission commit is pending');
|
|
222
|
+
}
|
|
223
|
+
function appliedRecord(input, proof, merkle) {
|
|
224
|
+
const applied = { txid: input.txid };
|
|
225
|
+
const firstSeen = input.applied?.firstSeenHeight ?? merkle?.blockHeight;
|
|
226
|
+
if (firstSeen !== undefined)
|
|
227
|
+
applied.firstSeenHeight = asStorageUint64(String(firstSeen));
|
|
228
|
+
if (proof !== undefined)
|
|
229
|
+
applied.proof = proof;
|
|
230
|
+
const blockHash = input.applied?.blockHash;
|
|
231
|
+
const height = input.applied?.blockHeight ?? merkle?.blockHeight;
|
|
232
|
+
const index = input.applied?.blockIndex ?? merkle?.blockIndex;
|
|
233
|
+
const merkleRoot = input.applied?.merkleRoot ?? merkle?.merkleRoot;
|
|
234
|
+
if (blockHash !== undefined &&
|
|
235
|
+
height !== undefined &&
|
|
236
|
+
index !== undefined &&
|
|
237
|
+
merkleRoot !== undefined) {
|
|
238
|
+
applied.block = {
|
|
239
|
+
height: asStorageUint64(String(height)),
|
|
240
|
+
hash: blockHash,
|
|
241
|
+
index: asStorageUint64(String(index)),
|
|
242
|
+
merkleRoot
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return applied;
|
|
246
|
+
}
|
|
247
|
+
function uniquePayloads(payloads) {
|
|
248
|
+
const seen = new Set();
|
|
249
|
+
const result = [];
|
|
250
|
+
for (const payload of payloads) {
|
|
251
|
+
const key = `${payload.kind}:${payload.digest}:${payload.byteLength}`;
|
|
252
|
+
if (seen.has(key))
|
|
253
|
+
continue;
|
|
254
|
+
seen.add(key);
|
|
255
|
+
result.push(payload);
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
function classifyCoins(tx, validation) {
|
|
260
|
+
const outputsConsumed = [];
|
|
261
|
+
const outputsToMarkStale = [];
|
|
262
|
+
for (const inputIndex of validation.previousCoins) {
|
|
263
|
+
const input = tx.inputs[inputIndex];
|
|
264
|
+
const previousTXID = input.sourceTXID ?? input.sourceTransaction?.id('hex');
|
|
265
|
+
if (typeof previousTXID !== 'string')
|
|
266
|
+
continue;
|
|
267
|
+
if (validation.admissibleOutputs.coinsToRetain.includes(inputIndex)) {
|
|
268
|
+
outputsConsumed.push({ txid: previousTXID, outputIndex: input.sourceOutputIndex });
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
outputsToMarkStale.push({
|
|
272
|
+
txid: previousTXID,
|
|
273
|
+
previousOutputIndex: input.sourceOutputIndex,
|
|
274
|
+
inputIndex
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return { outputsConsumed, outputsToMarkStale };
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=EngineAdmission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EngineAdmission.js","sourceRoot":"","sources":["../../../src/EngineAdmission.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import { assertGASPInitialResponse, assertGASPNode, assertHash, assertNonnegativeInteger, assertOutpoint, assertOutputIndex, assertTopic, MAX_GASP_NODE_JSON_BYTES, MAX_GASP_PAGE_SIZE, readPeerJSON, securePeerFetch } from '../RemoteSecurity.js';
|
|
1
2
|
export class OverlayGASPRemote {
|
|
2
3
|
endpointURL;
|
|
3
4
|
topic;
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
fetchImpl;
|
|
6
|
+
constructor(endpointURL, topic, fetchImpl) {
|
|
7
|
+
assertTopic(topic);
|
|
8
|
+
const secured = securePeerFetch(endpointURL, fetchImpl);
|
|
9
|
+
this.endpointURL = secured.endpoint;
|
|
6
10
|
this.topic = topic;
|
|
11
|
+
this.fetchImpl = secured.fetchImpl;
|
|
7
12
|
}
|
|
8
13
|
/**
|
|
9
14
|
* Given an outgoing initial request, sends the request to the foreign instance and obtains their initial response.
|
|
@@ -11,11 +16,13 @@ export class OverlayGASPRemote {
|
|
|
11
16
|
* @returns
|
|
12
17
|
*/
|
|
13
18
|
async getInitialResponse(request) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
assertNonnegativeInteger(request.since, 'GASP request since');
|
|
20
|
+
const pageLimit = request.limit ?? MAX_GASP_PAGE_SIZE;
|
|
21
|
+
if (!Number.isSafeInteger(pageLimit) || pageLimit < 1 || pageLimit > MAX_GASP_PAGE_SIZE) {
|
|
22
|
+
throw new TypeError(`GASP request limit must be between 1 and ${MAX_GASP_PAGE_SIZE}`);
|
|
23
|
+
}
|
|
17
24
|
const url = `${this.endpointURL}/requestSyncResponse`;
|
|
18
|
-
const response = await
|
|
25
|
+
const response = await this.fetchImpl(url, {
|
|
19
26
|
method: 'POST',
|
|
20
27
|
headers: {
|
|
21
28
|
'Content-Type': 'application/json',
|
|
@@ -23,22 +30,9 @@ export class OverlayGASPRemote {
|
|
|
23
30
|
},
|
|
24
31
|
body: JSON.stringify(request)
|
|
25
32
|
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const result = await response.json();
|
|
30
|
-
// Validate and return the response in the correct format
|
|
31
|
-
if (!Array.isArray(result.UTXOList) || typeof result.since !== 'number') {
|
|
32
|
-
throw new TypeError('Invalid response format');
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
UTXOList: result.UTXOList.map((utxo) => ({
|
|
36
|
-
txid: utxo.txid,
|
|
37
|
-
outputIndex: utxo.outputIndex,
|
|
38
|
-
score: utxo.score ?? 0
|
|
39
|
-
})),
|
|
40
|
-
since: result.since
|
|
41
|
-
};
|
|
33
|
+
const result = await readPeerJSON(response);
|
|
34
|
+
assertGASPInitialResponse(result, pageLimit);
|
|
35
|
+
return result;
|
|
42
36
|
}
|
|
43
37
|
/**
|
|
44
38
|
* Given an outgoing txid, outputIndex and optional metadata, request the associated GASP node from the foreign instance.
|
|
@@ -49,7 +43,11 @@ export class OverlayGASPRemote {
|
|
|
49
43
|
* @returns
|
|
50
44
|
*/
|
|
51
45
|
async requestNode(graphID, txid, outputIndex, metadata) {
|
|
52
|
-
|
|
46
|
+
assertOutpoint(graphID, 'GASP request graphID');
|
|
47
|
+
assertHash(txid, 'GASP request txid');
|
|
48
|
+
assertOutputIndex(outputIndex, 'GASP request outputIndex');
|
|
49
|
+
if (typeof metadata !== 'boolean')
|
|
50
|
+
throw new TypeError('GASP request metadata flag is invalid');
|
|
53
51
|
const url = `${this.endpointURL}/requestForeignGASPNode`;
|
|
54
52
|
const body = {
|
|
55
53
|
graphID,
|
|
@@ -57,31 +55,17 @@ export class OverlayGASPRemote {
|
|
|
57
55
|
outputIndex,
|
|
58
56
|
metadata
|
|
59
57
|
};
|
|
60
|
-
const response = await
|
|
58
|
+
const response = await this.fetchImpl(url, {
|
|
61
59
|
method: 'POST',
|
|
62
60
|
headers: {
|
|
63
|
-
'Content-Type': 'application/json'
|
|
61
|
+
'Content-Type': 'application/json',
|
|
62
|
+
'X-BSV-Topic': this.topic
|
|
64
63
|
},
|
|
65
64
|
body: JSON.stringify(body)
|
|
66
65
|
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const result = await response.json();
|
|
71
|
-
// Validate and return the response in the correct format
|
|
72
|
-
if (typeof result.graphID !== 'string' || typeof result.rawTx !== 'string' || typeof result.outputIndex !== 'number') {
|
|
73
|
-
throw new TypeError('Invalid response format');
|
|
74
|
-
}
|
|
75
|
-
const gaspNode = {
|
|
76
|
-
graphID: result.graphID,
|
|
77
|
-
rawTx: result.rawTx,
|
|
78
|
-
outputIndex: result.outputIndex,
|
|
79
|
-
proof: result.proof,
|
|
80
|
-
txMetadata: result.txMetadata,
|
|
81
|
-
outputMetadata: result.outputMetadata,
|
|
82
|
-
inputs: result.inputs
|
|
83
|
-
};
|
|
84
|
-
return gaspNode;
|
|
66
|
+
const result = await readPeerJSON(response, MAX_GASP_NODE_JSON_BYTES);
|
|
67
|
+
assertGASPNode(result, { graphID, txid, outputIndex });
|
|
68
|
+
return result;
|
|
85
69
|
}
|
|
86
70
|
// ---- Now optional methods ----
|
|
87
71
|
// When are only syncing to them
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayGASPRemote.js","sourceRoot":"","sources":["../../../../src/GASP/OverlayGASPRemote.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OverlayGASPRemote.js","sourceRoot":"","sources":["../../../../src/GASP/OverlayGASPRemote.ts"],"names":[],"mappings":"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"}
|