5
5
"encoding/binary"
6
6
"errors"
7
7
"fmt"
8
+ "sort"
8
9
9
10
"github.com/renproject/secp256k1"
10
11
)
@@ -73,13 +74,14 @@ func NewEmptyDKGState(n, t int) DKGState {
73
74
return DKGState {
74
75
Coefficients : coefficients ,
75
76
77
+ Step : 1 ,
76
78
Commitments : commitments ,
77
79
Shares : shares ,
78
80
}
79
81
}
80
82
81
83
func (state * DKGState ) Reset () {
82
- state .Coefficients = state . Coefficients [: 0 ]
84
+ state .Step = 1
83
85
84
86
for index := range state .Commitments {
85
87
delete (state .Commitments , index )
@@ -90,14 +92,8 @@ func (state *DKGState) Reset() {
90
92
}
91
93
}
92
94
93
- func DKGStart (state * DKGState , t int , ownIndex uint16 , context [32 ]byte ) DKGMessage {
94
- state .Step = 1
95
- for index := range state .Commitments {
96
- delete (state .Commitments , index )
97
- }
98
- for index := range state .Shares {
99
- delete (state .Shares , index )
100
- }
95
+ func DKGStart (state * DKGState , info * DKGCatchUpInfo , t int , ownIndex uint16 , context [32 ]byte ) DKGMessage {
96
+ state .Reset ()
101
97
102
98
coeffs := make ([]secp256k1.Fn , t )
103
99
for i := range coeffs {
@@ -110,6 +106,9 @@ func DKGStart(state *DKGState, t int, ownIndex uint16, context [32]byte) DKGMess
110
106
commitments [i ].BaseExp (& coeffs [i ])
111
107
}
112
108
109
+ // @Performance: In the future we might want to reuse the memory of
110
+ // state.Commitments between executions. This would require potential
111
+ // resizing to the call to Reset.
113
112
state .Commitments [ownIndex ] = commitments
114
113
115
114
var r secp256k1.Point
@@ -124,6 +123,16 @@ func DKGStart(state *DKGState, t int, ownIndex uint16, context [32]byte) DKGMess
124
123
125
124
proof := Proof {R : r , Mu : mu }
126
125
126
+ if info != nil {
127
+ info .Commitments = make ([]secp256k1.Point , t )
128
+ copy (info .Commitments , commitments )
129
+
130
+ info .Proof = proof
131
+
132
+ info .Coefficients = make ([]secp256k1.Fn , t )
133
+ copy (info .Coefficients , coeffs )
134
+ }
135
+
127
136
data := make ([]byte , ProofLenMarshalled + t * secp256k1 .PointSizeMarshalled )
128
137
proof .PutBytes (data [:ProofLenMarshalled ])
129
138
tail := data [ProofLenMarshalled :]
@@ -205,7 +214,7 @@ func DKGHandleShare(state *DKGState, ownIndex, from uint16, share secp256k1.Fn)
205
214
return nil
206
215
}
207
216
208
- func DKGHandleMessage (state * DKGState , ownIndex uint16 , indices []uint16 , t int , context [32 ]byte , message DKGMessage , from uint16 ) (bool , DKGOutput , []DKGMessageTo , error ) {
217
+ func DKGHandleMessage (state * DKGState , info * DKGCatchUpInfo , ownIndex uint16 , indices []uint16 , t int , context [32 ]byte , message DKGMessage , from uint16 ) (bool , DKGOutput , []DKGMessageTo , error ) {
209
218
n := len (indices )
210
219
211
220
switch message .Type {
@@ -244,7 +253,7 @@ func DKGHandleMessage(state *DKGState, ownIndex uint16, indices []uint16, t int,
244
253
}
245
254
246
255
if len (state .Commitments ) == n {
247
- return transitionToStep2 (state , ownIndex , indices )
256
+ return transitionToStep2 (state , info , ownIndex , indices )
248
257
} else {
249
258
return false , DKGOutput {}, nil , nil
250
259
}
@@ -272,7 +281,7 @@ func DKGHandleMessage(state *DKGState, ownIndex uint16, indices []uint16, t int,
272
281
}
273
282
}
274
283
275
- func DKGHandleTimeout (state * DKGState , ownIndex uint16 , indices []uint16 , t int ) (bool , DKGOutput , []DKGMessageTo , error ) {
284
+ func DKGHandleTimeout (state * DKGState , info * DKGCatchUpInfo , ownIndex uint16 , indices []uint16 , t int ) (bool , DKGOutput , []DKGMessageTo , error ) {
276
285
if state .Step != 1 {
277
286
return false , DKGOutput {}, nil , nil
278
287
}
@@ -281,10 +290,10 @@ func DKGHandleTimeout(state *DKGState, ownIndex uint16, indices []uint16, t int)
281
290
return false , DKGOutput {}, nil , fmt .Errorf ("timeout before obtaining sufficient commitments: needed at least %v, got %v" , t , len (state .Commitments ))
282
291
}
283
292
284
- return transitionToStep2 (state , ownIndex , indices )
293
+ return transitionToStep2 (state , info , ownIndex , indices )
285
294
}
286
295
287
- func transitionToStep2 (state * DKGState , ownIndex uint16 , indices []uint16 ) (bool , DKGOutput , []DKGMessageTo , error ) {
296
+ func transitionToStep2 (state * DKGState , info * DKGCatchUpInfo , ownIndex uint16 , indices []uint16 ) (bool , DKGOutput , []DKGMessageTo , error ) {
288
297
shareMessages := make ([]DKGMessageTo , 0 , len (state .Commitments )- 1 )
289
298
for index := range state .Commitments {
290
299
if index == ownIndex {
@@ -311,6 +320,15 @@ func transitionToStep2(state *DKGState, ownIndex uint16, indices []uint16) (bool
311
320
return true , computeOutputs (state , indices , ownIndex ), nil , nil
312
321
}
313
322
323
+ if info != nil {
324
+ info .IndexSubset = make ([]uint16 , 0 , len (state .Commitments ))
325
+ for index := range state .Commitments {
326
+ info .IndexSubset = append (info .IndexSubset , index )
327
+ }
328
+
329
+ sort .Slice (info .IndexSubset , func (i , j int ) bool { return info .IndexSubset [i ] < info .IndexSubset [j ] })
330
+ }
331
+
314
332
return false , DKGOutput {}, shareMessages , nil
315
333
}
316
334
@@ -388,3 +406,97 @@ func computeOutputs(state *DKGState, indices []uint16, ownIndex uint16) DKGOutpu
388
406
389
407
return DKGOutput {Share : share , PubKey : pubKey , PubKeyShares : pubKeyShares }
390
408
}
409
+
410
+ type DKGCatchUpInfo struct {
411
+ Commitments []secp256k1.Point
412
+ Proof
413
+ Coefficients []secp256k1.Fn
414
+ IndexSubset []uint16
415
+ }
416
+
417
+ func commitmentsMsgLen (t int ) int {
418
+ return 1 + t * secp256k1 .PointSizeMarshalled + ProofLenMarshalled
419
+ }
420
+
421
+ func shareMsgLen () int {
422
+ return 1 + secp256k1 .FnSizeMarshalled
423
+ }
424
+
425
+ func (info * DKGCatchUpInfo ) SerialisedMessage (index uint16 ) []byte {
426
+ t := len (info .Coefficients )
427
+
428
+ l := commitmentsMsgLen (t ) + shareMsgLen () + len (info .IndexSubset )* 2
429
+ bs := make ([]byte , l )
430
+ rem := bs
431
+
432
+ rem [0 ] = DKGTypeContribution
433
+ rem = rem [1 :]
434
+
435
+ info .Proof .PutBytes (rem )
436
+ rem = rem [ProofLenMarshalled :]
437
+
438
+ for i := range info .Commitments {
439
+ info .Commitments [i ].PutBytes (rem )
440
+ rem = rem [secp256k1 .PointSizeMarshalled :]
441
+ }
442
+
443
+ rem [0 ] = DKGTypeShare
444
+ rem = rem [1 :]
445
+ share := computeShare (index , info .Coefficients )
446
+ share .PutB32 (rem )
447
+ rem = rem [secp256k1 .FnSizeMarshalled :]
448
+
449
+ for i := range info .IndexSubset {
450
+ binary .LittleEndian .PutUint16 (rem , info .IndexSubset [i ])
451
+ rem = rem [2 :]
452
+ }
453
+
454
+ return bs
455
+ }
456
+
457
+ type DKGCatchUpMessage struct {
458
+ IndexSubset []uint16
459
+ CommitmentsMsg DKGMessage
460
+ ShareMsg DKGMessage
461
+ }
462
+
463
+ func DKGDeserialiseCatchUpMessage (bs []byte , n , t int ) (DKGCatchUpMessage , error ) {
464
+ commitmentsMsgLen := commitmentsMsgLen (t )
465
+ shareMsgLen := shareMsgLen ()
466
+
467
+ minLen := commitmentsMsgLen + shareMsgLen + t * 2
468
+ maxLen := commitmentsMsgLen + shareMsgLen + n * 2
469
+
470
+ if len (bs ) < minLen {
471
+ return DKGCatchUpMessage {}, fmt .Errorf ("serialised message too short: expected at least %v bytes, got %v" , minLen , len (bs ))
472
+ }
473
+
474
+ if len (bs ) > maxLen {
475
+ return DKGCatchUpMessage {}, fmt .Errorf ("serialised message too long: expected at most %v bytes, got %v" , maxLen , len (bs ))
476
+ }
477
+
478
+ commitmentsMsg := DKGMessage {
479
+ Type : bs [0 ],
480
+ Data : bs [1 :commitmentsMsgLen ],
481
+ }
482
+ bs = bs [commitmentsMsgLen :]
483
+
484
+ shareMsg := DKGMessage {
485
+ Type : bs [0 ],
486
+ Data : bs [1 :shareMsgLen ],
487
+ }
488
+ bs = bs [shareMsgLen :]
489
+
490
+ numIndices := len (bs ) / 2
491
+ indexSubset := make ([]uint16 , numIndices )
492
+ for i := range indexSubset {
493
+ indexSubset [i ] = binary .LittleEndian .Uint16 (bs )
494
+ bs = bs [2 :]
495
+ }
496
+
497
+ return DKGCatchUpMessage {
498
+ IndexSubset : indexSubset ,
499
+ CommitmentsMsg : commitmentsMsg ,
500
+ ShareMsg : shareMsg ,
501
+ }, nil
502
+ }
0 commit comments