@originals/sdk 1.8.2 → 1.8.3
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/package.json +5 -6
- package/src/adapters/FeeOracleMock.ts +0 -9
- package/src/adapters/index.ts +0 -5
- package/src/adapters/providers/OrdHttpProvider.ts +0 -126
- package/src/adapters/providers/OrdMockProvider.ts +0 -101
- package/src/adapters/types.ts +0 -66
- package/src/bitcoin/BitcoinManager.ts +0 -329
- package/src/bitcoin/BroadcastClient.ts +0 -54
- package/src/bitcoin/OrdinalsClient.ts +0 -120
- package/src/bitcoin/PSBTBuilder.ts +0 -106
- package/src/bitcoin/fee-calculation.ts +0 -38
- package/src/bitcoin/providers/OrdNodeProvider.ts +0 -92
- package/src/bitcoin/providers/OrdinalsProvider.ts +0 -56
- package/src/bitcoin/providers/types.ts +0 -59
- package/src/bitcoin/transactions/commit.ts +0 -465
- package/src/bitcoin/transactions/index.ts +0 -13
- package/src/bitcoin/transfer.ts +0 -43
- package/src/bitcoin/utxo-selection.ts +0 -322
- package/src/bitcoin/utxo.ts +0 -113
- package/src/cel/ExternalReferenceManager.ts +0 -87
- package/src/cel/OriginalsCel.ts +0 -460
- package/src/cel/algorithms/createEventLog.ts +0 -68
- package/src/cel/algorithms/deactivateEventLog.ts +0 -109
- package/src/cel/algorithms/index.ts +0 -11
- package/src/cel/algorithms/updateEventLog.ts +0 -99
- package/src/cel/algorithms/verifyEventLog.ts +0 -306
- package/src/cel/algorithms/witnessEvent.ts +0 -87
- package/src/cel/cli/create.ts +0 -330
- package/src/cel/cli/index.ts +0 -383
- package/src/cel/cli/inspect.ts +0 -549
- package/src/cel/cli/migrate.ts +0 -473
- package/src/cel/cli/verify.ts +0 -249
- package/src/cel/hash.ts +0 -71
- package/src/cel/index.ts +0 -16
- package/src/cel/layers/BtcoCelManager.ts +0 -408
- package/src/cel/layers/PeerCelManager.ts +0 -371
- package/src/cel/layers/WebVHCelManager.ts +0 -361
- package/src/cel/layers/index.ts +0 -27
- package/src/cel/serialization/cbor.ts +0 -189
- package/src/cel/serialization/index.ts +0 -10
- package/src/cel/serialization/json.ts +0 -209
- package/src/cel/types.ts +0 -160
- package/src/cel/witnesses/BitcoinWitness.ts +0 -184
- package/src/cel/witnesses/HttpWitness.ts +0 -241
- package/src/cel/witnesses/WitnessService.ts +0 -51
- package/src/cel/witnesses/index.ts +0 -11
- package/src/contexts/credentials-v1.json +0 -237
- package/src/contexts/credentials-v2-examples.json +0 -5
- package/src/contexts/credentials-v2.json +0 -340
- package/src/contexts/credentials.json +0 -237
- package/src/contexts/data-integrity-v2.json +0 -81
- package/src/contexts/dids.json +0 -58
- package/src/contexts/ed255192020.json +0 -93
- package/src/contexts/ordinals-plus.json +0 -23
- package/src/contexts/originals.json +0 -22
- package/src/core/OriginalsSDK.ts +0 -420
- package/src/crypto/Multikey.ts +0 -194
- package/src/crypto/Signer.ts +0 -262
- package/src/crypto/noble-init.ts +0 -138
- package/src/did/BtcoDidResolver.ts +0 -231
- package/src/did/DIDManager.ts +0 -705
- package/src/did/Ed25519Verifier.ts +0 -68
- package/src/did/KeyManager.ts +0 -239
- package/src/did/WebVHManager.ts +0 -499
- package/src/did/createBtcoDidDocument.ts +0 -60
- package/src/did/providers/OrdinalsClientProviderAdapter.ts +0 -68
- package/src/events/EventEmitter.ts +0 -222
- package/src/events/index.ts +0 -19
- package/src/events/types.ts +0 -331
- package/src/examples/basic-usage.ts +0 -78
- package/src/examples/create-module-original.ts +0 -435
- package/src/examples/full-lifecycle-flow.ts +0 -514
- package/src/examples/run.ts +0 -60
- package/src/index.ts +0 -204
- package/src/kinds/KindRegistry.ts +0 -320
- package/src/kinds/index.ts +0 -74
- package/src/kinds/types.ts +0 -470
- package/src/kinds/validators/AgentValidator.ts +0 -257
- package/src/kinds/validators/AppValidator.ts +0 -211
- package/src/kinds/validators/DatasetValidator.ts +0 -242
- package/src/kinds/validators/DocumentValidator.ts +0 -311
- package/src/kinds/validators/MediaValidator.ts +0 -269
- package/src/kinds/validators/ModuleValidator.ts +0 -225
- package/src/kinds/validators/base.ts +0 -276
- package/src/kinds/validators/index.ts +0 -12
- package/src/lifecycle/BatchOperations.ts +0 -381
- package/src/lifecycle/LifecycleManager.ts +0 -2156
- package/src/lifecycle/OriginalsAsset.ts +0 -524
- package/src/lifecycle/ProvenanceQuery.ts +0 -280
- package/src/lifecycle/ResourceVersioning.ts +0 -163
- package/src/migration/MigrationManager.ts +0 -587
- package/src/migration/audit/AuditLogger.ts +0 -176
- package/src/migration/checkpoint/CheckpointManager.ts +0 -112
- package/src/migration/checkpoint/CheckpointStorage.ts +0 -101
- package/src/migration/index.ts +0 -33
- package/src/migration/operations/BaseMigration.ts +0 -126
- package/src/migration/operations/PeerToBtcoMigration.ts +0 -105
- package/src/migration/operations/PeerToWebvhMigration.ts +0 -62
- package/src/migration/operations/WebvhToBtcoMigration.ts +0 -105
- package/src/migration/rollback/RollbackManager.ts +0 -170
- package/src/migration/state/StateMachine.ts +0 -92
- package/src/migration/state/StateTracker.ts +0 -156
- package/src/migration/types.ts +0 -356
- package/src/migration/validation/BitcoinValidator.ts +0 -107
- package/src/migration/validation/CredentialValidator.ts +0 -62
- package/src/migration/validation/DIDCompatibilityValidator.ts +0 -151
- package/src/migration/validation/LifecycleValidator.ts +0 -64
- package/src/migration/validation/StorageValidator.ts +0 -79
- package/src/migration/validation/ValidationPipeline.ts +0 -213
- package/src/resources/ResourceManager.ts +0 -655
- package/src/resources/index.ts +0 -21
- package/src/resources/types.ts +0 -202
- package/src/storage/LocalStorageAdapter.ts +0 -64
- package/src/storage/MemoryStorageAdapter.ts +0 -29
- package/src/storage/StorageAdapter.ts +0 -25
- package/src/storage/index.ts +0 -3
- package/src/types/bitcoin.ts +0 -98
- package/src/types/common.ts +0 -92
- package/src/types/credentials.ts +0 -89
- package/src/types/did.ts +0 -31
- package/src/types/external-shims.d.ts +0 -53
- package/src/types/index.ts +0 -7
- package/src/types/network.ts +0 -178
- package/src/utils/EventLogger.ts +0 -298
- package/src/utils/Logger.ts +0 -324
- package/src/utils/MetricsCollector.ts +0 -358
- package/src/utils/bitcoin-address.ts +0 -132
- package/src/utils/cbor.ts +0 -31
- package/src/utils/encoding.ts +0 -135
- package/src/utils/hash.ts +0 -12
- package/src/utils/retry.ts +0 -46
- package/src/utils/satoshi-validation.ts +0 -196
- package/src/utils/serialization.ts +0 -102
- package/src/utils/telemetry.ts +0 -44
- package/src/utils/validation.ts +0 -123
- package/src/vc/CredentialManager.ts +0 -955
- package/src/vc/Issuer.ts +0 -105
- package/src/vc/Verifier.ts +0 -54
- package/src/vc/cryptosuites/bbs.ts +0 -253
- package/src/vc/cryptosuites/bbsSimple.ts +0 -21
- package/src/vc/cryptosuites/eddsa.ts +0 -99
- package/src/vc/documentLoader.ts +0 -81
- package/src/vc/proofs/data-integrity.ts +0 -33
- package/src/vc/utils/jsonld.ts +0 -18
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* updateEventLog Algorithm
|
|
3
|
-
*
|
|
4
|
-
* Appends an update event to an existing Cryptographic Event Log.
|
|
5
|
-
* Each update event references the previous event via a hash chain.
|
|
6
|
-
*
|
|
7
|
-
* @see https://w3c-ccg.github.io/cel-spec/
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { EventLog, LogEntry, UpdateOptions, DataIntegrityProof } from '../types';
|
|
11
|
-
import { computeDigestMultibase } from '../hash';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Serializes a LogEntry to a deterministic byte representation for hashing.
|
|
15
|
-
* Uses JSON with sorted keys for reproducibility.
|
|
16
|
-
*
|
|
17
|
-
* @param entry - The log entry to serialize
|
|
18
|
-
* @returns UTF-8 encoded bytes
|
|
19
|
-
*/
|
|
20
|
-
function serializeEntry(entry: LogEntry): Uint8Array {
|
|
21
|
-
// Use JSON with sorted keys for deterministic serialization
|
|
22
|
-
const json = JSON.stringify(entry, Object.keys(entry).sort());
|
|
23
|
-
return new TextEncoder().encode(json);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Updates an event log by appending a new "update" event.
|
|
28
|
-
*
|
|
29
|
-
* The new event is cryptographically linked to the previous event
|
|
30
|
-
* via a hash of the last event (previousEvent field).
|
|
31
|
-
*
|
|
32
|
-
* @param log - The existing event log to update
|
|
33
|
-
* @param data - The update data (e.g., modified metadata, new resources)
|
|
34
|
-
* @param options - Signing options including signer function and verification method
|
|
35
|
-
* @returns A new EventLog with the update event appended (input is not mutated)
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* const updatedLog = await updateEventLog(
|
|
40
|
-
* existingLog,
|
|
41
|
-
* { name: 'Updated Asset Name', version: 2 },
|
|
42
|
-
* {
|
|
43
|
-
* signer: async (data) => createEdDsaProof(data, privateKey),
|
|
44
|
-
* verificationMethod: 'did:key:z6Mk...',
|
|
45
|
-
* proofPurpose: 'assertionMethod'
|
|
46
|
-
* }
|
|
47
|
-
* );
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export async function updateEventLog(
|
|
51
|
-
log: EventLog,
|
|
52
|
-
data: unknown,
|
|
53
|
-
options: UpdateOptions
|
|
54
|
-
): Promise<EventLog> {
|
|
55
|
-
const { signer, verificationMethod, proofPurpose = 'assertionMethod' } = options;
|
|
56
|
-
|
|
57
|
-
// Validate input log
|
|
58
|
-
if (!log.events || log.events.length === 0) {
|
|
59
|
-
throw new Error('Cannot update an empty event log');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Get the last event to compute the hash chain link
|
|
63
|
-
const lastEvent = log.events[log.events.length - 1];
|
|
64
|
-
|
|
65
|
-
// Compute the digestMultibase of the last event
|
|
66
|
-
const previousEvent = computeDigestMultibase(serializeEntry(lastEvent));
|
|
67
|
-
|
|
68
|
-
// Create the event structure without proof first
|
|
69
|
-
const eventBase = {
|
|
70
|
-
type: 'update' as const,
|
|
71
|
-
data,
|
|
72
|
-
previousEvent,
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Generate proof using the provided signer
|
|
76
|
-
const proof: DataIntegrityProof = await signer(eventBase);
|
|
77
|
-
|
|
78
|
-
// Validate the proof has required fields
|
|
79
|
-
if (!proof.type || !proof.cryptosuite || !proof.proofValue) {
|
|
80
|
-
throw new Error('Invalid proof: missing required fields (type, cryptosuite, proofValue)');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Construct the complete log entry
|
|
84
|
-
const entry: LogEntry = {
|
|
85
|
-
type: 'update',
|
|
86
|
-
data,
|
|
87
|
-
previousEvent,
|
|
88
|
-
proof: [proof],
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// Return a new event log (immutable - does not mutate input)
|
|
92
|
-
const eventLog: EventLog = {
|
|
93
|
-
events: [...log.events, entry],
|
|
94
|
-
// Preserve previousLog reference if it exists
|
|
95
|
-
...(log.previousLog ? { previousLog: log.previousLog } : {}),
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
return eventLog;
|
|
99
|
-
}
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* verifyEventLog Algorithm
|
|
3
|
-
*
|
|
4
|
-
* Verifies all proofs and hash chain integrity in a Cryptographic Event Log.
|
|
5
|
-
* Returns detailed per-event verification status.
|
|
6
|
-
*
|
|
7
|
-
* @see https://w3c-ccg.github.io/cel-spec/
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type {
|
|
11
|
-
EventLog,
|
|
12
|
-
LogEntry,
|
|
13
|
-
VerifyOptions,
|
|
14
|
-
VerificationResult,
|
|
15
|
-
EventVerification,
|
|
16
|
-
DataIntegrityProof
|
|
17
|
-
} from '../types';
|
|
18
|
-
import { computeDigestMultibase } from '../hash';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Serializes data to JCS (JSON Canonicalization Scheme) format.
|
|
22
|
-
* Uses JSON with sorted keys for deterministic serialization.
|
|
23
|
-
*
|
|
24
|
-
* @param data - The data to serialize
|
|
25
|
-
* @returns UTF-8 encoded bytes
|
|
26
|
-
*/
|
|
27
|
-
function serializeToJcs(data: unknown): Uint8Array {
|
|
28
|
-
// JCS uses JSON with lexicographically sorted keys
|
|
29
|
-
const json = JSON.stringify(data, (_, value) => {
|
|
30
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
31
|
-
return Object.keys(value).sort().reduce((sorted: Record<string, unknown>, key) => {
|
|
32
|
-
sorted[key] = value[key];
|
|
33
|
-
return sorted;
|
|
34
|
-
}, {});
|
|
35
|
-
}
|
|
36
|
-
return value;
|
|
37
|
-
});
|
|
38
|
-
return new TextEncoder().encode(json);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Serializes a LogEntry to a deterministic byte representation for hashing.
|
|
43
|
-
* Uses JSON with sorted keys for reproducibility.
|
|
44
|
-
* This must match the serialization used in createEventLog/updateEventLog.
|
|
45
|
-
*
|
|
46
|
-
* @param entry - The log entry to serialize
|
|
47
|
-
* @returns UTF-8 encoded bytes
|
|
48
|
-
*/
|
|
49
|
-
function serializeEntry(entry: LogEntry): Uint8Array {
|
|
50
|
-
// Use JSON with sorted keys for deterministic serialization
|
|
51
|
-
const json = JSON.stringify(entry, Object.keys(entry).sort());
|
|
52
|
-
return new TextEncoder().encode(json);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Default proof verifier using eddsa-jcs-2022 cryptosuite.
|
|
57
|
-
*
|
|
58
|
-
* This is a basic implementation that validates proof structure.
|
|
59
|
-
* For full cryptographic verification, a custom verifier should be provided
|
|
60
|
-
* that has access to the public key from the verificationMethod.
|
|
61
|
-
*
|
|
62
|
-
* @param proof - The proof to verify
|
|
63
|
-
* @param data - The data that was signed
|
|
64
|
-
* @returns True if proof structure is valid
|
|
65
|
-
*/
|
|
66
|
-
async function defaultVerifier(proof: DataIntegrityProof, data: unknown): Promise<boolean> {
|
|
67
|
-
// Validate proof has required fields
|
|
68
|
-
if (!proof.type || proof.type !== 'DataIntegrityProof') {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (!proof.cryptosuite) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!proof.proofValue || typeof proof.proofValue !== 'string' || proof.proofValue.length === 0) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (!proof.verificationMethod || typeof proof.verificationMethod !== 'string') {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!proof.proofPurpose || typeof proof.proofPurpose !== 'string') {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Check for valid cryptosuite
|
|
89
|
-
const validCryptosuites = ['eddsa-jcs-2022', 'eddsa-rdfc-2022'];
|
|
90
|
-
if (!validCryptosuites.includes(proof.cryptosuite)) {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Validate proofValue is properly formatted (multibase encoded)
|
|
95
|
-
// Most proofValues start with 'z' (base58btc) or 'u' (base64url)
|
|
96
|
-
if (!proof.proofValue.startsWith('z') && !proof.proofValue.startsWith('u')) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Verifies the hash chain for a single event.
|
|
105
|
-
*
|
|
106
|
-
* @param event - The current event to verify
|
|
107
|
-
* @param index - The index of the event in the log
|
|
108
|
-
* @param previousEvent - The previous event in the log (undefined for first event)
|
|
109
|
-
* @returns Object with chainValid boolean and any errors
|
|
110
|
-
*/
|
|
111
|
-
function verifyChain(
|
|
112
|
-
event: LogEntry,
|
|
113
|
-
index: number,
|
|
114
|
-
previousEvent: LogEntry | undefined
|
|
115
|
-
): { chainValid: boolean; errors: string[] } {
|
|
116
|
-
const errors: string[] = [];
|
|
117
|
-
|
|
118
|
-
if (index === 0) {
|
|
119
|
-
// First event must NOT have previousEvent
|
|
120
|
-
if (event.previousEvent !== undefined) {
|
|
121
|
-
errors.push(`Event ${index}: First event must not have previousEvent field`);
|
|
122
|
-
return { chainValid: false, errors };
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
// Subsequent events must have previousEvent that matches hash of prior event
|
|
126
|
-
if (event.previousEvent === undefined) {
|
|
127
|
-
errors.push(`Event ${index}: Missing previousEvent reference`);
|
|
128
|
-
return { chainValid: false, errors };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (!previousEvent) {
|
|
132
|
-
errors.push(`Event ${index}: Cannot verify chain - previous event not provided`);
|
|
133
|
-
return { chainValid: false, errors };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Compute the expected hash of the previous event
|
|
137
|
-
const expectedHash = computeDigestMultibase(serializeEntry(previousEvent));
|
|
138
|
-
|
|
139
|
-
if (event.previousEvent !== expectedHash) {
|
|
140
|
-
errors.push(`Event ${index}: Hash chain broken - previousEvent does not match hash of prior event`);
|
|
141
|
-
return { chainValid: false, errors };
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return { chainValid: true, errors: [] };
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Verifies a single event's proofs.
|
|
150
|
-
*
|
|
151
|
-
* @param event - The event to verify
|
|
152
|
-
* @param index - The index of the event in the log
|
|
153
|
-
* @param verifier - The proof verification function
|
|
154
|
-
* @param previousEvent - The previous event in the log (undefined for first event)
|
|
155
|
-
* @returns EventVerification result
|
|
156
|
-
*/
|
|
157
|
-
async function verifyEvent(
|
|
158
|
-
event: LogEntry,
|
|
159
|
-
index: number,
|
|
160
|
-
verifier: (proof: DataIntegrityProof, data: unknown) => Promise<boolean>,
|
|
161
|
-
previousEvent: LogEntry | undefined
|
|
162
|
-
): Promise<EventVerification> {
|
|
163
|
-
const errors: string[] = [];
|
|
164
|
-
|
|
165
|
-
// Verify hash chain
|
|
166
|
-
const chainResult = verifyChain(event, index, previousEvent);
|
|
167
|
-
const chainValid = chainResult.chainValid;
|
|
168
|
-
errors.push(...chainResult.errors);
|
|
169
|
-
|
|
170
|
-
// Check that event has proofs
|
|
171
|
-
if (!event.proof || !Array.isArray(event.proof) || event.proof.length === 0) {
|
|
172
|
-
errors.push(`Event ${index}: No proofs found`);
|
|
173
|
-
return {
|
|
174
|
-
index,
|
|
175
|
-
type: event.type,
|
|
176
|
-
proofValid: false,
|
|
177
|
-
chainValid,
|
|
178
|
-
errors,
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Verify each proof
|
|
183
|
-
let allProofsValid = true;
|
|
184
|
-
const eventData = {
|
|
185
|
-
type: event.type,
|
|
186
|
-
data: event.data,
|
|
187
|
-
...(event.previousEvent ? { previousEvent: event.previousEvent } : {}),
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
for (let proofIndex = 0; proofIndex < event.proof.length; proofIndex++) {
|
|
191
|
-
const proof = event.proof[proofIndex];
|
|
192
|
-
|
|
193
|
-
try {
|
|
194
|
-
const isValid = await verifier(proof, eventData);
|
|
195
|
-
if (!isValid) {
|
|
196
|
-
allProofsValid = false;
|
|
197
|
-
errors.push(`Event ${index}, Proof ${proofIndex}: Verification failed`);
|
|
198
|
-
}
|
|
199
|
-
} catch (error) {
|
|
200
|
-
allProofsValid = false;
|
|
201
|
-
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
202
|
-
errors.push(`Event ${index}, Proof ${proofIndex}: ${message}`);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return {
|
|
207
|
-
index,
|
|
208
|
-
type: event.type,
|
|
209
|
-
proofValid: allProofsValid,
|
|
210
|
-
chainValid,
|
|
211
|
-
errors,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Verifies all proofs and hash chain integrity in an event log.
|
|
217
|
-
*
|
|
218
|
-
* This algorithm verifies:
|
|
219
|
-
* - Each event has at least one proof
|
|
220
|
-
* - Each proof is structurally valid (type, cryptosuite, proofValue, verificationMethod, proofPurpose)
|
|
221
|
-
* - Proofs use valid cryptosuite (eddsa-jcs-2022 or eddsa-rdfc-2022)
|
|
222
|
-
* - The first event has no previousEvent field
|
|
223
|
-
* - Each subsequent event's previousEvent matches the digestMultibase of the prior event
|
|
224
|
-
*
|
|
225
|
-
* For full cryptographic verification, provide a custom verifier function
|
|
226
|
-
* in the options that can resolve the public key from the verificationMethod.
|
|
227
|
-
*
|
|
228
|
-
* @param log - The event log to verify
|
|
229
|
-
* @param options - Optional verification options including custom verifier
|
|
230
|
-
* @returns VerificationResult with detailed per-event status including chainValid
|
|
231
|
-
*
|
|
232
|
-
* @example
|
|
233
|
-
* ```typescript
|
|
234
|
-
* // Basic structural and chain verification
|
|
235
|
-
* const result = await verifyEventLog(eventLog);
|
|
236
|
-
* if (result.verified) {
|
|
237
|
-
* console.log('All proofs are valid and hash chain is intact');
|
|
238
|
-
* }
|
|
239
|
-
*
|
|
240
|
-
* // With custom cryptographic verifier
|
|
241
|
-
* const result = await verifyEventLog(eventLog, {
|
|
242
|
-
* verifier: async (proof, data) => {
|
|
243
|
-
* // Resolve public key and verify signature
|
|
244
|
-
* const publicKey = await resolvePublicKey(proof.verificationMethod);
|
|
245
|
-
* return verifyEdDsaSignature(data, proof.proofValue, publicKey);
|
|
246
|
-
* }
|
|
247
|
-
* });
|
|
248
|
-
* ```
|
|
249
|
-
*/
|
|
250
|
-
export async function verifyEventLog(
|
|
251
|
-
log: EventLog,
|
|
252
|
-
options?: VerifyOptions
|
|
253
|
-
): Promise<VerificationResult> {
|
|
254
|
-
const errors: string[] = [];
|
|
255
|
-
const eventVerifications: EventVerification[] = [];
|
|
256
|
-
|
|
257
|
-
// Use custom verifier if provided, otherwise use default
|
|
258
|
-
const verifier = options?.verifier ?? defaultVerifier;
|
|
259
|
-
|
|
260
|
-
// Validate log structure
|
|
261
|
-
if (!log || !log.events) {
|
|
262
|
-
return {
|
|
263
|
-
verified: false,
|
|
264
|
-
errors: ['Invalid event log: missing events array'],
|
|
265
|
-
events: [],
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (!Array.isArray(log.events)) {
|
|
270
|
-
return {
|
|
271
|
-
verified: false,
|
|
272
|
-
errors: ['Invalid event log: events is not an array'],
|
|
273
|
-
events: [],
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (log.events.length === 0) {
|
|
278
|
-
return {
|
|
279
|
-
verified: false,
|
|
280
|
-
errors: ['Invalid event log: empty events array'],
|
|
281
|
-
events: [],
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Verify each event's proofs and hash chain
|
|
286
|
-
for (let i = 0; i < log.events.length; i++) {
|
|
287
|
-
const event = log.events[i];
|
|
288
|
-
const previousEvent = i > 0 ? log.events[i - 1] : undefined;
|
|
289
|
-
const eventResult = await verifyEvent(event, i, verifier, previousEvent);
|
|
290
|
-
eventVerifications.push(eventResult);
|
|
291
|
-
|
|
292
|
-
if (!eventResult.proofValid || !eventResult.chainValid) {
|
|
293
|
-
errors.push(...eventResult.errors);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Determine overall verification status (both proofs AND chain must be valid)
|
|
298
|
-
const allProofsValid = eventVerifications.every(ev => ev.proofValid);
|
|
299
|
-
const allChainsValid = eventVerifications.every(ev => ev.chainValid);
|
|
300
|
-
|
|
301
|
-
return {
|
|
302
|
-
verified: allProofsValid && allChainsValid,
|
|
303
|
-
errors,
|
|
304
|
-
events: eventVerifications,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* witnessEvent Algorithm
|
|
3
|
-
*
|
|
4
|
-
* Adds a witness proof to an existing log entry. The witness proof is
|
|
5
|
-
* appended to the event's proof array, preserving the original controller proof.
|
|
6
|
-
*
|
|
7
|
-
* @see https://w3c-ccg.github.io/cel-spec/
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { LogEntry, WitnessProof } from '../types';
|
|
11
|
-
import type { WitnessService } from '../witnesses/WitnessService';
|
|
12
|
-
import { computeDigestMultibase } from '../hash';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Serializes a log entry to bytes for hashing.
|
|
16
|
-
* Uses deterministic JSON serialization with sorted keys.
|
|
17
|
-
*/
|
|
18
|
-
function serializeEntry(entry: LogEntry): Uint8Array {
|
|
19
|
-
// Create a canonical representation with sorted keys
|
|
20
|
-
const canonical = JSON.stringify(entry, (key, value) => {
|
|
21
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
22
|
-
return Object.keys(value)
|
|
23
|
-
.sort()
|
|
24
|
-
.reduce((sorted: Record<string, unknown>, k) => {
|
|
25
|
-
sorted[k] = value[k];
|
|
26
|
-
return sorted;
|
|
27
|
-
}, {});
|
|
28
|
-
}
|
|
29
|
-
return value;
|
|
30
|
-
});
|
|
31
|
-
return new TextEncoder().encode(canonical);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Adds a witness proof to an event by calling a witness service.
|
|
36
|
-
*
|
|
37
|
-
* The witness service attests to the event's digest and returns a proof
|
|
38
|
-
* that is appended to the event's proof array. This does not replace
|
|
39
|
-
* the original controller proof - it adds an additional attestation.
|
|
40
|
-
*
|
|
41
|
-
* @param event - The log entry to witness
|
|
42
|
-
* @param witness - The witness service to use for attestation
|
|
43
|
-
* @returns A new LogEntry with the witness proof appended to the proof array
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```typescript
|
|
47
|
-
* const httpWitness = new HttpWitness('https://witness.example.com');
|
|
48
|
-
* const witnessedEvent = await witnessEvent(myEvent, httpWitness);
|
|
49
|
-
* // witnessedEvent.proof now has 2 proofs: original + witness
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
export async function witnessEvent(
|
|
53
|
-
event: LogEntry,
|
|
54
|
-
witness: WitnessService
|
|
55
|
-
): Promise<LogEntry> {
|
|
56
|
-
// Validate inputs
|
|
57
|
-
if (!event) {
|
|
58
|
-
throw new Error('Event is required');
|
|
59
|
-
}
|
|
60
|
-
if (!event.proof || event.proof.length === 0) {
|
|
61
|
-
throw new Error('Event must have at least one proof (controller proof)');
|
|
62
|
-
}
|
|
63
|
-
if (!witness) {
|
|
64
|
-
throw new Error('Witness service is required');
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Compute digest of the event
|
|
68
|
-
const eventBytes = serializeEntry(event);
|
|
69
|
-
const digestMultibase = computeDigestMultibase(eventBytes);
|
|
70
|
-
|
|
71
|
-
// Get witness proof
|
|
72
|
-
const witnessProof: WitnessProof = await witness.witness(digestMultibase);
|
|
73
|
-
|
|
74
|
-
// Validate witness proof has required fields
|
|
75
|
-
if (!witnessProof.type || !witnessProof.cryptosuite || !witnessProof.proofValue) {
|
|
76
|
-
throw new Error('Invalid witness proof: missing required fields (type, cryptosuite, proofValue)');
|
|
77
|
-
}
|
|
78
|
-
if (!witnessProof.witnessedAt) {
|
|
79
|
-
throw new Error('Invalid witness proof: missing witnessedAt timestamp');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Return new event with witness proof appended (immutable - don't modify input)
|
|
83
|
-
return {
|
|
84
|
-
...event,
|
|
85
|
-
proof: [...event.proof, witnessProof],
|
|
86
|
-
};
|
|
87
|
-
}
|