@@ -17,8 +17,10 @@ import (
17
17
18
18
obskeyperdb "github.com/shutter-network/rolling-shutter/rolling-shutter/chainobserver/db/keyper"
19
19
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper"
20
+ corekeyperdb "github.com/shutter-network/rolling-shutter/rolling-shutter/keyper/database"
20
21
"github.com/shutter-network/rolling-shutter/rolling-shutter/medley/retry"
21
22
"github.com/shutter-network/rolling-shutter/rolling-shutter/medley/service"
23
+ "github.com/shutter-network/rolling-shutter/rolling-shutter/shdb"
22
24
)
23
25
24
26
const (
@@ -57,11 +59,13 @@ func NewEonKeyPublisher(
57
59
}
58
60
59
61
func (p * EonKeyPublisher ) Start (ctx context.Context , runner service.Runner ) error { //nolint: unparam
62
+ log .Info ().Msg ("starting eon key publisher" )
60
63
runner .Go (func () error {
64
+ p .publishOldKeys (ctx )
61
65
for {
62
66
select {
63
67
case key := <- p .keys :
64
- p .publish (ctx , key )
68
+ p .publishIfResponsible (ctx , key )
65
69
case <- ctx .Done ():
66
70
return ctx .Err ()
67
71
}
@@ -75,54 +79,93 @@ func (p *EonKeyPublisher) Publish(key keyper.EonPublicKey) {
75
79
p .keys <- key
76
80
}
77
81
78
- func (p * EonKeyPublisher ) publish (ctx context.Context , key keyper.EonPublicKey ) {
79
- _ , err := retry .FunctionCall [struct {}](ctx , func (ctx context.Context ) (struct {}, error ) {
80
- return struct {}{}, p .tryPublish (ctx , key )
81
- }, retry .Interval (retryInterval ))
82
+ // publishIfResponsible publishes a eon key if the keyper is part of the corresponding keyper
83
+ // set, unless the key is already confirmed or the keyper has already voted on it.
84
+ func (p * EonKeyPublisher ) publishIfResponsible (ctx context.Context , key keyper.EonPublicKey ) {
85
+ db := obskeyperdb .New (p .dbpool )
86
+ keyperSet , err := db .GetKeyperSetByKeyperConfigIndex (ctx , int64 (key .Eon ))
82
87
if err != nil {
83
88
log .Error ().
84
89
Err (err ).
85
90
Uint64 ("keyper-set-index" , key .KeyperConfigIndex ).
86
91
Hex ("key" , key .PublicKey ).
87
- Msg ("failed to publish eon key" )
88
- }
89
- }
90
-
91
- func (p * EonKeyPublisher ) tryPublish (ctx context.Context , key keyper.EonPublicKey ) error {
92
- db := obskeyperdb .New (p .dbpool )
93
- keyperSet , err := db .GetKeyperSetByKeyperConfigIndex (ctx , int64 (key .Eon ))
94
- if err != nil {
95
- return errors .Wrapf (err , "failed to query keyper set %d by index from db" , key .KeyperConfigIndex )
92
+ Msg ("failed to check if eon key should be published" )
93
+ return
96
94
}
97
95
keyperAddress := ethcrypto .PubkeyToAddress (p .privateKey .PublicKey )
98
96
keyperIndex , err := keyperSet .GetIndex (keyperAddress )
99
97
if err != nil {
100
98
log .Info ().
101
99
Uint64 ("keyper-set-index" , key .KeyperConfigIndex ).
102
100
Str ("keyper-address" , keyperAddress .Hex ()).
101
+ Hex ("key" , key .PublicKey ).
103
102
Msg ("not publishing eon key as keyper is not part of corresponding keyper set" )
104
- return nil
103
+ return
104
+ }
105
+ p .publish (ctx , key .PublicKey , key .KeyperConfigIndex , keyperIndex )
106
+ }
107
+
108
+ // publishOldKeys publishes all eon keys that are already in the database, unless they're already
109
+ // confirmed or the keyper has already voted on them.
110
+ func (p * EonKeyPublisher ) publishOldKeys (ctx context.Context ) {
111
+ db := corekeyperdb .New (p .dbpool )
112
+ dkgResultsDB , err := db .GetAllDKGResults (ctx )
113
+ if err != nil {
114
+ err := errors .Wrap (err , "failed to query DKG results from db" )
115
+ log .Error ().Err (err ).Msg ("failed to publish old eon keys" )
116
+ return
117
+ }
118
+ for _ , dkgResultDB := range dkgResultsDB {
119
+ if ! dkgResultDB .Success {
120
+ continue
121
+ }
122
+ dkgResult , err := shdb .DecodePureDKGResult (dkgResultDB .PureResult )
123
+ if err != nil {
124
+ err := errors .Wrapf (err , "failed to decode DKG result of eon %d" , dkgResultDB .Eon )
125
+ log .Error ().Err (err ).Msg ("failed to publish old eon keys" )
126
+ continue
127
+ }
128
+ p .publish (ctx , dkgResult .PublicKey .Marshal (), dkgResult .Eon , dkgResult .Keyper )
129
+ }
130
+ }
131
+
132
+ // publish publishes an eon key, unless it's already confirmed or the keyper has already voted on
133
+ // it. On errors, publishing will be retried a few times and eventually aborted.
134
+ func (p * EonKeyPublisher ) publish (ctx context.Context , key []byte , keyperSetIndex uint64 , keyperIndex uint64 ) {
135
+ _ , err := retry .FunctionCall [struct {}](ctx , func (ctx context.Context ) (struct {}, error ) {
136
+ return struct {}{}, p .tryPublish (ctx , key , keyperSetIndex , keyperIndex )
137
+ }, retry .Interval (retryInterval ))
138
+ if err != nil {
139
+ log .Error ().
140
+ Err (err ).
141
+ Uint64 ("keyper-set-index" , keyperSetIndex ).
142
+ Hex ("key" , key ).
143
+ Msg ("failed to publish eon key" )
105
144
}
145
+ }
106
146
147
+ func (p * EonKeyPublisher ) tryPublish (ctx context.Context , key []byte , keyperSetIndex uint64 , keyperIndex uint64 ) error {
148
+ keyperAddress := ethcrypto .PubkeyToAddress (p .privateKey .PublicKey )
107
149
hasAlreadyVoted , err := p .contract .HasKeyperVoted (& bind.CallOpts {}, keyperAddress )
108
150
if err != nil {
109
151
return errors .Wrap (err , "failed to query eon key publisher contract if keyper has already voted" )
110
152
}
111
153
if hasAlreadyVoted {
112
154
log .Info ().
113
- Uint64 ("keyper-set-index" , key . KeyperConfigIndex ).
155
+ Uint64 ("keyper-set-index" , keyperSetIndex ).
114
156
Str ("keyper-address" , keyperAddress .Hex ()).
157
+ Hex ("key" , key ).
115
158
Msg ("not publishing eon key as keyper has already voted" )
116
159
return nil
117
160
}
118
- isAlreadyConfirmed , err := p .contract .EonKeyConfirmed (& bind.CallOpts {}, key . PublicKey )
161
+ isAlreadyConfirmed , err := p .contract .EonKeyConfirmed (& bind.CallOpts {}, key )
119
162
if err != nil {
120
163
return errors .Wrap (err , "failed to query eon key publisher contract if eon key is confirmed" )
121
164
}
122
165
if isAlreadyConfirmed {
123
166
log .Info ().
124
- Uint64 ("keyper-set-index" , key . KeyperConfigIndex ).
125
- Hex ("key" , key . PublicKey ).
167
+ Uint64 ("keyper-set-index" , keyperSetIndex ).
168
+ Hex ("key" , key ).
126
169
Msg ("not publishing eon key as it is already confirmed" )
127
170
return nil
128
171
}
@@ -135,13 +178,13 @@ func (p *EonKeyPublisher) tryPublish(ctx context.Context, key keyper.EonPublicKe
135
178
if err != nil {
136
179
return errors .Wrap (err , "failed to construct tx opts" )
137
180
}
138
- tx , err := p .contract .PublishEonKey (opts , key . PublicKey , keyperIndex )
181
+ tx , err := p .contract .PublishEonKey (opts , key , keyperIndex )
139
182
if err != nil {
140
183
return errors .Wrap (err , "failed to send publish eon key tx" )
141
184
}
142
185
log .Info ().
143
- Uint64 ("keyper-set-index" , key . KeyperConfigIndex ).
144
- Hex ("key" , key . PublicKey ).
186
+ Uint64 ("keyper-set-index" , keyperSetIndex ).
187
+ Hex ("key" , key ).
145
188
Hex ("tx-hash" , tx .Hash ().Bytes ()).
146
189
Msg ("eon key publish tx sent" )
147
190
receipt , err := bind .WaitMined (ctx , p .client , tx )
@@ -156,6 +199,10 @@ func (p *EonKeyPublisher) tryPublish(ctx context.Context, key keyper.EonPublicKe
156
199
Msg ("eon key publish tx failed" )
157
200
return errors .New ("eon key publish tx failed" )
158
201
}
159
- log .Info ().Msg ("successfully published eon key" )
202
+ log .Info ().
203
+ Uint64 ("keyper-set-index" , keyperSetIndex ).
204
+ Hex ("key" , key ).
205
+ Hex ("tx-hash" , tx .Hash ().Bytes ()).
206
+ Msg ("successfully published eon key" )
160
207
return nil
161
208
}
0 commit comments