@digitaldefiance/ecies-lib 4.17.6 → 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 +3 -3
- 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
|
@@ -46,4 +46,15 @@ export { ThresholdKeyGenerator, InvalidThresholdConfigError, KeyGenerationFailed
|
|
|
46
46
|
export { PartialDecryptionService, InvalidPartialProofError, DeserializationError, } from './partial-decryption-service';
|
|
47
47
|
export { DecryptionCombiner, InsufficientPartialsError, InvalidPartialInCombineError, CombineFailedError, } from './decryption-combiner';
|
|
48
48
|
export { GuardianRegistry, GuardianAlreadyRegisteredError, GuardianNotFoundError, InvalidShareIndexError, RegistryFullError, } from './guardian-registry';
|
|
49
|
+
export { IntervalScheduler, PollNotConfiguredError, InvalidIntervalConfigError, PollSchedulingStateError, } from './interval-scheduler';
|
|
50
|
+
export { CeremonyCoordinator, CeremonyNotFoundError, CeremonyAlreadyCompleteError, DuplicatePartialSubmissionError, InvalidCeremonyPartialProofError, } from './ceremony-coordinator';
|
|
51
|
+
export { PublicTallyFeed } from './public-tally-feed';
|
|
52
|
+
export { TallyVerifier } from './tally-verifier';
|
|
53
|
+
export { ThresholdPoll } from './threshold-poll';
|
|
54
|
+
export { ThresholdPollFactory, InsufficientGuardiansError, InvalidThresholdPollConfigError, } from './threshold-poll-factory';
|
|
55
|
+
export { ThresholdPrecinctAggregator } from './threshold-precinct-aggregator';
|
|
56
|
+
export { ThresholdCountyAggregator } from './threshold-county-aggregator';
|
|
57
|
+
export { ThresholdStateAggregator } from './threshold-state-aggregator';
|
|
58
|
+
export { ThresholdNationalAggregator } from './threshold-national-aggregator';
|
|
59
|
+
export { ThresholdAuditLog } from './threshold-audit-log';
|
|
49
60
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,mBAAmB,cAAc,CAAC;AAGlC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,mBAAmB,cAAc,CAAC;AAGlC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,4BAA4B,EAC5B,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
* ```
|
|
43
43
|
*/
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.RegistryFullError = exports.InvalidShareIndexError = exports.GuardianNotFoundError = exports.GuardianAlreadyRegisteredError = exports.GuardianRegistry = exports.CombineFailedError = exports.InvalidPartialInCombineError = exports.InsufficientPartialsError = exports.DecryptionCombiner = exports.DeserializationError = exports.InvalidPartialProofError = exports.PartialDecryptionService = exports.KeyGenerationFailedError = exports.InvalidThresholdConfigError = exports.ThresholdKeyGenerator = void 0;
|
|
45
|
+
exports.ThresholdAuditLog = exports.ThresholdNationalAggregator = exports.ThresholdStateAggregator = exports.ThresholdCountyAggregator = exports.ThresholdPrecinctAggregator = exports.InvalidThresholdPollConfigError = exports.InsufficientGuardiansError = exports.ThresholdPollFactory = exports.ThresholdPoll = exports.TallyVerifier = exports.PublicTallyFeed = exports.InvalidCeremonyPartialProofError = exports.DuplicatePartialSubmissionError = exports.CeremonyAlreadyCompleteError = exports.CeremonyNotFoundError = exports.CeremonyCoordinator = exports.PollSchedulingStateError = exports.InvalidIntervalConfigError = exports.PollNotConfiguredError = exports.IntervalScheduler = exports.RegistryFullError = exports.InvalidShareIndexError = exports.GuardianNotFoundError = exports.GuardianAlreadyRegisteredError = exports.GuardianRegistry = exports.CombineFailedError = exports.InvalidPartialInCombineError = exports.InsufficientPartialsError = exports.DecryptionCombiner = exports.DeserializationError = exports.InvalidPartialProofError = exports.PartialDecryptionService = exports.KeyGenerationFailedError = exports.InvalidThresholdConfigError = exports.ThresholdKeyGenerator = void 0;
|
|
46
46
|
const tslib_1 = require("tslib");
|
|
47
47
|
// Re-export enumerations
|
|
48
48
|
tslib_1.__exportStar(require("./enumerations"), exports);
|
|
@@ -66,4 +66,35 @@ Object.defineProperty(exports, "GuardianAlreadyRegisteredError", { enumerable: t
|
|
|
66
66
|
Object.defineProperty(exports, "GuardianNotFoundError", { enumerable: true, get: function () { return guardian_registry_1.GuardianNotFoundError; } });
|
|
67
67
|
Object.defineProperty(exports, "InvalidShareIndexError", { enumerable: true, get: function () { return guardian_registry_1.InvalidShareIndexError; } });
|
|
68
68
|
Object.defineProperty(exports, "RegistryFullError", { enumerable: true, get: function () { return guardian_registry_1.RegistryFullError; } });
|
|
69
|
+
var interval_scheduler_1 = require("./interval-scheduler");
|
|
70
|
+
Object.defineProperty(exports, "IntervalScheduler", { enumerable: true, get: function () { return interval_scheduler_1.IntervalScheduler; } });
|
|
71
|
+
Object.defineProperty(exports, "PollNotConfiguredError", { enumerable: true, get: function () { return interval_scheduler_1.PollNotConfiguredError; } });
|
|
72
|
+
Object.defineProperty(exports, "InvalidIntervalConfigError", { enumerable: true, get: function () { return interval_scheduler_1.InvalidIntervalConfigError; } });
|
|
73
|
+
Object.defineProperty(exports, "PollSchedulingStateError", { enumerable: true, get: function () { return interval_scheduler_1.PollSchedulingStateError; } });
|
|
74
|
+
var ceremony_coordinator_1 = require("./ceremony-coordinator");
|
|
75
|
+
Object.defineProperty(exports, "CeremonyCoordinator", { enumerable: true, get: function () { return ceremony_coordinator_1.CeremonyCoordinator; } });
|
|
76
|
+
Object.defineProperty(exports, "CeremonyNotFoundError", { enumerable: true, get: function () { return ceremony_coordinator_1.CeremonyNotFoundError; } });
|
|
77
|
+
Object.defineProperty(exports, "CeremonyAlreadyCompleteError", { enumerable: true, get: function () { return ceremony_coordinator_1.CeremonyAlreadyCompleteError; } });
|
|
78
|
+
Object.defineProperty(exports, "DuplicatePartialSubmissionError", { enumerable: true, get: function () { return ceremony_coordinator_1.DuplicatePartialSubmissionError; } });
|
|
79
|
+
Object.defineProperty(exports, "InvalidCeremonyPartialProofError", { enumerable: true, get: function () { return ceremony_coordinator_1.InvalidCeremonyPartialProofError; } });
|
|
80
|
+
var public_tally_feed_1 = require("./public-tally-feed");
|
|
81
|
+
Object.defineProperty(exports, "PublicTallyFeed", { enumerable: true, get: function () { return public_tally_feed_1.PublicTallyFeed; } });
|
|
82
|
+
var tally_verifier_1 = require("./tally-verifier");
|
|
83
|
+
Object.defineProperty(exports, "TallyVerifier", { enumerable: true, get: function () { return tally_verifier_1.TallyVerifier; } });
|
|
84
|
+
var threshold_poll_1 = require("./threshold-poll");
|
|
85
|
+
Object.defineProperty(exports, "ThresholdPoll", { enumerable: true, get: function () { return threshold_poll_1.ThresholdPoll; } });
|
|
86
|
+
var threshold_poll_factory_1 = require("./threshold-poll-factory");
|
|
87
|
+
Object.defineProperty(exports, "ThresholdPollFactory", { enumerable: true, get: function () { return threshold_poll_factory_1.ThresholdPollFactory; } });
|
|
88
|
+
Object.defineProperty(exports, "InsufficientGuardiansError", { enumerable: true, get: function () { return threshold_poll_factory_1.InsufficientGuardiansError; } });
|
|
89
|
+
Object.defineProperty(exports, "InvalidThresholdPollConfigError", { enumerable: true, get: function () { return threshold_poll_factory_1.InvalidThresholdPollConfigError; } });
|
|
90
|
+
var threshold_precinct_aggregator_1 = require("./threshold-precinct-aggregator");
|
|
91
|
+
Object.defineProperty(exports, "ThresholdPrecinctAggregator", { enumerable: true, get: function () { return threshold_precinct_aggregator_1.ThresholdPrecinctAggregator; } });
|
|
92
|
+
var threshold_county_aggregator_1 = require("./threshold-county-aggregator");
|
|
93
|
+
Object.defineProperty(exports, "ThresholdCountyAggregator", { enumerable: true, get: function () { return threshold_county_aggregator_1.ThresholdCountyAggregator; } });
|
|
94
|
+
var threshold_state_aggregator_1 = require("./threshold-state-aggregator");
|
|
95
|
+
Object.defineProperty(exports, "ThresholdStateAggregator", { enumerable: true, get: function () { return threshold_state_aggregator_1.ThresholdStateAggregator; } });
|
|
96
|
+
var threshold_national_aggregator_1 = require("./threshold-national-aggregator");
|
|
97
|
+
Object.defineProperty(exports, "ThresholdNationalAggregator", { enumerable: true, get: function () { return threshold_national_aggregator_1.ThresholdNationalAggregator; } });
|
|
98
|
+
var threshold_audit_log_1 = require("./threshold-audit-log");
|
|
99
|
+
Object.defineProperty(exports, "ThresholdAuditLog", { enumerable: true, get: function () { return threshold_audit_log_1.ThresholdAuditLog; } });
|
|
69
100
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;;;;AAEH,yBAAyB;AACzB,yDAA+B;AAK/B,oBAAoB;AACpB,qEAImC;AAHjC,gIAAA,qBAAqB,OAAA;AACrB,sIAAA,2BAA2B,OAAA;AAC3B,mIAAA,wBAAwB,OAAA;AAG1B,2EAIsC;AAHpC,sIAAA,wBAAwB,OAAA;AACxB,sIAAA,wBAAwB,OAAA;AACxB,kIAAA,oBAAoB,OAAA;AAGtB,6DAK+B;AAJ7B,yHAAA,kBAAkB,OAAA;AAClB,gIAAA,yBAAyB,OAAA;AACzB,mIAAA,4BAA4B,OAAA;AAC5B,yHAAA,kBAAkB,OAAA;AAGpB,yDAM6B;AAL3B,qHAAA,gBAAgB,OAAA;AAChB,mIAAA,8BAA8B,OAAA;AAC9B,0HAAA,qBAAqB,OAAA;AACrB,2HAAA,sBAAsB,OAAA;AACtB,sHAAA,iBAAiB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;;;;AAEH,yBAAyB;AACzB,yDAA+B;AAK/B,oBAAoB;AACpB,qEAImC;AAHjC,gIAAA,qBAAqB,OAAA;AACrB,sIAAA,2BAA2B,OAAA;AAC3B,mIAAA,wBAAwB,OAAA;AAG1B,2EAIsC;AAHpC,sIAAA,wBAAwB,OAAA;AACxB,sIAAA,wBAAwB,OAAA;AACxB,kIAAA,oBAAoB,OAAA;AAGtB,6DAK+B;AAJ7B,yHAAA,kBAAkB,OAAA;AAClB,gIAAA,yBAAyB,OAAA;AACzB,mIAAA,4BAA4B,OAAA;AAC5B,yHAAA,kBAAkB,OAAA;AAGpB,yDAM6B;AAL3B,qHAAA,gBAAgB,OAAA;AAChB,mIAAA,8BAA8B,OAAA;AAC9B,0HAAA,qBAAqB,OAAA;AACrB,2HAAA,sBAAsB,OAAA;AACtB,sHAAA,iBAAiB,OAAA;AAGnB,2DAK8B;AAJ5B,uHAAA,iBAAiB,OAAA;AACjB,4HAAA,sBAAsB,OAAA;AACtB,gIAAA,0BAA0B,OAAA;AAC1B,8HAAA,wBAAwB,OAAA;AAG1B,+DAMgC;AAL9B,2HAAA,mBAAmB,OAAA;AACnB,6HAAA,qBAAqB,OAAA;AACrB,oIAAA,4BAA4B,OAAA;AAC5B,uIAAA,+BAA+B,OAAA;AAC/B,wIAAA,gCAAgC,OAAA;AAGlC,yDAAsD;AAA7C,oHAAA,eAAe,OAAA;AAExB,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AAEtB,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AAEtB,mEAIkC;AAHhC,8HAAA,oBAAoB,OAAA;AACpB,oIAAA,0BAA0B,OAAA;AAC1B,yIAAA,+BAA+B,OAAA;AAGjC,iFAA8E;AAArE,4IAAA,2BAA2B,OAAA;AAEpC,6EAA0E;AAAjE,wIAAA,yBAAyB,OAAA;AAElC,2EAAwE;AAA/D,sIAAA,wBAAwB,OAAA;AAEjC,iFAA8E;AAArE,4IAAA,2BAA2B,OAAA;AAEpC,6DAA0D;AAAjD,wHAAA,iBAAiB,OAAA"}
|
|
@@ -8,8 +8,8 @@ import type { ZKProof } from './zk-proof';
|
|
|
8
8
|
export interface PartialDecryption {
|
|
9
9
|
/** Guardian's share index */
|
|
10
10
|
readonly guardianIndex: number;
|
|
11
|
-
/** The partial decryption
|
|
12
|
-
readonly
|
|
11
|
+
/** The partial decryption values — one per ciphertext in the encrypted tally */
|
|
12
|
+
readonly values: readonly bigint[];
|
|
13
13
|
/** Zero-knowledge proof of correct computation */
|
|
14
14
|
readonly proof: ZKProof;
|
|
15
15
|
/** Ceremony-specific nonce (replay protection) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partial-decryption.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/interfaces/partial-decryption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,
|
|
1
|
+
{"version":3,"file":"partial-decryption.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/interfaces/partial-decryption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;IACnC,+BAA+B;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interval Scheduler
|
|
3
|
+
*
|
|
4
|
+
* Manages decryption interval triggers for threshold voting polls.
|
|
5
|
+
* Supports time-based, vote-count-based, and hybrid interval triggers
|
|
6
|
+
* with minimum interval enforcement to prevent excessive ceremonies.
|
|
7
|
+
*
|
|
8
|
+
* @module voting/threshold
|
|
9
|
+
*/
|
|
10
|
+
import type { PlatformID } from '../../../interfaces/platform-id';
|
|
11
|
+
import type { IntervalConfig } from './interfaces/interval-config';
|
|
12
|
+
import type { IIntervalScheduler } from './interfaces/interval-scheduler';
|
|
13
|
+
import type { IntervalTriggerEvent } from './interfaces/interval-trigger-event';
|
|
14
|
+
/**
|
|
15
|
+
* Error thrown when a poll is not configured for interval scheduling.
|
|
16
|
+
*/
|
|
17
|
+
export declare class PollNotConfiguredError extends Error {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Error thrown when an interval configuration is invalid.
|
|
22
|
+
*/
|
|
23
|
+
export declare class InvalidIntervalConfigError extends Error {
|
|
24
|
+
constructor(message: string);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Error thrown when a poll is already started or already stopped.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PollSchedulingStateError extends Error {
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Scheduler for interval decryption triggers in threshold voting.
|
|
34
|
+
*
|
|
35
|
+
* Supports three trigger modes:
|
|
36
|
+
* - **TimeBased**: Fires at fixed time intervals (e.g., every 30 minutes)
|
|
37
|
+
* - **VoteCountBased**: Fires after a certain number of new votes
|
|
38
|
+
* - **Hybrid**: Fires on whichever condition is met first (time or vote count)
|
|
39
|
+
*
|
|
40
|
+
* Enforces a minimum interval between triggers to prevent excessive
|
|
41
|
+
* decryption ceremonies.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const scheduler = new IntervalScheduler<string>();
|
|
46
|
+
* scheduler.configure('poll-1', {
|
|
47
|
+
* triggerType: IntervalTriggerType.TimeBased,
|
|
48
|
+
* timeIntervalMs: 60_000,
|
|
49
|
+
* minimumIntervalMs: 30_000,
|
|
50
|
+
* ceremonyTimeoutMs: 120_000,
|
|
51
|
+
* });
|
|
52
|
+
* scheduler.onTrigger((event) => {
|
|
53
|
+
* console.log(`Interval ${event.intervalNumber} triggered`);
|
|
54
|
+
* });
|
|
55
|
+
* scheduler.start('poll-1');
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare class IntervalScheduler<TID extends PlatformID = Uint8Array> implements IIntervalScheduler<TID> {
|
|
59
|
+
private readonly _polls;
|
|
60
|
+
private readonly _triggerListeners;
|
|
61
|
+
/**
|
|
62
|
+
* Configure interval scheduling for a poll.
|
|
63
|
+
*
|
|
64
|
+
* @throws InvalidIntervalConfigError if the configuration is invalid
|
|
65
|
+
* @throws PollSchedulingStateError if the poll is already running
|
|
66
|
+
*/
|
|
67
|
+
configure(pollId: TID, config: IntervalConfig): void;
|
|
68
|
+
/**
|
|
69
|
+
* Start scheduling for a poll.
|
|
70
|
+
*
|
|
71
|
+
* For time-based and hybrid triggers, starts a repeating timer.
|
|
72
|
+
* For vote-count-based triggers, the scheduler waits for notifyVote() calls.
|
|
73
|
+
*
|
|
74
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
75
|
+
* @throws PollSchedulingStateError if the poll is already running
|
|
76
|
+
*/
|
|
77
|
+
start(pollId: TID): void;
|
|
78
|
+
/**
|
|
79
|
+
* Stop scheduling for a poll.
|
|
80
|
+
*
|
|
81
|
+
* Clears any active timer and marks the poll as not running.
|
|
82
|
+
*
|
|
83
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
84
|
+
*/
|
|
85
|
+
stop(pollId: TID): void;
|
|
86
|
+
/**
|
|
87
|
+
* Notify the scheduler that a new vote has been cast.
|
|
88
|
+
*
|
|
89
|
+
* For vote-count-based and hybrid triggers, this may fire a trigger
|
|
90
|
+
* if the vote count threshold is reached.
|
|
91
|
+
*
|
|
92
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
93
|
+
*/
|
|
94
|
+
notifyVote(pollId: TID): void;
|
|
95
|
+
/**
|
|
96
|
+
* Trigger a final decryption ceremony when a poll closes.
|
|
97
|
+
*
|
|
98
|
+
* This always fires regardless of minimum interval enforcement,
|
|
99
|
+
* as the final tally must be computed.
|
|
100
|
+
*
|
|
101
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
102
|
+
*/
|
|
103
|
+
triggerFinal(pollId: TID): void;
|
|
104
|
+
/**
|
|
105
|
+
* Subscribe to interval trigger events.
|
|
106
|
+
*/
|
|
107
|
+
onTrigger(callback: (event: IntervalTriggerEvent<TID>) => void): void;
|
|
108
|
+
/**
|
|
109
|
+
* Get the current interval number for a poll.
|
|
110
|
+
*
|
|
111
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
112
|
+
*/
|
|
113
|
+
getCurrentInterval(pollId: TID): number;
|
|
114
|
+
/**
|
|
115
|
+
* Emit a trigger event, enforcing minimum interval between triggers.
|
|
116
|
+
*/
|
|
117
|
+
private emitTrigger;
|
|
118
|
+
/**
|
|
119
|
+
* Get the internal state for a poll, throwing if not configured.
|
|
120
|
+
*/
|
|
121
|
+
private getState;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=interval-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interval-scheduler.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/interval-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAEhF;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;gBACvC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AA0ED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,iBAAiB,CAC5B,GAAG,SAAS,UAAU,GAAG,UAAU,CACnC,YAAW,kBAAkB,CAAC,GAAG,CAAC;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAE3B;IAEP;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI;IAuBpD;;;;;;;;OAQG;IACH,KAAK,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAsBxB;;;;;;OAMG;IACH,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAavB;;;;;;;OAOG;IACH,UAAU,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAoB7B;;;;;;;OAOG;IACH,YAAY,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAwB/B;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,IAAI;IAIrE;;;;OAIG;IACH,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM;IAIvC;;OAEG;IACH,OAAO,CAAC,WAAW;IA6BnB;;OAEG;IACH,OAAO,CAAC,QAAQ;CAUjB"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interval Scheduler
|
|
4
|
+
*
|
|
5
|
+
* Manages decryption interval triggers for threshold voting polls.
|
|
6
|
+
* Supports time-based, vote-count-based, and hybrid interval triggers
|
|
7
|
+
* with minimum interval enforcement to prevent excessive ceremonies.
|
|
8
|
+
*
|
|
9
|
+
* @module voting/threshold
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IntervalScheduler = exports.PollSchedulingStateError = exports.InvalidIntervalConfigError = exports.PollNotConfiguredError = void 0;
|
|
13
|
+
const interval_trigger_type_1 = require("./enumerations/interval-trigger-type");
|
|
14
|
+
/**
|
|
15
|
+
* Error thrown when a poll is not configured for interval scheduling.
|
|
16
|
+
*/
|
|
17
|
+
class PollNotConfiguredError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'PollNotConfiguredError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.PollNotConfiguredError = PollNotConfiguredError;
|
|
24
|
+
/**
|
|
25
|
+
* Error thrown when an interval configuration is invalid.
|
|
26
|
+
*/
|
|
27
|
+
class InvalidIntervalConfigError extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'InvalidIntervalConfigError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.InvalidIntervalConfigError = InvalidIntervalConfigError;
|
|
34
|
+
/**
|
|
35
|
+
* Error thrown when a poll is already started or already stopped.
|
|
36
|
+
*/
|
|
37
|
+
class PollSchedulingStateError extends Error {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = 'PollSchedulingStateError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.PollSchedulingStateError = PollSchedulingStateError;
|
|
44
|
+
/**
|
|
45
|
+
* Converts a PlatformID to a string key for Map lookups.
|
|
46
|
+
*/
|
|
47
|
+
function toKey(id) {
|
|
48
|
+
if (id instanceof Uint8Array) {
|
|
49
|
+
return Array.from(id)
|
|
50
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
51
|
+
.join('');
|
|
52
|
+
}
|
|
53
|
+
return String(id);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validates an IntervalConfig, throwing InvalidIntervalConfigError on problems.
|
|
57
|
+
*/
|
|
58
|
+
function validateConfig(config) {
|
|
59
|
+
if (config.minimumIntervalMs < 0) {
|
|
60
|
+
throw new InvalidIntervalConfigError(`minimumIntervalMs must be >= 0, got ${config.minimumIntervalMs}`);
|
|
61
|
+
}
|
|
62
|
+
if (config.ceremonyTimeoutMs <= 0) {
|
|
63
|
+
throw new InvalidIntervalConfigError(`ceremonyTimeoutMs must be > 0, got ${config.ceremonyTimeoutMs}`);
|
|
64
|
+
}
|
|
65
|
+
const needsTime = config.triggerType === interval_trigger_type_1.IntervalTriggerType.TimeBased ||
|
|
66
|
+
config.triggerType === interval_trigger_type_1.IntervalTriggerType.Hybrid;
|
|
67
|
+
const needsVoteCount = config.triggerType === interval_trigger_type_1.IntervalTriggerType.VoteCountBased ||
|
|
68
|
+
config.triggerType === interval_trigger_type_1.IntervalTriggerType.Hybrid;
|
|
69
|
+
if (needsTime) {
|
|
70
|
+
if (config.timeIntervalMs === undefined || config.timeIntervalMs <= 0) {
|
|
71
|
+
throw new InvalidIntervalConfigError(`timeIntervalMs must be > 0 for ${config.triggerType} triggers, got ${config.timeIntervalMs}`);
|
|
72
|
+
}
|
|
73
|
+
if (config.timeIntervalMs < config.minimumIntervalMs) {
|
|
74
|
+
throw new InvalidIntervalConfigError(`timeIntervalMs (${config.timeIntervalMs}) must be >= minimumIntervalMs (${config.minimumIntervalMs})`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (needsVoteCount) {
|
|
78
|
+
if (config.voteCountInterval === undefined ||
|
|
79
|
+
config.voteCountInterval <= 0 ||
|
|
80
|
+
!Number.isInteger(config.voteCountInterval)) {
|
|
81
|
+
throw new InvalidIntervalConfigError(`voteCountInterval must be a positive integer for ${config.triggerType} triggers, got ${config.voteCountInterval}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Scheduler for interval decryption triggers in threshold voting.
|
|
87
|
+
*
|
|
88
|
+
* Supports three trigger modes:
|
|
89
|
+
* - **TimeBased**: Fires at fixed time intervals (e.g., every 30 minutes)
|
|
90
|
+
* - **VoteCountBased**: Fires after a certain number of new votes
|
|
91
|
+
* - **Hybrid**: Fires on whichever condition is met first (time or vote count)
|
|
92
|
+
*
|
|
93
|
+
* Enforces a minimum interval between triggers to prevent excessive
|
|
94
|
+
* decryption ceremonies.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const scheduler = new IntervalScheduler<string>();
|
|
99
|
+
* scheduler.configure('poll-1', {
|
|
100
|
+
* triggerType: IntervalTriggerType.TimeBased,
|
|
101
|
+
* timeIntervalMs: 60_000,
|
|
102
|
+
* minimumIntervalMs: 30_000,
|
|
103
|
+
* ceremonyTimeoutMs: 120_000,
|
|
104
|
+
* });
|
|
105
|
+
* scheduler.onTrigger((event) => {
|
|
106
|
+
* console.log(`Interval ${event.intervalNumber} triggered`);
|
|
107
|
+
* });
|
|
108
|
+
* scheduler.start('poll-1');
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
class IntervalScheduler {
|
|
112
|
+
_polls = new Map();
|
|
113
|
+
_triggerListeners = [];
|
|
114
|
+
/**
|
|
115
|
+
* Configure interval scheduling for a poll.
|
|
116
|
+
*
|
|
117
|
+
* @throws InvalidIntervalConfigError if the configuration is invalid
|
|
118
|
+
* @throws PollSchedulingStateError if the poll is already running
|
|
119
|
+
*/
|
|
120
|
+
configure(pollId, config) {
|
|
121
|
+
validateConfig(config);
|
|
122
|
+
const key = toKey(pollId);
|
|
123
|
+
const existing = this._polls.get(key);
|
|
124
|
+
if (existing?.running) {
|
|
125
|
+
throw new PollSchedulingStateError(`Cannot reconfigure poll '${key}' while it is running. Stop it first.`);
|
|
126
|
+
}
|
|
127
|
+
this._polls.set(key, {
|
|
128
|
+
pollId,
|
|
129
|
+
config,
|
|
130
|
+
intervalNumber: 0,
|
|
131
|
+
voteCount: 0,
|
|
132
|
+
votesSinceLastTrigger: 0,
|
|
133
|
+
running: false,
|
|
134
|
+
timerId: null,
|
|
135
|
+
lastTriggerTime: 0,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Start scheduling for a poll.
|
|
140
|
+
*
|
|
141
|
+
* For time-based and hybrid triggers, starts a repeating timer.
|
|
142
|
+
* For vote-count-based triggers, the scheduler waits for notifyVote() calls.
|
|
143
|
+
*
|
|
144
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
145
|
+
* @throws PollSchedulingStateError if the poll is already running
|
|
146
|
+
*/
|
|
147
|
+
start(pollId) {
|
|
148
|
+
const state = this.getState(pollId);
|
|
149
|
+
if (state.running) {
|
|
150
|
+
throw new PollSchedulingStateError(`Poll '${toKey(pollId)}' is already running`);
|
|
151
|
+
}
|
|
152
|
+
state.running = true;
|
|
153
|
+
state.lastTriggerTime = Date.now();
|
|
154
|
+
const needsTimer = state.config.triggerType === interval_trigger_type_1.IntervalTriggerType.TimeBased ||
|
|
155
|
+
state.config.triggerType === interval_trigger_type_1.IntervalTriggerType.Hybrid;
|
|
156
|
+
if (needsTimer && state.config.timeIntervalMs) {
|
|
157
|
+
state.timerId = setInterval(() => {
|
|
158
|
+
this.emitTrigger(state, 'time');
|
|
159
|
+
}, state.config.timeIntervalMs);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Stop scheduling for a poll.
|
|
164
|
+
*
|
|
165
|
+
* Clears any active timer and marks the poll as not running.
|
|
166
|
+
*
|
|
167
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
168
|
+
*/
|
|
169
|
+
stop(pollId) {
|
|
170
|
+
const state = this.getState(pollId);
|
|
171
|
+
if (!state.running) {
|
|
172
|
+
return; // idempotent
|
|
173
|
+
}
|
|
174
|
+
if (state.timerId !== null) {
|
|
175
|
+
clearInterval(state.timerId);
|
|
176
|
+
state.timerId = null;
|
|
177
|
+
}
|
|
178
|
+
state.running = false;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Notify the scheduler that a new vote has been cast.
|
|
182
|
+
*
|
|
183
|
+
* For vote-count-based and hybrid triggers, this may fire a trigger
|
|
184
|
+
* if the vote count threshold is reached.
|
|
185
|
+
*
|
|
186
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
187
|
+
*/
|
|
188
|
+
notifyVote(pollId) {
|
|
189
|
+
const state = this.getState(pollId);
|
|
190
|
+
if (!state.running)
|
|
191
|
+
return;
|
|
192
|
+
state.voteCount++;
|
|
193
|
+
state.votesSinceLastTrigger++;
|
|
194
|
+
const needsVoteCount = state.config.triggerType === interval_trigger_type_1.IntervalTriggerType.VoteCountBased ||
|
|
195
|
+
state.config.triggerType === interval_trigger_type_1.IntervalTriggerType.Hybrid;
|
|
196
|
+
if (needsVoteCount &&
|
|
197
|
+
state.config.voteCountInterval !== undefined &&
|
|
198
|
+
state.votesSinceLastTrigger >= state.config.voteCountInterval) {
|
|
199
|
+
this.emitTrigger(state, 'vote-count');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Trigger a final decryption ceremony when a poll closes.
|
|
204
|
+
*
|
|
205
|
+
* This always fires regardless of minimum interval enforcement,
|
|
206
|
+
* as the final tally must be computed.
|
|
207
|
+
*
|
|
208
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
209
|
+
*/
|
|
210
|
+
triggerFinal(pollId) {
|
|
211
|
+
const state = this.getState(pollId);
|
|
212
|
+
// Stop the scheduler if running
|
|
213
|
+
if (state.running) {
|
|
214
|
+
this.stop(pollId);
|
|
215
|
+
}
|
|
216
|
+
// Final trigger always fires, bypassing minimum interval
|
|
217
|
+
state.intervalNumber++;
|
|
218
|
+
const event = {
|
|
219
|
+
pollId: state.pollId,
|
|
220
|
+
intervalNumber: state.intervalNumber,
|
|
221
|
+
triggerType: state.config.triggerType,
|
|
222
|
+
triggerReason: 'poll-close',
|
|
223
|
+
currentVoteCount: state.voteCount,
|
|
224
|
+
timestamp: Date.now(),
|
|
225
|
+
};
|
|
226
|
+
for (const listener of this._triggerListeners) {
|
|
227
|
+
listener(event);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Subscribe to interval trigger events.
|
|
232
|
+
*/
|
|
233
|
+
onTrigger(callback) {
|
|
234
|
+
this._triggerListeners.push(callback);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get the current interval number for a poll.
|
|
238
|
+
*
|
|
239
|
+
* @throws PollNotConfiguredError if the poll has not been configured
|
|
240
|
+
*/
|
|
241
|
+
getCurrentInterval(pollId) {
|
|
242
|
+
return this.getState(pollId).intervalNumber;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Emit a trigger event, enforcing minimum interval between triggers.
|
|
246
|
+
*/
|
|
247
|
+
emitTrigger(state, reason) {
|
|
248
|
+
const now = Date.now();
|
|
249
|
+
const elapsed = now - state.lastTriggerTime;
|
|
250
|
+
if (elapsed < state.config.minimumIntervalMs) {
|
|
251
|
+
return; // Rate-limited
|
|
252
|
+
}
|
|
253
|
+
state.intervalNumber++;
|
|
254
|
+
state.lastTriggerTime = now;
|
|
255
|
+
state.votesSinceLastTrigger = 0;
|
|
256
|
+
const event = {
|
|
257
|
+
pollId: state.pollId,
|
|
258
|
+
intervalNumber: state.intervalNumber,
|
|
259
|
+
triggerType: state.config.triggerType,
|
|
260
|
+
triggerReason: reason,
|
|
261
|
+
currentVoteCount: state.voteCount,
|
|
262
|
+
timestamp: now,
|
|
263
|
+
};
|
|
264
|
+
for (const listener of this._triggerListeners) {
|
|
265
|
+
listener(event);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get the internal state for a poll, throwing if not configured.
|
|
270
|
+
*/
|
|
271
|
+
getState(pollId) {
|
|
272
|
+
const key = toKey(pollId);
|
|
273
|
+
const state = this._polls.get(key);
|
|
274
|
+
if (!state) {
|
|
275
|
+
throw new PollNotConfiguredError(`Poll '${key}' has not been configured for interval scheduling`);
|
|
276
|
+
}
|
|
277
|
+
return state;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.IntervalScheduler = IntervalScheduler;
|
|
281
|
+
//# sourceMappingURL=interval-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interval-scheduler.js","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/interval-scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partial-decryption-service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/partial-decryption-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EACV,yBAAyB,EACzB,QAAQ,EACR,iBAAiB,EAElB,MAAM,cAAc,CAAC;AAEtB;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,wBAAyB,YAAW,yBAAyB;IACxE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;gBAEhB,SAAS,EAAE,SAAS;IAKhC;;;;;;;OAOG;IACH,cAAc,CACZ,cAAc,EAAE,MAAM,EAAE,EACxB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,UAAU,GACxB,iBAAiB;
|
|
1
|
+
{"version":3,"file":"partial-decryption-service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/digitaldefiance-ecies-lib/src/lib/voting/threshold/partial-decryption-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EACV,yBAAyB,EACzB,QAAQ,EACR,iBAAiB,EAElB,MAAM,cAAc,CAAC;AAEtB;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,wBAAyB,YAAW,yBAAyB;IACxE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;gBAEhB,SAAS,EAAE,SAAS;IAKhC;;;;;;;OAOG;IACH,cAAc,CACZ,cAAc,EAAE,MAAM,EAAE,EACxB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,UAAU,GACxB,iBAAiB;IA+BpB;;;;;;;;;;;OAWG;IACH,aAAa,CACX,OAAO,EAAE,iBAAiB,EAC1B,cAAc,EAAE,MAAM,EAAE,EACxB,eAAe,EAAE,UAAU,EAC3B,SAAS,EAAE,SAAS,GACnB,OAAO;IAyCV;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU;IAgBjD;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,iBAAiB;IAiChD;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAiCrB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IA8CxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,OAAO,CAAC,GAAG;IAKX;;OAEG;IACH,OAAO,CAAC,MAAM;IAcd;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAO3B"}
|
|
@@ -63,21 +63,19 @@ class PartialDecryptionService {
|
|
|
63
63
|
if (encryptedTally.length === 0) {
|
|
64
64
|
throw new Error('Encrypted tally must not be empty');
|
|
65
65
|
}
|
|
66
|
+
// Compute the partial decryption exponent: 2 * share
|
|
67
|
+
// (We omit Δ scaling here for simplicity; the combiner accounts for it)
|
|
68
|
+
const exponent = 2n * keyShare.share;
|
|
69
|
+
// Compute partial decryption for each ciphertext: c_j^(2·sᵢ) mod n²
|
|
70
|
+
const values = encryptedTally.map((c) => this.modPow(c, exponent, this.n2));
|
|
66
71
|
// For the ZK proof, we use the first ciphertext as representative.
|
|
67
72
|
// In a real multi-ciphertext scenario, the proof would cover all,
|
|
68
73
|
// but for simplicity we prove over the first element and the
|
|
69
74
|
// verifier checks the relationship holds.
|
|
70
|
-
const
|
|
71
|
-
// Compute the partial decryption exponent: 2 * share
|
|
72
|
-
// (We omit Δ scaling here for simplicity; the combiner accounts for it)
|
|
73
|
-
const exponent = 2n * keyShare.share;
|
|
74
|
-
// partial_value = c^(2·sᵢ) mod n²
|
|
75
|
-
const value = this.modPow(c, exponent, this.n2);
|
|
76
|
-
// Generate ZK proof
|
|
77
|
-
const proof = this.generateProof(c, keyShare, ceremonyNonce);
|
|
75
|
+
const proof = this.generateProof(encryptedTally[0], keyShare, ceremonyNonce);
|
|
78
76
|
return {
|
|
79
77
|
guardianIndex: keyShare.index,
|
|
80
|
-
|
|
78
|
+
values,
|
|
81
79
|
proof,
|
|
82
80
|
ceremonyNonce: new Uint8Array(ceremonyNonce),
|
|
83
81
|
timestamp: Date.now(),
|
|
@@ -102,12 +100,11 @@ class PartialDecryptionService {
|
|
|
102
100
|
const n2 = publicKey.n * publicKey.n;
|
|
103
101
|
const c = encryptedTally[0];
|
|
104
102
|
const vk = this.uint8ArrayToBigint(verificationKey);
|
|
105
|
-
const g = publicKey.g;
|
|
106
103
|
const { commitment, challenge, response } = partial.proof;
|
|
107
104
|
// Check 1: c^(2·z) ≡ commitment_c · value^e mod n²
|
|
108
105
|
// commitment stores the ciphertext commitment (a = c^(2r))
|
|
109
106
|
const lhsCipher = this.modPow(c, 2n * response, n2);
|
|
110
|
-
const rhsCipher = this.mod(commitment * this.modPow(partial.
|
|
107
|
+
const rhsCipher = this.mod(commitment * this.modPow(partial.values[0], challenge, n2), n2);
|
|
111
108
|
if (lhsCipher !== rhsCipher) {
|
|
112
109
|
return false;
|
|
113
110
|
}
|
|
@@ -117,7 +114,7 @@ class PartialDecryptionService {
|
|
|
117
114
|
// But we can also just recompute the challenge and check it matches.
|
|
118
115
|
// The challenge includes vk, so a wrong vk produces a different challenge.
|
|
119
116
|
// Recompute challenge with the provided verification key
|
|
120
|
-
const recomputedChallenge = this.computeChallenge(c, partial.
|
|
117
|
+
const recomputedChallenge = this.computeChallenge(c, partial.values[0], commitment, partial.ceremonyNonce, n2, vk);
|
|
121
118
|
return challenge === recomputedChallenge;
|
|
122
119
|
}
|
|
123
120
|
/**
|
|
@@ -126,7 +123,7 @@ class PartialDecryptionService {
|
|
|
126
123
|
serialize(partial) {
|
|
127
124
|
const json = JSON.stringify({
|
|
128
125
|
guardianIndex: partial.guardianIndex,
|
|
129
|
-
|
|
126
|
+
values: partial.values.map((v) => v.toString(16)),
|
|
130
127
|
proof: {
|
|
131
128
|
commitment: partial.proof.commitment.toString(16),
|
|
132
129
|
challenge: partial.proof.challenge.toString(16),
|
|
@@ -146,7 +143,7 @@ class PartialDecryptionService {
|
|
|
146
143
|
const parsed = JSON.parse(json);
|
|
147
144
|
return {
|
|
148
145
|
guardianIndex: parsed.guardianIndex,
|
|
149
|
-
|
|
146
|
+
values: parsed.values.map((v) => BigInt('0x' + v)),
|
|
150
147
|
proof: {
|
|
151
148
|
commitment: BigInt('0x' + parsed.proof.commitment),
|
|
152
149
|
challenge: BigInt('0x' + parsed.proof.challenge),
|
|
@@ -198,7 +195,11 @@ class PartialDecryptionService {
|
|
|
198
195
|
const pvBytes = this.bigintToUint8Array(partialValue);
|
|
199
196
|
const cmBytes = this.bigintToUint8Array(commitment);
|
|
200
197
|
const vkBytes = this.bigintToUint8Array(verificationKey);
|
|
201
|
-
const totalLength = cBytes.length +
|
|
198
|
+
const totalLength = cBytes.length +
|
|
199
|
+
pvBytes.length +
|
|
200
|
+
cmBytes.length +
|
|
201
|
+
nonce.length +
|
|
202
|
+
vkBytes.length;
|
|
202
203
|
const combined = new Uint8Array(totalLength);
|
|
203
204
|
let offset = 0;
|
|
204
205
|
combined.set(cBytes, offset);
|