Skip to content

Commit 91cc050

Browse files
committed
feat: use new chainsyncer
keyper: add contract-addresses to config keyper-core: implement DB chaincache gnosis-keyper: use new chainsyncer gnosis-keyper: remove old sync-handler gnosisaccessnode: use new chainsyncer gnosisaccessnode: move storage to package gnosis-keyper: Rename some functions and types gnosis-keyper: refactor keyperCore init func gnosis-keyper: Pass dbpool to keyper core keyper: implement SyncStartBlock / DatabaseChainCache initial syncing gnosis-keyper: Add int64 overflow checks gnosis-keyper: add new synchandler chore: avoid var shadow feat(chainsync): add retry in initial block fetch chore: rename keypersetmanager synchandler chore: re-use the gnosis eth-client in keyper-core chore: refine comments chore: remove unnecessary import chore: fix generate, gci, gofumpt
1 parent 4c1e628 commit 91cc050

File tree

18 files changed

+704
-641
lines changed

18 files changed

+704
-641
lines changed

PR.md

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# 1/4 - Remove Optimism package.
2+
3+
- This is part of a series of 4 Pull Requests that all aim to refactor our old
4+
chainsync mechanism. The reason to split this up is to provide more digestible
5+
and grouped parts of the refactoring effort. I am aware this is a big change,
6+
but especially for refactoring an integral part of the system, and designing
7+
it at the same time, at least for me it is impossible to provide smaller
8+
increments of work that don't leave the code in an uncompilable,
9+
non-functional state. \*
10+
11+
We currently don't use the optimism package and for the following PRs I did not
12+
have the time to adapt the new chainsync mechanism and sync-handlers to the
13+
optimism package. If this package is chosen to continue working on, it can be
14+
re-integratated and the old state of the package can be retrieved from the git
15+
history and then adapted to the changes. Inspiration on how to integrate the new
16+
chainsync mechanism can be taken from the follow up PRs.
17+
18+
# 2/4 - Add new chainsync package
19+
20+
- This is part of a series of 4 Pull Requests that all aim to refactor our old
21+
chainsync mechanism. The reason to split this up is to provide more digestible
22+
and grouped parts of the refactoring effort. I am aware this is a big change,
23+
but especially for refactoring an integral part of the system, and designing
24+
it at the same time, at least for me it is impossible to provide smaller
25+
increments of work that don't leave the code in an uncompilable,
26+
non-functional state. \*
27+
28+
This adds a new `chainsync` package that receives new latest-block updates from
29+
an Ethereum JSON RPC server and backtracks a locally cached chain-segment of
30+
previous blocks in comparison with the updated header information. It does this
31+
in order to recognize reorgs and being able to invalidate all chain-state that
32+
was inserted for a reorged-away chain-segment. The information of the difference
33+
of old chain and new chain in case of reorgs is omitted by Ethereum JSON RPC
34+
servers, since it is possible that only the new latest header is received by the
35+
client, and intermediary sections of the new reorg chain are not passively
36+
received. Therefore the client itself has to keep track of the most recent chain
37+
and what gaps between the last common block of a potential new chain segment and
38+
it's old chain-state's segment have to be filled.
39+
40+
In addition to this active syncing mechanism, the `chainsync` package provides
41+
an easy way to register handler implementations that retrieve specific
42+
contract-event updates for the newly received chain-segments and the context of
43+
newly "reorged away" chain-segments are available in the same handler. That way,
44+
each handler can define behavior on how to remove old state-updates due to newly
45+
removed events and how to insert new state updates due to newly emitted events.
46+
47+
There is also the possibility to define and execute "chain-update" handler.
48+
Those will not only receive updates for when the newly synced to chain-segment
49+
contains a certain contract event, but they will be executed for every new chain
50+
update and will provide the same chain-update context as the contract-event
51+
handler.
52+
53+
# 3/4 - Implement event-handler
54+
55+
- This is part of a series of 4 Pull Requests that all aim to refactor our old
56+
chainsync mechanism. The reason to split this up is to provide more digestible
57+
and grouped parts of the refactoring effort. I am aware this is a big change,
58+
but especially for refactoring an integral part of the system, and designing
59+
it at the same time, at least for me it is impossible to provide smaller
60+
increments of work that don't leave the code in an uncompilable,
61+
non-functional state. \*
62+
63+
This will re-implement the event handling logic of the keyper and
64+
keyperimpl/gnosis packages for the new chainsync mechanism.
65+
66+
# 4/4 - Integrate the new chainsync handlers in the keyper packages
67+
68+
- This is part of a series of 4 Pull Requests that all aim to refactor our old
69+
chainsync mechanism. The reason to split this up is to provide more digestible
70+
and grouped parts of the refactoring effort. I am aware this is a big change,
71+
but especially for refactoring an integral part of the system, and designing
72+
it at the same time, at least for me it is impossible to provide smaller
73+
increments of work that don't leave the code in an uncompilable,
74+
non-functional state. \*
75+
76+
This will remove the old blockchain handling in the keyper and keyperimpl/gnosis
77+
packages and use the newly added re-implementation of this blockchain handling
78+
in the keyper packages.

