Skip to content

Commit 2d9bfc8

Browse files
authored
refactor: organize time-related consts (#60)
* Move stream constants * Move const WIP * Move const WIP [2] * unify usage of "signature received" * Streamline joinPartyMember * Streamline cleanupStaleNotifiers * Fix first tick * move sig notifier const * sig notifier ack deadline * tss keysign/keygen final timeout * Add comments * Fix test cases * Add comments
1 parent 14f84bf commit 2d9bfc8

File tree

13 files changed

+232
-161
lines changed

13 files changed

+232
-161
lines changed

config/const.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Package config contains the constants for the TSS library
2+
package config
3+
4+
import (
5+
"time"
6+
7+
"github.com/libp2p/go-libp2p"
8+
"github.com/libp2p/go-libp2p/core/protocol"
9+
resources "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
10+
)
11+
12+
const (
13+
// StreamTimeoutConnect allow this duration to connect to the peer
14+
StreamTimeoutConnect = 10 * time.Second
15+
16+
// StreamTimeoutRead allow this duration to read from the stream
17+
StreamTimeoutRead = 20 * time.Second
18+
19+
// StreamTimeoutWrite allow this duration to write to the stream
20+
StreamTimeoutWrite = 20 * time.Second
21+
22+
// StreamExcessTTL is the cleanup interval && TTL for "waste" streams (aka streams that are not used)
23+
StreamExcessTTL = 1 * time.Minute
24+
25+
// StreamMaxPayload is the max payload for a stream in bytes. 20MB
26+
StreamMaxPayload = 20 << 20
27+
)
28+
29+
// Signature Notifier related constants
30+
const (
31+
// SigNotifierAckTimeout is the duration to receive ACK back from the peer
32+
SigNotifierAckTimeout = 2 * time.Second
33+
34+
// SigNotifierTTL is the TTL for the notifier. Will be cleaned up if no response from the peer
35+
SigNotifierTTL = 30 * time.Second
36+
SigNotifierCleanupInterval = 15 * time.Second
37+
)
38+
39+
// TSSCommonFinalTimeout is the graceful timeout for keygen/keysign finalization
40+
const TSSCommonFinalTimeout = 5 * time.Second
41+
42+
// PartyJoinMemberRetryInterval retry interval for joining keygen/keysign party
43+
const PartyJoinMemberRetryInterval = 500 * time.Millisecond
44+
45+
// ScalingLimits creates a config for libp2p scaling limits
46+
func ScalingLimits(protocols ...protocol.ID) resources.ConcreteLimitConfig {
47+
limits := resources.DefaultLimits
48+
49+
base := resources.BaseLimit{
50+
Streams: 4096,
51+
StreamsInbound: 2048,
52+
StreamsOutbound: 2048,
53+
Memory: mb(512),
54+
}
55+
56+
increase := resources.BaseLimitIncrease{
57+
Streams: 512,
58+
StreamsInbound: 256,
59+
StreamsOutbound: 256,
60+
Memory: mb(64),
61+
}
62+
63+
limits.ProtocolBaseLimit = base
64+
limits.ProtocolLimitIncrease = increase
65+
66+
for _, protocol := range protocols {
67+
limits.AddProtocolLimit(protocol, base, increase)
68+
limits.AddProtocolPeerLimit(protocol, base, increase)
69+
}
70+
71+
// Add limits around included libp2p protocols
72+
libp2p.SetDefaultServiceLimits(&limits)
73+
74+
// Turn the scaling limits into a static set of limits using `.AutoScale`. This
75+
// scales the limits proportional to system's memory.
76+
return limits.AutoScale()
77+
}
78+
79+
// mb converts a number of megabytes to bytes
80+
func mb(n int64) int64 {
81+
return n << 20
82+
}

keygen/ecdsa/tss_keygen.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/zeta-chain/go-tss/blame"
1717
"github.com/zeta-chain/go-tss/common"
18+
"github.com/zeta-chain/go-tss/config"
1819
"github.com/zeta-chain/go-tss/conversion"
1920
"github.com/zeta-chain/go-tss/keygen"
2021
"github.com/zeta-chain/go-tss/logs"
@@ -151,7 +152,7 @@ func (kg *Keygen) GenerateNewKey(req keygen.Request) (*bcrypto.ECPoint, error) {
151152
}
152153

153154
select {
154-
case <-time.After(time.Second * 5):
155+
case <-time.After(config.TSSCommonFinalTimeout):
155156
close(kg.commStopChan)
156157
case <-kg.tssCommonStruct.GetTaskDone():
157158
close(kg.commStopChan)

keygen/eddsa/tss_keygen.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/zeta-chain/go-tss/blame"
1616
"github.com/zeta-chain/go-tss/common"
17+
"github.com/zeta-chain/go-tss/config"
1718
"github.com/zeta-chain/go-tss/conversion"
1819
"github.com/zeta-chain/go-tss/keygen"
1920
"github.com/zeta-chain/go-tss/logs"
@@ -142,9 +143,8 @@ func (kg *Keygen) GenerateNewKey(req keygen.Request) (*bcrypto.ECPoint, error) {
142143
}
143144

144145
select {
145-
case <-time.After(time.Second * 5):
146+
case <-time.After(config.TSSCommonFinalTimeout):
146147
close(kg.commStopChan)
147-
148148
case <-kg.tssCommonStruct.GetTaskDone():
149149
close(kg.commStopChan)
150150
}

keysign/ecdsa/tss_keysign.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/zeta-chain/go-tss/blame"
2222
"github.com/zeta-chain/go-tss/common"
23+
"github.com/zeta-chain/go-tss/config"
2324
"github.com/zeta-chain/go-tss/conversion"
2425
"github.com/zeta-chain/go-tss/logs"
2526
"github.com/zeta-chain/go-tss/messages"
@@ -207,7 +208,7 @@ func (tKeySign *TssKeySign) SignMessage(
207208
}
208209

209210
select {
210-
case <-time.After(time.Second * 5):
211+
case <-time.After(config.TSSCommonFinalTimeout):
211212
close(tKeySign.commStopChan)
212213
case <-tKeySign.tssCommonStruct.GetTaskDone():
213214
close(tKeySign.commStopChan)

keysign/eddsa/tss_keysign.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"github.com/zeta-chain/go-tss/blame"
2121
"github.com/zeta-chain/go-tss/common"
22+
"github.com/zeta-chain/go-tss/config"
2223
"github.com/zeta-chain/go-tss/conversion"
2324
"github.com/zeta-chain/go-tss/logs"
2425
"github.com/zeta-chain/go-tss/messages"
@@ -194,7 +195,7 @@ func (tKeySign *KeySign) SignMessage(
194195
}
195196

196197
select {
197-
case <-time.After(time.Second * 5):
198+
case <-time.After(config.TSSCommonFinalTimeout):
198199
close(tKeySign.commStopChan)
199200
case <-tKeySign.tssCommonStruct.GetTaskDone():
200201
close(tKeySign.commStopChan)

keysign/notifier.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import (
1313
"github.com/decred/dcrd/dcrec/edwards/v2"
1414
"github.com/pkg/errors"
1515
"github.com/tendermint/btcd/btcec"
16-
)
1716

18-
const defaultNotifierTTL = time.Second * 30
17+
"github.com/zeta-chain/go-tss/config"
18+
)
1919

2020
// notifier is design to receive keysign signature, success or failure
2121
type notifier struct {
@@ -48,7 +48,7 @@ func newNotifier(
4848
signatures: signatures,
4949
resp: make(chan []*common.SignatureData, 1),
5050
lastUpdated: time.Now(),
51-
ttl: defaultNotifierTTL,
51+
ttl: config.SigNotifierTTL,
5252
lock: sync.RWMutex{},
5353
}, nil
5454
}

keysign/signature_notifier.go

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/pkg/errors"
1414
"github.com/rs/zerolog"
1515

16+
"github.com/zeta-chain/go-tss/config"
1617
"github.com/zeta-chain/go-tss/logs"
1718
"github.com/zeta-chain/go-tss/messages"
1819
"github.com/zeta-chain/go-tss/p2p"
@@ -52,7 +53,7 @@ func NewSignatureNotifier(host host.Host, logger zerolog.Logger) *SignatureNotif
5253
host: host,
5354
notifierLock: &sync.Mutex{},
5455
notifiers: make(map[string]*notifier),
55-
streamMgr: p2p.NewStreamManager(logger),
56+
streamMgr: p2p.NewStreamManager(logger, config.StreamExcessTTL),
5657
logger: logger,
5758
}
5859

@@ -77,28 +78,37 @@ func (s *SignatureNotifier) Stop() {
7778
// for longer than notifierTTL. This was added because we allow broadcasts to create notifier objects
7879
// in handleStream, and need a way to cleanup notifiers that went unused
7980
func (s *SignatureNotifier) cleanupStaleNotifiers() {
80-
doCleanup := func() {
81+
cleanup := func() {
8182
s.notifierLock.Lock()
82-
for messageID, notifier := range s.notifiers {
83+
defer s.notifierLock.Unlock()
84+
85+
var deleted uint
86+
87+
for msgID, notifier := range s.notifiers {
8388
if time.Since(notifier.lastUpdated) > notifier.ttl {
84-
delete(s.notifiers, messageID)
89+
delete(s.notifiers, msgID)
90+
deleted++
8591
}
8692
}
87-
s.notifierLock.Unlock()
93+
94+
if deleted > 0 {
95+
s.logger.Info().Uint("deleted_notifiers", deleted).Msg("Cleaned stale notifiers")
96+
}
8897
}
89-
ticker := time.NewTicker(time.Second * 15)
98+
99+
ticker := time.NewTicker(config.SigNotifierCleanupInterval)
90100
defer ticker.Stop()
91101

92102
// quickly do an initial cleanup instead of waiting for the ticker. this aids
93103
// in testing so we don't have to wait for the ticker to fire
94-
doCleanup()
104+
cleanup()
95105

96106
for {
97107
select {
98108
case <-s.ctx.Done():
99109
return
100110
case <-ticker.C:
101-
doCleanup()
111+
cleanup()
102112
}
103113
}
104114
}
@@ -149,14 +159,14 @@ func (s *SignatureNotifier) handleStream(stream network.Stream) {
149159
signatures = append(signatures, &signature)
150160
}
151161

152-
_, err = s.createOrUpdateNotifier(msg.ID, nil, "", signatures, defaultNotifierTTL)
162+
_, err = s.createOrUpdateNotifier(msg.ID, nil, "", signatures, config.SigNotifierTTL)
153163
if err != nil {
154164
s.logger.Error().Err(err).Msg("fail to update notifier")
155165
}
156166
}
157167

158168
func (s *SignatureNotifier) sendOneMsgToPeer(m *signatureItem) error {
159-
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
169+
ctx, cancel := context.WithTimeout(context.Background(), config.StreamTimeoutConnect)
160170
defer cancel()
161171

162172
stream, err := s.host.NewStream(ctx, m.peerID, p2p.ProtocolSignatureNotifier)
@@ -198,8 +208,8 @@ func (s *SignatureNotifier) sendOneMsgToPeer(m *signatureItem) error {
198208
return errors.Wrapf(err, "fail to write KeysignSignature to stream")
199209
}
200210

201-
// we wait for 1 second to allow the receive notify us
202-
if err := stream.SetReadDeadline(time.Now().Add(time.Second * 1)); nil != err {
211+
// We allow this duration to receive ACK back from the peer
212+
if err := p2p.ApplyDeadline(stream, config.SigNotifierAckTimeout, true); err != nil {
203213
return errors.Wrapf(err, "fail to set read deadline to stream")
204214
}
205215

keysign/signature_notifier_test.go

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/rs/zerolog"
1616
"github.com/stretchr/testify/assert"
1717
"github.com/stretchr/testify/require"
18+
"github.com/zeta-chain/go-tss/config"
1819
"github.com/zeta-chain/go-tss/conversion"
1920

2021
"github.com/zeta-chain/go-tss/common"
@@ -94,58 +95,64 @@ func TestSignatureNotifierHappyPath(t *testing.T) {
9495
}
9596

9697
func TestSignatureNotifierBroadcastFirst(t *testing.T) {
97-
logger := zerolog.Nop()
98+
conversion.SetupBech32Prefix()
9899

99-
poolPubKey := `thorpub1addwnpepq0ul3xt882a6nm6m7uhxj4tk2n82zyu647dyevcs5yumuadn4uamqx7neak`
100+
logger := zerolog.New(zerolog.NewConsoleWriter(zerolog.ConsoleTestWriter(t)))
101+
102+
poolPubKey := "thorpub1addwnpepq0ul3xt882a6nm6m7uhxj4tk2n82zyu647dyevcs5yumuadn4uamqx7neak"
100103
messageToSign := "yhEwrxWuNBGnPT/L7PNnVWg7gFWNzCYTV+GuX3tKRH8="
104+
101105
buf, err := base64.StdEncoding.DecodeString(messageToSign)
102106
assert.NoError(t, err)
107+
103108
messageID, err := common.MsgToHashString(buf)
104109
assert.NoError(t, err)
110+
105111
id1 := tnet.RandIdentityOrFatal(t)
106112
id2 := tnet.RandIdentityOrFatal(t)
107113
id3 := tnet.RandIdentityOrFatal(t)
114+
108115
mn := mocknet.New()
109-
// add peers to mock net
110116

117+
// add peers to mock net
111118
a1 := tnet.RandLocalTCPAddress()
112119
a2 := tnet.RandLocalTCPAddress()
113120
a3 := tnet.RandLocalTCPAddress()
114121

115122
h1, err := mn.AddPeer(id1.PrivateKey(), a1)
116-
if err != nil {
117-
t.Fatal(err)
118-
}
119-
p1 := h1.ID()
123+
require.NoError(t, err)
124+
120125
h2, err := mn.AddPeer(id2.PrivateKey(), a2)
121-
if err != nil {
122-
t.Fatal(err)
123-
}
124-
p2 := h2.ID()
126+
require.NoError(t, err)
127+
125128
h3, err := mn.AddPeer(id3.PrivateKey(), a3)
126-
if err != nil {
127-
t.Fatal(err)
128-
}
129+
require.NoError(t, err)
130+
131+
p1 := h1.ID()
132+
p2 := h2.ID()
129133
p3 := h3.ID()
130-
if err := mn.LinkAll(); err != nil {
131-
t.Error(err)
132-
}
133-
if err := mn.ConnectAllButSelf(); err != nil {
134-
t.Error(err)
135-
}
134+
135+
require.NoError(t, mn.LinkAll())
136+
require.NoError(t, mn.ConnectAllButSelf())
137+
136138
n1 := NewSignatureNotifier(h1, logger)
137-
n2 := NewSignatureNotifier(h2, logger)
138-
n3 := NewSignatureNotifier(h3, logger)
139139
assert.NotNil(t, n1)
140+
141+
n2 := NewSignatureNotifier(h2, logger)
140142
assert.NotNil(t, n2)
143+
144+
n3 := NewSignatureNotifier(h3, logger)
141145
assert.NotNil(t, n3)
146+
142147
sigFile := "../test_data/signature_notify/sig1.json"
148+
143149
content, err := os.ReadFile(sigFile)
144150
assert.NoError(t, err)
145151
assert.NotNil(t, content)
152+
146153
var signature tsslibcommon.SignatureData
147-
err = json.Unmarshal(content, &signature)
148-
assert.NoError(t, err)
154+
assert.NoError(t, json.Unmarshal(content, &signature))
155+
149156
sigChan := make(chan string)
150157

151158
assert.NotContains(t, n1.notifiers, messageID)
@@ -163,11 +170,11 @@ func TestSignatureNotifierBroadcastFirst(t *testing.T) {
163170
notifier := n1.notifiers[messageID]
164171
n1.notifierLock.Unlock()
165172
assert.False(t, notifier.readyToProcess())
166-
assert.Equal(t, defaultNotifierTTL, notifier.ttl)
173+
assert.Equal(t, config.SigNotifierTTL, notifier.ttl)
167174

168-
sig, err := n1.WaitForSignature(messageID, [][]byte{buf}, poolPubKey, time.Second*30, sigChan)
169-
assert.NoError(t, err)
170-
assert.NotNil(t, sig)
175+
sig, err := n1.WaitForSignature(messageID, [][]byte{buf}, poolPubKey, config.SigNotifierTTL, sigChan)
176+
require.NoError(t, err)
177+
require.NotNil(t, sig)
171178

172179
n1.notifierLock.Lock()
173180
assert.NotContains(t, n1.notifiers, messageID)

0 commit comments

Comments
 (0)