forked from meshplus/bitxhub-core
/
tss.go
240 lines (214 loc) · 7.07 KB
/
tss.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
package tss
import (
"fmt"
"sync"
bkg "github.com/binance-chain/tss-lib/ecdsa/keygen"
btss "github.com/binance-chain/tss-lib/tss"
"github.com/libp2p/go-libp2p-core/crypto"
peer_mgr "github.com/meshplus/bitxhub-core/peer-mgr"
"github.com/meshplus/bitxhub-core/tss/blame"
"github.com/meshplus/bitxhub-core/tss/cache"
"github.com/meshplus/bitxhub-core/tss/conversion"
"github.com/meshplus/bitxhub-core/tss/message"
"github.com/meshplus/bitxhub-core/tss/p2p"
"github.com/meshplus/bitxhub-core/tss/storage"
"github.com/meshplus/bitxhub-model/pb"
"github.com/sirupsen/logrus"
)
var _ Tss = (*TssInstance)(nil)
// TssInstance is the structure that can provide all Keygen and Keysign features
type TssInstance struct {
// =================== tssmgr info
localPrivK crypto.PrivKey
localPubK crypto.PubKey
threshold int
keygenPreParams *bkg.LocalPreParams
conf TssConfig
keygenLocalState *storage.KeygenLocalState
// ==================== task info
msgID string
// the number of msgs contained in the current request (1 for Keygen request is and n for Keysign request)
msgNum int
localPartyID string
partyInfo *conversion.PartyInfo
partyLock *sync.Mutex
// receive task Messages
TssMsgChan chan *pb.Message
// receive end signal of the coroutine for inbound message handling (abnormal abort, timeout abort, end of task)
inMsgHandleStopChan chan struct{}
// receive the task end signal
taskDoneChan chan struct{}
// receive TSS shutdown signal
stopChan chan struct{}
// msg cache list
cachedWireBroadcastMsgLists *sync.Map
cachedWireUnicastMsgLists *sync.Map
// record the confirmation of broadcast messages
// partyID + round -> msgContent, msgHash
unConfirmedMessages map[string]*cache.LocalCacheItem
unConfirmedMsgLock *sync.Mutex
// record the participants who have completed the task
finishedParties map[string]bool
// malicious participation node
culprits []*btss.PartyID
culpritsLock *sync.RWMutex
blameMgr *blame.Manager
p2pComm *p2p.Communication
logger logrus.FieldLogger
}
// NewTss creates a new instance of Tss
func NewTssInstance(
conf TssConfig,
privKey crypto.PrivKey,
preParams *bkg.LocalPreParams,
keygenLocalState *storage.KeygenLocalState,
peerMgr peer_mgr.OrderPeerManager,
logger logrus.FieldLogger,
) (tssInstance *TssInstance, err error) {
// keygen pre params
// When using the keygen party it is recommended that you pre-compute the
// "safe primes" and Paillier secret beforehand because this can take some
// time.
// This code will generate those parameters using a concurrency limit equal
// to the number of available CPU cores.
if preParams == nil || !preParams.Validate() {
preParams, err = bkg.GeneratePreParams(conf.PreParamTimeout)
if err != nil {
return nil, fmt.Errorf("fail to generate pre parameters: %w", err)
}
}
if !preParams.Validate() {
return nil, fmt.Errorf("invalid preparams")
}
// network
comm, err := p2p.NewCommunication(peerMgr, logger)
if err != nil {
return nil, fmt.Errorf("fail to create communication layer: %w", err)
}
comm.Start()
tss := &TssInstance{
keygenLocalState: keygenLocalState,
keygenPreParams: preParams,
conf: conf,
localPrivK: privKey,
localPubK: privKey.GetPublic(),
partyLock: &sync.Mutex{},
partyInfo: &conversion.PartyInfo{
PartyMap: nil,
PartyIDMap: make(map[string]*btss.PartyID),
},
inMsgHandleStopChan: make(chan struct{}),
taskDoneChan: make(chan struct{}),
stopChan: make(chan struct{}),
cachedWireBroadcastMsgLists: &sync.Map{},
cachedWireUnicastMsgLists: &sync.Map{},
unConfirmedMessages: make(map[string]*cache.LocalCacheItem),
unConfirmedMsgLock: &sync.Mutex{},
finishedParties: make(map[string]bool),
culpritsLock: &sync.RWMutex{},
p2pComm: comm,
blameMgr: blame.NewBlameManager(logger),
logger: logger,
}
return tss, nil
}
// The current instance may be reused. Need to clear some information before using it
func (t *TssInstance) InitTssInfo(
msgId string,
msgNum int,
privKey crypto.PrivKey,
threshold uint64,
conf TssConfig,
preParams *bkg.LocalPreParams,
keygenLocalState *storage.KeygenLocalState,
peerMgr peer_mgr.OrderPeerManager,
logger logrus.FieldLogger,
) (err error) {
// keygen pre params
// When using the keygen party it is recommended that you pre-compute the
// "safe primes" and Paillier secret beforehand because this can take some
// time.
// This code will generate those parameters using a concurrency limit equal
// to the number of available CPU cores.
if preParams == nil || !preParams.Validate() {
preParams, err = bkg.GeneratePreParams(conf.PreParamTimeout)
if err != nil {
return fmt.Errorf("fail to generate pre parameters: %w", err)
}
}
if !preParams.Validate() {
return fmt.Errorf("invalid preparams")
}
t.keygenPreParams = preParams
t.localPrivK = privKey
t.localPubK = privKey.GetPublic()
t.threshold = int(threshold)
t.conf = conf
t.keygenLocalState = keygenLocalState
t.msgID = msgId
t.msgNum = msgNum
t.localPartyID = ""
t.partyInfo = &conversion.PartyInfo{
PartyMap: nil,
PartyIDMap: make(map[string]*btss.PartyID),
}
t.partyLock = &sync.Mutex{}
t.TssMsgChan = make(chan *pb.Message, msgNum)
t.inMsgHandleStopChan = make(chan struct{})
t.taskDoneChan = make(chan struct{})
t.stopChan = make(chan struct{})
t.cachedWireBroadcastMsgLists = &sync.Map{}
t.cachedWireUnicastMsgLists = &sync.Map{}
t.unConfirmedMessages = make(map[string]*cache.LocalCacheItem)
t.unConfirmedMsgLock = &sync.Mutex{}
t.finishedParties = make(map[string]bool)
t.culprits = []*btss.PartyID{}
t.culpritsLock = &sync.RWMutex{}
t.blameMgr = blame.NewBlameManager(logger)
comm, err := p2p.NewCommunication(peerMgr, logger)
if err != nil {
return fmt.Errorf("fail to create communication layer: %w", err)
}
t.p2pComm = comm
t.p2pComm.Start()
t.logger = logger
t.logger.Debugf("..... init instance %s", msgId)
return nil
}
func (t *TssInstance) setPartyInfo(partyInfo *conversion.PartyInfo) {
t.partyLock.Lock()
defer t.partyLock.Unlock()
t.partyInfo = partyInfo
}
func (t *TssInstance) getPartyInfo() *conversion.PartyInfo {
t.partyLock.Lock()
defer t.partyLock.Unlock()
return t.partyInfo
}
func (t *TssInstance) setLocalUnconfirmedMessages(key string, cacheItem *cache.LocalCacheItem) {
t.unConfirmedMsgLock.Lock()
defer t.unConfirmedMsgLock.Unlock()
t.unConfirmedMessages[key] = cacheItem
}
func (t *TssInstance) getLocalCacheItem(key string) *cache.LocalCacheItem {
t.unConfirmedMsgLock.Lock()
defer t.unConfirmedMsgLock.Unlock()
localCacheItem, ok := t.unConfirmedMessages[key]
if !ok {
return nil
}
return localCacheItem
}
func (t *TssInstance) renderToP2P(sendMsg *message.SendMsgChan) {
if t.p2pComm.SendMsgChan == nil {
t.logger.Warn("broadcast channel is not set")
return
}
t.p2pComm.SendMsgChan <- sendMsg
}
func (t *TssInstance) PutTssMsg(msg *pb.Message) {
t.TssMsgChan <- msg
t.logger.WithFields(logrus.Fields{
"msgID": t.msgID,
}).Debugf("PutTssMsg")
}