rolling-shutter/chainobserver/db/keyper/keyper.sqlc.gen.go

+137
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rolling-shutter/chainobserver/db/keyper/sql/queries/keyper.sql

+39-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,42 @@ ORDER BY activation_block_number DESC LIMIT 1;
1818

1919
-- name: GetKeyperSets :many
2020
SELECT * FROM keyper_set
21-
ORDER BY activation_block_number ASC;
21+
ORDER BY activation_block_number ASC;
22+
23+
-- name: InsertSyncedBlock :exec
24+
INSERT INTO recent_block (
25+
block_hash,
26+
block_number,
27+
parent_hash,
28+
timestamp,
29+
header
30+
) VALUES (
31+
$1, $2, $3, $4, $5
32+
) ON CONFLICT DO UPDATE SET
33+
block_hash = $1,
34+
block_number =$2 ,
35+
parent_hash =$3,
36+
timestamp =$4 ,
37+
header =$5
38+
;
39+
40+
-- name: GetSyncedBlockByHash :one
41+
SELECT * FROM recent_block
42+
WHERE block_hash = $1;
43+
44+
-- name: DeleteSyncedBlockByHash :exec
45+
DELETE FROM recent_block
46+
WHERE block_hash = $1;
47+
48+
-- name: GetSyncedBlocks :many
49+
SELECT * FROM recent_block
50+
ORDER BY block_number DESC;
51+
52+
-- name: GetLatestSyncedBlocks :many
53+
SELECT * FROM recent_block
54+
ORDER BY block_number DESC
55+
LIMIT $1;
56+
57+
-- name: EvictSyncedBlocksBefore :exec
58+
DELETE FROM recent_block
59+
WHERE block_number < $1;

rolling-shutter/eonkeypublisher/eonkeypublisher.go

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ const (
2929
)
3030

