@digitaldefiance/ecies-lib 4.17.10 → 4.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/package.json +2 -2
- package/src/lib/voting/threshold/ceremony-coordinator.d.ts +152 -0
- package/src/lib/voting/threshold/ceremony-coordinator.d.ts.map +1 -0
- package/src/lib/voting/threshold/ceremony-coordinator.js +316 -0
- package/src/lib/voting/threshold/ceremony-coordinator.js.map +1 -0
- package/src/lib/voting/threshold/decryption-combiner.d.ts.map +1 -1
- package/src/lib/voting/threshold/decryption-combiner.js +3 -3
- package/src/lib/voting/threshold/decryption-combiner.js.map +1 -1
- package/src/lib/voting/threshold/guardian-registry.d.ts +1 -1
- package/src/lib/voting/threshold/guardian-registry.d.ts.map +1 -1
- package/src/lib/voting/threshold/index.d.ts +11 -0
- package/src/lib/voting/threshold/index.d.ts.map +1 -1
- package/src/lib/voting/threshold/index.js +32 -1
- package/src/lib/voting/threshold/index.js.map +1 -1
- package/src/lib/voting/threshold/interfaces/partial-decryption.d.ts +2 -2
- package/src/lib/voting/threshold/interfaces/partial-decryption.d.ts.map +1 -1
- package/src/lib/voting/threshold/interval-scheduler.d.ts +123 -0
- package/src/lib/voting/threshold/interval-scheduler.d.ts.map +1 -0
- package/src/lib/voting/threshold/interval-scheduler.js +281 -0
- package/src/lib/voting/threshold/interval-scheduler.js.map +1 -0
- package/src/lib/voting/threshold/partial-decryption-service.d.ts.map +1 -1
- package/src/lib/voting/threshold/partial-decryption-service.js +16 -15
- package/src/lib/voting/threshold/partial-decryption-service.js.map +1 -1
- package/src/lib/voting/threshold/public-tally-feed.d.ts +100 -0
- package/src/lib/voting/threshold/public-tally-feed.d.ts.map +1 -0
- package/src/lib/voting/threshold/public-tally-feed.js +202 -0
- package/src/lib/voting/threshold/public-tally-feed.js.map +1 -0
- package/src/lib/voting/threshold/tally-verifier.d.ts +85 -0
- package/src/lib/voting/threshold/tally-verifier.d.ts.map +1 -0
- package/src/lib/voting/threshold/tally-verifier.js +169 -0
- package/src/lib/voting/threshold/tally-verifier.js.map +1 -0
- package/src/lib/voting/threshold/threshold-audit-log.d.ts +71 -0
- package/src/lib/voting/threshold/threshold-audit-log.d.ts.map +1 -0
- package/src/lib/voting/threshold/threshold-audit-log.js +243 -0
- package/src/lib/voting/threshold/threshold-audit-log.js.map +1 -0
- package/src/lib/voting/threshold/threshold-county-aggregator.d.ts +81 -0
- package/src/lib/voting/threshold/threshold-county-aggregator.d.ts.map +1 -0
- package/src/lib/voting/threshold/threshold-county-aggregator.js +154 -0
- package/src/lib/voting/threshold/threshold-county-aggregator.js.map +1 -0
- package/src/lib/voting/threshold/threshold-key-generator.d.ts.map +1 -1
- package/src/lib/voting/threshold/threshold-key-generator.js.map +1 -1
- package/src/lib/voting/threshold/threshold-national-aggregator.d.ts +95 -0
- package/src/lib/voting/threshold/threshold-national-aggregator.d.ts.map +1 -0
- package/src/lib/voting/threshold/threshold-national-aggregator.js +210 -0
- package/src/lib/voting/threshold/threshold-national-aggregator.js.map +1 -0
- package/src/lib/voting/threshold/threshold-poll-factory.d.ts +88 -0
- package/src/lib/voting/threshold/threshold-poll-factory.d.ts.map +1 -0
- package/src/lib/voting/threshold/threshold-poll-factory.js +156 -0
- package/src/lib/voting/threshold/threshold-poll-factory.js.map +1 -0
- package/src/lib/voting/threshold/threshold-poll.d.ts +76 -0
- package/src/lib/voting/threshold/threshold-poll.d.ts.map +1 -0
- package/src/lib/voting/threshold/threshold-poll.js +144 -0
- package/src/lib/voting/threshold/threshold-poll.js.map +1 -0
- package/src/lib/voting/threshold/threshold-precinct-aggregator.d.ts +86 -0
- package/src/lib/voting/threshold/threshold-precinct-aggregator.d.ts.map +1 -0
- package/src/lib/voting/threshold/threshold-precinct-aggregator.js +156 -0
- package/src/lib/voting/threshold/threshold-precinct-aggregator.js.map +1 -0
- package/src/lib/voting/threshold/threshold-state-aggregator.d.ts +85 -0
- package/src/lib/voting/threshold/threshold-state-aggregator.d.ts.map +1 -0
- package/src/lib/voting/threshold/threshold-state-aggregator.js +164 -0
- package/src/lib/voting/threshold/threshold-state-aggregator.js.map +1 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public Tally Feed
|
|
3
|
+
*
|
|
4
|
+
* Provides a real-time subscription API for publishing and consuming
|
|
5
|
+
* interval tally updates during threshold voting. Observers (media,
|
|
6
|
+
* auditors, public) subscribe to a poll and receive verified tallies
|
|
7
|
+
* as decryption ceremonies complete.
|
|
8
|
+
*
|
|
9
|
+
* @module voting/threshold
|
|
10
|
+
*/
|
|
11
|
+
import type { PlatformID } from '../../../interfaces/platform-id';
|
|
12
|
+
import type { IntervalTally } from './interfaces/interval-tally';
|
|
13
|
+
import type { IPublicTallyFeed } from './interfaces/public-tally-feed';
|
|
14
|
+
import type { TallySubscription } from './interfaces/tally-subscription';
|
|
15
|
+
/**
|
|
16
|
+
* Real-time public tally feed for threshold voting.
|
|
17
|
+
*
|
|
18
|
+
* Publishes verified interval tallies and allows subscribers to receive
|
|
19
|
+
* updates as they happen. Maintains a complete history of all published
|
|
20
|
+
* tallies per poll.
|
|
21
|
+
*
|
|
22
|
+
* Features:
|
|
23
|
+
* - Publish interval tallies with cryptographic proofs
|
|
24
|
+
* - Subscribe to real-time updates for a specific poll
|
|
25
|
+
* - Initial state delivery on subscription (current tally + history replay)
|
|
26
|
+
* - Historical access to all previous interval tallies
|
|
27
|
+
* - Lookup by specific interval number
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const feed = new PublicTallyFeed<string>();
|
|
32
|
+
*
|
|
33
|
+
* // Subscribe to updates
|
|
34
|
+
* const sub = feed.subscribe('poll-1', (tally) => {
|
|
35
|
+
* console.log(`Interval ${tally.intervalNumber}: ${tally.tallies}`);
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* // Publish a tally (triggers subscriber callbacks)
|
|
39
|
+
* feed.publish(intervalTally);
|
|
40
|
+
*
|
|
41
|
+
* // Query history
|
|
42
|
+
* const history = feed.getHistory('poll-1');
|
|
43
|
+
* const specific = feed.getTallyAtInterval('poll-1', 3);
|
|
44
|
+
*
|
|
45
|
+
* // Cleanup
|
|
46
|
+
* sub.unsubscribe();
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare class PublicTallyFeed<TID extends PlatformID = Uint8Array> implements IPublicTallyFeed<TID> {
|
|
50
|
+
/** Poll ID → ordered list of tallies (by publish order) */
|
|
51
|
+
private readonly _history;
|
|
52
|
+
/** Poll ID → interval number → tally (for fast lookup) */
|
|
53
|
+
private readonly _intervalIndex;
|
|
54
|
+
/** Subscription ID → Subscription */
|
|
55
|
+
private readonly _subscriptions;
|
|
56
|
+
/** Poll key → Set of subscription IDs */
|
|
57
|
+
private readonly _pollSubscriptions;
|
|
58
|
+
/**
|
|
59
|
+
* Publish a new interval tally.
|
|
60
|
+
*
|
|
61
|
+
* Stores the tally in history and notifies all subscribers for the poll.
|
|
62
|
+
*
|
|
63
|
+
* @param tally - The interval tally to publish
|
|
64
|
+
*/
|
|
65
|
+
publish(tally: IntervalTally<TID>): void;
|
|
66
|
+
/**
|
|
67
|
+
* Subscribe to tally updates for a poll.
|
|
68
|
+
*
|
|
69
|
+
* On subscription, the callback is immediately invoked with the current
|
|
70
|
+
* (latest) tally if one exists, providing initial state delivery.
|
|
71
|
+
*
|
|
72
|
+
* @param pollId - The poll to subscribe to
|
|
73
|
+
* @param onTally - Callback invoked for each new tally
|
|
74
|
+
* @returns A subscription handle with an `unsubscribe()` method
|
|
75
|
+
*/
|
|
76
|
+
subscribe(pollId: TID, onTally: (tally: IntervalTally<TID>) => void): TallySubscription<TID>;
|
|
77
|
+
/**
|
|
78
|
+
* Get the most recently published tally for a poll.
|
|
79
|
+
*
|
|
80
|
+
* @param pollId - The poll to query
|
|
81
|
+
* @returns The latest tally, or undefined if none published
|
|
82
|
+
*/
|
|
83
|
+
getCurrentTally(pollId: TID): IntervalTally<TID> | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Get all historical tallies for a poll in publication order.
|
|
86
|
+
*
|
|
87
|
+
* @param pollId - The poll to query
|
|
88
|
+
* @returns Ordered array of all published tallies
|
|
89
|
+
*/
|
|
90
|
+
getHistory(pollId: TID): readonly IntervalTally<TID>[];
|
|
91
|
+
/**
|
|
92
|
+
* Get the tally for a specific interval number.
|
|
93
|
+
*
|
|
94
|
+
* @param pollId - The poll to query
|
|
95
|
+
* @param intervalNumber - The interval number to look up
|
|
96
|
+
* @returns The tally for that interval, or undefined if not found
|
|
97
|
+
*/
|
|
98
|
+
getTallyAtInterval(pollId: TID, intervalNumber: number): IntervalTally<TID> | undefined;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=public-tally-feed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-tally-feed.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/public-tally-feed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAkDzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,eAAe,CAC1B,GAAG,SAAS,UAAU,GAAG,UAAU,CACnC,YAAW,gBAAgB,CAAC,GAAG,CAAC;IAChC,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgD;IAEzE,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAGjB;IAEd,qCAAqC;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6C;IAE5E,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAuC;IAE1E;;;;;;OAMG;IACH,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI;IA+BxC;;;;;;;;;OASG;IACH,SAAS,CACP,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,IAAI,GAC3C,iBAAiB,CAAC,GAAG,CAAC;IAgCzB;;;;;OAKG;IACH,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,SAAS;IAM5D;;;;;OAKG;IACH,UAAU,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE;IAItD;;;;;;OAMG;IACH,kBAAkB,CAChB,MAAM,EAAE,GAAG,EACX,cAAc,EAAE,MAAM,GACrB,aAAa,CAAC,GAAG,CAAC,GAAG,SAAS;CAKlC"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Public Tally Feed
|
|
4
|
+
*
|
|
5
|
+
* Provides a real-time subscription API for publishing and consuming
|
|
6
|
+
* interval tally updates during threshold voting. Observers (media,
|
|
7
|
+
* auditors, public) subscribe to a poll and receive verified tallies
|
|
8
|
+
* as decryption ceremonies complete.
|
|
9
|
+
*
|
|
10
|
+
* @module voting/threshold
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.PublicTallyFeed = void 0;
|
|
14
|
+
/**
|
|
15
|
+
* Converts a PlatformID to a string key for Map lookups.
|
|
16
|
+
*/
|
|
17
|
+
function toKey(id) {
|
|
18
|
+
if (id instanceof Uint8Array) {
|
|
19
|
+
return Array.from(id)
|
|
20
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
21
|
+
.join('');
|
|
22
|
+
}
|
|
23
|
+
return String(id);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generates a unique subscription ID.
|
|
27
|
+
*/
|
|
28
|
+
function generateSubscriptionId() {
|
|
29
|
+
const bytes = new Uint8Array(16);
|
|
30
|
+
crypto.getRandomValues(bytes);
|
|
31
|
+
return Array.from(bytes)
|
|
32
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
33
|
+
.join('');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Internal subscription record that implements TallySubscription.
|
|
37
|
+
*/
|
|
38
|
+
class Subscription {
|
|
39
|
+
id;
|
|
40
|
+
pollId;
|
|
41
|
+
onTally;
|
|
42
|
+
_removeCallback;
|
|
43
|
+
constructor(pollId, onTally, removeCallback) {
|
|
44
|
+
this.id = generateSubscriptionId();
|
|
45
|
+
this.pollId = pollId;
|
|
46
|
+
this.onTally = onTally;
|
|
47
|
+
this._removeCallback = removeCallback;
|
|
48
|
+
}
|
|
49
|
+
unsubscribe() {
|
|
50
|
+
this._removeCallback(this.id);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Real-time public tally feed for threshold voting.
|
|
55
|
+
*
|
|
56
|
+
* Publishes verified interval tallies and allows subscribers to receive
|
|
57
|
+
* updates as they happen. Maintains a complete history of all published
|
|
58
|
+
* tallies per poll.
|
|
59
|
+
*
|
|
60
|
+
* Features:
|
|
61
|
+
* - Publish interval tallies with cryptographic proofs
|
|
62
|
+
* - Subscribe to real-time updates for a specific poll
|
|
63
|
+
* - Initial state delivery on subscription (current tally + history replay)
|
|
64
|
+
* - Historical access to all previous interval tallies
|
|
65
|
+
* - Lookup by specific interval number
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const feed = new PublicTallyFeed<string>();
|
|
70
|
+
*
|
|
71
|
+
* // Subscribe to updates
|
|
72
|
+
* const sub = feed.subscribe('poll-1', (tally) => {
|
|
73
|
+
* console.log(`Interval ${tally.intervalNumber}: ${tally.tallies}`);
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* // Publish a tally (triggers subscriber callbacks)
|
|
77
|
+
* feed.publish(intervalTally);
|
|
78
|
+
*
|
|
79
|
+
* // Query history
|
|
80
|
+
* const history = feed.getHistory('poll-1');
|
|
81
|
+
* const specific = feed.getTallyAtInterval('poll-1', 3);
|
|
82
|
+
*
|
|
83
|
+
* // Cleanup
|
|
84
|
+
* sub.unsubscribe();
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
class PublicTallyFeed {
|
|
88
|
+
/** Poll ID → ordered list of tallies (by publish order) */
|
|
89
|
+
_history = new Map();
|
|
90
|
+
/** Poll ID → interval number → tally (for fast lookup) */
|
|
91
|
+
_intervalIndex = new Map();
|
|
92
|
+
/** Subscription ID → Subscription */
|
|
93
|
+
_subscriptions = new Map();
|
|
94
|
+
/** Poll key → Set of subscription IDs */
|
|
95
|
+
_pollSubscriptions = new Map();
|
|
96
|
+
/**
|
|
97
|
+
* Publish a new interval tally.
|
|
98
|
+
*
|
|
99
|
+
* Stores the tally in history and notifies all subscribers for the poll.
|
|
100
|
+
*
|
|
101
|
+
* @param tally - The interval tally to publish
|
|
102
|
+
*/
|
|
103
|
+
publish(tally) {
|
|
104
|
+
const pollKey = toKey(tally.pollId);
|
|
105
|
+
// Store in history
|
|
106
|
+
let history = this._history.get(pollKey);
|
|
107
|
+
if (!history) {
|
|
108
|
+
history = [];
|
|
109
|
+
this._history.set(pollKey, history);
|
|
110
|
+
}
|
|
111
|
+
history.push(tally);
|
|
112
|
+
// Index by interval number
|
|
113
|
+
let intervalMap = this._intervalIndex.get(pollKey);
|
|
114
|
+
if (!intervalMap) {
|
|
115
|
+
intervalMap = new Map();
|
|
116
|
+
this._intervalIndex.set(pollKey, intervalMap);
|
|
117
|
+
}
|
|
118
|
+
intervalMap.set(tally.intervalNumber, tally);
|
|
119
|
+
// Notify subscribers
|
|
120
|
+
const subIds = this._pollSubscriptions.get(pollKey);
|
|
121
|
+
if (subIds) {
|
|
122
|
+
for (const subId of subIds) {
|
|
123
|
+
const sub = this._subscriptions.get(subId);
|
|
124
|
+
if (sub) {
|
|
125
|
+
sub.onTally(tally);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Subscribe to tally updates for a poll.
|
|
132
|
+
*
|
|
133
|
+
* On subscription, the callback is immediately invoked with the current
|
|
134
|
+
* (latest) tally if one exists, providing initial state delivery.
|
|
135
|
+
*
|
|
136
|
+
* @param pollId - The poll to subscribe to
|
|
137
|
+
* @param onTally - Callback invoked for each new tally
|
|
138
|
+
* @returns A subscription handle with an `unsubscribe()` method
|
|
139
|
+
*/
|
|
140
|
+
subscribe(pollId, onTally) {
|
|
141
|
+
const pollKey = toKey(pollId);
|
|
142
|
+
const subscription = new Subscription(pollId, onTally, (id) => {
|
|
143
|
+
this._subscriptions.delete(id);
|
|
144
|
+
const subs = this._pollSubscriptions.get(pollKey);
|
|
145
|
+
if (subs) {
|
|
146
|
+
subs.delete(id);
|
|
147
|
+
if (subs.size === 0) {
|
|
148
|
+
this._pollSubscriptions.delete(pollKey);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
this._subscriptions.set(subscription.id, subscription);
|
|
153
|
+
let pollSubs = this._pollSubscriptions.get(pollKey);
|
|
154
|
+
if (!pollSubs) {
|
|
155
|
+
pollSubs = new Set();
|
|
156
|
+
this._pollSubscriptions.set(pollKey, pollSubs);
|
|
157
|
+
}
|
|
158
|
+
pollSubs.add(subscription.id);
|
|
159
|
+
// Initial state delivery: replay current tally
|
|
160
|
+
const current = this.getCurrentTally(pollId);
|
|
161
|
+
if (current) {
|
|
162
|
+
onTally(current);
|
|
163
|
+
}
|
|
164
|
+
return subscription;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get the most recently published tally for a poll.
|
|
168
|
+
*
|
|
169
|
+
* @param pollId - The poll to query
|
|
170
|
+
* @returns The latest tally, or undefined if none published
|
|
171
|
+
*/
|
|
172
|
+
getCurrentTally(pollId) {
|
|
173
|
+
const history = this._history.get(toKey(pollId));
|
|
174
|
+
if (!history || history.length === 0)
|
|
175
|
+
return undefined;
|
|
176
|
+
return history[history.length - 1];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get all historical tallies for a poll in publication order.
|
|
180
|
+
*
|
|
181
|
+
* @param pollId - The poll to query
|
|
182
|
+
* @returns Ordered array of all published tallies
|
|
183
|
+
*/
|
|
184
|
+
getHistory(pollId) {
|
|
185
|
+
return this._history.get(toKey(pollId)) ?? [];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get the tally for a specific interval number.
|
|
189
|
+
*
|
|
190
|
+
* @param pollId - The poll to query
|
|
191
|
+
* @param intervalNumber - The interval number to look up
|
|
192
|
+
* @returns The tally for that interval, or undefined if not found
|
|
193
|
+
*/
|
|
194
|
+
getTallyAtInterval(pollId, intervalNumber) {
|
|
195
|
+
const intervalMap = this._intervalIndex.get(toKey(pollId));
|
|
196
|
+
if (!intervalMap)
|
|
197
|
+
return undefined;
|
|
198
|
+
return intervalMap.get(intervalNumber);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.PublicTallyFeed = PublicTallyFeed;
|
|
202
|
+
//# sourceMappingURL=public-tally-feed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-tally-feed.js","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/public-tally-feed.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tally Verifier
|
|
3
|
+
*
|
|
4
|
+
* Third-party verification of published interval tallies.
|
|
5
|
+
* Validates that tallies were correctly decrypted by checking:
|
|
6
|
+
* 1. Combined ZK proof validity
|
|
7
|
+
* 2. Tally consistency with encrypted aggregate
|
|
8
|
+
* 3. Guardian authorization
|
|
9
|
+
* 4. Timestamp validity
|
|
10
|
+
*
|
|
11
|
+
* Designed to be implementable by any third party using only public information.
|
|
12
|
+
*
|
|
13
|
+
* @module voting/threshold
|
|
14
|
+
*/
|
|
15
|
+
import type { PublicKey } from 'paillier-bigint';
|
|
16
|
+
import type { PlatformID } from '../../../interfaces/platform-id';
|
|
17
|
+
import type { IntervalTally, VerificationResult, ITallyVerifier, ThresholdKeyConfig } from './interfaces';
|
|
18
|
+
/**
|
|
19
|
+
* Verifies published interval tallies using only public information.
|
|
20
|
+
*
|
|
21
|
+
* Each verification produces a detailed {@link VerificationResult} indicating
|
|
22
|
+
* which checks passed and which failed, enabling auditors to pinpoint issues.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const verifier = new TallyVerifier(publicKey, verificationKeys, thresholdConfig, theta);
|
|
27
|
+
*
|
|
28
|
+
* const result = verifier.verify(
|
|
29
|
+
* publishedTally,
|
|
30
|
+
* encryptedTally,
|
|
31
|
+
* verificationKeys,
|
|
32
|
+
* publicKey,
|
|
33
|
+
* [1, 2, 3, 5, 7], // registered Guardian indices
|
|
34
|
+
* );
|
|
35
|
+
*
|
|
36
|
+
* if (!result.valid) {
|
|
37
|
+
* console.error('Verification failed:', result.error);
|
|
38
|
+
* console.log('Checks:', result.checks);
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare class TallyVerifier<TID extends PlatformID = Uint8Array> implements ITallyVerifier<TID> {
|
|
43
|
+
private readonly combiner;
|
|
44
|
+
private readonly thresholdConfig;
|
|
45
|
+
constructor(publicKey: PublicKey, verificationKeys: readonly Uint8Array[], thresholdConfig: ThresholdKeyConfig, theta: bigint);
|
|
46
|
+
/**
|
|
47
|
+
* Verify a published interval tally.
|
|
48
|
+
*
|
|
49
|
+
* Performs four independent checks:
|
|
50
|
+
* 1. **proofValid** – the combined ZK proof is cryptographically valid
|
|
51
|
+
* 2. **guardiansAuthorized** – all participating Guardians are registered
|
|
52
|
+
* 3. **tallyMatchesEncrypted** – the tally is consistent with the encrypted aggregate
|
|
53
|
+
* 4. **timestampValid** – the timestamp is a reasonable positive value
|
|
54
|
+
*
|
|
55
|
+
* @param tally - The published interval tally to verify
|
|
56
|
+
* @param encryptedTally - The encrypted aggregate ciphertexts
|
|
57
|
+
* @param verificationKeys - Public verification keys for all Guardians
|
|
58
|
+
* @param publicKey - The Paillier public key
|
|
59
|
+
* @param registeredGuardians - Indices of all registered Guardians
|
|
60
|
+
* @returns Detailed verification result with per-check status
|
|
61
|
+
*/
|
|
62
|
+
verify(tally: IntervalTally<TID>, encryptedTally: bigint[], verificationKeys: readonly Uint8Array[], publicKey: PublicKey, registeredGuardians: readonly number[]): VerificationResult;
|
|
63
|
+
/**
|
|
64
|
+
* Validate the combined ZK proof using the DecryptionCombiner's verification.
|
|
65
|
+
*/
|
|
66
|
+
private checkProof;
|
|
67
|
+
/**
|
|
68
|
+
* Verify all participating Guardians are in the registered set
|
|
69
|
+
* and that at least k Guardians participated.
|
|
70
|
+
*/
|
|
71
|
+
private checkGuardians;
|
|
72
|
+
/**
|
|
73
|
+
* Verify the tally dimensions match the encrypted aggregate.
|
|
74
|
+
*
|
|
75
|
+
* A full re-decryption is not possible without key shares (by design),
|
|
76
|
+
* so we verify structural consistency: the number of tally entries
|
|
77
|
+
* must match the number of encrypted ciphertexts.
|
|
78
|
+
*/
|
|
79
|
+
private checkTallyMatchesEncrypted;
|
|
80
|
+
/**
|
|
81
|
+
* Verify the timestamp is a valid positive number.
|
|
82
|
+
*/
|
|
83
|
+
private checkTimestamp;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=tally-verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tally-verifier.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/tally-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,aAAa,CACxB,GAAG,SAAS,UAAU,GAAG,UAAU,CACnC,YAAW,cAAc,CAAC,GAAG,CAAC;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;gBAGnD,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,SAAS,UAAU,EAAE,EACvC,eAAe,EAAE,kBAAkB,EACnC,KAAK,EAAE,MAAM;IAMf;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CACJ,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,cAAc,EAAE,MAAM,EAAE,EACxB,gBAAgB,EAAE,SAAS,UAAU,EAAE,EACvC,SAAS,EAAE,SAAS,EACpB,mBAAmB,EAAE,SAAS,MAAM,EAAE,GACrC,kBAAkB;IA6CrB;;OAEG;IACH,OAAO,CAAC,UAAU;IAqClB;;;OAGG;IACH,OAAO,CAAC,cAAc;IA4BtB;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IA4BlC;;OAEG;IACH,OAAO,CAAC,cAAc;CAQvB"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tally Verifier
|
|
4
|
+
*
|
|
5
|
+
* Third-party verification of published interval tallies.
|
|
6
|
+
* Validates that tallies were correctly decrypted by checking:
|
|
7
|
+
* 1. Combined ZK proof validity
|
|
8
|
+
* 2. Tally consistency with encrypted aggregate
|
|
9
|
+
* 3. Guardian authorization
|
|
10
|
+
* 4. Timestamp validity
|
|
11
|
+
*
|
|
12
|
+
* Designed to be implementable by any third party using only public information.
|
|
13
|
+
*
|
|
14
|
+
* @module voting/threshold
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.TallyVerifier = void 0;
|
|
18
|
+
const decryption_combiner_1 = require("./decryption-combiner");
|
|
19
|
+
/**
|
|
20
|
+
* Verifies published interval tallies using only public information.
|
|
21
|
+
*
|
|
22
|
+
* Each verification produces a detailed {@link VerificationResult} indicating
|
|
23
|
+
* which checks passed and which failed, enabling auditors to pinpoint issues.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const verifier = new TallyVerifier(publicKey, verificationKeys, thresholdConfig, theta);
|
|
28
|
+
*
|
|
29
|
+
* const result = verifier.verify(
|
|
30
|
+
* publishedTally,
|
|
31
|
+
* encryptedTally,
|
|
32
|
+
* verificationKeys,
|
|
33
|
+
* publicKey,
|
|
34
|
+
* [1, 2, 3, 5, 7], // registered Guardian indices
|
|
35
|
+
* );
|
|
36
|
+
*
|
|
37
|
+
* if (!result.valid) {
|
|
38
|
+
* console.error('Verification failed:', result.error);
|
|
39
|
+
* console.log('Checks:', result.checks);
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
class TallyVerifier {
|
|
44
|
+
combiner;
|
|
45
|
+
thresholdConfig;
|
|
46
|
+
constructor(publicKey, verificationKeys, thresholdConfig, theta) {
|
|
47
|
+
this.combiner = new decryption_combiner_1.DecryptionCombiner(publicKey, verificationKeys, theta);
|
|
48
|
+
this.thresholdConfig = thresholdConfig;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Verify a published interval tally.
|
|
52
|
+
*
|
|
53
|
+
* Performs four independent checks:
|
|
54
|
+
* 1. **proofValid** – the combined ZK proof is cryptographically valid
|
|
55
|
+
* 2. **guardiansAuthorized** – all participating Guardians are registered
|
|
56
|
+
* 3. **tallyMatchesEncrypted** – the tally is consistent with the encrypted aggregate
|
|
57
|
+
* 4. **timestampValid** – the timestamp is a reasonable positive value
|
|
58
|
+
*
|
|
59
|
+
* @param tally - The published interval tally to verify
|
|
60
|
+
* @param encryptedTally - The encrypted aggregate ciphertexts
|
|
61
|
+
* @param verificationKeys - Public verification keys for all Guardians
|
|
62
|
+
* @param publicKey - The Paillier public key
|
|
63
|
+
* @param registeredGuardians - Indices of all registered Guardians
|
|
64
|
+
* @returns Detailed verification result with per-check status
|
|
65
|
+
*/
|
|
66
|
+
verify(tally, encryptedTally, verificationKeys, publicKey, registeredGuardians) {
|
|
67
|
+
const errors = [];
|
|
68
|
+
const proofValid = this.checkProof(tally, encryptedTally, verificationKeys, publicKey, errors);
|
|
69
|
+
const guardiansAuthorized = this.checkGuardians(tally, registeredGuardians, errors);
|
|
70
|
+
const tallyMatchesEncrypted = this.checkTallyMatchesEncrypted(tally, encryptedTally, errors);
|
|
71
|
+
const timestampValid = this.checkTimestamp(tally, errors);
|
|
72
|
+
const checks = {
|
|
73
|
+
proofValid,
|
|
74
|
+
guardiansAuthorized,
|
|
75
|
+
tallyMatchesEncrypted,
|
|
76
|
+
timestampValid,
|
|
77
|
+
};
|
|
78
|
+
const valid = proofValid &&
|
|
79
|
+
guardiansAuthorized &&
|
|
80
|
+
tallyMatchesEncrypted &&
|
|
81
|
+
timestampValid;
|
|
82
|
+
return {
|
|
83
|
+
valid,
|
|
84
|
+
checks,
|
|
85
|
+
...(errors.length > 0 ? { error: errors.join('; ') } : {}),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Validate the combined ZK proof using the DecryptionCombiner's verification.
|
|
90
|
+
*/
|
|
91
|
+
checkProof(tally, encryptedTally, verificationKeys, publicKey, errors) {
|
|
92
|
+
try {
|
|
93
|
+
// Build a CombinedDecryption from the tally to pass to verifyCombined
|
|
94
|
+
const combinedDecryption = {
|
|
95
|
+
tallies: [...tally.tallies],
|
|
96
|
+
combinedProof: tally.proof,
|
|
97
|
+
participatingGuardians: tally.participatingGuardians,
|
|
98
|
+
ceremonyId: '',
|
|
99
|
+
timestamp: tally.timestamp,
|
|
100
|
+
};
|
|
101
|
+
const valid = this.combiner.verifyCombined(combinedDecryption, encryptedTally, verificationKeys, publicKey);
|
|
102
|
+
if (!valid) {
|
|
103
|
+
errors.push('Combined ZK proof verification failed');
|
|
104
|
+
}
|
|
105
|
+
return valid;
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
errors.push(`Proof verification threw: ${e instanceof Error ? e.message : String(e)}`);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Verify all participating Guardians are in the registered set
|
|
114
|
+
* and that at least k Guardians participated.
|
|
115
|
+
*/
|
|
116
|
+
checkGuardians(tally, registeredGuardians, errors) {
|
|
117
|
+
const registeredSet = new Set(registeredGuardians);
|
|
118
|
+
// Check that enough Guardians participated
|
|
119
|
+
if (tally.participatingGuardians.length < this.thresholdConfig.threshold) {
|
|
120
|
+
errors.push(`Insufficient participating Guardians: ${tally.participatingGuardians.length} < threshold ${this.thresholdConfig.threshold}`);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
// Check each participating Guardian is registered
|
|
124
|
+
for (const guardianIndex of tally.participatingGuardians) {
|
|
125
|
+
if (!registeredSet.has(guardianIndex)) {
|
|
126
|
+
errors.push(`Guardian ${guardianIndex} is not in the registered Guardian set`);
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Verify the tally dimensions match the encrypted aggregate.
|
|
134
|
+
*
|
|
135
|
+
* A full re-decryption is not possible without key shares (by design),
|
|
136
|
+
* so we verify structural consistency: the number of tally entries
|
|
137
|
+
* must match the number of encrypted ciphertexts.
|
|
138
|
+
*/
|
|
139
|
+
checkTallyMatchesEncrypted(tally, encryptedTally, errors) {
|
|
140
|
+
if (encryptedTally.length === 0) {
|
|
141
|
+
errors.push('Encrypted tally is empty');
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (tally.tallies.length !== encryptedTally.length) {
|
|
145
|
+
errors.push(`Tally length (${tally.tallies.length}) does not match encrypted tally length (${encryptedTally.length})`);
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
// Verify tallies are non-negative
|
|
149
|
+
for (let i = 0; i < tally.tallies.length; i++) {
|
|
150
|
+
if (tally.tallies[i] < 0n) {
|
|
151
|
+
errors.push(`Tally at index ${i} is negative: ${tally.tallies[i]}`);
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Verify the timestamp is a valid positive number.
|
|
159
|
+
*/
|
|
160
|
+
checkTimestamp(tally, errors) {
|
|
161
|
+
if (tally.timestamp <= 0) {
|
|
162
|
+
errors.push(`Invalid timestamp: ${tally.timestamp}`);
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.TallyVerifier = TallyVerifier;
|
|
169
|
+
//# sourceMappingURL=tally-verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tally-verifier.js","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/tally-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threshold Audit Log
|
|
3
|
+
*
|
|
4
|
+
* Immutable, hash-chained audit log for threshold voting operations.
|
|
5
|
+
* Maintains a separate chain from the base poll audit log, dedicated
|
|
6
|
+
* to tracking all threshold-related events: key generation, share
|
|
7
|
+
* distribution, ceremony lifecycle, and tally publication.
|
|
8
|
+
*
|
|
9
|
+
* @module voting/threshold
|
|
10
|
+
*/
|
|
11
|
+
import type { IMember, PlatformID } from '../../../interfaces';
|
|
12
|
+
import type { ThresholdAuditEntry } from './interfaces/threshold-audit-entry';
|
|
13
|
+
/**
|
|
14
|
+
* Immutable audit log for threshold voting operations with cryptographic hash chain.
|
|
15
|
+
*
|
|
16
|
+
* Each entry is hash-chained to the previous entry and signed by the authority,
|
|
17
|
+
* ensuring tamper-evidence and non-repudiation.
|
|
18
|
+
*/
|
|
19
|
+
export declare class ThresholdAuditLog<TID extends PlatformID = Uint8Array> {
|
|
20
|
+
private readonly entries;
|
|
21
|
+
private readonly authority;
|
|
22
|
+
private sequence;
|
|
23
|
+
constructor(authority: IMember<TID>);
|
|
24
|
+
/**
|
|
25
|
+
* Record threshold key generation event.
|
|
26
|
+
*/
|
|
27
|
+
recordKeyGeneration(pollId: TID, metadata: Record<string, string | number | boolean>): ThresholdAuditEntry<TID>;
|
|
28
|
+
/**
|
|
29
|
+
* Record key share distribution to a Guardian.
|
|
30
|
+
*/
|
|
31
|
+
recordKeyShareDistribution(pollId: TID, guardianId: TID, guardianIndex: number, metadata: Record<string, string | number | boolean>): ThresholdAuditEntry<TID>;
|
|
32
|
+
/**
|
|
33
|
+
* Record a decryption ceremony starting.
|
|
34
|
+
*/
|
|
35
|
+
recordCeremonyStarted(pollId: TID, ceremonyId: string, metadata: Record<string, string | number | boolean>): ThresholdAuditEntry<TID>;
|
|
36
|
+
/**
|
|
37
|
+
* Record a partial decryption submission from a Guardian.
|
|
38
|
+
*/
|
|
39
|
+
recordPartialSubmitted(pollId: TID, ceremonyId: string, guardianId: TID, guardianIndex: number, metadata: Record<string, string | number | boolean>): ThresholdAuditEntry<TID>;
|
|
40
|
+
/**
|
|
41
|
+
* Record a decryption ceremony completing successfully.
|
|
42
|
+
*/
|
|
43
|
+
recordCeremonyCompleted(pollId: TID, ceremonyId: string, metadata: Record<string, string | number | boolean>): ThresholdAuditEntry<TID>;
|
|
44
|
+
/**
|
|
45
|
+
* Record a tally being published to the public feed.
|
|
46
|
+
*/
|
|
47
|
+
recordTallyPublished(pollId: TID, metadata: Record<string, string | number | boolean>): ThresholdAuditEntry<TID>;
|
|
48
|
+
/** Get all entries in chronological order. */
|
|
49
|
+
getEntries(): readonly ThresholdAuditEntry<TID>[];
|
|
50
|
+
/** Get entries for a specific poll. */
|
|
51
|
+
getEntriesForPoll(pollId: TID): readonly ThresholdAuditEntry<TID>[];
|
|
52
|
+
/** Get entries for a specific ceremony. */
|
|
53
|
+
getEntriesForCeremony(ceremonyId: string): readonly ThresholdAuditEntry<TID>[];
|
|
54
|
+
/** Verify the entire hash chain integrity. */
|
|
55
|
+
verifyChain(): boolean;
|
|
56
|
+
/** Verify a single entry's signature. */
|
|
57
|
+
verifyEntry(entry: ThresholdAuditEntry<TID>): boolean;
|
|
58
|
+
private appendEntry;
|
|
59
|
+
private computeEntryHash;
|
|
60
|
+
private serializeEntryForHashing;
|
|
61
|
+
private serializeEntryForSigning;
|
|
62
|
+
private getMicrosecondTimestamp;
|
|
63
|
+
private sha256Sync;
|
|
64
|
+
private encodeNumber;
|
|
65
|
+
private encodeString;
|
|
66
|
+
private concat;
|
|
67
|
+
private arraysEqual;
|
|
68
|
+
private idToBytes;
|
|
69
|
+
private toHex;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=threshold-audit-log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threshold-audit-log.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/threshold-audit-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAE9E;;;;;GAKG;AACH,qBAAa,iBAAiB,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAK;gBAET,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC;IAInC;;OAEG;IACH,mBAAmB,CACjB,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAClD,mBAAmB,CAAC,GAAG,CAAC;IAQ3B;;OAEG;IACH,0BAA0B,CACxB,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,GAAG,EACf,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAClD,mBAAmB,CAAC,GAAG,CAAC;IAU3B;;OAEG;IACH,qBAAqB,CACnB,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAClD,mBAAmB,CAAC,GAAG,CAAC;IAS3B;;OAEG;IACH,sBAAsB,CACpB,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,GAAG,EACf,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAClD,mBAAmB,CAAC,GAAG,CAAC;IAW3B;;OAEG;IACH,uBAAuB,CACrB,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAClD,mBAAmB,CAAC,GAAG,CAAC;IAS3B;;OAEG;IACH,oBAAoB,CAClB,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAClD,mBAAmB,CAAC,GAAG,CAAC;IAQ3B,8CAA8C;IAC9C,UAAU,IAAI,SAAS,mBAAmB,CAAC,GAAG,CAAC,EAAE;IAIjD,uCAAuC;IACvC,iBAAiB,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,mBAAmB,CAAC,GAAG,CAAC,EAAE;IAWnE,2CAA2C;IAC3C,qBAAqB,CACnB,UAAU,EAAE,MAAM,GACjB,SAAS,mBAAmB,CAAC,GAAG,CAAC,EAAE;IAMtC,8CAA8C;IAC9C,WAAW,IAAI,OAAO;IA0BtB,yCAAyC;IACzC,WAAW,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,GAAG,OAAO;IAKrD,OAAO,CAAC,WAAW;IAgCnB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,wBAAwB;IA0BhC,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,KAAK;CAKd"}
|