@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.
Files changed (62) hide show
  1. package/README.md +3 -2
  2. package/package.json +3 -3
  3. package/src/lib/voting/threshold/ceremony-coordinator.d.ts +152 -0
  4. package/src/lib/voting/threshold/ceremony-coordinator.d.ts.map +1 -0
  5. package/src/lib/voting/threshold/ceremony-coordinator.js +316 -0
  6. package/src/lib/voting/threshold/ceremony-coordinator.js.map +1 -0
  7. package/src/lib/voting/threshold/decryption-combiner.d.ts.map +1 -1
  8. package/src/lib/voting/threshold/decryption-combiner.js +3 -3
  9. package/src/lib/voting/threshold/decryption-combiner.js.map +1 -1
  10. package/src/lib/voting/threshold/guardian-registry.d.ts +1 -1
  11. package/src/lib/voting/threshold/guardian-registry.d.ts.map +1 -1
  12. package/src/lib/voting/threshold/index.d.ts +11 -0
  13. package/src/lib/voting/threshold/index.d.ts.map +1 -1
  14. package/src/lib/voting/threshold/index.js +32 -1
  15. package/src/lib/voting/threshold/index.js.map +1 -1
  16. package/src/lib/voting/threshold/interfaces/partial-decryption.d.ts +2 -2
  17. package/src/lib/voting/threshold/interfaces/partial-decryption.d.ts.map +1 -1
  18. package/src/lib/voting/threshold/interval-scheduler.d.ts +123 -0
  19. package/src/lib/voting/threshold/interval-scheduler.d.ts.map +1 -0
  20. package/src/lib/voting/threshold/interval-scheduler.js +281 -0
  21. package/src/lib/voting/threshold/interval-scheduler.js.map +1 -0
  22. package/src/lib/voting/threshold/partial-decryption-service.d.ts.map +1 -1
  23. package/src/lib/voting/threshold/partial-decryption-service.js +16 -15
  24. package/src/lib/voting/threshold/partial-decryption-service.js.map +1 -1
  25. package/src/lib/voting/threshold/public-tally-feed.d.ts +100 -0
  26. package/src/lib/voting/threshold/public-tally-feed.d.ts.map +1 -0
  27. package/src/lib/voting/threshold/public-tally-feed.js +202 -0
  28. package/src/lib/voting/threshold/public-tally-feed.js.map +1 -0
  29. package/src/lib/voting/threshold/tally-verifier.d.ts +85 -0
  30. package/src/lib/voting/threshold/tally-verifier.d.ts.map +1 -0
  31. package/src/lib/voting/threshold/tally-verifier.js +169 -0
  32. package/src/lib/voting/threshold/tally-verifier.js.map +1 -0
  33. package/src/lib/voting/threshold/threshold-audit-log.d.ts +71 -0
  34. package/src/lib/voting/threshold/threshold-audit-log.d.ts.map +1 -0
  35. package/src/lib/voting/threshold/threshold-audit-log.js +243 -0
  36. package/src/lib/voting/threshold/threshold-audit-log.js.map +1 -0
  37. package/src/lib/voting/threshold/threshold-county-aggregator.d.ts +81 -0
  38. package/src/lib/voting/threshold/threshold-county-aggregator.d.ts.map +1 -0
  39. package/src/lib/voting/threshold/threshold-county-aggregator.js +154 -0
  40. package/src/lib/voting/threshold/threshold-county-aggregator.js.map +1 -0
  41. package/src/lib/voting/threshold/threshold-key-generator.d.ts.map +1 -1
  42. package/src/lib/voting/threshold/threshold-key-generator.js.map +1 -1
  43. package/src/lib/voting/threshold/threshold-national-aggregator.d.ts +95 -0
  44. package/src/lib/voting/threshold/threshold-national-aggregator.d.ts.map +1 -0
  45. package/src/lib/voting/threshold/threshold-national-aggregator.js +210 -0
  46. package/src/lib/voting/threshold/threshold-national-aggregator.js.map +1 -0
  47. package/src/lib/voting/threshold/threshold-poll-factory.d.ts +88 -0
  48. package/src/lib/voting/threshold/threshold-poll-factory.d.ts.map +1 -0
  49. package/src/lib/voting/threshold/threshold-poll-factory.js +156 -0
  50. package/src/lib/voting/threshold/threshold-poll-factory.js.map +1 -0
  51. package/src/lib/voting/threshold/threshold-poll.d.ts +76 -0
  52. package/src/lib/voting/threshold/threshold-poll.d.ts.map +1 -0
  53. package/src/lib/voting/threshold/threshold-poll.js +144 -0
  54. package/src/lib/voting/threshold/threshold-poll.js.map +1 -0
  55. package/src/lib/voting/threshold/threshold-precinct-aggregator.d.ts +86 -0
  56. package/src/lib/voting/threshold/threshold-precinct-aggregator.d.ts.map +1 -0
  57. package/src/lib/voting/threshold/threshold-precinct-aggregator.js +156 -0
  58. package/src/lib/voting/threshold/threshold-precinct-aggregator.js.map +1 -0
  59. package/src/lib/voting/threshold/threshold-state-aggregator.d.ts +85 -0
  60. package/src/lib/voting/threshold/threshold-state-aggregator.d.ts.map +1 -0
  61. package/src/lib/voting/threshold/threshold-state-aggregator.js +164 -0
  62. 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 value */
12
- readonly value: bigint;
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,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,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"}
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;IA8BpB;;;;;;;;;;;OAWG;IACH,aAAa,CACX,OAAO,EAAE,iBAAiB,EAC1B,cAAc,EAAE,MAAM,EAAE,EACxB,eAAe,EAAE,UAAU,EAC3B,SAAS,EAAE,SAAS,GACnB,OAAO;IA0CV;;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;IA0CxB;;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"}
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 c = encryptedTally[0];
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
- value,
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.value, challenge, n2), n2);
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.value, commitment, partial.ceremonyNonce, n2, vk);
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
- value: partial.value.toString(16),
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
- value: BigInt('0x' + parsed.value),
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 + pvBytes.length + cmBytes.length + nonce.length + vkBytes.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);