3131
// EonKeyPublisher is a service that publishes eon keys via a eon key publisher contract.
32+
// E.g. in the Gnosis keyper implementation this is used to publish keys onchain
33+
// instead of broadcasting it on the p2p-network.
3234
type EonKeyPublisher struct {
3335
dbpool *pgxpool.Pool
3436
client *ethclient.Client

rolling-shutter/gnosisaccessnode/node.go

+30-53
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,17 @@ package gnosisaccessnode
22

33
import (
44
"context"
5+
"fmt"
56

7+
"github.com/ethereum/go-ethereum/ethclient"
68
"github.com/pkg/errors"
7-
"github.com/rs/zerolog/log"
89

9-
"github.com/shutter-network/shutter/shlib/shcrypto"
10-
11-
obskeyperdatabase "github.com/shutter-network/rolling-shutter/rolling-shutter/chainobserver/db/keyper"
1210
"github.com/shutter-network/rolling-shutter/rolling-shutter/gnosisaccessnode/storage"
13-
chainsync "github.com/shutter-network/rolling-shutter/rolling-shutter/medley/legacychainsync"
14-
syncevent "github.com/shutter-network/rolling-shutter/rolling-shutter/medley/legacychainsync/event"
11+
"github.com/shutter-network/rolling-shutter/rolling-shutter/gnosisaccessnode/synchandler"
12+
"github.com/shutter-network/rolling-shutter/rolling-shutter/medley/chainsync"
1513
"github.com/shutter-network/rolling-shutter/rolling-shutter/medley/metricsserver"
1614
"github.com/shutter-network/rolling-shutter/rolling-shutter/medley/service"
1715
"github.com/shutter-network/rolling-shutter/rolling-shutter/p2p"
18-
"github.com/shutter-network/rolling-shutter/rolling-shutter/shdb"
1916
)
2017

2118
type GnosisAccessNode struct {
@@ -40,59 +37,39 @@ func (node *GnosisAccessNode) Start(ctx context.Context, runner service.Runner)
4037
messageSender.AddMessageHandler(NewDecryptionKeysHandler(node.config, node.storage))
4138
services = append(services, messageSender)
4239

43-
chainSyncClient, err := chainsync.NewClient(
44-
ctx,
45-
chainsync.WithClientURL(node.config.GnosisNode.EthereumURL),
46-
chainsync.WithKeyperSetManager(node.config.Contracts.KeyperSetManager),
47-
chainsync.WithKeyBroadcastContract(node.config.Contracts.KeyBroadcastContract),
48-
chainsync.WithSyncNewKeyperSet(node.onNewKeyperSet),
49-
chainsync.WithSyncNewEonKey(node.onNewEonKey),
40+
ethClient, err := ethclient.DialContext(ctx, node.config.GnosisNode.EthereumURL)
41+
if err != nil {
42+
return err
43+
}
44+
keyperSetAdded, err := synchandler.NewKeyperSetAdded(
45+
ethClient,
46+
node.storage,
47+
node.config.Contracts.KeyperSetManager,
5048
)
5149
if err != nil {
52-
return errors.Wrap(err, "failed to initialize chain sync client")
50+
return err
5351
}
54-
services = append(services, chainSyncClient)
55-
52+
eonKeyBroadcast, err := synchandler.NewEonKeyBroadcast(
53+
node.storage,
54+
node.config.Contracts.KeyBroadcastContract,
55+
)
56+
if err != nil {
57+
return err
58+
}
59+
chainsyncOpts := []chainsync.Option{
60+
chainsync.WithClient(ethClient),
61+
chainsync.WithContractEventHandler(keyperSetAdded),
62+
chainsync.WithContractEventHandler(eonKeyBroadcast),
63+
}
64+
chainsyncer, err := chainsync.New(chainsyncOpts...)
65+
if err != nil {
66+
return fmt.Errorf("can't instantiate chainsync: %w", err)
67+
}
68+
services = append(services, chainsyncer)
5669
if node.config.Metrics.Enabled {
5770
metricsServer := metricsserver.New(node.config.Metrics)
5871
services = append(services, metricsServer)
5972
}
6073

6174
return runner.StartService(services...)
6275
}
63-
64-
func (node *GnosisAccessNode) onNewKeyperSet(_ context.Context, keyperSet *syncevent.KeyperSet) error {
65-
obsKeyperSet := obskeyperdatabase.KeyperSet{
66-
KeyperConfigIndex: int64(keyperSet.Eon),
67-
ActivationBlockNumber: int64(keyperSet.ActivationBlock),
68-
Keypers: shdb.EncodeAddresses(keyperSet.Members),
69-
Threshold: int32(keyperSet.Threshold),
70-
}
71-
log.Info().
72-
Uint64("keyper-config-index", keyperSet.Eon).
73-
Uint64("activation-block-number", keyperSet.ActivationBlock).
74-
Int("num-keypers", len(keyperSet.Members)).
75-
Uint64("threshold", keyperSet.Threshold).
76-
Msg("adding keyper set")
77-
node.storage.AddKeyperSet(keyperSet.Eon, &obsKeyperSet)
78-
return nil
79-
}
80-
81-
func (node *GnosisAccessNode) onNewEonKey(_ context.Context, eonKey *syncevent.EonPublicKey) error {
82-
key := new(shcrypto.EonPublicKey)
83-
err := key.Unmarshal(eonKey.Key)
84-
if err != nil {
85-
log.Error().
86-
Err(err).
87-
Hex("key", eonKey.Key).
88-
Int("keyper-config-index", int(eonKey.Eon)).
89-
Msg("received invalid eon key")
90-
return nil
91-
}
92-
log.Info().
93-
Int("keyper-config-index", int(eonKey.Eon)).
94-
Hex("key", eonKey.Key).
95-
Msg("adding eon key")
96-
node.storage.AddEonKey(eonKey.Eon, key)
97-
return nil
98-
}

0 commit comments

Comments
 (0)