@agentaos/engine 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +199 -0
- package/README.md +44 -0
- package/dist/cggmp24/cggmp24.scheme.d.ts +116 -0
- package/dist/cggmp24/cggmp24.scheme.d.ts.map +1 -0
- package/dist/cggmp24/cggmp24.scheme.js +543 -0
- package/dist/cggmp24/cggmp24.scheme.js.map +1 -0
- package/dist/cggmp24/user-server-sign.integration.test.d.ts +15 -0
- package/dist/cggmp24/user-server-sign.integration.test.d.ts.map +1 -0
- package/dist/cggmp24/user-server-sign.integration.test.js +229 -0
- package/dist/cggmp24/user-server-sign.integration.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to the Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by the Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding any notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. Please also get an
|
|
185
|
+
OpenPGP-compatible signature on the file.
|
|
186
|
+
|
|
187
|
+
Copyright 2025-2026 Aristokrates OÜ
|
|
188
|
+
|
|
189
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
190
|
+
you may not use this file except in compliance with the License.
|
|
191
|
+
You may obtain a copy of the License at
|
|
192
|
+
|
|
193
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
194
|
+
|
|
195
|
+
Unless required by applicable law or agreed to in writing, software
|
|
196
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
197
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
198
|
+
See the License for the specific language governing permissions and
|
|
199
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @agentaos/engine
|
|
2
|
+
|
|
3
|
+
**CGGMP24 threshold ECDSA signing scheme for AgentaOS.**
|
|
4
|
+
|
|
5
|
+
[](../../LICENSE)
|
|
6
|
+
[](https://www.npmjs.com/package/@agentaos/engine)
|
|
7
|
+
|
|
8
|
+
Implements the `IThresholdScheme` interface from `@agentaos/core` using CGGMP24 (Canetti-Gennaro-Goldfeder-Makriyannis-Peled 2024) threshold ECDSA over secp256k1. Wraps a Rust WASM module for the cryptographic operations.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @agentaos/engine
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { CGGMP24Scheme, SchemeRegistry } from '@agentaos/engine';
|
|
20
|
+
|
|
21
|
+
// Direct usage
|
|
22
|
+
const scheme = new CGGMP24Scheme();
|
|
23
|
+
|
|
24
|
+
// Or via registry
|
|
25
|
+
const scheme = SchemeRegistry.get('cggmp24');
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This package is used internally by `@agentaos/sdk` and `@agentaos/server`. Most users should use the higher-level `Agenta` facade from the signer package instead.
|
|
29
|
+
|
|
30
|
+
## What It Does
|
|
31
|
+
|
|
32
|
+
- **DKG (Distributed Key Generation)** -- 3-party key generation ceremony producing 3 shares
|
|
33
|
+
- **Threshold Signing** -- 2-of-3 interactive signing protocol (3 rounds)
|
|
34
|
+
- **Aux Info Generation** -- Pre-computation for efficient signing
|
|
35
|
+
- **Address Derivation** -- secp256k1 public key to Ethereum address
|
|
36
|
+
|
|
37
|
+
## Dependencies
|
|
38
|
+
|
|
39
|
+
- `@agentaos/core` -- interfaces and types
|
|
40
|
+
- `@agentaos/crypto` -- Rust WASM binary (CGGMP24 implementation)
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
Apache-2.0 -- see [LICENSE](../../LICENSE).
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CGGMP24 threshold ECDSA scheme backed by the @agentaos/crypto Rust WASM module.
|
|
3
|
+
*
|
|
4
|
+
* - Two-phase DKG: auxInfoGen (Paillier primes) + keygen (shares) — run as single WASM call
|
|
5
|
+
* - Signing requires messageHash upfront
|
|
6
|
+
* - Protocol produces signature when complete (no separate finalize step)
|
|
7
|
+
* - Key material is split: CoreKeyShare + AuxInfo
|
|
8
|
+
* - State machine API: safe to serialize between rounds
|
|
9
|
+
*
|
|
10
|
+
* THE FULL PRIVATE KEY NEVER EXISTS — signing is a distributed computation.
|
|
11
|
+
*/
|
|
12
|
+
import type { AuxInfoRoundResult, DKGRoundResult, IThresholdScheme } from '@agentaos/core';
|
|
13
|
+
import type { CurveName } from '@agentaos/core';
|
|
14
|
+
import type { SchemeName } from '@agentaos/core';
|
|
15
|
+
/** Typed DKG result returned by runDkg() */
|
|
16
|
+
export interface DkgResult {
|
|
17
|
+
shares: Array<{
|
|
18
|
+
coreShare: Uint8Array;
|
|
19
|
+
auxInfo: Uint8Array;
|
|
20
|
+
}>;
|
|
21
|
+
publicKey: Uint8Array;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* CGGMP24 threshold ECDSA scheme.
|
|
25
|
+
*
|
|
26
|
+
* Wraps the @agentaos/crypto Rust WASM module for all cryptographic
|
|
27
|
+
* operations. When the native GMP binary is available, signing is routed
|
|
28
|
+
* through it for ~10x faster Paillier operations. Falls back to WASM
|
|
29
|
+
* automatically (browser, or when binary is not built).
|
|
30
|
+
*
|
|
31
|
+
* Key material format:
|
|
32
|
+
* - coreShare = serialised CoreKeyShare (from keygen)
|
|
33
|
+
* - auxInfo = serialised AuxInfo (from aux_info_gen)
|
|
34
|
+
*
|
|
35
|
+
* Both are JSON-serialised by the WASM module and can be stored/loaded
|
|
36
|
+
* as opaque Uint8Array blobs.
|
|
37
|
+
*/
|
|
38
|
+
export declare class CGGMP24Scheme implements IThresholdScheme {
|
|
39
|
+
readonly name: SchemeName;
|
|
40
|
+
readonly curve: CurveName;
|
|
41
|
+
private readonly signSessions;
|
|
42
|
+
/** undefined = not checked yet, string = path, null = not available */
|
|
43
|
+
private _nativeBinPath;
|
|
44
|
+
/** Check if the native GMP signing binary is available (async for ESM compat). */
|
|
45
|
+
private nativeBinaryAvailable;
|
|
46
|
+
private cleanupExpiredSessions;
|
|
47
|
+
/**
|
|
48
|
+
* Run a DKG ceremony via native binary:
|
|
49
|
+
*
|
|
50
|
+
* 1. **Pool AuxInfo** → keygen only → **~1s** (Phase A pre-computed by AuxInfo pool)
|
|
51
|
+
* 2. **Cold start** → full DKG → **~180s** (everything computed inline)
|
|
52
|
+
*/
|
|
53
|
+
runDkg(n?: number, threshold?: number, options?: {
|
|
54
|
+
cachedAuxInfo?: string;
|
|
55
|
+
}): Promise<DkgResult>;
|
|
56
|
+
/** Resolve path to the native DKG binary. */
|
|
57
|
+
private resolveNativeBinaryPath;
|
|
58
|
+
private runNativeDkg;
|
|
59
|
+
/**
|
|
60
|
+
* Initialize the WASM module for signing operations.
|
|
61
|
+
* DKG uses the native binary, but signing still needs WASM.
|
|
62
|
+
* Call this on server startup.
|
|
63
|
+
*/
|
|
64
|
+
initWasm(): Promise<void>;
|
|
65
|
+
auxInfoGen(_sessionId: string, _round: number, _incoming: Uint8Array[]): Promise<AuxInfoRoundResult>;
|
|
66
|
+
dkg(_sessionId: string, _round: number, _incoming: Uint8Array[]): Promise<DKGRoundResult>;
|
|
67
|
+
deriveAddress(publicKey: Uint8Array): string;
|
|
68
|
+
/** Extract public key from serialised key share via WASM. */
|
|
69
|
+
extractPublicKey(keyShareBytes: Uint8Array): Uint8Array;
|
|
70
|
+
createSignSession(keyMaterialBytes: Uint8Array[], messageHash: Uint8Array, options?: {
|
|
71
|
+
partyIndex?: number;
|
|
72
|
+
partiesAtKeygen?: number[];
|
|
73
|
+
eid?: Uint8Array;
|
|
74
|
+
/** Force WASM backend (skip native GMP). Required when the other
|
|
75
|
+
* signing party also uses WASM (e.g. browser User+Server path)
|
|
76
|
+
* to avoid cross-backend protocol incompatibilities. */
|
|
77
|
+
forceWasm?: boolean;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
sessionId: string;
|
|
80
|
+
firstMessages: Uint8Array[];
|
|
81
|
+
}>;
|
|
82
|
+
processSignRound(sessionId: string, incomingMessages: Uint8Array[]): Promise<{
|
|
83
|
+
outgoingMessages: Uint8Array[];
|
|
84
|
+
complete: boolean;
|
|
85
|
+
}>;
|
|
86
|
+
finalizeSign(sessionId: string): Promise<{
|
|
87
|
+
r: Uint8Array;
|
|
88
|
+
s: Uint8Array;
|
|
89
|
+
v: number;
|
|
90
|
+
}>;
|
|
91
|
+
createPresignSession(_keyMaterialBytes: Uint8Array[]): {
|
|
92
|
+
sessionId: string;
|
|
93
|
+
firstMessages: Uint8Array[];
|
|
94
|
+
};
|
|
95
|
+
processPresignRound(_sessionId: string, _incomingMessages: Uint8Array[]): {
|
|
96
|
+
outgoingMessages: Uint8Array[];
|
|
97
|
+
complete: boolean;
|
|
98
|
+
};
|
|
99
|
+
extractPresignature(_sessionId: string): {
|
|
100
|
+
presignature: Uint8Array;
|
|
101
|
+
commitment: Uint8Array;
|
|
102
|
+
};
|
|
103
|
+
issuePartialSignature(_presignature: Uint8Array, _messageHash: Uint8Array): Uint8Array;
|
|
104
|
+
combinePartialSignatures(_partials: Uint8Array[], _commitment: Uint8Array, _messageHash: Uint8Array): {
|
|
105
|
+
r: Uint8Array;
|
|
106
|
+
s: Uint8Array;
|
|
107
|
+
v: number;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Compute the Ethereum signature recovery ID (v = 27 or 28).
|
|
111
|
+
* Tries both recovery bits and matches the recovered public key
|
|
112
|
+
* against the expected DKG public key.
|
|
113
|
+
*/
|
|
114
|
+
private computeRecoveryId;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=cggmp24.scheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cggmp24.scheme.d.ts","sourceRoot":"","sources":["../../src/cggmp24/cggmp24.scheme.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CGGMP24 threshold ECDSA scheme backed by the @agentaos/crypto Rust WASM module.
|
|
3
|
+
*
|
|
4
|
+
* - Two-phase DKG: auxInfoGen (Paillier primes) + keygen (shares) — run as single WASM call
|
|
5
|
+
* - Signing requires messageHash upfront
|
|
6
|
+
* - Protocol produces signature when complete (no separate finalize step)
|
|
7
|
+
* - Key material is split: CoreKeyShare + AuxInfo
|
|
8
|
+
* - State machine API: safe to serialize between rounds
|
|
9
|
+
*
|
|
10
|
+
* THE FULL PRIVATE KEY NEVER EXISTS — signing is a distributed computation.
|
|
11
|
+
*/
|
|
12
|
+
import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
13
|
+
import { getAddress, keccak256, toHex } from 'viem';
|
|
14
|
+
// Node.js-only imports — lazily loaded so the browser can use signing methods
|
|
15
|
+
// without pulling in node:child_process or node:fs.
|
|
16
|
+
// @vite-ignore comments prevent Vite/Rollup from bundling these for the browser.
|
|
17
|
+
let _execFile;
|
|
18
|
+
async function getExecFile() {
|
|
19
|
+
if (!_execFile) {
|
|
20
|
+
const mod = await import(/* @vite-ignore */ 'node:child_process');
|
|
21
|
+
_execFile = mod.execFile;
|
|
22
|
+
}
|
|
23
|
+
return _execFile;
|
|
24
|
+
}
|
|
25
|
+
let _spawn;
|
|
26
|
+
async function getSpawn() {
|
|
27
|
+
if (!_spawn) {
|
|
28
|
+
const mod = await import(/* @vite-ignore */ 'node:child_process');
|
|
29
|
+
_spawn = mod.spawn;
|
|
30
|
+
}
|
|
31
|
+
return _spawn;
|
|
32
|
+
}
|
|
33
|
+
let _createReadlineInterface;
|
|
34
|
+
async function getReadlineInterface() {
|
|
35
|
+
if (!_createReadlineInterface) {
|
|
36
|
+
const mod = await import(/* @vite-ignore */ 'node:readline');
|
|
37
|
+
_createReadlineInterface = mod.createInterface;
|
|
38
|
+
}
|
|
39
|
+
return _createReadlineInterface;
|
|
40
|
+
}
|
|
41
|
+
let _existsSync;
|
|
42
|
+
async function getExistsSyncAsync() {
|
|
43
|
+
if (_existsSync !== undefined)
|
|
44
|
+
return _existsSync;
|
|
45
|
+
try {
|
|
46
|
+
const fs = await import(/* @vite-ignore */ 'node:fs');
|
|
47
|
+
_existsSync = fs.existsSync;
|
|
48
|
+
return _existsSync;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Synchronous version for non-async contexts — only works if already loaded
|
|
55
|
+
function getExistsSync() {
|
|
56
|
+
return _existsSync ?? null;
|
|
57
|
+
}
|
|
58
|
+
let wasmModule = null;
|
|
59
|
+
async function getWasm() {
|
|
60
|
+
if (wasmModule)
|
|
61
|
+
return wasmModule;
|
|
62
|
+
const mod = await import('@agentaos/crypto');
|
|
63
|
+
// The web build (pkg-web) exports a default init function that must be
|
|
64
|
+
// called to fetch + instantiate the .wasm file. The Node.js build (pkg)
|
|
65
|
+
// auto-initializes via readFileSync, so its default export is undefined.
|
|
66
|
+
if (typeof mod.default === 'function') {
|
|
67
|
+
await mod.default();
|
|
68
|
+
}
|
|
69
|
+
wasmModule = mod;
|
|
70
|
+
return wasmModule;
|
|
71
|
+
}
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Helpers
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
function generateEid() {
|
|
76
|
+
const eid = new Uint8Array(32);
|
|
77
|
+
crypto.getRandomValues(eid);
|
|
78
|
+
return eid;
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Session state types (for interactive signing)
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
const SESSION_TTL_MS = 120_000;
|
|
84
|
+
/**
|
|
85
|
+
* Manages a single native GMP-accelerated signing session.
|
|
86
|
+
*
|
|
87
|
+
* One child process per session — communicates via line-delimited JSON
|
|
88
|
+
* on stdin/stdout. Wire-compatible with WASM (same WasmSignMessage format).
|
|
89
|
+
*/
|
|
90
|
+
class NativeSignProcess {
|
|
91
|
+
process;
|
|
92
|
+
lineIterator;
|
|
93
|
+
signature;
|
|
94
|
+
constructor(process, lineIterator) {
|
|
95
|
+
this.process = process;
|
|
96
|
+
this.lineIterator = lineIterator;
|
|
97
|
+
}
|
|
98
|
+
/** Read one JSON line from the child's stdout. */
|
|
99
|
+
async readLine() {
|
|
100
|
+
const { value, done } = await this.lineIterator.next();
|
|
101
|
+
if (done)
|
|
102
|
+
throw new Error('Native signing process ended unexpectedly');
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Spawn a native signing process and get first messages.
|
|
107
|
+
*
|
|
108
|
+
* @returns The process handle and first protocol messages.
|
|
109
|
+
*/
|
|
110
|
+
static async create(binaryPath, coreShare, auxInfo, messageHash, partyIndex, partiesAtKeygen, eid) {
|
|
111
|
+
const spawnFn = await getSpawn();
|
|
112
|
+
const createInterface = await getReadlineInterface();
|
|
113
|
+
const child = spawnFn(binaryPath, ['sign'], {
|
|
114
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
115
|
+
});
|
|
116
|
+
// Create async line iterator on stdout
|
|
117
|
+
const rl = createInterface({ input: child.stdout });
|
|
118
|
+
const lineIterator = rl[Symbol.asyncIterator]();
|
|
119
|
+
const nativeProcess = new NativeSignProcess(child, lineIterator);
|
|
120
|
+
// Build init payload
|
|
121
|
+
const b64Encode = (bytes) => Buffer.from(bytes).toString('base64');
|
|
122
|
+
const hexEncode = (bytes) => Buffer.from(bytes).toString('hex');
|
|
123
|
+
const initPayload = JSON.stringify({
|
|
124
|
+
core_share: b64Encode(coreShare),
|
|
125
|
+
aux_info: b64Encode(auxInfo),
|
|
126
|
+
message_hash: hexEncode(messageHash),
|
|
127
|
+
party_index: partyIndex,
|
|
128
|
+
parties_at_keygen: partiesAtKeygen,
|
|
129
|
+
eid: hexEncode(eid),
|
|
130
|
+
});
|
|
131
|
+
// Write init line to stdin
|
|
132
|
+
child.stdin?.write(`${initPayload}\n`);
|
|
133
|
+
// Read first response
|
|
134
|
+
const responseLine = await nativeProcess.readLine();
|
|
135
|
+
const response = JSON.parse(responseLine);
|
|
136
|
+
return { nativeProcess, firstMessages: response.messages };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Process one round: send incoming messages, receive response.
|
|
140
|
+
*/
|
|
141
|
+
async processRound(incoming) {
|
|
142
|
+
// Write incoming messages to stdin
|
|
143
|
+
this.process.stdin?.write(`${JSON.stringify(incoming)}\n`);
|
|
144
|
+
// Read response
|
|
145
|
+
const line = await this.readLine();
|
|
146
|
+
const response = JSON.parse(line);
|
|
147
|
+
if (response.complete && response.r && response.s) {
|
|
148
|
+
this.signature = {
|
|
149
|
+
r: new Uint8Array(Buffer.from(response.r, 'hex')),
|
|
150
|
+
s: new Uint8Array(Buffer.from(response.s, 'hex')),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return { messages: response.messages, complete: response.complete };
|
|
154
|
+
}
|
|
155
|
+
/** Kill the child process. */
|
|
156
|
+
destroy() {
|
|
157
|
+
try {
|
|
158
|
+
this.process.kill();
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Best-effort cleanup
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// CGGMP24Scheme
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
/**
|
|
169
|
+
* CGGMP24 threshold ECDSA scheme.
|
|
170
|
+
*
|
|
171
|
+
* Wraps the @agentaos/crypto Rust WASM module for all cryptographic
|
|
172
|
+
* operations. When the native GMP binary is available, signing is routed
|
|
173
|
+
* through it for ~10x faster Paillier operations. Falls back to WASM
|
|
174
|
+
* automatically (browser, or when binary is not built).
|
|
175
|
+
*
|
|
176
|
+
* Key material format:
|
|
177
|
+
* - coreShare = serialised CoreKeyShare (from keygen)
|
|
178
|
+
* - auxInfo = serialised AuxInfo (from aux_info_gen)
|
|
179
|
+
*
|
|
180
|
+
* Both are JSON-serialised by the WASM module and can be stored/loaded
|
|
181
|
+
* as opaque Uint8Array blobs.
|
|
182
|
+
*/
|
|
183
|
+
export class CGGMP24Scheme {
|
|
184
|
+
name = 'cggmp24';
|
|
185
|
+
curve = 'secp256k1';
|
|
186
|
+
signSessions = new Map();
|
|
187
|
+
/** undefined = not checked yet, string = path, null = not available */
|
|
188
|
+
_nativeBinPath = undefined;
|
|
189
|
+
/** Check if the native GMP signing binary is available (async for ESM compat). */
|
|
190
|
+
async nativeBinaryAvailable() {
|
|
191
|
+
if (this._nativeBinPath === undefined) {
|
|
192
|
+
const existsSyncFn = await getExistsSyncAsync();
|
|
193
|
+
if (!existsSyncFn) {
|
|
194
|
+
// Browser environment — no fs access
|
|
195
|
+
this._nativeBinPath = null;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
try {
|
|
199
|
+
const { dirname, join, resolve } = await import(/* @vite-ignore */ 'node:path');
|
|
200
|
+
const { fileURLToPath } = await import(/* @vite-ignore */ 'node:url');
|
|
201
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
202
|
+
let found = false;
|
|
203
|
+
for (const candidate of [
|
|
204
|
+
resolve(thisDir, '..', '..', '..', 'mpc-wasm'),
|
|
205
|
+
resolve(thisDir, '..', '..', '..', '..', 'mpc-wasm'),
|
|
206
|
+
resolve(thisDir, '..', '..', '..', '..', 'packages', 'mpc-wasm'),
|
|
207
|
+
]) {
|
|
208
|
+
const binPath = join(candidate, 'native-gen', 'target', 'release', 'agenta-gen-primes');
|
|
209
|
+
if (existsSyncFn(binPath)) {
|
|
210
|
+
this._nativeBinPath = binPath;
|
|
211
|
+
found = true;
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (!found) {
|
|
216
|
+
this._nativeBinPath = null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
this._nativeBinPath = null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return this._nativeBinPath !== null;
|
|
225
|
+
}
|
|
226
|
+
// ---- Session cleanup ----
|
|
227
|
+
cleanupExpiredSessions() {
|
|
228
|
+
const now = Date.now();
|
|
229
|
+
for (const [id, state] of this.signSessions) {
|
|
230
|
+
if (now - state.createdAt > SESSION_TTL_MS) {
|
|
231
|
+
// Destroy the backend session
|
|
232
|
+
if (state.nativeProcess) {
|
|
233
|
+
state.nativeProcess.destroy();
|
|
234
|
+
}
|
|
235
|
+
else if (wasmModule && state.wasmSessionId) {
|
|
236
|
+
try {
|
|
237
|
+
wasmModule.sign_destroy_session(state.wasmSessionId);
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
// Best-effort cleanup
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
this.signSessions.delete(id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// ---- Full DKG (native binary — GMP accelerated) ----
|
|
248
|
+
/**
|
|
249
|
+
* Run a DKG ceremony via native binary:
|
|
250
|
+
*
|
|
251
|
+
* 1. **Pool AuxInfo** → keygen only → **~1s** (Phase A pre-computed by AuxInfo pool)
|
|
252
|
+
* 2. **Cold start** → full DKG → **~180s** (everything computed inline)
|
|
253
|
+
*/
|
|
254
|
+
async runDkg(n = 3, threshold = 2, options) {
|
|
255
|
+
const execFileFn = await getExecFile();
|
|
256
|
+
const nativeBinary = await this.resolveNativeBinaryPath();
|
|
257
|
+
if (!nativeBinary) {
|
|
258
|
+
throw new Error('Native DKG binary not found — cannot run DKG');
|
|
259
|
+
}
|
|
260
|
+
const eidBytes = new Uint8Array(32);
|
|
261
|
+
crypto.getRandomValues(eidBytes);
|
|
262
|
+
const eidHex = Buffer.from(eidBytes).toString('hex');
|
|
263
|
+
// Fast path: externally supplied AuxInfo (from server pool)
|
|
264
|
+
if (options?.cachedAuxInfo) {
|
|
265
|
+
console.log('[DKG] Using pool AuxInfo — keygen only (~1s)');
|
|
266
|
+
return this.runNativeDkg(execFileFn, nativeBinary, 'dkg-with-aux', n, threshold, eidHex, options.cachedAuxInfo);
|
|
267
|
+
}
|
|
268
|
+
// Cold start — full DKG (~180s)
|
|
269
|
+
console.log('[DKG] No pool AuxInfo — cold start (generating primes + aux_info inline)');
|
|
270
|
+
return this.runNativeDkg(execFileFn, nativeBinary, 'dkg', n, threshold, eidHex, null);
|
|
271
|
+
}
|
|
272
|
+
/** Resolve path to the native DKG binary. */
|
|
273
|
+
async resolveNativeBinaryPath() {
|
|
274
|
+
const existsSyncFn = await getExistsSyncAsync();
|
|
275
|
+
if (!existsSyncFn)
|
|
276
|
+
return null;
|
|
277
|
+
try {
|
|
278
|
+
const { dirname, join, resolve } = await import(/* @vite-ignore */ 'node:path');
|
|
279
|
+
const { fileURLToPath } = await import(/* @vite-ignore */ 'node:url');
|
|
280
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
281
|
+
for (const candidate of [
|
|
282
|
+
resolve(thisDir, '..', '..', '..', 'mpc-wasm'),
|
|
283
|
+
resolve(thisDir, '..', '..', '..', '..', 'mpc-wasm'),
|
|
284
|
+
resolve(thisDir, '..', '..', '..', '..', 'packages', 'mpc-wasm'),
|
|
285
|
+
]) {
|
|
286
|
+
const binPath = join(candidate, 'native-gen', 'target', 'release', 'agenta-gen-primes');
|
|
287
|
+
if (existsSyncFn(binPath))
|
|
288
|
+
return binPath;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// No native binary available
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
async runNativeDkg(execFileFn, nativeBinary, mode, n, threshold, eidHex, stdinData) {
|
|
297
|
+
const result = await new Promise((resolve, reject) => {
|
|
298
|
+
const child = execFileFn(nativeBinary, [mode, String(n), String(threshold), eidHex], { maxBuffer: 50 * 1024 * 1024, timeout: 600_000 }, (err, stdout, stderr) => {
|
|
299
|
+
if (stderr) {
|
|
300
|
+
for (const line of stderr.split('\n').filter((l) => l.trim())) {
|
|
301
|
+
console.log(`[DKG-native] ${line}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (err) {
|
|
305
|
+
reject(new Error(`Native DKG failed: ${err.message}`));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
const parsed = JSON.parse(stdout.trim());
|
|
310
|
+
resolve(parsed);
|
|
311
|
+
}
|
|
312
|
+
catch (e) {
|
|
313
|
+
reject(new Error(`Failed to parse DKG output: ${String(e)}`));
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
if (stdinData && child.stdin) {
|
|
317
|
+
child.stdin.write(stdinData);
|
|
318
|
+
child.stdin.end();
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
const publicKey = new Uint8Array(Buffer.from(result.public_key, 'hex'));
|
|
322
|
+
return {
|
|
323
|
+
shares: result.shares.map((s) => ({
|
|
324
|
+
coreShare: new Uint8Array(Buffer.from(s.core_share, 'base64')),
|
|
325
|
+
auxInfo: new Uint8Array(Buffer.from(s.aux_info, 'base64')),
|
|
326
|
+
})),
|
|
327
|
+
publicKey,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Initialize the WASM module for signing operations.
|
|
332
|
+
* DKG uses the native binary, but signing still needs WASM.
|
|
333
|
+
* Call this on server startup.
|
|
334
|
+
*/
|
|
335
|
+
async initWasm() {
|
|
336
|
+
await getWasm();
|
|
337
|
+
}
|
|
338
|
+
// ---- IThresholdScheme: auxInfoGen / dkg (delegated to runDkg) ----
|
|
339
|
+
// These round-by-round methods exist for interface compliance.
|
|
340
|
+
// The DKG service should use runDkg() directly instead.
|
|
341
|
+
async auxInfoGen(_sessionId, _round, _incoming) {
|
|
342
|
+
throw new Error('auxInfoGen rounds are not used — call runDkg() for single-call DKG');
|
|
343
|
+
}
|
|
344
|
+
async dkg(_sessionId, _round, _incoming) {
|
|
345
|
+
throw new Error('dkg rounds are not used — call runDkg() for single-call DKG');
|
|
346
|
+
}
|
|
347
|
+
// ---- Address derivation ----
|
|
348
|
+
deriveAddress(publicKey) {
|
|
349
|
+
let uncompressedNoPrefix;
|
|
350
|
+
if (publicKey.length === 33) {
|
|
351
|
+
const point = secp256k1.Point.fromBytes(publicKey);
|
|
352
|
+
const uncompressed = point.toBytes(false); // 65 bytes: 0x04 + x + y
|
|
353
|
+
uncompressedNoPrefix = uncompressed.slice(1);
|
|
354
|
+
}
|
|
355
|
+
else if (publicKey.length === 65) {
|
|
356
|
+
uncompressedNoPrefix = publicKey.slice(1);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
throw new Error(`Invalid public key length: ${String(publicKey.length)}. Expected 33 or 65.`);
|
|
360
|
+
}
|
|
361
|
+
const hash = keccak256(toHex(uncompressedNoPrefix));
|
|
362
|
+
const addressHex = `0x${hash.slice(-40)}`;
|
|
363
|
+
return getAddress(addressHex);
|
|
364
|
+
}
|
|
365
|
+
/** Extract public key from serialised key share via WASM. */
|
|
366
|
+
extractPublicKey(keyShareBytes) {
|
|
367
|
+
// Synchronous — WASM module handles deserialization
|
|
368
|
+
// This will be called after WASM is loaded
|
|
369
|
+
if (!wasmModule) {
|
|
370
|
+
throw new Error('WASM module not yet loaded — call runDkg() first');
|
|
371
|
+
}
|
|
372
|
+
return new Uint8Array(wasmModule.extract_public_key(keyShareBytes));
|
|
373
|
+
}
|
|
374
|
+
// ---- Interactive signing (hash required upfront) ----
|
|
375
|
+
async createSignSession(keyMaterialBytes, messageHash, options) {
|
|
376
|
+
this.cleanupExpiredSessions();
|
|
377
|
+
if (keyMaterialBytes.length < 2) {
|
|
378
|
+
throw new Error(`Need [coreShare, auxInfo] — got ${String(keyMaterialBytes.length)} items`);
|
|
379
|
+
}
|
|
380
|
+
if (messageHash.length !== 32) {
|
|
381
|
+
throw new Error(`messageHash must be 32 bytes, got ${String(messageHash.length)}`);
|
|
382
|
+
}
|
|
383
|
+
// Safe: guarded by length check above
|
|
384
|
+
const coreShare = keyMaterialBytes[0];
|
|
385
|
+
const auxInfo = keyMaterialBytes[1];
|
|
386
|
+
const partyIndex = options?.partyIndex ?? 0;
|
|
387
|
+
const partiesAtKeygen = options?.partiesAtKeygen ?? [0, 1];
|
|
388
|
+
const eid = options?.eid ?? generateEid();
|
|
389
|
+
// Extract public key from the core share for recovery ID computation
|
|
390
|
+
let publicKey = new Uint8Array(33);
|
|
391
|
+
if (wasmModule) {
|
|
392
|
+
try {
|
|
393
|
+
publicKey = new Uint8Array(wasmModule.extract_public_key(coreShare));
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
// Will fail for recovery ID if not available
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// Try native GMP path (Node.js only — ~10x faster than WASM)
|
|
400
|
+
// Skip native when forceWasm is set (cross-backend protocol messages
|
|
401
|
+
// are incompatible between rug/GMP and num-bigint backends).
|
|
402
|
+
if (!options?.forceWasm && (await this.nativeBinaryAvailable())) {
|
|
403
|
+
const { nativeProcess, firstMessages: nativeMsgs } = await NativeSignProcess.create(this._nativeBinPath, coreShare, auxInfo, messageHash, partyIndex, partiesAtKeygen, eid);
|
|
404
|
+
const sessionId = crypto.randomUUID();
|
|
405
|
+
this.signSessions.set(sessionId, {
|
|
406
|
+
nativeProcess,
|
|
407
|
+
messageHash: new Uint8Array(messageHash),
|
|
408
|
+
publicKey,
|
|
409
|
+
complete: false,
|
|
410
|
+
createdAt: Date.now(),
|
|
411
|
+
});
|
|
412
|
+
// Serialize native messages to Uint8Array[] for the caller
|
|
413
|
+
const firstMessages = nativeMsgs.map((msg) => new TextEncoder().encode(JSON.stringify(msg)));
|
|
414
|
+
return { sessionId, firstMessages };
|
|
415
|
+
}
|
|
416
|
+
// WASM fallback
|
|
417
|
+
if (!wasmModule) {
|
|
418
|
+
throw new Error('WASM module not yet loaded — call runDkg() or ensure WASM is initialized first');
|
|
419
|
+
}
|
|
420
|
+
// Call WASM to create the signing state machine and get first messages
|
|
421
|
+
const wasmResult = wasmModule.sign_create_session(coreShare, auxInfo, messageHash, partyIndex, new Uint16Array(partiesAtKeygen), eid);
|
|
422
|
+
// Generate a TS-side session ID (maps to the WASM-side session)
|
|
423
|
+
const sessionId = crypto.randomUUID();
|
|
424
|
+
this.signSessions.set(sessionId, {
|
|
425
|
+
wasmSessionId: wasmResult.session_id,
|
|
426
|
+
messageHash: new Uint8Array(messageHash),
|
|
427
|
+
publicKey,
|
|
428
|
+
complete: false,
|
|
429
|
+
createdAt: Date.now(),
|
|
430
|
+
});
|
|
431
|
+
// Serialize WASM messages to Uint8Array[] for the caller
|
|
432
|
+
const firstMessages = wasmResult.messages.map((msg) => new TextEncoder().encode(JSON.stringify(msg)));
|
|
433
|
+
return { sessionId, firstMessages };
|
|
434
|
+
}
|
|
435
|
+
async processSignRound(sessionId, incomingMessages) {
|
|
436
|
+
const state = this.signSessions.get(sessionId);
|
|
437
|
+
if (!state) {
|
|
438
|
+
throw new Error(`No sign session found for id: ${sessionId}`);
|
|
439
|
+
}
|
|
440
|
+
// Deserialize incoming messages from Uint8Array[] to WasmSignMessage[]
|
|
441
|
+
const incoming = incomingMessages.map((bytes) => {
|
|
442
|
+
const json = new TextDecoder().decode(bytes);
|
|
443
|
+
return JSON.parse(json);
|
|
444
|
+
});
|
|
445
|
+
// Native GMP path
|
|
446
|
+
if (state.nativeProcess) {
|
|
447
|
+
const result = await state.nativeProcess.processRound(incoming);
|
|
448
|
+
if (result.complete && state.nativeProcess.signature) {
|
|
449
|
+
state.complete = true;
|
|
450
|
+
state.signature = state.nativeProcess.signature;
|
|
451
|
+
}
|
|
452
|
+
const outgoingMessages = result.messages.map((msg) => new TextEncoder().encode(JSON.stringify(msg)));
|
|
453
|
+
return { outgoingMessages, complete: result.complete };
|
|
454
|
+
}
|
|
455
|
+
// WASM fallback
|
|
456
|
+
if (!wasmModule) {
|
|
457
|
+
throw new Error('WASM module not yet loaded');
|
|
458
|
+
}
|
|
459
|
+
// Call WASM to process the round
|
|
460
|
+
const wasmResult = wasmModule.sign_process_round(state.wasmSessionId, incoming);
|
|
461
|
+
if (wasmResult.complete && wasmResult.signature) {
|
|
462
|
+
state.complete = true;
|
|
463
|
+
state.signature = {
|
|
464
|
+
r: new Uint8Array(wasmResult.signature.r),
|
|
465
|
+
s: new Uint8Array(wasmResult.signature.s),
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
// Serialize outgoing messages
|
|
469
|
+
const outgoingMessages = wasmResult.messages.map((msg) => new TextEncoder().encode(JSON.stringify(msg)));
|
|
470
|
+
return { outgoingMessages, complete: wasmResult.complete };
|
|
471
|
+
}
|
|
472
|
+
async finalizeSign(sessionId) {
|
|
473
|
+
const state = this.signSessions.get(sessionId);
|
|
474
|
+
if (!state) {
|
|
475
|
+
throw new Error(`No sign session found for id: ${sessionId}`);
|
|
476
|
+
}
|
|
477
|
+
if (!state.complete || !state.signature) {
|
|
478
|
+
throw new Error('Sign session not yet complete. Run all rounds first.');
|
|
479
|
+
}
|
|
480
|
+
try {
|
|
481
|
+
const { r, s } = state.signature;
|
|
482
|
+
const v = this.computeRecoveryId(r, s, state.messageHash, state.publicKey);
|
|
483
|
+
return { r, s, v };
|
|
484
|
+
}
|
|
485
|
+
finally {
|
|
486
|
+
// Destroy the backend session
|
|
487
|
+
if (state.nativeProcess) {
|
|
488
|
+
state.nativeProcess.destroy();
|
|
489
|
+
}
|
|
490
|
+
else if (wasmModule && state.wasmSessionId) {
|
|
491
|
+
try {
|
|
492
|
+
wasmModule.sign_destroy_session(state.wasmSessionId);
|
|
493
|
+
}
|
|
494
|
+
catch {
|
|
495
|
+
// Best-effort cleanup
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
this.signSessions.delete(sessionId);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
// ---- Presignature support (stubs — to be implemented) ----
|
|
502
|
+
createPresignSession(_keyMaterialBytes) {
|
|
503
|
+
throw new Error('Presignature support not yet implemented');
|
|
504
|
+
}
|
|
505
|
+
processPresignRound(_sessionId, _incomingMessages) {
|
|
506
|
+
throw new Error('Presignature support not yet implemented');
|
|
507
|
+
}
|
|
508
|
+
extractPresignature(_sessionId) {
|
|
509
|
+
throw new Error('Presignature support not yet implemented');
|
|
510
|
+
}
|
|
511
|
+
issuePartialSignature(_presignature, _messageHash) {
|
|
512
|
+
throw new Error('Presignature support not yet implemented');
|
|
513
|
+
}
|
|
514
|
+
combinePartialSignatures(_partials, _commitment, _messageHash) {
|
|
515
|
+
throw new Error('Presignature support not yet implemented');
|
|
516
|
+
}
|
|
517
|
+
// ---- Internal helpers ----
|
|
518
|
+
/**
|
|
519
|
+
* Compute the Ethereum signature recovery ID (v = 27 or 28).
|
|
520
|
+
* Tries both recovery bits and matches the recovered public key
|
|
521
|
+
* against the expected DKG public key.
|
|
522
|
+
*/
|
|
523
|
+
computeRecoveryId(r, s, messageHash, expectedPublicKey) {
|
|
524
|
+
const rBig = BigInt(`0x${Buffer.from(r).toString('hex')}`);
|
|
525
|
+
const sBig = BigInt(`0x${Buffer.from(s).toString('hex')}`);
|
|
526
|
+
const expectedHex = toHex(expectedPublicKey);
|
|
527
|
+
for (const recoveryBit of [0, 1]) {
|
|
528
|
+
try {
|
|
529
|
+
const sig = new secp256k1.Signature(rBig, sBig).addRecoveryBit(recoveryBit);
|
|
530
|
+
const recovered = sig.recoverPublicKey(messageHash);
|
|
531
|
+
const recoveredHex = toHex(recovered.toBytes(true));
|
|
532
|
+
if (recoveredHex === expectedHex) {
|
|
533
|
+
return recoveryBit + 27;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch {
|
|
537
|
+
// Try next recovery bit
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
throw new Error('Failed to compute recovery ID: neither v=27 nor v=28 recovers the expected public key');
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
//# sourceMappingURL=cggmp24.scheme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cggmp24.scheme.js","sourceRoot":"","sources":["../../src/cggmp24/cggmp24.scheme.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test: User+Server signing path (parties [1,2]).
|
|
3
|
+
*
|
|
4
|
+
* This test simulates the browser signing flow in Node.js to isolate
|
|
5
|
+
* whether the "signing protocol error: signing protocol failed" error
|
|
6
|
+
* comes from the WASM protocol itself or from the browser transport layer.
|
|
7
|
+
*
|
|
8
|
+
* Compares:
|
|
9
|
+
* - CLI path: Signer(0) + Server(1) — known working
|
|
10
|
+
* - Browser path: Server(1) + User(2) — currently failing in browser
|
|
11
|
+
*
|
|
12
|
+
* Requires: native binary (for DKG) + WASM module (for signing)
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=user-server-sign.integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-server-sign.integration.test.d.ts","sourceRoot":"","sources":["../../src/cggmp24/user-server-sign.integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test: User+Server signing path (parties [1,2]).
|
|
3
|
+
*
|
|
4
|
+
* This test simulates the browser signing flow in Node.js to isolate
|
|
5
|
+
* whether the "signing protocol error: signing protocol failed" error
|
|
6
|
+
* comes from the WASM protocol itself or from the browser transport layer.
|
|
7
|
+
*
|
|
8
|
+
* Compares:
|
|
9
|
+
* - CLI path: Signer(0) + Server(1) — known working
|
|
10
|
+
* - Browser path: Server(1) + User(2) — currently failing in browser
|
|
11
|
+
*
|
|
12
|
+
* Requires: native binary (for DKG) + WASM module (for signing)
|
|
13
|
+
*/
|
|
14
|
+
import { keccak256, toHex } from 'viem';
|
|
15
|
+
import { beforeAll, describe, expect, it } from 'vitest';
|
|
16
|
+
import { CGGMP24Scheme } from './cggmp24.scheme.js';
|
|
17
|
+
// Shared DKG result across all tests (DKG is expensive ~1-15s)
|
|
18
|
+
let dkgResult;
|
|
19
|
+
let scheme;
|
|
20
|
+
let hasNativeBinary = false;
|
|
21
|
+
describe('User+Server signing path (integration)', () => {
|
|
22
|
+
beforeAll(async () => {
|
|
23
|
+
scheme = new CGGMP24Scheme();
|
|
24
|
+
// Check if native binary is available (required for DKG)
|
|
25
|
+
const binaryPath = await scheme.resolveNativeBinaryPath?.();
|
|
26
|
+
if (!binaryPath) {
|
|
27
|
+
console.log('[TEST] Native DKG binary not found — skipping integration tests');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
hasNativeBinary = true;
|
|
31
|
+
// Initialize WASM for signing
|
|
32
|
+
await scheme.initWasm();
|
|
33
|
+
// Run DKG to get 3 shares: share[0]=signer, share[1]=server, share[2]=user
|
|
34
|
+
console.log('[TEST] Running DKG (3-of-2)...');
|
|
35
|
+
dkgResult = await scheme.runDkg(3, 2);
|
|
36
|
+
console.log(`[TEST] DKG complete. Address: ${scheme.deriveAddress(dkgResult.publicKey)}`);
|
|
37
|
+
console.log(`[TEST] Shares: ${dkgResult.shares.length}`);
|
|
38
|
+
}, 300_000); // 5 min timeout for cold-start DKG
|
|
39
|
+
it('CLI path: Signer(0) + Server(1) signs successfully', async () => {
|
|
40
|
+
if (!hasNativeBinary)
|
|
41
|
+
return; // skip — no native binary in CI
|
|
42
|
+
// This path works — use as baseline
|
|
43
|
+
const messageHash = makeMessageHash('hello from CLI');
|
|
44
|
+
const eid = randomEid();
|
|
45
|
+
const serverScheme = new CGGMP24Scheme();
|
|
46
|
+
await serverScheme.initWasm();
|
|
47
|
+
const clientScheme = new CGGMP24Scheme();
|
|
48
|
+
await clientScheme.initWasm();
|
|
49
|
+
// Create sessions — same as CLI ThresholdSigner + InteractiveSignService
|
|
50
|
+
const serverSession = await serverScheme.createSignSession([dkgResult.shares[1].coreShare, dkgResult.shares[1].auxInfo], messageHash, { partyIndex: 1, partiesAtKeygen: [0, 1], eid, forceWasm: true });
|
|
51
|
+
const clientSession = await clientScheme.createSignSession([dkgResult.shares[0].coreShare, dkgResult.shares[0].auxInfo], messageHash, { partyIndex: 0, partiesAtKeygen: [0, 1], eid, forceWasm: true });
|
|
52
|
+
console.log(`[CLI] Server first msgs: ${serverSession.firstMessages.length}`);
|
|
53
|
+
console.log(`[CLI] Client first msgs: ${clientSession.firstMessages.length}`);
|
|
54
|
+
// Exchange messages — simulate the round loop
|
|
55
|
+
const result = await exchangeRounds(serverScheme, serverSession.sessionId, serverSession.firstMessages, clientScheme, clientSession.sessionId, clientSession.firstMessages);
|
|
56
|
+
expect(result.serverComplete).toBe(true);
|
|
57
|
+
expect(result.clientComplete).toBe(true);
|
|
58
|
+
// Finalize both
|
|
59
|
+
const serverSig = await serverScheme.finalizeSign(serverSession.sessionId);
|
|
60
|
+
const clientSig = await clientScheme.finalizeSign(clientSession.sessionId);
|
|
61
|
+
console.log(`[CLI] Server sig: r=${toHex(serverSig.r).slice(0, 10)}... v=${serverSig.v}`);
|
|
62
|
+
console.log(`[CLI] Client sig: r=${toHex(clientSig.r).slice(0, 10)}... v=${clientSig.v}`);
|
|
63
|
+
// Both should produce the same signature
|
|
64
|
+
expect(toHex(serverSig.r)).toBe(toHex(clientSig.r));
|
|
65
|
+
expect(toHex(serverSig.s)).toBe(toHex(clientSig.s));
|
|
66
|
+
}, 120_000);
|
|
67
|
+
it('Browser path: Server(1) + User(2) signs successfully', async () => {
|
|
68
|
+
if (!hasNativeBinary)
|
|
69
|
+
return; // skip — no native binary in CI
|
|
70
|
+
// This is the path that fails in the browser
|
|
71
|
+
const messageHash = makeMessageHash('hello from browser');
|
|
72
|
+
const eid = randomEid();
|
|
73
|
+
const serverScheme = new CGGMP24Scheme();
|
|
74
|
+
await serverScheme.initWasm();
|
|
75
|
+
const browserScheme = new CGGMP24Scheme();
|
|
76
|
+
await browserScheme.initWasm();
|
|
77
|
+
// Create sessions — same as InteractiveSignService (USER_SERVER path)
|
|
78
|
+
// Server: party 1, Browser: party 2, partiesAtKeygen: [1, 2]
|
|
79
|
+
const serverSession = await serverScheme.createSignSession([dkgResult.shares[1].coreShare, dkgResult.shares[1].auxInfo], messageHash, { partyIndex: 1, partiesAtKeygen: [1, 2], eid, forceWasm: true });
|
|
80
|
+
const browserSession = await browserScheme.createSignSession([dkgResult.shares[2].coreShare, dkgResult.shares[2].auxInfo], messageHash, { partyIndex: 2, partiesAtKeygen: [1, 2], eid, forceWasm: true });
|
|
81
|
+
console.log(`[Browser] Server first msgs: ${serverSession.firstMessages.length}`);
|
|
82
|
+
console.log(`[Browser] Browser first msgs: ${browserSession.firstMessages.length}`);
|
|
83
|
+
// Exchange messages — simulate the round loop
|
|
84
|
+
const result = await exchangeRounds(serverScheme, serverSession.sessionId, serverSession.firstMessages, browserScheme, browserSession.sessionId, browserSession.firstMessages);
|
|
85
|
+
expect(result.serverComplete).toBe(true);
|
|
86
|
+
expect(result.clientComplete).toBe(true);
|
|
87
|
+
// Finalize both
|
|
88
|
+
const serverSig = await serverScheme.finalizeSign(serverSession.sessionId);
|
|
89
|
+
const browserSig = await browserScheme.finalizeSign(browserSession.sessionId);
|
|
90
|
+
console.log(`[Browser] Server sig: r=${toHex(serverSig.r).slice(0, 10)}... v=${serverSig.v}`);
|
|
91
|
+
console.log(`[Browser] Browser sig: r=${toHex(browserSig.r).slice(0, 10)}... v=${browserSig.v}`);
|
|
92
|
+
// Both should produce the same signature
|
|
93
|
+
expect(toHex(serverSig.r)).toBe(toHex(browserSig.r));
|
|
94
|
+
expect(toHex(serverSig.s)).toBe(toHex(browserSig.s));
|
|
95
|
+
}, 120_000);
|
|
96
|
+
it('Browser path with HTTP-style base64 serialization roundtrip', async () => {
|
|
97
|
+
if (!hasNativeBinary)
|
|
98
|
+
return; // skip — no native binary in CI
|
|
99
|
+
// Simulate the EXACT serialization path used by browser-signer.ts ↔ signing.controller.ts
|
|
100
|
+
const messageHash = makeMessageHash('hello with base64 roundtrip');
|
|
101
|
+
const eid = randomEid();
|
|
102
|
+
const serverScheme = new CGGMP24Scheme();
|
|
103
|
+
await serverScheme.initWasm();
|
|
104
|
+
const browserScheme = new CGGMP24Scheme();
|
|
105
|
+
await browserScheme.initWasm();
|
|
106
|
+
// Server creates session
|
|
107
|
+
const serverSession = await serverScheme.createSignSession([dkgResult.shares[1].coreShare, dkgResult.shares[1].auxInfo], messageHash, { partyIndex: 1, partiesAtKeygen: [1, 2], eid, forceWasm: true });
|
|
108
|
+
// Controller serializes firstMessages to base64 (as done in signing.controller.ts)
|
|
109
|
+
const serverFirstMessagesBase64 = serverSession.firstMessages.map(bytesToBase64);
|
|
110
|
+
// Browser receives base64, decodes, parses JSON to WasmSignMessage[]
|
|
111
|
+
const serverFirstParsed = serverFirstMessagesBase64.map((b64) => {
|
|
112
|
+
const bytes = base64ToBytes(b64);
|
|
113
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
114
|
+
});
|
|
115
|
+
// Browser creates its own session (same as browser-signer.ts)
|
|
116
|
+
const browserSession = await browserScheme.createSignSession([dkgResult.shares[2].coreShare, dkgResult.shares[2].auxInfo], messageHash, { partyIndex: 2, partiesAtKeygen: [1, 2], eid, forceWasm: true });
|
|
117
|
+
// Browser serializes its first messages to WasmSignMessage[]
|
|
118
|
+
const browserFirstParsed = browserSession.firstMessages.map((bytes) => JSON.parse(new TextDecoder().decode(bytes)));
|
|
119
|
+
// Browser processes server's first messages via WASM
|
|
120
|
+
// First re-serialize for processSignRound (expects Uint8Array[])
|
|
121
|
+
const serverFirstBytes = serverFirstParsed.map((msg) => new TextEncoder().encode(JSON.stringify(msg)));
|
|
122
|
+
const processResult = await browserScheme.processSignRound(browserSession.sessionId, serverFirstBytes);
|
|
123
|
+
console.log(`[B64] Browser processResult: complete=${processResult.complete} outgoing=${processResult.outgoingMessages.length}`);
|
|
124
|
+
// Combine browser first messages + processResult messages (as browser-signer.ts does)
|
|
125
|
+
const browserFirstBytes = browserFirstParsed.map((msg) => new TextEncoder().encode(JSON.stringify(msg)));
|
|
126
|
+
let outgoing = [...browserFirstBytes, ...processResult.outgoingMessages];
|
|
127
|
+
// Round loop (simulating browser-signer.ts round exchange)
|
|
128
|
+
const MAX_ROUNDS = 20;
|
|
129
|
+
let serverComplete = false;
|
|
130
|
+
let roundCount = 0;
|
|
131
|
+
while (!serverComplete) {
|
|
132
|
+
if (++roundCount > MAX_ROUNDS) {
|
|
133
|
+
throw new Error(`Protocol did not complete after ${MAX_ROUNDS} rounds`);
|
|
134
|
+
}
|
|
135
|
+
// Browser → base64 → Server (as browser-signer.ts + signing.controller.ts)
|
|
136
|
+
const outgoingBase64 = outgoing.map(bytesToBase64);
|
|
137
|
+
const incomingForServer = outgoingBase64.map(base64ToBytes);
|
|
138
|
+
// Server processes
|
|
139
|
+
const serverResult = await serverScheme.processSignRound(serverSession.sessionId, incomingForServer);
|
|
140
|
+
serverComplete = serverResult.complete;
|
|
141
|
+
console.log(`[B64] Round ${roundCount}: server complete=${serverComplete} outgoing=${serverResult.outgoingMessages.length}`);
|
|
142
|
+
if (serverResult.outgoingMessages.length > 0 && !serverComplete) {
|
|
143
|
+
// Server → base64 → Browser
|
|
144
|
+
const serverOutBase64 = serverResult.outgoingMessages.map(bytesToBase64);
|
|
145
|
+
const incomingForBrowser = serverOutBase64.map((b64) => new TextEncoder().encode(JSON.stringify(JSON.parse(new TextDecoder().decode(base64ToBytes(b64))))));
|
|
146
|
+
const browserResult = await browserScheme.processSignRound(browserSession.sessionId, incomingForBrowser);
|
|
147
|
+
outgoing = browserResult.outgoingMessages;
|
|
148
|
+
console.log(`[B64] Round ${roundCount}: browser complete=${browserResult.complete} outgoing=${browserResult.outgoingMessages.length}`);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
outgoing = [];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Finalize
|
|
155
|
+
const serverSig = await serverScheme.finalizeSign(serverSession.sessionId);
|
|
156
|
+
console.log(`[B64] Server sig: r=${toHex(serverSig.r).slice(0, 10)}... v=${serverSig.v}`);
|
|
157
|
+
expect(serverSig.v).toBeGreaterThanOrEqual(27);
|
|
158
|
+
expect(serverSig.v).toBeLessThanOrEqual(28);
|
|
159
|
+
expect(serverSig.r.length).toBe(32);
|
|
160
|
+
expect(serverSig.s.length).toBe(32);
|
|
161
|
+
}, 120_000);
|
|
162
|
+
});
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Helpers
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
function makeMessageHash(msg) {
|
|
167
|
+
const hex = keccak256(toHex(new TextEncoder().encode(msg)));
|
|
168
|
+
return new Uint8Array(Buffer.from(hex.slice(2), 'hex'));
|
|
169
|
+
}
|
|
170
|
+
function randomEid() {
|
|
171
|
+
const eid = new Uint8Array(32);
|
|
172
|
+
crypto.getRandomValues(eid);
|
|
173
|
+
return eid;
|
|
174
|
+
}
|
|
175
|
+
function bytesToBase64(bytes) {
|
|
176
|
+
return Buffer.from(bytes).toString('base64');
|
|
177
|
+
}
|
|
178
|
+
function base64ToBytes(b64) {
|
|
179
|
+
return new Uint8Array(Buffer.from(b64, 'base64'));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Exchange messages between two scheme instances until both complete.
|
|
183
|
+
* Simulates the round loop in both the CLI and browser paths.
|
|
184
|
+
*/
|
|
185
|
+
async function exchangeRounds(schemeA, sessionIdA, firstMessagesA, schemeB, sessionIdB, firstMessagesB) {
|
|
186
|
+
// Each side processes the other's first messages
|
|
187
|
+
const resultA = await schemeA.processSignRound(sessionIdA, firstMessagesB);
|
|
188
|
+
const resultB = await schemeB.processSignRound(sessionIdB, firstMessagesA);
|
|
189
|
+
let outgoingA = resultA.outgoingMessages;
|
|
190
|
+
let outgoingB = resultB.outgoingMessages;
|
|
191
|
+
let completeA = resultA.complete;
|
|
192
|
+
let completeB = resultB.complete;
|
|
193
|
+
console.log(` Round 0: A complete=${completeA} outA=${outgoingA.length} | B complete=${completeB} outB=${outgoingB.length}`);
|
|
194
|
+
const MAX_ROUNDS = 20;
|
|
195
|
+
let round = 0;
|
|
196
|
+
while (!completeA || !completeB) {
|
|
197
|
+
if (++round > MAX_ROUNDS) {
|
|
198
|
+
throw new Error(`Protocol did not complete after ${MAX_ROUNDS} rounds`);
|
|
199
|
+
}
|
|
200
|
+
// Save previous outgoing before processing (both sides process simultaneously)
|
|
201
|
+
const prevOutA = outgoingA;
|
|
202
|
+
const prevOutB = outgoingB;
|
|
203
|
+
// A processes B's previous messages
|
|
204
|
+
if (prevOutB.length > 0 && !completeA) {
|
|
205
|
+
const resA = await schemeA.processSignRound(sessionIdA, prevOutB);
|
|
206
|
+
outgoingA = resA.outgoingMessages;
|
|
207
|
+
completeA = resA.complete;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
outgoingA = [];
|
|
211
|
+
}
|
|
212
|
+
// B processes A's previous messages (not the new ones from this round!)
|
|
213
|
+
if (prevOutA.length > 0 && !completeB) {
|
|
214
|
+
const resB = await schemeB.processSignRound(sessionIdB, prevOutA);
|
|
215
|
+
outgoingB = resB.outgoingMessages;
|
|
216
|
+
completeB = resB.complete;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
outgoingB = [];
|
|
220
|
+
}
|
|
221
|
+
console.log(` Round ${round}: A complete=${completeA} outA=${outgoingA.length} | B complete=${completeB} outB=${outgoingB.length}`);
|
|
222
|
+
// Safety: if both have no outgoing and neither is complete, we're stuck
|
|
223
|
+
if (outgoingA.length === 0 && outgoingB.length === 0 && (!completeA || !completeB)) {
|
|
224
|
+
throw new Error(`Protocol stuck at round ${round}: A=${completeA} B=${completeB}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return { serverComplete: completeA, clientComplete: completeB, rounds: round };
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=user-server-sign.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-server-sign.integration.test.js","sourceRoot":"","sources":["../../src/cggmp24/user-server-sign.integration.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentaos/engine",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "CGGMP24 threshold ECDSA signing scheme (WASM)",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "AgentaOS <hello@agentaos.ai>",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/AgentaOS/agentaos.git",
|
|
10
|
+
"directory": "packages/schemes"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/AgentaOS/agentaos",
|
|
13
|
+
"bugs": "https://github.com/AgentaOS/agentaos/issues",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"threshold",
|
|
16
|
+
"wallet",
|
|
17
|
+
"mpc",
|
|
18
|
+
"ecdsa",
|
|
19
|
+
"cggmp24",
|
|
20
|
+
"wasm",
|
|
21
|
+
"signing"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=20.0.0"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@noble/curves": "^2.0.1",
|
|
43
|
+
"viem": "^2.21.0",
|
|
44
|
+
"@agentaos/core": "0.2.0",
|
|
45
|
+
"@agentaos/crypto": "0.2.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"lint": "biome check src/",
|
|
51
|
+
"test": "vitest run --passWithNoTests",
|
|
52
|
+
"typecheck": "tsc --noEmit",
|
|
53
|
+
"clean": "rm -rf dist"
|
|
54
|
+
}
|
|
55
|
+
}
|