Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions rolling-shutter/chainobserver/db/keyper/keyper.sqlc.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ ORDER BY activation_block_number DESC LIMIT 1;

-- name: GetKeyperSets :many
SELECT * FROM keyper_set
ORDER BY activation_block_number ASC;
ORDER BY activation_block_number ASC;

-- name: GetKeyperSetIndices :many
SELECT keyper_config_index FROM keyper_set
ORDER BY keyper_config_index ASC;
6 changes: 6 additions & 0 deletions rolling-shutter/keyperimpl/gnosis/keyper.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
sequencerBindings "github.com/shutter-network/gnosh-contracts/gnoshcontracts/sequencer"
validatorRegistryBindings "github.com/shutter-network/gnosh-contracts/gnoshcontracts/validatorregistry"

obskeyper "github.com/shutter-network/rolling-shutter/rolling-shutter/chainobserver/db/keyper"
"github.com/shutter-network/rolling-shutter/rolling-shutter/eonkeypublisher"
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper"
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper/epochkghandler"
Expand Down Expand Up @@ -109,6 +110,10 @@ func (kpr *Keyper) Start(ctx context.Context, runner service.Runner) error {
return errors.Wrap(err, "can't instantiate keyper core")
}

ksIndices, err := obskeyper.New(kpr.dbpool).GetKeyperSetIndices(ctx)
if err != nil {
return errors.Wrap(err, "failed to load keyper set indices")
}
kpr.chainSyncClient, err = chainsync.NewClient(
ctx,
chainsync.WithClientURL(kpr.config.Gnosis.Node.EthereumURL),
Expand All @@ -118,6 +123,7 @@ func (kpr *Keyper) Start(ctx context.Context, runner service.Runner) error {
chainsync.WithSyncNewKeyperSet(kpr.channelNewKeyperSet),
chainsync.WithPrivateKey(kpr.config.Gnosis.Node.PrivateKey.Key),
chainsync.WithLogger(gethLog.NewLogger(slog.Default().Handler())),
chainsync.WithKnownKeyperSetIndices(ksIndices),
)
if err != nil {
return err
Expand Down
5 changes: 5 additions & 0 deletions rolling-shutter/keyperimpl/optimism/keyper.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,18 @@ func (kpr *Keyper) Start(ctx context.Context, runner service.Runner) error {
if err != nil {
return errors.Wrap(err, "can't instantiate keyper core")
}
ksIndices, err := obskeyper.New(kpr.dbpool).GetKeyperSetIndices(ctx)
if err != nil {
return errors.Wrap(err, "failed to load keyper set indices")
}
// TODO: wrap the logger and pass in
kpr.l2Client, err = chainsync.NewClient(
ctx,
chainsync.WithClientURL(kpr.config.Optimism.JSONRPCURL),
chainsync.WithSyncNewBlock(kpr.newBlock),
chainsync.WithSyncNewKeyperSet(kpr.newKeyperSet),
chainsync.WithPrivateKey(kpr.config.Optimism.PrivateKey.Key),
chainsync.WithKnownKeyperSetIndices(ksIndices),
)
if err != nil {
return err
Expand Down
6 changes: 6 additions & 0 deletions rolling-shutter/keyperimpl/primev/keyper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
providerregistry "github.com/primev/mev-commit/contracts-abi/clients/ProviderRegistry"
"github.com/rs/zerolog/log"

obskeyper "github.com/shutter-network/rolling-shutter/rolling-shutter/chainobserver/db/keyper"
"github.com/shutter-network/rolling-shutter/rolling-shutter/eonkeypublisher"
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper"
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper/epochkghandler"
Expand Down Expand Up @@ -77,6 +78,10 @@ func (k *Keyper) Start(ctx context.Context, runner service.Runner) error {
return errors.Wrap(err, "can't instantiate keyper core")
}

ksIndices, err := obskeyper.New(k.dbpool).GetKeyperSetIndices(ctx)
if err != nil {
return errors.Wrap(err, "failed to load keyper set indices")
}
k.chainSyncClient, err = chainsync.NewClient(
ctx,
chainsync.WithClientURL(k.config.Chain.Node.EthereumURL),
Expand All @@ -86,6 +91,7 @@ func (k *Keyper) Start(ctx context.Context, runner service.Runner) error {
chainsync.WithSyncNewBlock(k.channelNewBlock),
chainsync.WithPrivateKey(k.config.Chain.Node.PrivateKey.Key),
chainsync.WithLogger(gethLog.NewLogger(slog.Default().Handler())),
chainsync.WithKnownKeyperSetIndices(ksIndices),
)
if err != nil {
return err
Expand Down
6 changes: 6 additions & 0 deletions rolling-shutter/keyperimpl/shutterservice/keyper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
triggerRegistryV1Bindings "github.com/shutter-network/contracts/v2/bindings/shuttereventtriggerregistryv1"
registryBindings "github.com/shutter-network/contracts/v2/bindings/shutterregistry"

obskeyper "github.com/shutter-network/rolling-shutter/rolling-shutter/chainobserver/db/keyper"
"github.com/shutter-network/rolling-shutter/rolling-shutter/eonkeypublisher"
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper"
"github.com/shutter-network/rolling-shutter/rolling-shutter/keyper/epochkghandler"
Expand Down Expand Up @@ -83,6 +84,10 @@ func (kpr *Keyper) Start(ctx context.Context, runner service.Runner) error {
if err != nil {
return errors.Wrap(err, "can't instantiate keyper core")
}
ksIndices, err := obskeyper.New(kpr.dbpool).GetKeyperSetIndices(ctx)
if err != nil {
return errors.Wrap(err, "failed to load keyper set indices")
}
kpr.chainSyncClient, err = chainsync.NewClient(
ctx,
chainsync.WithClientURL(kpr.config.Chain.Node.EthereumURL),
Expand All @@ -92,6 +97,7 @@ func (kpr *Keyper) Start(ctx context.Context, runner service.Runner) error {
chainsync.WithSyncNewKeyperSet(kpr.channelNewKeyperSet),
chainsync.WithPrivateKey(kpr.config.Chain.Node.PrivateKey.Key),
chainsync.WithLogger(gethLog.NewLogger(slog.Default().Handler())),
chainsync.WithKnownKeyperSetIndices(ksIndices),
)
if err != nil {
return err
Expand Down
27 changes: 18 additions & 9 deletions rolling-shutter/medley/chainsync/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ type options struct {
syncStart *number.BlockNumber
privKey *ecdsa.PrivateKey

handlerShutterState event.ShutterStateHandler
handlerKeyperSet event.KeyperSetHandler
handlerEonPublicKey event.EonPublicKeyHandler
handlerBlock event.BlockHandler
handlerShutterState event.ShutterStateHandler
handlerKeyperSet event.KeyperSetHandler
handlerEonPublicKey event.EonPublicKeyHandler
handlerBlock event.BlockHandler
knownKeyperSetIndices []int64
}

func (o *options) verify() error {
Expand Down Expand Up @@ -85,11 +86,12 @@ func (o *options) apply(ctx context.Context, c *Client) error {
return err
}
c.kssync = &syncer.KeyperSetSyncer{
Client: client,
Contract: c.KeyperSetManager,
Log: c.log,
StartBlock: o.syncStart,
Handler: o.handlerKeyperSet,
Client: client,
Contract: c.KeyperSetManager,
Log: c.log,
StartBlock: o.syncStart,
Handler: o.handlerKeyperSet,
KnownIndices: o.knownKeyperSetIndices,
}
if o.handlerKeyperSet != nil {
c.services = append(c.services, c.kssync)
Expand Down Expand Up @@ -214,6 +216,13 @@ func WithSyncNewKeyperSet(handler event.KeyperSetHandler) Option {
}
}

func WithKnownKeyperSetIndices(indices []int64) Option {
return func(o *options) error {
o.knownKeyperSetIndices = indices
return nil
}
}

func WithSyncNewBlock(handler event.BlockHandler) Option {
return func(o *options) error {
o.handlerBlock = handler
Expand Down
45 changes: 23 additions & 22 deletions rolling-shutter/medley/chainsync/syncer/keyperset.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ func makeCallError(attrName string, err error) error {
const channelSize = 10

type KeyperSetSyncer struct {
Client client.Client
Contract *bindings.KeyperSetManager
Log log.Logger
StartBlock *number.BlockNumber
Handler event.KeyperSetHandler
Client client.Client
Contract *bindings.KeyperSetManager
Log log.Logger
StartBlock *number.BlockNumber
Handler event.KeyperSetHandler
KnownIndices []int64

keyperAddedCh chan *bindings.KeyperSetManagerKeyperSetAdded
}
Expand Down Expand Up @@ -81,6 +82,20 @@ func (s *KeyperSetSyncer) Start(ctx context.Context, runner service.Runner) erro
return nil
}

func missingIndices(known []int64, total uint64) []uint64 {
knownSet := make(map[uint64]struct{}, len(known))
for _, k := range known {
knownSet[uint64(k)] = struct{}{} //nolint:gosec
}
var result []uint64
for i := uint64(0); i < total; i++ {
if _, ok := knownSet[i]; !ok {
result = append(result, i)
}
}
return result
}

func (s *KeyperSetSyncer) getInitialKeyperSets(ctx context.Context) ([]*event.KeyperSet, error) {
opts := &bind.CallOpts{
Context: ctx,
Expand All @@ -89,34 +104,20 @@ func (s *KeyperSetSyncer) getInitialKeyperSets(ctx context.Context) ([]*event.Ke
if err := guardCallOpts(opts, false); err != nil {
return nil, err
}
bn := s.StartBlock.ToUInt64Ptr()
if bn == nil {
// this should not be the case
return nil, errors.New("start block is 'latest'")
}

initialKeyperSets := []*event.KeyperSet{}
// this blocknumber specifies the argument to the contract
// getter
ks, err := s.GetKeyperSetForBlock(ctx, opts, s.StartBlock)
if err != nil {
return nil, err
}
initialKeyperSets = append(initialKeyperSets, ks)

numKS, err := s.Contract.GetNumKeyperSets(opts)
if err != nil {
return nil, err
}

for i := ks.Eon + 1; i < numKS; i++ {
ks, err = s.GetKeyperSetByIndex(ctx, opts, i)
var initialKeyperSets []*event.KeyperSet
for _, i := range missingIndices(s.KnownIndices, numKS) {
ks, err := s.GetKeyperSetByIndex(ctx, opts, i)
if err != nil {
return nil, err
}
initialKeyperSets = append(initialKeyperSets, ks)
}

return initialKeyperSets, nil
}

Expand Down
76 changes: 76 additions & 0 deletions rolling-shutter/medley/chainsync/syncer/keyperset_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package syncer

import (
"testing"

"gotest.tools/v3/assert"
)

func TestMissingIndices(t *testing.T) {
tests := []struct {
name string
known []int64
total uint64
want []uint64
}{
{
name: "nothing known, fetch all",
known: nil,
total: 4,
want: []uint64{0, 1, 2, 3},
},
{
name: "nothing known, empty contract",
known: nil,
total: 0,
want: nil,
},
{
name: "all known",
known: []int64{0, 1, 2, 3},
total: 4,
want: nil,
},
{
name: "gap at the start",
known: []int64{3, 4, 5},
total: 6,
want: []uint64{0, 1, 2},
},
{
name: "gap at the end",
known: []int64{0, 1, 2},
total: 6,
want: []uint64{3, 4, 5},
},
{
name: "gap in the middle",
known: []int64{0, 1, 5, 6},
total: 7,
want: []uint64{2, 3, 4},
},
{
name: "known indices beyond total are ignored",
known: []int64{0, 1, 10, 20},
total: 4,
want: []uint64{2, 3},
},
{
name: "duplicate known indices",
known: []int64{1, 1, 2, 2},
total: 4,
want: []uint64{0, 3},
},
{
name: "unordered known indices",
known: []int64{4, 1, 3},
total: 5,
want: []uint64{0, 2},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.DeepEqual(t, missingIndices(tc.known, tc.total), tc.want)
})
}
}