Skip to content

Commit c863874

Browse files
authored
tECDSA DKG: Integration with the asynchronous state machine (#3392)
Here we integrate the tECDSA DKG protocol with the async state machine introduced by #3362. The presented changes are analogous to the recent changes introduced to the tECDSA signing protocol by #3379. Long story short, we no longer use a fixed block duration for protocol's states but move to a global timeout for the entire protocol attempt and switch states as soon as possible. As result, the time of a single DKG attempt can be reduced as the protocol is no longer fixed and can adjust to the slowest participant. The aforementioned change in the DKG protocol also involves a similar change in the DKG result publication step. The publication step is now based on the asynchronous state machine as well. This has two major consequences: - Firstly, so far, the participants were waiting for at least a group quorum of DKG result signatures for a fixed block duration and then moved to the result submission state. Now, all members wait for the actual group size of DKG result signatures and move to the result submission. This way, we are introducing an additional health check of group participants at the result publication step thus we maximize the final number of operating group members. This is based on the assumption that if DKG went to the publication step, all participants had to complete the computation step successfully, so they should be still operating for publication. - Secondly, the result submission queue is now time-based. Since the publication step relies on the async state machine, we can no longer use the block counter to set the submission eligibility queue. Each member preserves a time delay, according to its member index, before attempting to submit the DKG result Last but not least, we were forced to improve the message retransmission mechanism. As the DKG's TSS round two is computationally expensive, it takes ~100 blocks to complete their computations. The current retransmission strategy retransmits every message on every new block. On TSS round two, each member already retransmits messages from the ephemeral key generation state and from TSS round one. If the TSS round two state takes ~100 blocks, the amount of messages flying around the network is really huge and often caused network congestion. Also, the TSS round two state always takes almost all available CPU so, the situation became even worse. This resulted in a poor DKG success rate. To improve the situation and lower the number of messages passed through the network, we introduced a retransmission backoff strategy (#3396). All messages are now retransmitted at a decreasing rate so older messages are retransmitted less and less frequently. This allowed us to achieve a good success rate of the DKG protocol. Changes presented in this PR were tested on a local environment with three clients. Performed five DKGs and all were completed with success after ~18 minutes. That means we achieved an improvement as the DKG based on the sync machine always took ~26 minutes (fixed duration of 125 computation blocks and 5 publication blocks with an average block time of 12 seconds)
2 parents e75e83b + 45ed1f3 commit c863874

18 files changed

Lines changed: 683 additions & 1199 deletions

File tree

pkg/chain/ethereum/tbtc.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,11 @@ func (tc *TbtcChain) GetConfig() *tbtc.ChainConfig {
116116
groupSize := 100
117117
groupQuorum := 90
118118
honestThreshold := 51
119-
resultPublicationBlockStep := 1
120119

121120
return &tbtc.ChainConfig{
122-
GroupSize: groupSize,
123-
GroupQuorum: groupQuorum,
124-
HonestThreshold: honestThreshold,
125-
ResultPublicationBlockStep: uint64(resultPublicationBlockStep),
121+
GroupSize: groupSize,
122+
GroupQuorum: groupQuorum,
123+
HonestThreshold: honestThreshold,
126124
}
127125
}
128126

pkg/internal/interception/interception.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (c *channel) Name() string {
5959
func (c *channel) Send(
6060
ctx context.Context,
6161
m net.TaggedMarshaler,
62-
strategy ...net.RetransmissionStrategy,
62+
retransmissionStrategy ...net.RetransmissionStrategy,
6363
) error {
6464
altered := c.rules(m)
6565
if altered == nil {

pkg/net/libp2p/channel.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func (c *channel) Name() string {
9191
func (c *channel) Send(
9292
ctx context.Context,
9393
message net.TaggedMarshaler,
94-
strategy ...net.RetransmissionStrategy,
94+
retransmissionStrategy ...net.RetransmissionStrategy,
9595
) error {
9696
messageProto, err := c.messageProto(message)
9797
if err != nil {
@@ -104,20 +104,20 @@ func (c *channel) Send(
104104
return c.publish(messageProto)
105105
}
106106

107-
var selectedStrategy net.RetransmissionStrategy
108-
switch len(strategy) {
107+
var strategy net.RetransmissionStrategy
108+
switch len(retransmissionStrategy) {
109109
case 1:
110-
selectedStrategy = strategy[0]
110+
strategy = retransmissionStrategy[0]
111111
default:
112-
selectedStrategy = net.StandardRetransmissionStrategy
112+
strategy = net.StandardRetransmissionStrategy
113113
}
114114

115115
retransmission.ScheduleRetransmissions(
116116
ctx,
117117
logger,
118118
c.retransmissionTicker,
119119
doSend,
120-
retransmission.WithStrategy(selectedStrategy),
120+
retransmission.WithStrategy(strategy),
121121
)
122122

123123
return doSend()

pkg/net/local/broadcast_channel.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func (lc *localChannel) Name() string {
4343
func (lc *localChannel) Send(
4444
ctx context.Context,
4545
message net.TaggedMarshaler,
46-
strategy ...net.RetransmissionStrategy,
46+
retransmissionStrategy ...net.RetransmissionStrategy,
4747
) error {
4848
bytes, err := message.Marshal()
4949
if err != nil {
@@ -71,12 +71,12 @@ func (lc *localChannel) Send(
7171
lc.nextSeqno(),
7272
)
7373

74-
var selectedStrategy net.RetransmissionStrategy
75-
switch len(strategy) {
74+
var strategy net.RetransmissionStrategy
75+
switch len(retransmissionStrategy) {
7676
case 1:
77-
selectedStrategy = strategy[0]
77+
strategy = retransmissionStrategy[0]
7878
default:
79-
selectedStrategy = net.StandardRetransmissionStrategy
79+
strategy = net.StandardRetransmissionStrategy
8080
}
8181

8282
retransmission.ScheduleRetransmissions(
@@ -86,7 +86,7 @@ func (lc *localChannel) Send(
8686
func() error {
8787
return broadcastMessage(lc.name, netMessage)
8888
},
89-
retransmission.WithStrategy(selectedStrategy),
89+
retransmission.WithStrategy(strategy),
9090
)
9191

9292
return broadcastMessage(lc.name, netMessage)

pkg/net/net.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package net
22

33
import (
44
"context"
5+
56
"github.com/keep-network/keep-core/pkg/internal/pb"
67
"github.com/keep-network/keep-core/pkg/operator"
78
)
@@ -14,7 +15,7 @@ const (
1415
// that retransmit the message with a constant frequency.
1516
StandardRetransmissionStrategy RetransmissionStrategy = iota
1617
// BackoffRetransmissionStrategy is a retransmission strategy that
17-
// retransmit the message with an exponentially increasing delay between
18+
// retransmits the message with an exponentially increasing delay between
1819
// subsequent retransmissions.
1920
BackoffRetransmissionStrategy
2021
)
@@ -109,13 +110,13 @@ type BroadcastChannel interface {
109110
// conform to the marshalling interface. Message will be periodically
110111
// retransmitted by the channel for the lifetime of the provided context
111112
// according to the default StandardRetransmissionStrategy. Retransmission
112-
// strategy can be set through the `strategy` vararg. If the vararg is
113-
// given more than one value, the first value is used as the valid
114-
// strategy.
113+
// strategy can be set through the `retransmissionStrategy` vararg. If the
114+
// vararg is given more than one value, the first value is used as the
115+
// valid strategy.
115116
Send(
116117
ctx context.Context,
117118
message TaggedMarshaler,
118-
strategy ...RetransmissionStrategy,
119+
retransmissionStrategy ...RetransmissionStrategy,
119120
) error
120121
// Recv installs a message handler that will receive messages from the
121122
// channel for the entire lifetime of the provided context.

pkg/tbtc/chain.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,6 @@ type ChainConfig struct {
138138
// HonestThreshold is the minimum number of active participants behaving
139139
// according to the protocol needed to generate a signature.
140140
HonestThreshold int
141-
// ResultPublicationBlockStep is the duration (in blocks) that has to pass
142-
// between publication attempts made by individual members.
143-
ResultPublicationBlockStep uint64
144141
}
145142

146143
// DishonestThreshold is the maximum number of misbehaving participants for

pkg/tbtc/chain_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,10 @@ func ConnectWithKey(
226226
) *localChain {
227227
blockCounter, _ := local_v1.BlockCounter()
228228

229-
resultPublicationBlockStep := uint64(3)
230229
chainConfig := &ChainConfig{
231-
GroupSize: groupSize,
232-
GroupQuorum: groupQuorum,
233-
HonestThreshold: honestThreshold,
234-
ResultPublicationBlockStep: resultPublicationBlockStep,
230+
GroupSize: groupSize,
231+
GroupQuorum: groupQuorum,
232+
HonestThreshold: honestThreshold,
235233
}
236234

237235
return &localChain{

0 commit comments

Comments
 (0)