Skip to content

Commit db250a4

Browse files
committed
Trigger in new slots instead of blocks
1 parent 4b160de commit db250a4

File tree

10 files changed

+126
-76
lines changed

10 files changed

+126
-76
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package database
2+
3+
import (
4+
"github.com/ethereum/go-ethereum/common"
5+
6+
"github.com/shutter-network/rolling-shutter/rolling-shutter/shdb"
7+
)
8+
9+
func (s *KeyperSet) Contains(address common.Address) bool {
10+
encodedAddress := shdb.EncodeAddress(address)
11+
for _, m := range s.Keypers {
12+
if m == encodedAddress {
13+
return true
14+
}
15+
}
16+
return false
17+
}

rolling-shutter/keyperimpl/gnosis/database/gnosiskeyper.sqlc.gen.go

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

rolling-shutter/keyperimpl/gnosis/database/models.sqlc.gen.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rolling-shutter/keyperimpl/gnosis/database/sql/queries/gnosiskeyper.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ SELECT * FROM tx_pointer
4343
WHERE eon = $1;
4444

4545
-- name: InitTxPointer :exec
46-
INSERT INTO tx_pointer (eon, block, value)
46+
INSERT INTO tx_pointer (eon, slot, value)
4747
VALUES ($1, $2, 0)
4848
ON CONFLICT DO NOTHING;
4949

5050
-- name: SetTxPointer :exec
51-
INSERT INTO tx_pointer (eon, block, value)
51+
INSERT INTO tx_pointer (eon, slot, value)
5252
VALUES ($1, $2, $3)
5353
ON CONFLICT (eon) DO UPDATE
54-
SET block = $2, value = $3;
54+
SET slot = $2, value = $3;
5555

5656
-- name: SetCurrentDecryptionTrigger :exec
5757
INSERT INTO current_decryption_trigger (eon, slot, tx_pointer, identities_hash)

