@bitgo-beta/sdk-lib-mpc 8.2.1-alpha.467 → 8.2.1-alpha.469
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/dist/src/tss/dkls-vrf/dkg.d.ts +91 -0
- package/dist/src/tss/dkls-vrf/dkg.d.ts.map +1 -0
- package/dist/src/tss/dkls-vrf/dkg.js +278 -0
- package/dist/src/tss/dkls-vrf/index.d.ts +4 -0
- package/dist/src/tss/dkls-vrf/index.d.ts.map +1 -0
- package/dist/src/tss/dkls-vrf/index.js +40 -0
- package/dist/src/tss/dkls-vrf/types.d.ts +28 -0
- package/dist/src/tss/dkls-vrf/types.d.ts.map +1 -0
- package/dist/src/tss/dkls-vrf/types.js +23 -0
- package/dist/src/tss/dkls-vrf/util.d.ts +29 -0
- package/dist/src/tss/dkls-vrf/util.d.ts.map +1 -0
- package/dist/src/tss/dkls-vrf/util.js +113 -0
- package/dist/src/tss/ecdsa-dkls/derive.d.ts +111 -0
- package/dist/src/tss/ecdsa-dkls/derive.d.ts.map +1 -0
- package/dist/src/tss/ecdsa-dkls/derive.js +329 -0
- package/dist/src/tss/ecdsa-dkls/dkg.d.ts +3 -1
- package/dist/src/tss/ecdsa-dkls/dkg.d.ts.map +1 -1
- package/dist/src/tss/ecdsa-dkls/dkg.js +1 -1
- package/dist/src/tss/ecdsa-dkls/index.d.ts +1 -0
- package/dist/src/tss/ecdsa-dkls/index.d.ts.map +1 -1
- package/dist/src/tss/ecdsa-dkls/index.js +3 -2
- package/dist/src/tss/eddsa-mps/derive.d.ts +34 -0
- package/dist/src/tss/eddsa-mps/derive.d.ts.map +1 -0
- package/dist/src/tss/eddsa-mps/derive.js +198 -0
- package/dist/src/tss/eddsa-mps/dkg.d.ts +7 -2
- package/dist/src/tss/eddsa-mps/dkg.d.ts.map +1 -1
- package/dist/src/tss/eddsa-mps/dkg.js +13 -3
- package/dist/src/tss/eddsa-mps/index.d.ts +2 -0
- package/dist/src/tss/eddsa-mps/index.d.ts.map +1 -1
- package/dist/src/tss/eddsa-mps/index.js +3 -2
- package/dist/src/tss/eddsa-mps/types.d.ts +13 -0
- package/dist/src/tss/eddsa-mps/types.d.ts.map +1 -1
- package/dist/src/tss/eddsa-mps/types.js +1 -1
- package/dist/src/tss/eddsa-mps/util.d.ts +2 -2
- package/dist/src/tss/eddsa-mps/util.d.ts.map +1 -1
- package/dist/src/tss/eddsa-mps/util.js +5 -5
- package/dist/src/tss/eddsa-mps-vrf/dkg.d.ts +65 -0
- package/dist/src/tss/eddsa-mps-vrf/dkg.d.ts.map +1 -0
- package/dist/src/tss/eddsa-mps-vrf/dkg.js +246 -0
- package/dist/src/tss/eddsa-mps-vrf/index.d.ts +4 -0
- package/dist/src/tss/eddsa-mps-vrf/index.d.ts.map +1 -0
- package/dist/src/tss/eddsa-mps-vrf/index.js +40 -0
- package/dist/src/tss/eddsa-mps-vrf/types.d.ts +31 -0
- package/dist/src/tss/eddsa-mps-vrf/types.d.ts.map +1 -0
- package/dist/src/tss/eddsa-mps-vrf/types.js +97 -0
- package/dist/src/tss/eddsa-mps-vrf/util.d.ts +9 -0
- package/dist/src/tss/eddsa-mps-vrf/util.d.ts.map +1 -0
- package/dist/src/tss/eddsa-mps-vrf/util.js +36 -0
- package/dist/src/tss/index.d.ts +3 -0
- package/dist/src/tss/index.d.ts.map +1 -1
- package/dist/src/tss/index.js +4 -1
- package/dist/src/tss/redpallas-mps/commsLayer.d.ts +34 -0
- package/dist/src/tss/redpallas-mps/commsLayer.d.ts.map +1 -0
- package/dist/src/tss/redpallas-mps/commsLayer.js +100 -0
- package/dist/src/tss/redpallas-mps/dkg.d.ts +103 -0
- package/dist/src/tss/redpallas-mps/dkg.d.ts.map +1 -0
- package/dist/src/tss/redpallas-mps/dkg.js +285 -0
- package/dist/src/tss/redpallas-mps/dsg.d.ts +108 -0
- package/dist/src/tss/redpallas-mps/dsg.d.ts.map +1 -0
- package/dist/src/tss/redpallas-mps/dsg.js +355 -0
- package/dist/src/tss/redpallas-mps/index.d.ts +7 -0
- package/dist/src/tss/redpallas-mps/index.d.ts.map +1 -0
- package/dist/src/tss/redpallas-mps/index.js +42 -0
- package/dist/src/tss/redpallas-mps/types.d.ts +85 -0
- package/dist/src/tss/redpallas-mps/types.d.ts.map +1 -0
- package/dist/src/tss/redpallas-mps/types.js +112 -0
- package/dist/src/tss/redpallas-mps/util.d.ts +43 -0
- package/dist/src/tss/redpallas-mps/util.d.ts.map +1 -0
- package/dist/src/tss/redpallas-mps/util.js +147 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -6
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.detachSignMpsMessage = detachSignMpsMessage;
|
|
37
|
+
exports.verifyMpsMessage = verifyMpsMessage;
|
|
38
|
+
exports.extractEd25519PublicKey = extractEd25519PublicKey;
|
|
39
|
+
exports.extractEd25519KeyPair = extractEd25519KeyPair;
|
|
40
|
+
const pgp = __importStar(require("openpgp"));
|
|
41
|
+
/**
|
|
42
|
+
* PGP detached-signs raw WASM bytes with the given private key.
|
|
43
|
+
* Returns an MPSSignedMessage with the base64-encoded payload and armored signature.
|
|
44
|
+
*
|
|
45
|
+
* Mirrors `detachSignMpsMessage` in `../eddsa-mps/commsLayer.ts`. Kept as an independent
|
|
46
|
+
* copy (rather than a shared import) so RedPallas MPS never depends on the EdDSA MPS
|
|
47
|
+
* module, and vice versa.
|
|
48
|
+
*/
|
|
49
|
+
async function detachSignMpsMessage(rawBytes, signingKey) {
|
|
50
|
+
const signature = await pgp.sign({
|
|
51
|
+
message: await pgp.createMessage({ binary: rawBytes }),
|
|
52
|
+
signingKeys: signingKey,
|
|
53
|
+
detached: true,
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
message: Buffer.from(rawBytes).toString('base64'),
|
|
57
|
+
signature: signature,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Verifies a PGP detached signature on an MPSSignedMessage and returns the decoded raw bytes.
|
|
62
|
+
* Throws if the signature is invalid or not present.
|
|
63
|
+
*/
|
|
64
|
+
async function verifyMpsMessage(msg, verificationKey) {
|
|
65
|
+
const rawBytes = Buffer.from(msg.message, 'base64');
|
|
66
|
+
const result = await pgp.verify({
|
|
67
|
+
message: await pgp.createMessage({ binary: rawBytes }),
|
|
68
|
+
signature: await pgp.readSignature({ armoredSignature: msg.signature }),
|
|
69
|
+
verificationKeys: verificationKey,
|
|
70
|
+
expectSigned: true,
|
|
71
|
+
});
|
|
72
|
+
await result.signatures[0].verified;
|
|
73
|
+
return rawBytes;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Extracts the X25519 public key bytes from a GPG key's encryption subkey.
|
|
77
|
+
* Works for both public-only and private keys — use this for third-party keys (e.g. BitGo's).
|
|
78
|
+
*
|
|
79
|
+
* @param key - A GPG key with an X25519 encryption subkey.
|
|
80
|
+
* @returns 32-byte X25519 public key.
|
|
81
|
+
*/
|
|
82
|
+
async function extractEd25519PublicKey(key) {
|
|
83
|
+
const { keyPacket } = await key.getEncryptionKey();
|
|
84
|
+
return Buffer.from(keyPacket.publicParams.Q).subarray(1);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Extracts the X25519 public and private key bytes from a GPG ed25519 private key's
|
|
88
|
+
* encryption subkey. Encapsulates the keyPacket internals and the little-endian scalar
|
|
89
|
+
* reversal in one place so sdk-core only deals with plain Buffers.
|
|
90
|
+
*
|
|
91
|
+
* @param privateKey - An ed25519 GPG private key with an X25519 encryption subkey.
|
|
92
|
+
* @returns [pk, sk] — 32-byte X25519 public key and private scalar.
|
|
93
|
+
*/
|
|
94
|
+
async function extractEd25519KeyPair(privateKey) {
|
|
95
|
+
const encKey = await privateKey.getEncryptionKey();
|
|
96
|
+
const pk = Buffer.from(encKey.keyPacket.publicParams.Q).subarray(1);
|
|
97
|
+
const sk = Buffer.from(encKey.keyPacket.privateParams.d).reverse();
|
|
98
|
+
return [pk, sk];
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbXNMYXllci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy90c3MvcmVkcGFsbGFzLW1wcy9jb21tc0xheWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBV0Esb0RBYUM7QUFNRCw0Q0FVQztBQVNELDBEQUdDO0FBVUQsc0RBT0M7QUFyRUQsNkNBQStCO0FBRy9COzs7Ozs7O0dBT0c7QUFDSSxLQUFLLFVBQVUsb0JBQW9CLENBQ3hDLFFBQTZCLEVBQzdCLFVBQTBCO0lBRTFCLE1BQU0sU0FBUyxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQztRQUMvQixPQUFPLEVBQUUsTUFBTSxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDO1FBQ3RELFdBQVcsRUFBRSxVQUFVO1FBQ3ZCLFFBQVEsRUFBRSxJQUFJO0tBQ2YsQ0FBQyxDQUFDO0lBQ0gsT0FBTztRQUNMLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDakQsU0FBUyxFQUFFLFNBQW1CO0tBQy9CLENBQUM7QUFDSixDQUFDO0FBRUQ7OztHQUdHO0FBQ0ksS0FBSyxVQUFVLGdCQUFnQixDQUFDLEdBQXFCLEVBQUUsZUFBd0I7SUFDcEYsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3BELE1BQU0sTUFBTSxHQUFHLE1BQU0sR0FBRyxDQUFDLE1BQU0sQ0FBQztRQUM5QixPQUFPLEVBQUUsTUFBTSxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDO1FBQ3RELFNBQVMsRUFBRSxNQUFNLEdBQUcsQ0FBQyxhQUFhLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDdkUsZ0JBQWdCLEVBQUUsZUFBZTtRQUNqQyxZQUFZLEVBQUUsSUFBSTtLQUNuQixDQUFDLENBQUM7SUFDSCxNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0lBQ3BDLE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSSxLQUFLLFVBQVUsdUJBQXVCLENBQUMsR0FBWTtJQUN4RCxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsTUFBTSxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNuRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUUsU0FBUyxDQUFDLFlBQWtDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xGLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0ksS0FBSyxVQUFVLHFCQUFxQixDQUFDLFVBQTBCO0lBQ3BFLE1BQU0sTUFBTSxHQUFHLE1BQU0sVUFBVSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDbkQsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBRSxNQUFNLENBQUMsU0FBUyxDQUFDLFlBQWtDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNGLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQ25CLE1BQU0sQ0FBQyxTQUE2RCxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQ3RGLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDWixPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwZ3AgZnJvbSAnb3BlbnBncCc7XG5pbXBvcnQgeyBNUFNTaWduZWRNZXNzYWdlIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogUEdQIGRldGFjaGVkLXNpZ25zIHJhdyBXQVNNIGJ5dGVzIHdpdGggdGhlIGdpdmVuIHByaXZhdGUga2V5LlxuICogUmV0dXJucyBhbiBNUFNTaWduZWRNZXNzYWdlIHdpdGggdGhlIGJhc2U2NC1lbmNvZGVkIHBheWxvYWQgYW5kIGFybW9yZWQgc2lnbmF0dXJlLlxuICpcbiAqIE1pcnJvcnMgYGRldGFjaFNpZ25NcHNNZXNzYWdlYCBpbiBgLi4vZWRkc2EtbXBzL2NvbW1zTGF5ZXIudHNgLiBLZXB0IGFzIGFuIGluZGVwZW5kZW50XG4gKiBjb3B5IChyYXRoZXIgdGhhbiBhIHNoYXJlZCBpbXBvcnQpIHNvIFJlZFBhbGxhcyBNUFMgbmV2ZXIgZGVwZW5kcyBvbiB0aGUgRWREU0EgTVBTXG4gKiBtb2R1bGUsIGFuZCB2aWNlIHZlcnNhLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGV0YWNoU2lnbk1wc01lc3NhZ2UoXG4gIHJhd0J5dGVzOiBCdWZmZXIgfCBVaW50OEFycmF5LFxuICBzaWduaW5nS2V5OiBwZ3AuUHJpdmF0ZUtleVxuKTogUHJvbWlzZTxNUFNTaWduZWRNZXNzYWdlPiB7XG4gIGNvbnN0IHNpZ25hdHVyZSA9IGF3YWl0IHBncC5zaWduKHtcbiAgICBtZXNzYWdlOiBhd2FpdCBwZ3AuY3JlYXRlTWVzc2FnZSh7IGJpbmFyeTogcmF3Qnl0ZXMgfSksXG4gICAgc2lnbmluZ0tleXM6IHNpZ25pbmdLZXksXG4gICAgZGV0YWNoZWQ6IHRydWUsXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIG1lc3NhZ2U6IEJ1ZmZlci5mcm9tKHJhd0J5dGVzKS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgc2lnbmF0dXJlOiBzaWduYXR1cmUgYXMgc3RyaW5nLFxuICB9O1xufVxuXG4vKipcbiAqIFZlcmlmaWVzIGEgUEdQIGRldGFjaGVkIHNpZ25hdHVyZSBvbiBhbiBNUFNTaWduZWRNZXNzYWdlIGFuZCByZXR1cm5zIHRoZSBkZWNvZGVkIHJhdyBieXRlcy5cbiAqIFRocm93cyBpZiB0aGUgc2lnbmF0dXJlIGlzIGludmFsaWQgb3Igbm90IHByZXNlbnQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlNcHNNZXNzYWdlKG1zZzogTVBTU2lnbmVkTWVzc2FnZSwgdmVyaWZpY2F0aW9uS2V5OiBwZ3AuS2V5KTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgY29uc3QgcmF3Qnl0ZXMgPSBCdWZmZXIuZnJvbShtc2cubWVzc2FnZSwgJ2Jhc2U2NCcpO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBwZ3AudmVyaWZ5KHtcbiAgICBtZXNzYWdlOiBhd2FpdCBwZ3AuY3JlYXRlTWVzc2FnZSh7IGJpbmFyeTogcmF3Qnl0ZXMgfSksXG4gICAgc2lnbmF0dXJlOiBhd2FpdCBwZ3AucmVhZFNpZ25hdHVyZSh7IGFybW9yZWRTaWduYXR1cmU6IG1zZy5zaWduYXR1cmUgfSksXG4gICAgdmVyaWZpY2F0aW9uS2V5czogdmVyaWZpY2F0aW9uS2V5LFxuICAgIGV4cGVjdFNpZ25lZDogdHJ1ZSxcbiAgfSk7XG4gIGF3YWl0IHJlc3VsdC5zaWduYXR1cmVzWzBdLnZlcmlmaWVkO1xuICByZXR1cm4gcmF3Qnl0ZXM7XG59XG5cbi8qKlxuICogRXh0cmFjdHMgdGhlIFgyNTUxOSBwdWJsaWMga2V5IGJ5dGVzIGZyb20gYSBHUEcga2V5J3MgZW5jcnlwdGlvbiBzdWJrZXkuXG4gKiBXb3JrcyBmb3IgYm90aCBwdWJsaWMtb25seSBhbmQgcHJpdmF0ZSBrZXlzIOKAlCB1c2UgdGhpcyBmb3IgdGhpcmQtcGFydHkga2V5cyAoZS5nLiBCaXRHbydzKS5cbiAqXG4gKiBAcGFyYW0ga2V5IC0gQSBHUEcga2V5IHdpdGggYW4gWDI1NTE5IGVuY3J5cHRpb24gc3Via2V5LlxuICogQHJldHVybnMgMzItYnl0ZSBYMjU1MTkgcHVibGljIGtleS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4dHJhY3RFZDI1NTE5UHVibGljS2V5KGtleTogcGdwLktleSk6IFByb21pc2U8QnVmZmVyPiB7XG4gIGNvbnN0IHsga2V5UGFja2V0IH0gPSBhd2FpdCBrZXkuZ2V0RW5jcnlwdGlvbktleSgpO1xuICByZXR1cm4gQnVmZmVyLmZyb20oKGtleVBhY2tldC5wdWJsaWNQYXJhbXMgYXMgeyBROiBVaW50OEFycmF5IH0pLlEpLnN1YmFycmF5KDEpO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIHRoZSBYMjU1MTkgcHVibGljIGFuZCBwcml2YXRlIGtleSBieXRlcyBmcm9tIGEgR1BHIGVkMjU1MTkgcHJpdmF0ZSBrZXknc1xuICogZW5jcnlwdGlvbiBzdWJrZXkuIEVuY2Fwc3VsYXRlcyB0aGUga2V5UGFja2V0IGludGVybmFscyBhbmQgdGhlIGxpdHRsZS1lbmRpYW4gc2NhbGFyXG4gKiByZXZlcnNhbCBpbiBvbmUgcGxhY2Ugc28gc2RrLWNvcmUgb25seSBkZWFscyB3aXRoIHBsYWluIEJ1ZmZlcnMuXG4gKlxuICogQHBhcmFtIHByaXZhdGVLZXkgLSBBbiBlZDI1NTE5IEdQRyBwcml2YXRlIGtleSB3aXRoIGFuIFgyNTUxOSBlbmNyeXB0aW9uIHN1YmtleS5cbiAqIEByZXR1cm5zICBbcGssIHNrXSDigJQgMzItYnl0ZSBYMjU1MTkgcHVibGljIGtleSBhbmQgcHJpdmF0ZSBzY2FsYXIuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBleHRyYWN0RWQyNTUxOUtleVBhaXIocHJpdmF0ZUtleTogcGdwLlByaXZhdGVLZXkpOiBQcm9taXNlPFtCdWZmZXIsIEJ1ZmZlcl0+IHtcbiAgY29uc3QgZW5jS2V5ID0gYXdhaXQgcHJpdmF0ZUtleS5nZXRFbmNyeXB0aW9uS2V5KCk7XG4gIGNvbnN0IHBrID0gQnVmZmVyLmZyb20oKGVuY0tleS5rZXlQYWNrZXQucHVibGljUGFyYW1zIGFzIHsgUTogVWludDhBcnJheSB9KS5RKS5zdWJhcnJheSgxKTtcbiAgY29uc3Qgc2sgPSBCdWZmZXIuZnJvbShcbiAgICAoZW5jS2V5LmtleVBhY2tldCBhcyB1bmtub3duIGFzIHsgcHJpdmF0ZVBhcmFtczogeyBkOiBVaW50OEFycmF5IH0gfSkucHJpdmF0ZVBhcmFtcy5kXG4gICkucmV2ZXJzZSgpO1xuICByZXR1cm4gW3BrLCBza107XG59XG4iXX0=
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { DeserializedMessage, DeserializedMessages, RedPallasDkgState } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* RedPallas (Zcash Ironwood) Distributed Key Generation (DKG) implementation using @bitgo/wasm-mps.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the structure of the EdDSA MPS `DKG` class (see `../eddsa-mps/dkg.ts`), but wraps the
|
|
6
|
+
* `redpallas_dkg_*` WASM bindings. Round2 additionally requires a `derivationSeed` and returns a
|
|
7
|
+
* `MsgDerivationInit` (msg/pk/share/state) rather than a final `Share`, because RedPallas key
|
|
8
|
+
* derivation (ask/nk/rivk/ivks, via `redpallas_derivation_process`) is a separate, subsequent
|
|
9
|
+
* process that is platform-side only and intentionally not exposed here.
|
|
10
|
+
*
|
|
11
|
+
* State is explicit: each round function returns `{ msg, state }` bytes. The state bytes are
|
|
12
|
+
* stored between rounds and passed to the next round function, mirroring the server-side
|
|
13
|
+
* persistence pattern (state would be serialised to DB, or in OVC's case, a microSD card).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const dkg = new RedPallasDKG(3, 2, 0);
|
|
18
|
+
* // X25519 keys come from GPG encryption subkeys (extracted by the orchestrator)
|
|
19
|
+
* await dkg.initDkg(myX25519PrivKey, [otherParty1X25519PubKey, otherParty2X25519PubKey]);
|
|
20
|
+
* const msg1 = dkg.getFirstMessage();
|
|
21
|
+
* const msg2s = dkg.handleIncomingMessages(allThreeMsg1s);
|
|
22
|
+
* dkg.handleIncomingMessages(allThreeMsg2s, derivationSeed); // completes DKG
|
|
23
|
+
* const keyShare = dkg.getKeyShare();
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class RedPallasDKG {
|
|
27
|
+
protected n: number;
|
|
28
|
+
protected t: number;
|
|
29
|
+
protected partyIdx: number;
|
|
30
|
+
/** Private X25519 key (from GPG encryption subkey) */
|
|
31
|
+
private decryptionKey;
|
|
32
|
+
/** Other parties' X25519 public keys (from their GPG encryption subkeys), sorted by party index */
|
|
33
|
+
private otherPubKeys;
|
|
34
|
+
/** Serialised round state bytes returned by the previous round function */
|
|
35
|
+
private dkgStateBytes;
|
|
36
|
+
/** Opaque bincode-serialised keyshare from round2 */
|
|
37
|
+
private keyShare;
|
|
38
|
+
/** RedPallas public key (verification key) from round2 */
|
|
39
|
+
private sharePk;
|
|
40
|
+
/** Lazily loaded WASM module */
|
|
41
|
+
private wasmMps;
|
|
42
|
+
protected dkgState: RedPallasDkgState;
|
|
43
|
+
constructor(n: number, t: number, partyIdx: number);
|
|
44
|
+
private loadWasmMps;
|
|
45
|
+
private getWasmMps;
|
|
46
|
+
getState(): RedPallasDkgState;
|
|
47
|
+
/**
|
|
48
|
+
* Initialises the DKG session with this party's X25519 private key and the other parties'
|
|
49
|
+
* X25519 public keys. Keys are extracted from GPG encryption subkeys by the orchestrator.
|
|
50
|
+
*
|
|
51
|
+
* @param decryptionKey - This party's 32-byte X25519 private key (GPG enc subkey private part).
|
|
52
|
+
* @param otherEncPublicKeys - Other parties' 32-byte X25519 public keys, sorted by ascending
|
|
53
|
+
* party index (excluding own). For a 3-party setup, this is [party_A_pub, party_B_pub].
|
|
54
|
+
*/
|
|
55
|
+
initDkg(decryptionKey: Buffer, otherEncPublicKeys: Buffer[]): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Runs round0 of the DKG protocol. Returns this party's broadcast message.
|
|
58
|
+
* Stores the round state bytes internally for the next round.
|
|
59
|
+
*
|
|
60
|
+
* @param dkgSeed - Optional 32-byte seed for deterministic DKG output (testing only).
|
|
61
|
+
*/
|
|
62
|
+
getFirstMessage(dkgSeed?: Buffer): DeserializedMessage;
|
|
63
|
+
/**
|
|
64
|
+
* Handles incoming messages from all parties and advances the protocol.
|
|
65
|
+
*
|
|
66
|
+
* - In WaitMsg1: runs round1, returns this party's round1 broadcast message.
|
|
67
|
+
* - In WaitMsg2: runs round2, completes DKG, returns [].
|
|
68
|
+
*
|
|
69
|
+
* The caller passes all n messages (including own); own message is filtered
|
|
70
|
+
* out internally. Other parties' messages are sorted by ascending party index,
|
|
71
|
+
* matching the ordering expected by @bitgo/wasm-mps.
|
|
72
|
+
*
|
|
73
|
+
* @param messagesForIthRound - All n messages for this round (including own).
|
|
74
|
+
*/
|
|
75
|
+
handleIncomingMessages(messagesForIthRound: DeserializedMessages): DeserializedMessages;
|
|
76
|
+
/**
|
|
77
|
+
* Returns the opaque bincode-serialised keyshare produced by round2.
|
|
78
|
+
* This is used as input to the (platform-side) signing and derivation protocols.
|
|
79
|
+
*/
|
|
80
|
+
getKeyShare(): Buffer;
|
|
81
|
+
/**
|
|
82
|
+
* Returns the RedPallas public key (verification key) agreed by all parties during DKG.
|
|
83
|
+
*/
|
|
84
|
+
getSharePublicKey(): Buffer;
|
|
85
|
+
/**
|
|
86
|
+
* Returns a CBOR-encoded ReducedKeyShare buffer containing the party's opaque
|
|
87
|
+
* signing key share in the `keyShare` field. This buffer is private key material.
|
|
88
|
+
* The caller encrypts it and stores it as `reducedEncryptedPrv` on the key card QR code.
|
|
89
|
+
*/
|
|
90
|
+
getReducedKeyShare(): Buffer;
|
|
91
|
+
/**
|
|
92
|
+
* Exports the current session state as a JSON string for persistence.
|
|
93
|
+
* Includes: round state bytes, current DKG round, decryption key, other parties' pub keys.
|
|
94
|
+
* This mirrors what a server would store in a database between API rounds.
|
|
95
|
+
*/
|
|
96
|
+
getSession(): string;
|
|
97
|
+
/**
|
|
98
|
+
* Restores a previously exported session. Allows the protocol to continue
|
|
99
|
+
* from where it left off, as if the round state was loaded from a database.
|
|
100
|
+
*/
|
|
101
|
+
restoreSession(session: string): void;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=dkg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dkg.d.ts","sourceRoot":"","sources":["../../../../src/tss/redpallas-mps/dkg.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,iBAAiB,EAA4B,MAAM,SAAS,CAAC;AAMjH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,YAAY;IACvB,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE3B,sDAAsD;IACtD,OAAO,CAAC,aAAa,CAAuB;IAC5C,mGAAmG;IACnG,OAAO,CAAC,YAAY,CAAyB;IAC7C,2EAA2E;IAC3E,OAAO,CAAC,aAAa,CAAuB;IAC5C,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAuB;IACvC,0DAA0D;IAC1D,OAAO,CAAC,OAAO,CAAuB;IACtC,gCAAgC;IAChC,OAAO,CAAC,OAAO,CAAwB;IAEvC,SAAS,CAAC,QAAQ,EAAE,iBAAiB,CAAmC;gBAE5D,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;YAMpC,WAAW;IAoBzB,OAAO,CAAC,UAAU;IAOlB,QAAQ,IAAI,iBAAiB;IAI7B;;;;;;;OAOG;IACG,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBjF;;;;;OAKG;IACH,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,mBAAmB;IAmBtD;;;;;;;;;;;OAWG;IACH,sBAAsB,CAAC,mBAAmB,EAAE,oBAAoB,GAAG,oBAAoB;IAsDvF;;;OAGG;IACH,WAAW,IAAI,MAAM;IAOrB;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAO3B;;;;OAIG;IACH,kBAAkB,IAAI,MAAM;IAW5B;;;;OAIG;IACH,UAAU,IAAI,MAAM;IAepB;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAOtC"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.RedPallasDKG = void 0;
|
|
40
|
+
const cbor_x_1 = require("cbor-x");
|
|
41
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
42
|
+
const types_1 = require("./types");
|
|
43
|
+
/**
|
|
44
|
+
* RedPallas (Zcash Ironwood) Distributed Key Generation (DKG) implementation using @bitgo/wasm-mps.
|
|
45
|
+
*
|
|
46
|
+
* Mirrors the structure of the EdDSA MPS `DKG` class (see `../eddsa-mps/dkg.ts`), but wraps the
|
|
47
|
+
* `redpallas_dkg_*` WASM bindings. Round2 additionally requires a `derivationSeed` and returns a
|
|
48
|
+
* `MsgDerivationInit` (msg/pk/share/state) rather than a final `Share`, because RedPallas key
|
|
49
|
+
* derivation (ask/nk/rivk/ivks, via `redpallas_derivation_process`) is a separate, subsequent
|
|
50
|
+
* process that is platform-side only and intentionally not exposed here.
|
|
51
|
+
*
|
|
52
|
+
* State is explicit: each round function returns `{ msg, state }` bytes. The state bytes are
|
|
53
|
+
* stored between rounds and passed to the next round function, mirroring the server-side
|
|
54
|
+
* persistence pattern (state would be serialised to DB, or in OVC's case, a microSD card).
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const dkg = new RedPallasDKG(3, 2, 0);
|
|
59
|
+
* // X25519 keys come from GPG encryption subkeys (extracted by the orchestrator)
|
|
60
|
+
* await dkg.initDkg(myX25519PrivKey, [otherParty1X25519PubKey, otherParty2X25519PubKey]);
|
|
61
|
+
* const msg1 = dkg.getFirstMessage();
|
|
62
|
+
* const msg2s = dkg.handleIncomingMessages(allThreeMsg1s);
|
|
63
|
+
* dkg.handleIncomingMessages(allThreeMsg2s, derivationSeed); // completes DKG
|
|
64
|
+
* const keyShare = dkg.getKeyShare();
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
class RedPallasDKG {
|
|
68
|
+
constructor(n, t, partyIdx) {
|
|
69
|
+
/** Private X25519 key (from GPG encryption subkey) */
|
|
70
|
+
this.decryptionKey = null;
|
|
71
|
+
/** Other parties' X25519 public keys (from their GPG encryption subkeys), sorted by party index */
|
|
72
|
+
this.otherPubKeys = null;
|
|
73
|
+
/** Serialised round state bytes returned by the previous round function */
|
|
74
|
+
this.dkgStateBytes = null;
|
|
75
|
+
/** Opaque bincode-serialised keyshare from round2 */
|
|
76
|
+
this.keyShare = null;
|
|
77
|
+
/** RedPallas public key (verification key) from round2 */
|
|
78
|
+
this.sharePk = null;
|
|
79
|
+
/** Lazily loaded WASM module */
|
|
80
|
+
this.wasmMps = null;
|
|
81
|
+
this.dkgState = types_1.RedPallasDkgState.Uninitialized;
|
|
82
|
+
this.n = n;
|
|
83
|
+
this.t = t;
|
|
84
|
+
this.partyIdx = partyIdx;
|
|
85
|
+
}
|
|
86
|
+
async loadWasmMps() {
|
|
87
|
+
if (!this.wasmMps) {
|
|
88
|
+
if (typeof window !== 'undefined' &&
|
|
89
|
+
/* checks for electron processes */
|
|
90
|
+
!window.process &&
|
|
91
|
+
!window.process?.['type']) {
|
|
92
|
+
// Browser: web build has explicit init() — guaranteed ready after await
|
|
93
|
+
// eslint-disable-next-line import/no-internal-modules -- @bitgo/wasm-mps exposes environment-specific subpath exports.
|
|
94
|
+
const webWasm = await Promise.resolve().then(() => __importStar(require('@bitgo/wasm-mps/web')));
|
|
95
|
+
await webWasm.default();
|
|
96
|
+
this.wasmMps = webWasm;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// Node.js: dynamic import() rewritten to require() by tsc → CJS build → readFileSync
|
|
100
|
+
this.wasmMps = await Promise.resolve().then(() => __importStar(require('@bitgo/wasm-mps')));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
getWasmMps() {
|
|
105
|
+
if (!this.wasmMps) {
|
|
106
|
+
throw Error('WASM module not loaded');
|
|
107
|
+
}
|
|
108
|
+
return this.wasmMps;
|
|
109
|
+
}
|
|
110
|
+
getState() {
|
|
111
|
+
return this.dkgState;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Initialises the DKG session with this party's X25519 private key and the other parties'
|
|
115
|
+
* X25519 public keys. Keys are extracted from GPG encryption subkeys by the orchestrator.
|
|
116
|
+
*
|
|
117
|
+
* @param decryptionKey - This party's 32-byte X25519 private key (GPG enc subkey private part).
|
|
118
|
+
* @param otherEncPublicKeys - Other parties' 32-byte X25519 public keys, sorted by ascending
|
|
119
|
+
* party index (excluding own). For a 3-party setup, this is [party_A_pub, party_B_pub].
|
|
120
|
+
*/
|
|
121
|
+
async initDkg(decryptionKey, otherEncPublicKeys) {
|
|
122
|
+
await this.loadWasmMps();
|
|
123
|
+
if (!decryptionKey || decryptionKey.length !== 32) {
|
|
124
|
+
throw Error('Missing or invalid decryption key: must be 32 bytes');
|
|
125
|
+
}
|
|
126
|
+
if (!otherEncPublicKeys || otherEncPublicKeys.length !== this.n - 1) {
|
|
127
|
+
throw Error(`Expected ${this.n - 1} other parties' public keys`);
|
|
128
|
+
}
|
|
129
|
+
if (this.t > this.n || this.partyIdx >= this.n) {
|
|
130
|
+
throw Error('Invalid parameters for DKG');
|
|
131
|
+
}
|
|
132
|
+
this.decryptionKey = decryptionKey;
|
|
133
|
+
this.otherPubKeys = otherEncPublicKeys;
|
|
134
|
+
this.dkgState = types_1.RedPallasDkgState.Init;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Runs round0 of the DKG protocol. Returns this party's broadcast message.
|
|
138
|
+
* Stores the round state bytes internally for the next round.
|
|
139
|
+
*
|
|
140
|
+
* @param dkgSeed - Optional 32-byte seed for deterministic DKG output (testing only).
|
|
141
|
+
*/
|
|
142
|
+
getFirstMessage(dkgSeed) {
|
|
143
|
+
if (this.dkgState !== types_1.RedPallasDkgState.Init) {
|
|
144
|
+
throw Error('DKG session not initialized');
|
|
145
|
+
}
|
|
146
|
+
const seed = dkgSeed ?? crypto_1.default.randomBytes(32);
|
|
147
|
+
const wasm = this.getWasmMps();
|
|
148
|
+
let result;
|
|
149
|
+
try {
|
|
150
|
+
result = wasm.redpallas_dkg_round0_process(this.partyIdx, this.decryptionKey, this.otherPubKeys, seed);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
throw new Error(`Error while creating the first message from party ${this.partyIdx}: ${err}`);
|
|
154
|
+
}
|
|
155
|
+
this.dkgStateBytes = Buffer.from(result.state);
|
|
156
|
+
this.dkgState = types_1.RedPallasDkgState.WaitMsg1;
|
|
157
|
+
return { payload: new Uint8Array(result.msg), from: this.partyIdx };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Handles incoming messages from all parties and advances the protocol.
|
|
161
|
+
*
|
|
162
|
+
* - In WaitMsg1: runs round1, returns this party's round1 broadcast message.
|
|
163
|
+
* - In WaitMsg2: runs round2, completes DKG, returns [].
|
|
164
|
+
*
|
|
165
|
+
* The caller passes all n messages (including own); own message is filtered
|
|
166
|
+
* out internally. Other parties' messages are sorted by ascending party index,
|
|
167
|
+
* matching the ordering expected by @bitgo/wasm-mps.
|
|
168
|
+
*
|
|
169
|
+
* @param messagesForIthRound - All n messages for this round (including own).
|
|
170
|
+
*/
|
|
171
|
+
handleIncomingMessages(messagesForIthRound) {
|
|
172
|
+
if (this.dkgState === types_1.RedPallasDkgState.Complete) {
|
|
173
|
+
throw Error('DKG session already completed');
|
|
174
|
+
}
|
|
175
|
+
if (this.dkgState === types_1.RedPallasDkgState.Uninitialized) {
|
|
176
|
+
throw Error('DKG session not initialized');
|
|
177
|
+
}
|
|
178
|
+
if (this.dkgState === types_1.RedPallasDkgState.Init) {
|
|
179
|
+
throw Error('DKG session must call getFirstMessage() before handling incoming messages. Call getFirstMessage() first.');
|
|
180
|
+
}
|
|
181
|
+
if (messagesForIthRound.length !== this.n) {
|
|
182
|
+
throw Error('Invalid number of messages for the round. Number of messages should be equal to N');
|
|
183
|
+
}
|
|
184
|
+
// Extract other parties' messages, sorted by party index (ascending)
|
|
185
|
+
const otherMsgs = messagesForIthRound
|
|
186
|
+
.filter((m) => m.from !== this.partyIdx)
|
|
187
|
+
.sort((a, b) => a.from - b.from)
|
|
188
|
+
.map((m) => m.payload);
|
|
189
|
+
const wasm = this.getWasmMps();
|
|
190
|
+
if (this.dkgState === types_1.RedPallasDkgState.WaitMsg1) {
|
|
191
|
+
let result;
|
|
192
|
+
try {
|
|
193
|
+
result = wasm.redpallas_dkg_round1_process(otherMsgs, this.dkgStateBytes);
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
throw new Error(`Error while creating messages from party ${this.partyIdx}, round ${this.dkgState}: ${err}`);
|
|
197
|
+
}
|
|
198
|
+
// Store new state; this is what would be persisted between API rounds / microSD exchanges
|
|
199
|
+
this.dkgStateBytes = Buffer.from(result.state);
|
|
200
|
+
this.dkgState = types_1.RedPallasDkgState.WaitMsg2;
|
|
201
|
+
return [{ payload: new Uint8Array(result.msg), from: this.partyIdx }];
|
|
202
|
+
}
|
|
203
|
+
if (this.dkgState === types_1.RedPallasDkgState.WaitMsg2) {
|
|
204
|
+
let result;
|
|
205
|
+
try {
|
|
206
|
+
result = wasm.redpallas_dkg_round2_process(otherMsgs, this.dkgStateBytes);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
throw new Error(`Error while creating messages from party ${this.partyIdx}, round ${this.dkgState}: ${err}`);
|
|
210
|
+
}
|
|
211
|
+
this.keyShare = Buffer.from(result.share);
|
|
212
|
+
this.sharePk = Buffer.from(result.pk);
|
|
213
|
+
this.dkgStateBytes = null;
|
|
214
|
+
this.dkgState = types_1.RedPallasDkgState.Complete;
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
throw Error('Unexpected DKG state');
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Returns the opaque bincode-serialised keyshare produced by round2.
|
|
221
|
+
* This is used as input to the (platform-side) signing and derivation protocols.
|
|
222
|
+
*/
|
|
223
|
+
getKeyShare() {
|
|
224
|
+
if (!this.keyShare) {
|
|
225
|
+
throw Error('DKG session not initialized');
|
|
226
|
+
}
|
|
227
|
+
return this.keyShare;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Returns the RedPallas public key (verification key) agreed by all parties during DKG.
|
|
231
|
+
*/
|
|
232
|
+
getSharePublicKey() {
|
|
233
|
+
if (!this.sharePk) {
|
|
234
|
+
throw Error('DKG session not initialized');
|
|
235
|
+
}
|
|
236
|
+
return this.sharePk;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Returns a CBOR-encoded ReducedKeyShare buffer containing the party's opaque
|
|
240
|
+
* signing key share in the `keyShare` field. This buffer is private key material.
|
|
241
|
+
* The caller encrypts it and stores it as `reducedEncryptedPrv` on the key card QR code.
|
|
242
|
+
*/
|
|
243
|
+
getReducedKeyShare() {
|
|
244
|
+
if (!this.keyShare || !this.sharePk) {
|
|
245
|
+
throw Error('DKG session not initialized');
|
|
246
|
+
}
|
|
247
|
+
const reducedKeyShare = {
|
|
248
|
+
keyShare: Array.from(this.keyShare),
|
|
249
|
+
pub: Array.from(this.sharePk),
|
|
250
|
+
};
|
|
251
|
+
return Buffer.from((0, cbor_x_1.encode)(reducedKeyShare));
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Exports the current session state as a JSON string for persistence.
|
|
255
|
+
* Includes: round state bytes, current DKG round, decryption key, other parties' pub keys.
|
|
256
|
+
* This mirrors what a server would store in a database between API rounds.
|
|
257
|
+
*/
|
|
258
|
+
getSession() {
|
|
259
|
+
if (this.dkgState === types_1.RedPallasDkgState.Complete) {
|
|
260
|
+
throw Error('DKG session is complete. Exporting the session is not allowed.');
|
|
261
|
+
}
|
|
262
|
+
if (this.dkgState === types_1.RedPallasDkgState.Uninitialized) {
|
|
263
|
+
throw Error('DKG session not initialized');
|
|
264
|
+
}
|
|
265
|
+
return JSON.stringify({
|
|
266
|
+
dkgStateBytes: this.dkgStateBytes?.toString('base64') ?? null,
|
|
267
|
+
dkgRound: this.dkgState,
|
|
268
|
+
decryptionKey: this.decryptionKey?.toString('base64') ?? null,
|
|
269
|
+
otherPubKeys: this.otherPubKeys?.map((k) => k.toString('base64')) ?? null,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Restores a previously exported session. Allows the protocol to continue
|
|
274
|
+
* from where it left off, as if the round state was loaded from a database.
|
|
275
|
+
*/
|
|
276
|
+
restoreSession(session) {
|
|
277
|
+
const data = JSON.parse(session);
|
|
278
|
+
this.dkgStateBytes = data.dkgStateBytes ? Buffer.from(data.dkgStateBytes, 'base64') : null;
|
|
279
|
+
this.dkgState = data.dkgRound;
|
|
280
|
+
this.decryptionKey = data.decryptionKey ? Buffer.from(data.decryptionKey, 'base64') : null;
|
|
281
|
+
this.otherPubKeys = data.otherPubKeys ? data.otherPubKeys.map((k) => Buffer.from(k, 'base64')) : null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
exports.RedPallasDKG = RedPallasDKG;
|
|
285
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGtnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3Rzcy9yZWRwYWxsYXMtbXBzL2RrZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFDQSxtQ0FBZ0M7QUFDaEMsb0RBQTRCO0FBQzVCLG1DQUFpSDtBQU1qSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFDSCxNQUFhLFlBQVk7SUFvQnZCLFlBQVksQ0FBUyxFQUFFLENBQVMsRUFBRSxRQUFnQjtRQWZsRCxzREFBc0Q7UUFDOUMsa0JBQWEsR0FBa0IsSUFBSSxDQUFDO1FBQzVDLG1HQUFtRztRQUMzRixpQkFBWSxHQUFvQixJQUFJLENBQUM7UUFDN0MsMkVBQTJFO1FBQ25FLGtCQUFhLEdBQWtCLElBQUksQ0FBQztRQUM1QyxxREFBcUQ7UUFDN0MsYUFBUSxHQUFrQixJQUFJLENBQUM7UUFDdkMsMERBQTBEO1FBQ2xELFlBQU8sR0FBa0IsSUFBSSxDQUFDO1FBQ3RDLGdDQUFnQztRQUN4QixZQUFPLEdBQW1CLElBQUksQ0FBQztRQUU3QixhQUFRLEdBQXNCLHlCQUFpQixDQUFDLGFBQWEsQ0FBQztRQUd0RSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNYLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDM0IsQ0FBQztJQUVPLEtBQUssQ0FBQyxXQUFXO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbEIsSUFDRSxPQUFPLE1BQU0sS0FBSyxXQUFXO2dCQUM3QixtQ0FBbUM7Z0JBQ25DLENBQUMsTUFBTSxDQUFDLE9BQU87Z0JBQ2YsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQ3pCLENBQUM7Z0JBQ0Qsd0VBQXdFO2dCQUN4RSx1SEFB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QUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUMzRixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFFLElBQUksQ0FBQyxZQUF5QixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3RILENBQUM7Q0FDRjtBQWpQRCxvQ0FpUEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IE1zZ1N0YXRlIH0gZnJvbSAnQGJpdGdvL3dhc20tbXBzJztcbmltcG9ydCB7IGVuY29kZSB9IGZyb20gJ2Nib3IteCc7XG5pbXBvcnQgY3J5cHRvIGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBEZXNlcmlhbGl6ZWRNZXNzYWdlLCBEZXNlcmlhbGl6ZWRNZXNzYWdlcywgUmVkUGFsbGFzRGtnU3RhdGUsIFJlZFBhbGxhc1JlZHVjZWRLZXlTaGFyZSB9IGZyb20gJy4vdHlwZXMnO1xuXG50eXBlIE5vZGVXYXNtZXIgPSB0eXBlb2YgaW1wb3J0KCdAYml0Z28vd2FzbS1tcHMnKTtcbnR5cGUgV2ViV2FzbWVyID0gdHlwZW9mIGltcG9ydCgnQGJpdGdvL3dhc20tbXBzL3dlYicpO1xudHlwZSBXYXNtTXBzID0gTm9kZVdhc21lciB8IFdlYldhc21lcjtcblxuLyoqXG4gKiBSZWRQYWxsYXMgKFpjYXNoIElyb253b29kKSBEaXN0cmlidXRlZCBLZXkgR2VuZXJhdGlvbiAoREtHKSBpbXBsZW1lbnRhdGlvbiB1c2luZyBAYml0Z28vd2FzbS1tcHMuXG4gKlxuICogTWlycm9ycyB0aGUgc3RydWN0dXJlIG9mIHRoZSBFZERTQSBNUFMgYERLR2AgY2xhc3MgKHNlZSBgLi4vZWRkc2EtbXBzL2RrZy50c2ApLCBidXQgd3JhcHMgdGhlXG4gKiBgcmVkcGFsbGFzX2RrZ18qYCBXQVNNIGJpbmRpbmdzLiBSb3VuZDIgYWRkaXRpb25hbGx5IHJlcXVpcmVzIGEgYGRlcml2YXRpb25TZWVkYCBhbmQgcmV0dXJucyBhXG4gKiBgTXNnRGVyaXZhdGlvbkluaXRgIChtc2cvcGsvc2hhcmUvc3RhdGUpIHJhdGhlciB0aGFuIGEgZmluYWwgYFNoYXJlYCwgYmVjYXVzZSBSZWRQYWxsYXMga2V5XG4gKiBkZXJpdmF0aW9uIChhc2svbmsvcml2ay9pdmtzLCB2aWEgYHJlZHBhbGxhc19kZXJpdmF0aW9uX3Byb2Nlc3NgKSBpcyBhIHNlcGFyYXRlLCBzdWJzZXF1ZW50XG4gKiBwcm9jZXNzIHRoYXQgaXMgcGxhdGZvcm0tc2lkZSBvbmx5IGFuZCBpbnRlbnRpb25hbGx5IG5vdCBleHBvc2VkIGhlcmUuXG4gKlxuICogU3RhdGUgaXMgZXhwbGljaXQ6IGVhY2ggcm91bmQgZnVuY3Rpb24gcmV0dXJucyBgeyBtc2csIHN0YXRlIH1gIGJ5dGVzLiBUaGUgc3RhdGUgYnl0ZXMgYXJlXG4gKiBzdG9yZWQgYmV0d2VlbiByb3VuZHMgYW5kIHBhc3NlZCB0byB0aGUgbmV4dCByb3VuZCBmdW5jdGlvbiwgbWlycm9yaW5nIHRoZSBzZXJ2ZXItc2lkZVxuICogcGVyc2lzdGVuY2UgcGF0dGVybiAoc3RhdGUgd291bGQgYmUgc2VyaWFsaXNlZCB0byBEQiwgb3IgaW4gT1ZDJ3MgY2FzZSwgYSBtaWNyb1NEIGNhcmQpLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBka2cgPSBuZXcgUmVkUGFsbGFzREtHKDMsIDIsIDApO1xuICogLy8gWDI1NTE5IGtleXMgY29tZSBmcm9tIEdQRyBlbmNyeXB0aW9uIHN1YmtleXMgKGV4dHJhY3RlZCBieSB0aGUgb3JjaGVzdHJhdG9yKVxuICogYXdhaXQgZGtnLmluaXREa2cobXlYMjU1MTlQcml2S2V5LCBbb3RoZXJQYXJ0eTFYMjU1MTlQdWJLZXksIG90aGVyUGFydHkyWDI1NTE5UHViS2V5XSk7XG4gKiBjb25zdCBtc2cxID0gZGtnLmdldEZpcnN0TWVzc2FnZSgpO1xuICogY29uc3QgbXNnMnMgPSBka2cuaGFuZGxlSW5jb21pbmdNZXNzYWdlcyhhbGxUaHJlZU1zZzFzKTtcbiAqIGRrZy5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKGFsbFRocmVlTXNnMnMsIGRlcml2YXRpb25TZWVkKTsgIC8vIGNvbXBsZXRlcyBES0dcbiAqIGNvbnN0IGtleVNoYXJlID0gZGtnLmdldEtleVNoYXJlKCk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFJlZFBhbGxhc0RLRyB7XG4gIHByb3RlY3RlZCBuOiBudW1iZXI7XG4gIHByb3RlY3RlZCB0OiBudW1iZXI7XG4gIHByb3RlY3RlZCBwYXJ0eUlkeDogbnVtYmVyO1xuXG4gIC8qKiBQcml2YXRlIFgyNTUxOSBrZXkgKGZyb20gR1BHIGVuY3J5cHRpb24gc3Via2V5KSAqL1xuICBwcml2YXRlIGRlY3J5cHRpb25LZXk6IEJ1ZmZlciB8IG51bGwgPSBudWxsO1xuICAvKiogT3RoZXIgcGFydGllcycgWDI1NTE5IHB1YmxpYyBrZXlzIChmcm9tIHRoZWlyIEdQRyBlbmNyeXB0aW9uIHN1YmtleXMpLCBzb3J0ZWQgYnkgcGFydHkgaW5kZXggKi9cbiAgcHJpdmF0ZSBvdGhlclB1YktleXM6IEJ1ZmZlcltdIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBTZXJpYWxpc2VkIHJvdW5kIHN0YXRlIGJ5dGVzIHJldHVybmVkIGJ5IHRoZSBwcmV2aW91cyByb3VuZCBmdW5jdGlvbiAqL1xuICBwcml2YXRlIGRrZ1N0YXRlQnl0ZXM6IEJ1ZmZlciB8IG51bGwgPSBudWxsO1xuICAvKiogT3BhcXVlIGJpbmNvZGUtc2VyaWFsaXNlZCBrZXlzaGFyZSBmcm9tIHJvdW5kMiAqL1xuICBwcml2YXRlIGtleVNoYXJlOiBCdWZmZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqIFJlZFBhbGxhcyBwdWJsaWMga2V5ICh2ZXJpZmljYXRpb24ga2V5KSBmcm9tIHJvdW5kMiAqL1xuICBwcml2YXRlIHNoYXJlUGs6IEJ1ZmZlciB8IG51bGwgPSBudWxsO1xuICAvKiogTGF6aWx5IGxvYWRlZCBXQVNNIG1vZHVsZSAqL1xuICBwcml2YXRlIHdhc21NcHM6IFdhc21NcHMgfCBudWxsID0gbnVsbDtcblxuICBwcm90ZWN0ZWQgZGtnU3RhdGU6IFJlZFBhbGxhc0RrZ1N0YXRlID0gUmVkUGFsbGFzRGtnU3RhdGUuVW5pbml0aWFsaXplZDtcblxuICBjb25zdHJ1Y3RvcihuOiBudW1iZXIsIHQ6IG51bWJlciwgcGFydHlJZHg6IG51bWJlcikge1xuICAgIHRoaXMubiA9IG47XG4gICAgdGhpcy50ID0gdDtcbiAgICB0aGlzLnBhcnR5SWR4ID0gcGFydHlJZHg7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWRXYXNtTXBzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy53YXNtTXBzKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIC8qIGNoZWNrcyBmb3IgZWxlY3Ryb24gcHJvY2Vzc2VzICovXG4gICAgICAgICF3aW5kb3cucHJvY2VzcyAmJlxuICAgICAgICAhd2luZG93LnByb2Nlc3M/LlsndHlwZSddXG4gICAgICApIHtcbiAgICAgICAgLy8gQnJvd3Nlcjogd2ViIGJ1aWxkIGhhcyBleHBsaWNpdCBpbml0KCkg4oCUIGd1YXJhbnRlZWQgcmVhZHkgYWZ0ZXIgYXdhaXRcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1pbnRlcm5hbC1tb2R1bGVzIC0tIEBiaXRnby93YXNtLW1wcyBleHBvc2VzIGVudmlyb25tZW50LXNwZWNpZmljIHN1YnBhdGggZXhwb3J0cy5cbiAgICAgICAgY29uc3Qgd2ViV2FzbSA9IGF3YWl0IGltcG9ydCgnQGJpdGdvL3dhc20tbXBzL3dlYicpO1xuICAgICAgICBhd2FpdCB3ZWJXYXNtLmRlZmF1bHQoKTtcbiAgICAgICAgdGhpcy53YXNtTXBzID0gd2ViV2FzbTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE5vZGUuanM6IGR5bmFtaWMgaW1wb3J0KCkgcmV3cml0dGVuIHRvIHJlcXVpcmUoKSBieSB0c2Mg4oaSIENKUyBidWlsZCDihpIgcmVhZEZpbGVTeW5jXG4gICAgICAgIHRoaXMud2FzbU1wcyA9IGF3YWl0IGltcG9ydCgnQGJpdGdvL3dhc20tbXBzJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRXYXNtTXBzKCk6IFdhc21NcHMge1xuICAgIGlmICghdGhpcy53YXNtTXBzKSB7XG4gICAgICB0aHJvdyBFcnJvcignV0FTTSBtb2R1bGUgbm90IGxvYWRlZCcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy53YXNtTXBzO1xuICB9XG5cbiAgZ2V0U3RhdGUoKTogUmVkUGFsbGFzRGtnU3RhdGUge1xuICAgIHJldHVybiB0aGlzLmRrZ1N0YXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpc2VzIHRoZSBES0cgc2Vzc2lvbiB3aXRoIHRoaXMgcGFydHkncyBYMjU1MTkgcHJpdmF0ZSBrZXkgYW5kIHRoZSBvdGhlciBwYXJ0aWVzJ1xuICAgKiBYMjU1MTkgcHVibGljIGtleXMuIEtleXMgYXJlIGV4dHJhY3RlZCBmcm9tIEdQRyBlbmNyeXB0aW9uIHN1YmtleXMgYnkgdGhlIG9yY2hlc3RyYXRvci5cbiAgICpcbiAgICogQHBhcmFtIGRlY3J5cHRpb25LZXkgLSBUaGlzIHBhcnR5J3MgMzItYnl0ZSBYMjU1MTkgcHJpdmF0ZSBrZXkgKEdQRyBlbmMgc3Via2V5IHByaXZhdGUgcGFydCkuXG4gICAqIEBwYXJhbSBvdGhlckVuY1B1YmxpY0tleXMgLSBPdGhlciBwYXJ0aWVzJyAzMi1ieXRlIFgyNTUxOSBwdWJsaWMga2V5cywgc29ydGVkIGJ5IGFzY2VuZGluZ1xuICAgKiAgIHBhcnR5IGluZGV4IChleGNsdWRpbmcgb3duKS4gRm9yIGEgMy1wYXJ0eSBzZXR1cCwgdGhpcyBpcyBbcGFydHlfQV9wdWIsIHBhcnR5X0JfcHViXS5cbiAgICovXG4gIGFzeW5jIGluaXREa2coZGVjcnlwdGlvbktleTogQnVmZmVyLCBvdGhlckVuY1B1YmxpY0tleXM6IEJ1ZmZlcltdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5sb2FkV2FzbU1wcygpO1xuICAgIGlmICghZGVjcnlwdGlvbktleSB8fCBkZWNyeXB0aW9uS2V5Lmxlbmd0aCAhPT0gMzIpIHtcbiAgICAgIHRocm93IEVycm9yKCdNaXNzaW5nIG9yIGludmFsaWQgZGVjcnlwdGlvbiBrZXk6IG11c3QgYmUgMzIgYnl0ZXMnKTtcbiAgICB9XG4gICAgaWYgKCFvdGhlckVuY1B1YmxpY0tleXMgfHwgb3RoZXJFbmNQdWJsaWNLZXlzLmxlbmd0aCAhPT0gdGhpcy5uIC0gMSkge1xuICAgICAgdGhyb3cgRXJyb3IoYEV4cGVjdGVkICR7dGhpcy5uIC0gMX0gb3RoZXIgcGFydGllcycgcHVibGljIGtleXNgKTtcbiAgICB9XG4gICAgaWYgKHRoaXMudCA+IHRoaXMubiB8fCB0aGlzLnBhcnR5SWR4ID49IHRoaXMubikge1xuICAgICAgdGhyb3cgRXJyb3IoJ0ludmFsaWQgcGFyYW1ldGVycyBmb3IgREtHJyk7XG4gICAgfVxuXG4gICAgdGhpcy5kZWNyeXB0aW9uS2V5ID0gZGVjcnlwdGlvbktleTtcbiAgICB0aGlzLm90aGVyUHViS2V5cyA9IG90aGVyRW5jUHVibGljS2V5cztcbiAgICB0aGlzLmRrZ1N0YXRlID0gUmVkUGFsbGFzRGtnU3RhdGUuSW5pdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHJvdW5kMCBvZiB0aGUgREtHIHByb3RvY29sLiBSZXR1cm5zIHRoaXMgcGFydHkncyBicm9hZGNhc3QgbWVzc2FnZS5cbiAgICogU3RvcmVzIHRoZSByb3VuZCBzdGF0ZSBieXRlcyBpbnRlcm5hbGx5IGZvciB0aGUgbmV4dCByb3VuZC5cbiAgICpcbiAgICogQHBhcmFtIGRrZ1NlZWQgLSBPcHRpb25hbCAzMi1ieXRlIHNlZWQgZm9yIGRldGVybWluaXN0aWMgREtHIG91dHB1dCAodGVzdGluZyBvbmx5KS5cbiAgICovXG4gIGdldEZpcnN0TWVzc2FnZShka2dTZWVkPzogQnVmZmVyKTogRGVzZXJpYWxpemVkTWVzc2FnZSB7XG4gICAgaWYgKHRoaXMuZGtnU3RhdGUgIT09IFJlZFBhbGxhc0RrZ1N0YXRlLkluaXQpIHtcbiAgICAgIHRocm93IEVycm9yKCdES0cgc2Vzc2lvbiBub3QgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBzZWVkID0gZGtnU2VlZCA/PyBjcnlwdG8ucmFuZG9tQnl0ZXMoMzIpO1xuICAgIGNvbnN0IHdhc20gPSB0aGlzLmdldFdhc21NcHMoKTtcbiAgICBsZXQgcmVzdWx0OiBNc2dTdGF0ZTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gd2FzbS5yZWRwYWxsYXNfZGtnX3JvdW5kMF9wcm9jZXNzKHRoaXMucGFydHlJZHgsIHRoaXMuZGVjcnlwdGlvbktleSEsIHRoaXMub3RoZXJQdWJLZXlzISwgc2VlZCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoaWxlIGNyZWF0aW5nIHRoZSBmaXJzdCBtZXNzYWdlIGZyb20gcGFydHkgJHt0aGlzLnBhcnR5SWR4fTogJHtlcnJ9YCk7XG4gICAgfVxuXG4gICAgdGhpcy5ka2dTdGF0ZUJ5dGVzID0gQnVmZmVyLmZyb20ocmVzdWx0LnN0YXRlKTtcbiAgICB0aGlzLmRrZ1N0YXRlID0gUmVkUGFsbGFzRGtnU3RhdGUuV2FpdE1zZzE7XG4gICAgcmV0dXJuIHsgcGF5bG9hZDogbmV3IFVpbnQ4QXJyYXkocmVzdWx0Lm1zZyksIGZyb206IHRoaXMucGFydHlJZHggfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIGluY29taW5nIG1lc3NhZ2VzIGZyb20gYWxsIHBhcnRpZXMgYW5kIGFkdmFuY2VzIHRoZSBwcm90b2NvbC5cbiAgICpcbiAgICogLSBJbiBXYWl0TXNnMTogcnVucyByb3VuZDEsIHJldHVybnMgdGhpcyBwYXJ0eSdzIHJvdW5kMSBicm9hZGNhc3QgbWVzc2FnZS5cbiAgICogLSBJbiBXYWl0TXNnMjogcnVucyByb3VuZDIsIGNvbXBsZXRlcyBES0csIHJldHVybnMgW10uXG4gICAqXG4gICAqIFRoZSBjYWxsZXIgcGFzc2VzIGFsbCBuIG1lc3NhZ2VzIChpbmNsdWRpbmcgb3duKTsgb3duIG1lc3NhZ2UgaXMgZmlsdGVyZWRcbiAgICogb3V0IGludGVybmFsbHkuIE90aGVyIHBhcnRpZXMnIG1lc3NhZ2VzIGFyZSBzb3J0ZWQgYnkgYXNjZW5kaW5nIHBhcnR5IGluZGV4LFxuICAgKiBtYXRjaGluZyB0aGUgb3JkZXJpbmcgZXhwZWN0ZWQgYnkgQGJpdGdvL3dhc20tbXBzLlxuICAgKlxuICAgKiBAcGFyYW0gbWVzc2FnZXNGb3JJdGhSb3VuZCAtIEFsbCBuIG1lc3NhZ2VzIGZvciB0aGlzIHJvdW5kIChpbmNsdWRpbmcgb3duKS5cbiAgICovXG4gIGhhbmRsZUluY29taW5nTWVzc2FnZXMobWVzc2FnZXNGb3JJdGhSb3VuZDogRGVzZXJpYWxpemVkTWVzc2FnZXMpOiBEZXNlcmlhbGl6ZWRNZXNzYWdlcyB7XG4gICAgaWYgKHRoaXMuZGtnU3RhdGUgPT09IFJlZFBhbGxhc0RrZ1N0YXRlLkNvbXBsZXRlKSB7XG4gICAgICB0aHJvdyBFcnJvcignREtHIHNlc3Npb24gYWxyZWFkeSBjb21wbGV0ZWQnKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZGtnU3RhdGUgPT09IFJlZFBhbGxhc0RrZ1N0YXRlLlVuaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRocm93IEVycm9yKCdES0cgc2Vzc2lvbiBub3QgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZGtnU3RhdGUgPT09IFJlZFBhbGxhc0RrZ1N0YXRlLkluaXQpIHtcbiAgICAgIHRocm93IEVycm9yKFxuICAgICAgICAnREtHIHNlc3Npb24gbXVzdCBjYWxsIGdldEZpcnN0TWVzc2FnZSgpIGJlZm9yZSBoYW5kbGluZyBpbmNvbWluZyBtZXNzYWdlcy4gQ2FsbCBnZXRGaXJzdE1lc3NhZ2UoKSBmaXJzdC4nXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAobWVzc2FnZXNGb3JJdGhSb3VuZC5sZW5ndGggIT09IHRoaXMubikge1xuICAgICAgdGhyb3cgRXJyb3IoJ0ludmFsaWQgbnVtYmVyIG9mIG1lc3NhZ2VzIGZvciB0aGUgcm91bmQuIE51bWJlciBvZiBtZXNzYWdlcyBzaG91bGQgYmUgZXF1YWwgdG8gTicpO1xuICAgIH1cblxuICAgIC8vIEV4dHJhY3Qgb3RoZXIgcGFydGllcycgbWVzc2FnZXMsIHNvcnRlZCBieSBwYXJ0eSBpbmRleCAoYXNjZW5kaW5nKVxuICAgIGNvbnN0IG90aGVyTXNncyA9IG1lc3NhZ2VzRm9ySXRoUm91bmRcbiAgICAgIC5maWx0ZXIoKG0pID0+IG0uZnJvbSAhPT0gdGhpcy5wYXJ0eUlkeClcbiAgICAgIC5zb3J0KChhLCBiKSA9PiBhLmZyb20gLSBiLmZyb20pXG4gICAgICAubWFwKChtKSA9PiBtLnBheWxvYWQpO1xuXG4gICAgY29uc3Qgd2FzbSA9IHRoaXMuZ2V0V2FzbU1wcygpO1xuXG4gICAgaWYgKHRoaXMuZGtnU3RhdGUgPT09IFJlZFBhbGxhc0RrZ1N0YXRlLldhaXRNc2cxKSB7XG4gICAgICBsZXQgcmVzdWx0OiBNc2dTdGF0ZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlc3VsdCA9IHdhc20ucmVkcGFsbGFzX2RrZ19yb3VuZDFfcHJvY2VzcyhvdGhlck1zZ3MsIHRoaXMuZGtnU3RhdGVCeXRlcyEpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hpbGUgY3JlYXRpbmcgbWVzc2FnZXMgZnJvbSBwYXJ0eSAke3RoaXMucGFydHlJZHh9LCByb3VuZCAke3RoaXMuZGtnU3RhdGV9OiAke2Vycn1gKTtcbiAgICAgIH1cbiAgICAgIC8vIFN0b3JlIG5ldyBzdGF0ZTsgdGhpcyBpcyB3aGF0IHdvdWxkIGJlIHBlcnNpc3RlZCBiZXR3ZWVuIEFQSSByb3VuZHMgLyBtaWNyb1NEIGV4Y2hhbmdlc1xuICAgICAgdGhpcy5ka2dTdGF0ZUJ5dGVzID0gQnVmZmVyLmZyb20ocmVzdWx0LnN0YXRlKTtcbiAgICAgIHRoaXMuZGtnU3RhdGUgPSBSZWRQYWxsYXNEa2dTdGF0ZS5XYWl0TXNnMjtcbiAgICAgIHJldHVybiBbeyBwYXlsb2FkOiBuZXcgVWludDhBcnJheShyZXN1bHQubXNnKSwgZnJvbTogdGhpcy5wYXJ0eUlkeCB9XTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5ka2dTdGF0ZSA9PT0gUmVkUGFsbGFzRGtnU3RhdGUuV2FpdE1zZzIpIHtcbiAgICAgIGxldCByZXN1bHQ7XG4gICAgICB0cnkge1xuICAgICAgICByZXN1bHQgPSB3YXNtLnJlZHBhbGxhc19ka2dfcm91bmQyX3Byb2Nlc3Mob3RoZXJNc2dzLCB0aGlzLmRrZ1N0YXRlQnl0ZXMhKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoaWxlIGNyZWF0aW5nIG1lc3NhZ2VzIGZyb20gcGFydHkgJHt0aGlzLnBhcnR5SWR4fSwgcm91bmQgJHt0aGlzLmRrZ1N0YXRlfTogJHtlcnJ9YCk7XG4gICAgICB9XG4gICAgICB0aGlzLmtleVNoYXJlID0gQnVmZmVyLmZyb20ocmVzdWx0LnNoYXJlKTtcbiAgICAgIHRoaXMuc2hhcmVQayA9IEJ1ZmZlci5mcm9tKHJlc3VsdC5wayk7XG4gICAgICB0aGlzLmRrZ1N0YXRlQnl0ZXMgPSBudWxsO1xuICAgICAgdGhpcy5ka2dTdGF0ZSA9IFJlZFBhbGxhc0RrZ1N0YXRlLkNvbXBsZXRlO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHRocm93IEVycm9yKCdVbmV4cGVjdGVkIERLRyBzdGF0ZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG9wYXF1ZSBiaW5jb2RlLXNlcmlhbGlzZWQga2V5c2hhcmUgcHJvZHVjZWQgYnkgcm91bmQyLlxuICAgKiBUaGlzIGlzIHVzZWQgYXMgaW5wdXQgdG8gdGhlIChwbGF0Zm9ybS1zaWRlKSBzaWduaW5nIGFuZCBkZXJpdmF0aW9uIHByb3RvY29scy5cbiAgICovXG4gIGdldEtleVNoYXJlKCk6IEJ1ZmZlciB7XG4gICAgaWYgKCF0aGlzLmtleVNoYXJlKSB7XG4gICAgICB0aHJvdyBFcnJvcignREtHIHNlc3Npb24gbm90IGluaXRpYWxpemVkJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmtleVNoYXJlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFJlZFBhbGxhcyBwdWJsaWMga2V5ICh2ZXJpZmljYXRpb24ga2V5KSBhZ3JlZWQgYnkgYWxsIHBhcnRpZXMgZHVyaW5nIERLRy5cbiAgICovXG4gIGdldFNoYXJlUHVibGljS2V5KCk6IEJ1ZmZlciB7XG4gICAgaWYgKCF0aGlzLnNoYXJlUGspIHtcbiAgICAgIHRocm93IEVycm9yKCdES0cgc2Vzc2lvbiBub3QgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2hhcmVQaztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgQ0JPUi1lbmNvZGVkIFJlZHVjZWRLZXlTaGFyZSBidWZmZXIgY29udGFpbmluZyB0aGUgcGFydHkncyBvcGFxdWVcbiAgICogc2lnbmluZyBrZXkgc2hhcmUgaW4gdGhlIGBrZXlTaGFyZWAgZmllbGQuIFRoaXMgYnVmZmVyIGlzIHByaXZhdGUga2V5IG1hdGVyaWFsLlxuICAgKiBUaGUgY2FsbGVyIGVuY3J5cHRzIGl0IGFuZCBzdG9yZXMgaXQgYXMgYHJlZHVjZWRFbmNyeXB0ZWRQcnZgIG9uIHRoZSBrZXkgY2FyZCBRUiBjb2RlLlxuICAgKi9cbiAgZ2V0UmVkdWNlZEtleVNoYXJlKCk6IEJ1ZmZlciB7XG4gICAgaWYgKCF0aGlzLmtleVNoYXJlIHx8ICF0aGlzLnNoYXJlUGspIHtcbiAgICAgIHRocm93IEVycm9yKCdES0cgc2Vzc2lvbiBub3QgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG4gICAgY29uc3QgcmVkdWNlZEtleVNoYXJlOiBSZWRQYWxsYXNSZWR1Y2VkS2V5U2hhcmUgPSB7XG4gICAgICBrZXlTaGFyZTogQXJyYXkuZnJvbSh0aGlzLmtleVNoYXJlKSxcbiAgICAgIHB1YjogQXJyYXkuZnJvbSh0aGlzLnNoYXJlUGspLFxuICAgIH07XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGVuY29kZShyZWR1Y2VkS2V5U2hhcmUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBvcnRzIHRoZSBjdXJyZW50IHNlc3Npb24gc3RhdGUgYXMgYSBKU09OIHN0cmluZyBmb3IgcGVyc2lzdGVuY2UuXG4gICAqIEluY2x1ZGVzOiByb3VuZCBzdGF0ZSBieXRlcywgY3VycmVudCBES0cgcm91bmQsIGRlY3J5cHRpb24ga2V5LCBvdGhlciBwYXJ0aWVzJyBwdWIga2V5cy5cbiAgICogVGhpcyBtaXJyb3JzIHdoYXQgYSBzZXJ2ZXIgd291bGQgc3RvcmUgaW4gYSBkYXRhYmFzZSBiZXR3ZWVuIEFQSSByb3VuZHMuXG4gICAqL1xuICBnZXRTZXNzaW9uKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuZGtnU3RhdGUgPT09IFJlZFBhbGxhc0RrZ1N0YXRlLkNvbXBsZXRlKSB7XG4gICAgICB0aHJvdyBFcnJvcignREtHIHNlc3Npb24gaXMgY29tcGxldGUuIEV4cG9ydGluZyB0aGUgc2Vzc2lvbiBpcyBub3QgYWxsb3dlZC4nKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZGtnU3RhdGUgPT09IFJlZFBhbGxhc0RrZ1N0YXRlLlVuaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRocm93IEVycm9yKCdES0cgc2Vzc2lvbiBub3QgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIGRrZ1N0YXRlQnl0ZXM6IHRoaXMuZGtnU3RhdGVCeXRlcz8udG9TdHJpbmcoJ2Jhc2U2NCcpID8/IG51bGwsXG4gICAgICBka2dSb3VuZDogdGhpcy5ka2dTdGF0ZSxcbiAgICAgIGRlY3J5cHRpb25LZXk6IHRoaXMuZGVjcnlwdGlvbktleT8udG9TdHJpbmcoJ2Jhc2U2NCcpID8/IG51bGwsXG4gICAgICBvdGhlclB1YktleXM6IHRoaXMub3RoZXJQdWJLZXlzPy5tYXAoKGspID0+IGsudG9TdHJpbmcoJ2Jhc2U2NCcpKSA/PyBudWxsLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc3RvcmVzIGEgcHJldmlvdXNseSBleHBvcnRlZCBzZXNzaW9uLiBBbGxvd3MgdGhlIHByb3RvY29sIHRvIGNvbnRpbnVlXG4gICAqIGZyb20gd2hlcmUgaXQgbGVmdCBvZmYsIGFzIGlmIHRoZSByb3VuZCBzdGF0ZSB3YXMgbG9hZGVkIGZyb20gYSBkYXRhYmFzZS5cbiAgICovXG4gIHJlc3RvcmVTZXNzaW9uKHNlc3Npb246IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGRhdGEgPSBKU09OLnBhcnNlKHNlc3Npb24pO1xuICAgIHRoaXMuZGtnU3RhdGVCeXRlcyA9IGRhdGEuZGtnU3RhdGVCeXRlcyA/IEJ1ZmZlci5mcm9tKGRhdGEuZGtnU3RhdGVCeXRlcywgJ2Jhc2U2NCcpIDogbnVsbDtcbiAgICB0aGlzLmRrZ1N0YXRlID0gZGF0YS5ka2dSb3VuZDtcbiAgICB0aGlzLmRlY3J5cHRpb25LZXkgPSBkYXRhLmRlY3J5cHRpb25LZXkgPyBCdWZmZXIuZnJvbShkYXRhLmRlY3J5cHRpb25LZXksICdiYXNlNjQnKSA6IG51bGw7XG4gICAgdGhpcy5vdGhlclB1YktleXMgPSBkYXRhLm90aGVyUHViS2V5cyA/IChkYXRhLm90aGVyUHViS2V5cyBhcyBzdHJpbmdbXSkubWFwKChrKSA9PiBCdWZmZXIuZnJvbShrLCAnYmFzZTY0JykpIDogbnVsbDtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { DeserializedMessage, DeserializedMessages, RedPallasDsgState, RedPallasSignatureResult } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* RedPallas (Zcash Ironwood) Distributed Sign Generation (DSG) implementation using
|
|
4
|
+
* @bitgo/wasm-mps.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors the structure of the EdDSA MPS `DSG` class (see `../eddsa-mps/dsg.ts`), but wraps
|
|
7
|
+
* the `redpallas_dsg_*` WASM bindings. Unlike the EdDSA version:
|
|
8
|
+
*
|
|
9
|
+
* - `redpallas_dsg_round0_process` does not take a derivation path: RedPallas key derivation
|
|
10
|
+
* (ask/nk/rivk/ivks) happens upstream, as part of DKG (`redpallas_dkg_round2_process` +
|
|
11
|
+
* the platform-side-only `redpallas_derivation_process`); DSG only ever operates on an
|
|
12
|
+
* already-derived (or root) opaque `Keyshare`.
|
|
13
|
+
* - Round3 does not return a raw signature; it returns a `RedPallasSignature` bundle of
|
|
14
|
+
* `signature` (64 raw bytes), `rk` (the randomized verification key the signature
|
|
15
|
+
* verifies against — NOT the DKG public key) and `alpha` (the 32-byte randomizer scalar
|
|
16
|
+
* used to re-randomize the DKG public key into `rk`). See `RedPallasSignatureResult`.
|
|
17
|
+
*
|
|
18
|
+
* State is explicit: each WASM round function returns `{ msg, state }` bytes; the state
|
|
19
|
+
* bytes are stored between rounds and passed to the next round function (this is what a
|
|
20
|
+
* server would persist to a database between API rounds).
|
|
21
|
+
*
|
|
22
|
+
* The protocol is hard-coded 2-of-3: each signing party communicates with exactly one
|
|
23
|
+
* counterpart. `handleIncomingMessages` accepts both messages (own + counterpart), and
|
|
24
|
+
* filters own out internally.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const dsg = new RedPallasDSG(0); // partyIdx 0
|
|
29
|
+
* await dsg.initDsg(keyShare, message, 2); // counterpart is party 2
|
|
30
|
+
* const msg1 = dsg.getFirstMessage();
|
|
31
|
+
* const msg2 = dsg.handleIncomingMessages([msg1, peerMsg1]); // emits SignMsg2
|
|
32
|
+
* const msg3 = dsg.handleIncomingMessages([msg2[0], peerMsg2]); // emits SignMsg3
|
|
33
|
+
* dsg.handleIncomingMessages([msg3[0], peerMsg3]); // completes DSG
|
|
34
|
+
* const { signature, rk, alpha } = dsg.getSignature(); // 64-byte RedPallas signature + rk/alpha
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare class RedPallasDSG {
|
|
38
|
+
protected partyIdx: number;
|
|
39
|
+
protected otherPartyIdx: number | null;
|
|
40
|
+
/** Opaque bincode-serialised Keyshare from a prior DKG (already derived, if applicable) */
|
|
41
|
+
private keyShare;
|
|
42
|
+
/** Raw message bytes to sign */
|
|
43
|
+
private message;
|
|
44
|
+
/** Serialised round state bytes returned by the previous round function */
|
|
45
|
+
private dsgStateBytes;
|
|
46
|
+
/** Final signature bundle, available after WaitMsg3 -> Complete */
|
|
47
|
+
private signatureResult;
|
|
48
|
+
/** Lazily loaded WASM module */
|
|
49
|
+
private wasmMps;
|
|
50
|
+
protected dsgState: RedPallasDsgState;
|
|
51
|
+
constructor(partyIdx: number);
|
|
52
|
+
getState(): RedPallasDsgState;
|
|
53
|
+
getPartyIdx(): number;
|
|
54
|
+
getOtherPartyIdx(): number | null;
|
|
55
|
+
private loadWasmMps;
|
|
56
|
+
private getWasmMps;
|
|
57
|
+
/**
|
|
58
|
+
* Initialises the DSG session. The keyshare must come from a prior DKG run (and, if a
|
|
59
|
+
* derived key is being used, from the subsequent platform-side derivation process), and
|
|
60
|
+
* `otherPartyIdx` must be the single counterpart who will co-sign with this party.
|
|
61
|
+
*
|
|
62
|
+
* @param keyShare - Opaque bincode-serialised Keyshare bytes from `RedPallasDKG.getKeyShare()`.
|
|
63
|
+
* @param message - Raw message bytes to sign.
|
|
64
|
+
* @param otherPartyIdx - Party index of the single counterpart in this signing session.
|
|
65
|
+
* Must differ from this party's own `partyIdx` and be in `[0, 2]`.
|
|
66
|
+
*/
|
|
67
|
+
initDsg(keyShare: Buffer, message: Buffer, otherPartyIdx: number): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Runs round 0 of the DSG protocol. Returns this party's broadcast message
|
|
70
|
+
* (a `SignMsg1` containing the commitment to `R_i`). Stores the round state
|
|
71
|
+
* bytes internally for the next round.
|
|
72
|
+
*/
|
|
73
|
+
getFirstMessage(): DeserializedMessage;
|
|
74
|
+
/**
|
|
75
|
+
* Handles incoming messages for the current round and advances the protocol.
|
|
76
|
+
*
|
|
77
|
+
* - In `WaitMsg1`: runs round 1, returns this party's `SignMsg2` broadcast.
|
|
78
|
+
* - In `WaitMsg2`: runs round 2 (which internally fuses two Silence Labs transitions),
|
|
79
|
+
* returns this party's `SignMsg3` broadcast (partial signature).
|
|
80
|
+
* - In `WaitMsg3`: runs round 3, completes DSG, returns `[]`.
|
|
81
|
+
*
|
|
82
|
+
* The caller passes both messages (own + counterpart) for symmetry with
|
|
83
|
+
* `RedPallasDKG.handleIncomingMessages`. Own message is filtered out internally; only the
|
|
84
|
+
* counterpart's payload is forwarded to the WASM round function.
|
|
85
|
+
*
|
|
86
|
+
* @param messagesForIthRound - Both messages for this round (own + counterpart).
|
|
87
|
+
*/
|
|
88
|
+
handleIncomingMessages(messagesForIthRound: DeserializedMessages): DeserializedMessages;
|
|
89
|
+
/**
|
|
90
|
+
* Returns the final signature bundle produced by round 3: the 64-byte raw RedPallas
|
|
91
|
+
* signature, the randomized verification key `rk` it must be verified against (via
|
|
92
|
+
* `redpallas_verify(rk, signature, message)` — NOT the DKG public key), and the
|
|
93
|
+
* `alpha` randomizer scalar used to derive `rk` from the DKG public key.
|
|
94
|
+
*/
|
|
95
|
+
getSignature(): RedPallasSignatureResult;
|
|
96
|
+
/**
|
|
97
|
+
* Exports the current session state as a JSON string for persistence.
|
|
98
|
+
* Includes the opaque round state bytes plus everything needed to re-enter the
|
|
99
|
+
* protocol after a restart (keyshare, message, counterpart).
|
|
100
|
+
*/
|
|
101
|
+
getSession(): string;
|
|
102
|
+
/**
|
|
103
|
+
* Restores a previously exported session. Allows the protocol to continue from
|
|
104
|
+
* where it left off, as if the round state was loaded from a database.
|
|
105
|
+
*/
|
|
106
|
+
restoreSession(session: string): Promise<void>;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=dsg.d.ts.map
|