@@ -3,8 +3,8 @@ package epochkghandler
3
3
import (
4
4
"bytes"
5
5
"context"
6
- "math"
7
6
7
+ lru "github.com/hashicorp/golang-lru/v2"
8
8
"github.com/jackc/pgx/v4"
9
9
"github.com/jackc/pgx/v4/pgxpool"
10
10
pubsub "github.com/libp2p/go-libp2p-pubsub"
@@ -14,18 +14,23 @@ import (
14
14
"github.com/shutter-network/shutter/shlib/shcrypto"
15
15
16
16
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper/database"
17
+ "github.com/shutter-network/rolling-shutter/rolling-shutter/medley"
17
18
"github.com/shutter-network/rolling-shutter/rolling-shutter/p2p"
18
19
"github.com/shutter-network/rolling-shutter/rolling-shutter/p2pmsg"
19
20
"github.com/shutter-network/rolling-shutter/rolling-shutter/shdb"
20
21
)
21
22
22
23
func NewDecryptionKeyHandler (config Config , dbpool * pgxpool.Pool ) p2p.MessageHandler {
23
- return & DecryptionKeyHandler {config : config , dbpool : dbpool }
24
+ // Not catching the error as it only can happen if non-positive size was applied
25
+ cache , _ := lru.New [shcrypto.EpochSecretKey , []byte ](1024 )
26
+ return & DecryptionKeyHandler {config : config , dbpool : dbpool , cache : cache }
24
27
}
25
28
26
29
type DecryptionKeyHandler struct {
27
30
config Config
28
31
dbpool * pgxpool.Pool
32
+ // keep 1024 verified keys in Cache to skip additional verifications
33
+ cache * lru.Cache [shcrypto.EpochSecretKey , []byte ]
29
34
}
30
35
31
36
func (* DecryptionKeyHandler ) MessagePrototypes () []p2pmsg.Message {
@@ -38,34 +43,33 @@ func (handler *DecryptionKeyHandler) ValidateMessage(ctx context.Context, msg p2
38
43
return pubsub .ValidationReject ,
39
44
errors .Errorf ("instance ID mismatch (want=%d, have=%d)" , handler .config .GetInstanceID (), key .GetInstanceID ())
40
45
}
41
- if key .Eon > math .MaxInt64 {
42
- return pubsub .ValidationReject , errors .Errorf ("eon %d overflows int64" , key .Eon )
46
+ eon , err := medley .Uint64ToInt64Safe (key .Eon )
47
+ if err != nil {
48
+ return pubsub .ValidationReject , errors .Wrapf (err , "overflow error while converting eon to int64 %d" , eon )
43
49
}
44
50
45
51
queries := database .New (handler .dbpool )
46
-
47
- _ , isKeyper , err := queries .GetKeyperIndex (ctx , int64 (key .Eon ), handler .config .GetAddress ())
52
+ _ , isKeyper , err := queries .GetKeyperIndex (ctx , eon , handler .config .GetAddress ())
48
53
if err != nil {
49
54
return pubsub .ValidationReject , err
50
55
}
51
56
if ! isKeyper {
52
57
log .Debug ().Uint64 ("eon" , key .Eon ).Msg ("Ignoring decryptionKey for eon; we're not a Keyper" )
53
58
return pubsub .ValidationReject , nil
54
59
}
55
-
56
- dkgResultDB , err := queries .GetDKGResultForKeyperConfigIndex (ctx , int64 (key .Eon ))
57
- if err == pgx .ErrNoRows {
58
- return pubsub .ValidationReject , errors .Errorf ("no DKG result found for eon %d" , key .Eon )
60
+ dkgResultDB , err := queries .GetDKGResultForKeyperConfigIndex (ctx , eon )
61
+ if errors .Is (err , pgx .ErrNoRows ) {
62
+ return pubsub .ValidationReject , errors .Errorf ("no DKG result found for eon %d" , eon )
59
63
}
60
64
if err != nil {
61
- return pubsub .ValidationReject , errors .Wrapf (err , "failed to get dkg result for eon %d from db" , key . Eon )
65
+ return pubsub .ValidationReject , errors .Wrapf (err , "failed to get dkg result for eon %d from db" , eon )
62
66
}
63
67
if ! dkgResultDB .Success {
64
- return pubsub .ValidationReject , errors .Errorf ("no successful DKG result found for eon %d" , key . Eon )
68
+ return pubsub .ValidationReject , errors .Errorf ("no successful DKG result found for eon %d" , eon )
65
69
}
66
70
pureDKGResult , err := shdb .DecodePureDKGResult (dkgResultDB .PureResult )
67
71
if err != nil {
68
- return pubsub .ValidationReject , errors .Wrapf (err , "error while decoding pure DKG result for eon %d" , key . Eon )
72
+ return pubsub .ValidationReject , errors .Wrapf (err , "error while decoding pure DKG result for eon %d" , eon )
69
73
}
70
74
71
75
if len (key .Keys ) == 0 {
@@ -74,19 +78,26 @@ func (handler *DecryptionKeyHandler) ValidateMessage(ctx context.Context, msg p2
74
78
if len (key .Keys ) > int (handler .config .GetMaxNumKeysPerMessage ()) {
75
79
return pubsub .ValidationReject , errors .Errorf ("too many keys in message (%d > %d)" , len (key .Keys ), handler .config .GetMaxNumKeysPerMessage ())
76
80
}
81
+
77
82
for i , k := range key .Keys {
78
83
epochSecretKey , err := k .GetEpochSecretKey ()
79
84
if err != nil {
80
85
return pubsub .ValidationReject , err
81
86
}
87
+ identity , exists := handler .cache .Get (* epochSecretKey )
88
+ if exists {
89
+ if bytes .Equal (k .Identity , identity ) {
90
+ continue
91
+ }
92
+ return pubsub .ValidationReject , errors .Errorf ("epoch secret key for identity %x is not valid" , k .Identity )
93
+ }
82
94
ok , err := shcrypto .VerifyEpochSecretKey (epochSecretKey , pureDKGResult .PublicKey , k .Identity )
83
95
if err != nil {
84
96
return pubsub .ValidationReject , errors .Wrapf (err , "error while checking epoch secret key for identity %x" , k .Identity )
85
97
}
86
98
if ! ok {
87
99
return pubsub .ValidationReject , errors .Errorf ("epoch secret key for identity %x is not valid" , k .Identity )
88
100
}
89
-
90
101
if i > 0 && bytes .Compare (k .Identity , key .Keys [i - 1 ].Identity ) < 0 {
91
102
return pubsub .ValidationReject , errors .Errorf ("keys not ordered" )
92
103
}
@@ -97,7 +108,15 @@ func (handler *DecryptionKeyHandler) ValidateMessage(ctx context.Context, msg p2
97
108
func (handler * DecryptionKeyHandler ) HandleMessage (ctx context.Context , msg p2pmsg.Message ) ([]p2pmsg.Message , error ) {
98
109
metricsEpochKGDecryptionKeysReceived .Inc ()
99
110
key := msg .(* p2pmsg.DecryptionKeys )
100
- // Insert the key into the db. We assume that it's valid as it already passed the libp2p
101
- // validator.
111
+ // We assume that it's valid as it already passed the libp2p validator.
112
+ // Insert the key into the cache.
113
+ for _ , k := range key .Keys {
114
+ epochSecretKey , err := k .GetEpochSecretKey ()
115
+ if err != nil {
116
+ return nil , err
117
+ }
118
+ handler .cache .Add (* epochSecretKey , k .Identity )
119
+ }
120
+ // Insert the key into the db.
102
121
return nil , database .New (handler .dbpool ).InsertDecryptionKeysMsg (ctx , key )
103
122
}
0 commit comments