rolling-shutter/keyperimpl/gnosis/database/sql/schemas/gnosiskeyper.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ CREATE TABLE transaction_submitted_event_count(
2929

3030
CREATE TABLE tx_pointer(
3131
eon bigint PRIMARY KEY,
32-
block bigint NOT NULL DEFAULT 0,
32+
slot bigint NOT NULL DEFAULT 0,
3333
value bigint NOT NULL DEFAULT 0
3434
);
3535

rolling-shutter/keyperimpl/gnosis/handlers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,14 @@ func (h *DecryptionKeysHandler) HandleMessage(ctx context.Context, msg p2pmsg.Me
276276
newTxPointer := int64(extra.TxPointer) + int64(len(keys.Keys)) - 1
277277
log.Debug().
278278
Uint64("eon", keys.Eon).
279-
Uint64("block", extra.Slot).
279+
Uint64("slot", extra.Slot).
280280
Uint64("tx-pointer-msg", extra.TxPointer).
281281
Int("num-keys", len(keys.Keys)).
282282
Int64("tx-pointer-updated", newTxPointer).
283283
Msg("updating tx pointer")
284284
err := gnosisDB.SetTxPointer(ctx, database.SetTxPointerParams{
285285
Eon: int64(keys.Eon),
286-
Block: int64(extra.Slot),
286+
Slot: int64(extra.Slot),
287287
Value: newTxPointer,
288288
})
289289
if err != nil {

rolling-shutter/keyperimpl/gnosis/keyper.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ import (
2929

3030
var ErrParseKeyperSet = errors.New("cannot parse KeyperSet")
3131

32-
// Maximum age of a tx pointer in blocks before it is considered outdated.
33-
const maxTxPointerAge = 2
34-
3532
type Keyper struct {
3633
core *keyper.KeyperCore
3734
config *Config

rolling-shutter/keyperimpl/gnosis/messagingmiddleware.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,14 +273,14 @@ func (i *MessagingMiddleware) advanceTxPointer(ctx context.Context, msg *p2pmsg.
273273
newTxPointer := int64(extra.TxPointer) + int64(len(msg.Keys)) - 1
274274
log.Debug().
275275
Uint64("eon", msg.Eon).
276-
Uint64("block", extra.Slot).
276+
Uint64("slot", extra.Slot).
277277
Uint64("tx-pointer-msg", extra.TxPointer).
278278
Int("num-keys", len(msg.Keys)).
279279
Int64("tx-pointer-updated", newTxPointer).
280280
Msg("updating tx pointer")
281281
err := gnosisDB.SetTxPointer(ctx, database.SetTxPointerParams{
282282
Eon: int64(msg.Eon),
283-
Block: int64(extra.Slot),
283+
Slot: int64(extra.Slot),
284284
Value: newTxPointer,
285285
})
286286
if err != nil {

rolling-shutter/keyperimpl/gnosis/newslot.go

Lines changed: 90 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,18 @@ import (
2222
"github.com/shutter-network/rolling-shutter/rolling-shutter/shdb"
2323
)
2424

25+
// Maximum age of a tx pointer in blocks before it is considered outdated.
26+
const maxTxPointerAge = 2
27+
28+
var errZeroTxPointerAge = errors.New("tx pointer has age 0")
29+
2530
func (kpr *Keyper) processNewSlot(ctx context.Context, slot slotticker.Slot) error {
31+
fmt.Println("")
32+
fmt.Println("")
33+
fmt.Println(slot.Number)
34+
fmt.Println("")
35+
fmt.Println("")
36+
2637
gnosisKeyperDB := gnosisdatabase.New(kpr.dbpool)
2738
syncedUntil, err := gnosisKeyperDB.GetTransactionSubmittedEventsSyncedUntil(ctx)
2839
if err != nil {
@@ -35,93 +46,119 @@ func (kpr *Keyper) processNewSlot(ctx context.Context, slot slotticker.Slot) err
3546
// already been built, so we return an error.
3647
return errors.Errorf("processing slot %d for which a block has already been processed", slot.Number)
3748
}
49+
nextBlock := syncedUntil.BlockNumber + 1
3850

3951
queries := obskeyper.New(kpr.dbpool)
40-
keyperSet, err := queries.GetKeyperSet(ctx, syncedUntil.BlockNumber)
52+
keyperSet, err := queries.GetKeyperSet(ctx, nextBlock)
4153
if err == pgx.ErrNoRows {
4254
log.Debug().
4355
Uint64("slot", slot.Number).
44-
Int64("block-number", syncedUntil.BlockNumber).
56+
Int64("block-number", nextBlock).
4557
Msg("ignoring slot as no keyper set has been found for it")
4658
return nil
4759
}
4860
if err != nil {
49-
return errors.Wrapf(err, "failed to query keyper set for block %d", syncedUntil.BlockNumber)
61+
return errors.Wrapf(err, "failed to query keyper set for block %d", nextBlock)
5062
}
51-
for _, m := range keyperSet.Keypers {
52-
if m == shdb.EncodeAddress(kpr.config.GetAddress()) {
53-
return kpr.triggerDecryption(ctx, slot, syncedUntil, &keyperSet)
54-
}
63+
if keyperSet.Contains(kpr.config.GetAddress()) {
64+
return kpr.triggerDecryption(ctx, slot, nextBlock, &keyperSet)
5565
}
56-
log.Debug().Uint64("slot", slot.Number).Msg("ignoring block as not part of keyper set")
66+
log.Debug().
67+
Uint64("slot", slot.Number).
68+
Int64("block-number", nextBlock).
69+
Int64("keyper-set-index", keyperSet.KeyperConfigIndex).
70+
Str("address", kpr.config.GetAddress().Hex()).
71+
Msg("ignoring block as not part of keyper set")
5772
return nil
5873
}
5974

60-
func (kpr *Keyper) triggerDecryption(
61-
ctx context.Context,
62-
slot slotticker.Slot,
63-
syncedUntil gnosisdatabase.TransactionSubmittedEventsSyncedUntil,
64-
keyperSet *obskeyper.KeyperSet,
65-
) error {
66-
fmt.Println("")
67-
fmt.Println("")
68-
fmt.Println(slot.Number)
69-
fmt.Println("")
70-
fmt.Println("")
75+
func (kpr *Keyper) getTxPointer(ctx context.Context, eon int64, slot int64, keyperConfigIndex int64) (int64, error) {
7176
gnosisKeyperDB := gnosisdatabase.New(kpr.dbpool)
72-
coreKeyperDB := corekeyperdatabase.New(kpr.dbpool)
73-
74-
eonStruct, err := coreKeyperDB.GetEonForBlockNumber(ctx, syncedUntil.BlockNumber)
75-
if err != nil {
76-
return errors.Wrapf(err, "failed to query eon for block number %d from db", syncedUntil.BlockNumber)
77-
}
78-
eon := eonStruct.Eon
79-
80-
var txPointer int64
81-
var txPointerAge int64
77+
var txPointer, txPointerAge int64
8278
txPointerDB, err := gnosisKeyperDB.GetTxPointer(ctx, eon)
8379
if err == pgx.ErrNoRows {
80+
// The tx pointer is expected to be missing from the db if the eon has just started. In
81+
// this case, we should initialize it to zero with an age of 1, ie decrypt starting with
82+
// the first transaction.
83+
// The tx pointer may also be missing if the keyper has been started late and no decryption
84+
// key has been generated or received yet (receiving the keys message would update the
85+
// pointer). In this case, the true age is unknown, as we only know the start block but
86+
// not the start slot of the eon. However, we can ignore this edge case as it will be
87+
// resolved automatically when the first keys message is received. If key generation
88+
// continues to fail, eventually our tx pointer age will exceed the maximum value and we
89+
// will start participating in the recovery process, albeit a bit late.
90+
err := gnosisKeyperDB.SetTxPointer(ctx, gnosisdatabase.SetTxPointerParams{
91+
Eon: eon,
92+
Slot: slot,
93+
Value: 0,
94+
})
95+
if err != nil {
96+
return 0, errors.Wrap(err, "failed to initialize tx pointer")
97+
}
8498
txPointer = 0
85-
txPointerAge = syncedUntil.BlockNumber - keyperSet.ActivationBlockNumber + 1
99+
txPointerAge = 1
86100
} else if err != nil {
87-
return errors.Wrap(err, "failed to query tx pointer from db")
101+
return 0, errors.Wrap(err, "failed to query tx pointer from db")
88102
} else {
89-
txPointerAge = syncedUntil.BlockNumber - txPointerDB.Block
90103
txPointer = txPointerDB.Value
104+
txPointerAge = slot - txPointerDB.Slot
91105
}
92106
if txPointerAge == 0 {
93107
// A pointer of age 0 means we already received the pointer from a DecryptionKeys message
94108
// even though we haven't sent our shares yet. In that case, sending our shares is
95109
// unnecessary.
110+
return 0, errZeroTxPointerAge
111+
}
112+
// If the tx pointer is outdated, the system has failed to generate decryption keys (or at
113+
// least we haven't received them). This either means not enough keypers are online or they
114+
// don't agree on the current value of the tx pointer. In order to recover, we choose the
115+
// current length of the transaction queue as the new tx pointer, as this is a value
116+
// everyone can agree on.
117+
isOutdated := txPointerAge > maxTxPointerAge
118+
if isOutdated {
96119
log.Warn().
97-
Uint64("slot", slot.Number).
98-
Int64("block-number", syncedUntil.BlockNumber).
99-
Int64("eon", eon).
100-
Int64("tx-pointer", txPointer).
101-
Int64("tx-pointer-age", txPointerAge).
102-
Msg("ignoring new block as tx pointer age is 0")
103-
return nil
104-
}
105-
if txPointerAge > maxTxPointerAge {
106-
// If the tx pointer is outdated, the system has failed to generate decryption keys (or at
107-
// least we haven't received them). This either means not enough keypers are online or they
108-
// don't agree on the current value of the tx pointer. In order to recover, we choose the
109-
// current length of the transaction queue as the new tx pointer, as this is a value
110-
// everyone can agree on.
111-
log.Warn().
112-
Uint64("slot", slot.Number).
113-
Int64("block-number", syncedUntil.BlockNumber).
120+
Int64("slot", slot).
114121
Int64("eon", eon).
115122
Int64("tx-pointer", txPointer).
116123
Int64("tx-pointer-age", txPointerAge).
117124
Msg("outdated tx pointer")
118-
txPointer, err = gnosisKeyperDB.GetTransactionSubmittedEventCount(ctx, keyperSet.KeyperConfigIndex)
125+
txPointer, err = gnosisKeyperDB.GetTransactionSubmittedEventCount(ctx, keyperConfigIndex)
119126
if err == pgx.ErrNoRows {
120127
txPointer = 0
121128
} else if err != nil {
122-
return errors.Wrap(err, "failed to query transaction submitted event count from db")
129+
return 0, errors.Wrap(err, "failed to query transaction submitted event count from db")
123130
}
124131
}
132+
return txPointer, nil
133+
}
134+
135+
func (kpr *Keyper) triggerDecryption(
136+
ctx context.Context,
137+
slot slotticker.Slot,
138+
nextBlock int64,
139+
keyperSet *obskeyper.KeyperSet,
140+
) error {
141+
gnosisKeyperDB := gnosisdatabase.New(kpr.dbpool)
142+
coreKeyperDB := corekeyperdatabase.New(kpr.dbpool)
143+
144+
eonStruct, err := coreKeyperDB.GetEonForBlockNumber(ctx, nextBlock)
145+
if err != nil {
146+
return errors.Wrapf(err, "failed to query eon for block number %d from db", nextBlock)
147+
}
148+
eon := eonStruct.Eon
149+
150+
txPointer, err := kpr.getTxPointer(ctx, eon, int64(slot.Number), keyperSet.KeyperConfigIndex)
151+
if err == errZeroTxPointerAge {
152+
log.Warn().
153+
Uint64("slot", slot.Number).
154+
Int64("block-number", nextBlock).
155+
Int64("eon", eon).
156+
Int64("tx-pointer", txPointer).
157+
Msg("ignoring new block as tx pointer age is 0")
158+
return nil
159+
} else if err != nil {
160+
return err
161+
}
125162

126163
identityPreimages, err := kpr.getDecryptionIdentityPreimages(ctx, slot, keyperSet.KeyperConfigIndex, txPointer)
127164
if err != nil {
@@ -137,16 +174,15 @@ func (kpr *Keyper) triggerDecryption(
137174
return errors.Wrap(err, "failed to insert published tx pointer into db")
138175
}
139176
trigger := epochkghandler.DecryptionTrigger{
140-
BlockNumber: uint64(syncedUntil.BlockNumber),
177+
BlockNumber: uint64(nextBlock),
141178
IdentityPreimages: identityPreimages,
142179
}
143180
event := broker.NewEvent(&trigger)
144181
log.Debug().
145182
Uint64("slot", slot.Number).
146-
Uint64("block-number", uint64(syncedUntil.BlockNumber)).
183+
Uint64("block-number", uint64(nextBlock)).
147184
Int("num-identities", len(trigger.IdentityPreimages)).
148185
Int64("tx-pointer", txPointer).
149-
Int64("tx-pointer-age", txPointerAge).
150186
Msg("sending decryption trigger")
151187
kpr.decryptionTriggerChannel <- event
152188

0 commit comments

Comments
 (0)