Skip to content

Commit 21311d0

Browse files
committed
Publish eon keys from db on startup
Before, only newly generated keys would be published. Now, keys that are already in the db on startup are published, unless they already have been.
1 parent a50cc4f commit 21311d0

File tree

3 files changed

+104
-23
lines changed

3 files changed

+104
-23
lines changed

rolling-shutter/eonkeypublisher/eonkeypublisher.go

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import (
1717

1818
obskeyperdb "github.com/shutter-network/rolling-shutter/rolling-shutter/chainobserver/db/keyper"
1919
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper"
20+
corekeyperdb "github.com/shutter-network/rolling-shutter/rolling-shutter/keyper/database"
2021
"github.com/shutter-network/rolling-shutter/rolling-shutter/medley/retry"
2122
"github.com/shutter-network/rolling-shutter/rolling-shutter/medley/service"
23+
"github.com/shutter-network/rolling-shutter/rolling-shutter/shdb"
2224
)
2325

2426
const (
@@ -57,11 +59,13 @@ func NewEonKeyPublisher(
5759
}
5860

5961
func (p *EonKeyPublisher) Start(ctx context.Context, runner service.Runner) error { //nolint: unparam
62+
log.Info().Msg("starting eon key publisher")
6063
runner.Go(func() error {
64+
p.publishOldKeys(ctx)
6165
for {
6266
select {
6367
case key := <-p.keys:
64-
p.publish(ctx, key)
68+
p.publishIfResponsible(ctx, key)
6569
case <-ctx.Done():
6670
return ctx.Err()
6771
}
@@ -75,54 +79,93 @@ func (p *EonKeyPublisher) Publish(key keyper.EonPublicKey) {
7579
p.keys <- key
7680
}
7781

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))
8287
if err != nil {
8388
log.Error().
8489
Err(err).
8590
Uint64("keyper-set-index", key.KeyperConfigIndex).
8691
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
9694
}
9795
keyperAddress := ethcrypto.PubkeyToAddress(p.privateKey.PublicKey)
9896
keyperIndex, err := keyperSet.GetIndex(keyperAddress)
9997
if err != nil {
10098
log.Info().
10199
Uint64("keyper-set-index", key.KeyperConfigIndex).
102100
Str("keyper-address", keyperAddress.Hex()).
101+
Hex("key", key.PublicKey).
103102
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")
105144
}
145+
}
106146

147+
func (p *EonKeyPublisher) tryPublish(ctx context.Context, key []byte, keyperSetIndex uint64, keyperIndex uint64) error {
148+
keyperAddress := ethcrypto.PubkeyToAddress(p.privateKey.PublicKey)
107149
hasAlreadyVoted, err := p.contract.HasKeyperVoted(&bind.CallOpts{}, keyperAddress)
108150
if err != nil {
109151
return errors.Wrap(err, "failed to query eon key publisher contract if keyper has already voted")
110152
}
111153
if hasAlreadyVoted {
112154
log.Info().
113-
Uint64("keyper-set-index", key.KeyperConfigIndex).
155+
Uint64("keyper-set-index", keyperSetIndex).
114156
Str("keyper-address", keyperAddress.Hex()).
157+
Hex("key", key).
115158
Msg("not publishing eon key as keyper has already voted")
116159
return nil
117160
}
118-
isAlreadyConfirmed, err := p.contract.EonKeyConfirmed(&bind.CallOpts{}, key.PublicKey)
161+
isAlreadyConfirmed, err := p.contract.EonKeyConfirmed(&bind.CallOpts{}, key)
119162
if err != nil {
120163
return errors.Wrap(err, "failed to query eon key publisher contract if eon key is confirmed")
121164
}
122165
if isAlreadyConfirmed {
123166
log.Info().
124-
Uint64("keyper-set-index", key.KeyperConfigIndex).
125-
Hex("key", key.PublicKey).
167+
Uint64("keyper-set-index", keyperSetIndex).
168+
Hex("key", key).
126169
Msg("not publishing eon key as it is already confirmed")
127170
return nil
128171
}
@@ -135,13 +178,13 @@ func (p *EonKeyPublisher) tryPublish(ctx context.Context, key keyper.EonPublicKe
135178
if err != nil {
136179
return errors.Wrap(err, "failed to construct tx opts")
137180
}
138-
tx, err := p.contract.PublishEonKey(opts, key.PublicKey, keyperIndex)
181+
tx, err := p.contract.PublishEonKey(opts, key, keyperIndex)
139182
if err != nil {
140183
return errors.Wrap(err, "failed to send publish eon key tx")
141184
}
142185
log.Info().
143-
Uint64("keyper-set-index", key.KeyperConfigIndex).
144-
Hex("key", key.PublicKey).
186+
Uint64("keyper-set-index", keyperSetIndex).
187+
Hex("key", key).
145188
Hex("tx-hash", tx.Hash().Bytes()).
146189
Msg("eon key publish tx sent")
147190
receipt, err := bind.WaitMined(ctx, p.client, tx)
@@ -156,6 +199,10 @@ func (p *EonKeyPublisher) tryPublish(ctx context.Context, key keyper.EonPublicKe
156199
Msg("eon key publish tx failed")
157200
return errors.New("eon key publish tx failed")
158201
}
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")
160207
return nil
161208
}

rolling-shutter/keyper/database/keyper.sqlc.gen.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rolling-shutter/keyper/database/sql/queries/keyper.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ WHERE eon = (SELECT eon FROM eons WHERE activation_block_number <= sqlc.arg(bloc
169169
ORDER BY activation_block_number DESC, height DESC
170170
LIMIT 1);
171171

172+
-- name: GetAllDKGResults :many
173+
SELECT * FROM dkg_result
174+
ORDER BY eon ASC;
175+
172176
-- name: InsertEonPublicKey :exec
173177
INSERT INTO outgoing_eon_keys (eon_public_key, eon)
174178
VALUES ($1, $2);

0 commit comments

Comments
 (0)