@bitshard.io/bitshard-sdk 0.0.1
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/BitShardSDK.d.ts +156 -0
- package/dist/BitShardSDK.d.ts.map +1 -0
- package/dist/BitShardSDK.js +350 -0
- package/dist/BitShardSDK.js.map +1 -0
- package/dist/chains/bitcoin/BitcoinChain.d.ts +6 -0
- package/dist/chains/bitcoin/BitcoinChain.d.ts.map +1 -0
- package/dist/chains/bitcoin/BitcoinChain.js +10 -0
- package/dist/chains/bitcoin/BitcoinChain.js.map +1 -0
- package/dist/chains/config.d.ts +5 -0
- package/dist/chains/config.d.ts.map +1 -0
- package/dist/chains/config.js +7 -0
- package/dist/chains/config.js.map +1 -0
- package/dist/chains/evm/EVMChain.d.ts +6 -0
- package/dist/chains/evm/EVMChain.d.ts.map +1 -0
- package/dist/chains/evm/EVMChain.js +10 -0
- package/dist/chains/evm/EVMChain.js.map +1 -0
- package/dist/core/DKLSParty.d.ts +132 -0
- package/dist/core/DKLSParty.d.ts.map +1 -0
- package/dist/core/DKLSParty.js +267 -0
- package/dist/core/DKLSParty.js.map +1 -0
- package/dist/core/DKLSService.d.ts +83 -0
- package/dist/core/DKLSService.d.ts.map +1 -0
- package/dist/core/DKLSService.js +325 -0
- package/dist/core/DKLSService.js.map +1 -0
- package/dist/core/ThresholdConfig.d.ts +76 -0
- package/dist/core/ThresholdConfig.d.ts.map +1 -0
- package/dist/core/ThresholdConfig.js +127 -0
- package/dist/core/ThresholdConfig.js.map +1 -0
- package/dist/core/types.d.ts +238 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/crypto/addresses.d.ts +82 -0
- package/dist/crypto/addresses.d.ts.map +1 -0
- package/dist/crypto/addresses.js +242 -0
- package/dist/crypto/addresses.js.map +1 -0
- package/dist/crypto/elliptic.d.ts +19 -0
- package/dist/crypto/elliptic.d.ts.map +1 -0
- package/dist/crypto/elliptic.js +114 -0
- package/dist/crypto/elliptic.js.map +1 -0
- package/dist/crypto/encoding.d.ts +111 -0
- package/dist/crypto/encoding.d.ts.map +1 -0
- package/dist/crypto/encoding.js +224 -0
- package/dist/crypto/encoding.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/protocols/keygen.d.ts +6 -0
- package/dist/protocols/keygen.d.ts.map +1 -0
- package/dist/protocols/keygen.js +12 -0
- package/dist/protocols/keygen.js.map +1 -0
- package/dist/protocols/presignature.d.ts +68 -0
- package/dist/protocols/presignature.d.ts.map +1 -0
- package/dist/protocols/presignature.js +147 -0
- package/dist/protocols/presignature.js.map +1 -0
- package/dist/protocols/refresh.d.ts +5 -0
- package/dist/protocols/refresh.d.ts.map +1 -0
- package/dist/protocols/refresh.js +10 -0
- package/dist/protocols/refresh.js.map +1 -0
- package/dist/protocols/signing.d.ts +7 -0
- package/dist/protocols/signing.d.ts.map +1 -0
- package/dist/protocols/signing.js +12 -0
- package/dist/protocols/signing.js.map +1 -0
- package/dist/rpc/RPCProvider.d.ts +6 -0
- package/dist/rpc/RPCProvider.d.ts.map +1 -0
- package/dist/rpc/RPCProvider.js +6 -0
- package/dist/rpc/RPCProvider.js.map +1 -0
- package/dist/rpc/methods.d.ts +5 -0
- package/dist/rpc/methods.d.ts.map +1 -0
- package/dist/rpc/methods.js +10 -0
- package/dist/rpc/methods.js.map +1 -0
- package/dist/websocket/coordinator.d.ts +6 -0
- package/dist/websocket/coordinator.d.ts.map +1 -0
- package/dist/websocket/coordinator.js +10 -0
- package/dist/websocket/coordinator.js.map +1 -0
- package/dist/websocket/messages.d.ts +9 -0
- package/dist/websocket/messages.d.ts.map +1 -0
- package/dist/websocket/messages.js +7 -0
- package/dist/websocket/messages.js.map +1 -0
- package/dist/websocket/session.d.ts +5 -0
- package/dist/websocket/session.d.ts.map +1 -0
- package/dist/websocket/session.js +7 -0
- package/dist/websocket/session.js.map +1 -0
- package/dist/wire/format.d.ts +8 -0
- package/dist/wire/format.d.ts.map +1 -0
- package/dist/wire/format.js +11 -0
- package/dist/wire/format.js.map +1 -0
- package/dist/wire/validation.d.ts +6 -0
- package/dist/wire/validation.d.ts.map +1 -0
- package/dist/wire/validation.js +13 -0
- package/dist/wire/validation.js.map +1 -0
- package/package.json +67 -0
- package/src/BitShardSDK.ts +428 -0
- package/src/chains/bitcoin/BitcoinChain.ts +7 -0
- package/src/chains/config.ts +7 -0
- package/src/chains/evm/EVMChain.ts +7 -0
- package/src/core/DKLSParty.ts +317 -0
- package/src/core/DKLSService.ts +426 -0
- package/src/core/ThresholdConfig.ts +159 -0
- package/src/core/types.ts +253 -0
- package/src/crypto/addresses.ts +282 -0
- package/src/crypto/elliptic.ts +133 -0
- package/src/crypto/encoding.ts +227 -0
- package/src/index.ts +40 -0
- package/src/protocols/keygen.ts +8 -0
- package/src/protocols/presignature.ts +196 -0
- package/src/protocols/refresh.ts +7 -0
- package/src/protocols/signing.ts +9 -0
- package/src/rpc/RPCProvider.ts +7 -0
- package/src/rpc/methods.ts +7 -0
- package/src/websocket/coordinator.ts +7 -0
- package/src/websocket/messages.ts +11 -0
- package/src/websocket/session.ts +7 -0
- package/src/wire/format.ts +10 -0
- package/src/wire/validation.ts +14 -0
- package/test-sdk.js +234 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KeygenSession,
|
|
3
|
+
SignSession,
|
|
4
|
+
Keyshare
|
|
5
|
+
} from '@silencelaboratories/dkls-wasm-ll-node';
|
|
6
|
+
import type { PartyConfig, WireMessage } from './types';
|
|
7
|
+
import { ThresholdConfig } from './ThresholdConfig';
|
|
8
|
+
import { DKLSService } from './DKLSService';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents a single party in the MPC protocol
|
|
12
|
+
*/
|
|
13
|
+
export class DKLSParty {
|
|
14
|
+
private readonly config: PartyConfig;
|
|
15
|
+
private readonly thresholdConfig: ThresholdConfig;
|
|
16
|
+
private keygenSession?: KeygenSession;
|
|
17
|
+
private signSession?: SignSession;
|
|
18
|
+
private keyshare?: Keyshare;
|
|
19
|
+
private messageQueue: WireMessage[] = [];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a new DKLS party
|
|
23
|
+
* @param config Party configuration
|
|
24
|
+
*/
|
|
25
|
+
constructor(config: PartyConfig) {
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.thresholdConfig = new ThresholdConfig(
|
|
28
|
+
config.totalParties,
|
|
29
|
+
config.threshold,
|
|
30
|
+
Array.from({ length: config.totalParties }, (_, i) => i)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Validate party ID
|
|
34
|
+
if (!this.thresholdConfig.isValidParty(config.partyId)) {
|
|
35
|
+
throw new Error(`Invalid party ID: ${config.partyId}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get party ID
|
|
41
|
+
*/
|
|
42
|
+
get partyId(): number {
|
|
43
|
+
return this.config.partyId;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get party role
|
|
48
|
+
*/
|
|
49
|
+
get role(): string {
|
|
50
|
+
return this.config.role ?? 'signer';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if this party is the coordinator
|
|
55
|
+
*/
|
|
56
|
+
isCoordinator(): boolean {
|
|
57
|
+
return this.config.role === 'coordinator';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Initialize key generation session
|
|
62
|
+
*/
|
|
63
|
+
initializeKeygen(): void {
|
|
64
|
+
if (this.keygenSession) {
|
|
65
|
+
throw new Error('Keygen session already initialized');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.keygenSession = new KeygenSession(
|
|
69
|
+
this.config.totalParties,
|
|
70
|
+
this.config.threshold,
|
|
71
|
+
this.config.partyId
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Initialize key rotation session
|
|
77
|
+
* @param existingKeyshare Existing keyshare to rotate
|
|
78
|
+
*/
|
|
79
|
+
initializeKeyRotation(existingKeyshare: Keyshare): void {
|
|
80
|
+
if (this.keygenSession) {
|
|
81
|
+
throw new Error('Keygen session already initialized');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this.keygenSession = KeygenSession.initKeyRotation(existingKeyshare);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create first message for current protocol
|
|
89
|
+
* @returns Wire format message
|
|
90
|
+
*/
|
|
91
|
+
createFirstMessage(): WireMessage {
|
|
92
|
+
if (this.keygenSession) {
|
|
93
|
+
const msg = this.keygenSession.createFirstMessage();
|
|
94
|
+
return DKLSService.toWireMessage(msg);
|
|
95
|
+
} else if (this.signSession) {
|
|
96
|
+
const msg = this.signSession.createFirstMessage();
|
|
97
|
+
return DKLSService.toWireMessage(msg);
|
|
98
|
+
} else {
|
|
99
|
+
throw new Error('No active session');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Handle incoming messages
|
|
105
|
+
* @param messages Array of wire format messages
|
|
106
|
+
* @param commitments Optional commitments for keygen round 3
|
|
107
|
+
* @returns Array of response messages
|
|
108
|
+
*/
|
|
109
|
+
handleMessages(messages: WireMessage[], commitments?: any[]): WireMessage[] {
|
|
110
|
+
const dklsMessages = messages.map(m => DKLSService.fromWireMessage(m));
|
|
111
|
+
|
|
112
|
+
if (this.keygenSession) {
|
|
113
|
+
const responses = this.keygenSession.handleMessages(dklsMessages, commitments);
|
|
114
|
+
return responses.map(m => DKLSService.toWireMessage(m));
|
|
115
|
+
} else if (this.signSession) {
|
|
116
|
+
const responses = this.signSession.handleMessages(dklsMessages);
|
|
117
|
+
return responses.map(m => DKLSService.toWireMessage(m));
|
|
118
|
+
} else {
|
|
119
|
+
throw new Error('No active session');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Calculate chain code commitment (for keygen)
|
|
125
|
+
* @returns Commitment data
|
|
126
|
+
*/
|
|
127
|
+
calculateChainCodeCommitment(): any {
|
|
128
|
+
if (!this.keygenSession) {
|
|
129
|
+
throw new Error('No active keygen session');
|
|
130
|
+
}
|
|
131
|
+
return this.keygenSession.calculateChainCodeCommitment();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Finalize key generation and extract keyshare
|
|
136
|
+
* @returns The generated keyshare
|
|
137
|
+
*/
|
|
138
|
+
finalizeKeygen(): Keyshare {
|
|
139
|
+
if (!this.keygenSession) {
|
|
140
|
+
throw new Error('No active keygen session');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.keyshare = this.keygenSession.keyshare();
|
|
144
|
+
this.keygenSession = undefined; // Session is consumed
|
|
145
|
+
|
|
146
|
+
return this.keyshare;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Finalize key rotation
|
|
151
|
+
* @param oldKeyshare The old keyshare being rotated
|
|
152
|
+
*/
|
|
153
|
+
finalizeKeyRotation(oldKeyshare: Keyshare): void {
|
|
154
|
+
if (!this.keyshare) {
|
|
155
|
+
throw new Error('No new keyshare generated');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.keyshare.finishKeyRotation(oldKeyshare);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Initialize signing session
|
|
163
|
+
* @param keyshare Keyshare to use for signing
|
|
164
|
+
* @param derivationPath Derivation path (currently only "m" supported)
|
|
165
|
+
*/
|
|
166
|
+
initializeSigning(keyshare?: Keyshare, derivationPath: string = "m"): void {
|
|
167
|
+
if (this.signSession) {
|
|
168
|
+
throw new Error('Sign session already initialized');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const shareToUse = keyshare ?? this.keyshare;
|
|
172
|
+
if (!shareToUse) {
|
|
173
|
+
throw new Error('No keyshare available for signing');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// SignSession consumes the keyshare
|
|
177
|
+
this.signSession = new SignSession(shareToUse, derivationPath);
|
|
178
|
+
|
|
179
|
+
// Clear stored keyshare if it was consumed
|
|
180
|
+
if (!keyshare && this.keyshare) {
|
|
181
|
+
this.keyshare = undefined;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Generate last message with actual message hash
|
|
187
|
+
* @param messageHash The message hash to sign
|
|
188
|
+
* @returns Wire format message
|
|
189
|
+
*/
|
|
190
|
+
lastMessage(messageHash: Uint8Array): WireMessage {
|
|
191
|
+
if (!this.signSession) {
|
|
192
|
+
throw new Error('No active sign session');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const msg = this.signSession.lastMessage(messageHash);
|
|
196
|
+
return DKLSService.toWireMessage(msg);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Combine messages to produce final signature
|
|
201
|
+
* @param messages Final round messages
|
|
202
|
+
* @returns Signature components [r, s]
|
|
203
|
+
*/
|
|
204
|
+
combine(messages: WireMessage[]): [Uint8Array, Uint8Array] {
|
|
205
|
+
if (!this.signSession) {
|
|
206
|
+
throw new Error('No active sign session');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const dklsMessages = messages.map(m => DKLSService.fromWireMessage(m));
|
|
210
|
+
const signature = this.signSession.combine(dklsMessages);
|
|
211
|
+
|
|
212
|
+
// Session is consumed after combine
|
|
213
|
+
this.signSession = undefined;
|
|
214
|
+
|
|
215
|
+
// Ensure we have exactly 2 components
|
|
216
|
+
if (!Array.isArray(signature) || signature.length !== 2) {
|
|
217
|
+
throw new Error('Invalid signature format');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return [signature[0], signature[1]];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get stored keyshare
|
|
225
|
+
*/
|
|
226
|
+
getKeyshare(): Keyshare | undefined {
|
|
227
|
+
return this.keyshare;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Set keyshare (for restoring from storage)
|
|
232
|
+
* @param keyshare Keyshare to set
|
|
233
|
+
*/
|
|
234
|
+
setKeyshare(keyshare: Keyshare): void {
|
|
235
|
+
this.keyshare = keyshare;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Serialize keyshare to base64
|
|
240
|
+
* @returns Base64 encoded keyshare or undefined
|
|
241
|
+
*/
|
|
242
|
+
serializeKeyshare(): string | undefined {
|
|
243
|
+
if (!this.keyshare) {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const bytes = this.keyshare.toBytes();
|
|
248
|
+
return Buffer.from(bytes).toString('base64');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Restore keyshare from base64
|
|
253
|
+
* @param data Base64 encoded keyshare
|
|
254
|
+
*/
|
|
255
|
+
deserializeKeyshare(data: string): void {
|
|
256
|
+
const bytes = new Uint8Array(Buffer.from(data, 'base64'));
|
|
257
|
+
this.keyshare = Keyshare.fromBytes(bytes);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Add message to queue
|
|
262
|
+
* @param message Wire format message
|
|
263
|
+
*/
|
|
264
|
+
queueMessage(message: WireMessage): void {
|
|
265
|
+
this.messageQueue.push(message);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Get and clear message queue
|
|
270
|
+
* @returns Queued messages
|
|
271
|
+
*/
|
|
272
|
+
getQueuedMessages(): WireMessage[] {
|
|
273
|
+
const messages = [...this.messageQueue];
|
|
274
|
+
this.messageQueue = [];
|
|
275
|
+
return messages;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Get messages for this party from a list
|
|
280
|
+
* @param messages Array of messages
|
|
281
|
+
* @returns Messages intended for this party
|
|
282
|
+
*/
|
|
283
|
+
filterIncomingMessages(messages: WireMessage[]): WireMessage[] {
|
|
284
|
+
return messages.filter(m =>
|
|
285
|
+
m.to_id === undefined || // Broadcast message
|
|
286
|
+
m.to_id === this.partyId // P2P message for this party
|
|
287
|
+
).filter(m =>
|
|
288
|
+
m.from_id !== this.partyId // Exclude own messages
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Check if party has an active session
|
|
294
|
+
*/
|
|
295
|
+
hasActiveSession(): boolean {
|
|
296
|
+
return !!(this.keygenSession || this.signSession);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Get current session type
|
|
301
|
+
*/
|
|
302
|
+
getSessionType(): 'keygen' | 'signing' | 'none' {
|
|
303
|
+
if (this.keygenSession) return 'keygen';
|
|
304
|
+
if (this.signSession) return 'signing';
|
|
305
|
+
return 'none';
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Clear all sessions and state
|
|
310
|
+
*/
|
|
311
|
+
reset(): void {
|
|
312
|
+
this.keygenSession = undefined;
|
|
313
|
+
this.signSession = undefined;
|
|
314
|
+
this.messageQueue = [];
|
|
315
|
+
// Note: We don't clear keyshare as it might be needed later
|
|
316
|
+
}
|
|
317
|
+
}
|