diff --git a/pkg/cannon/cannon.go b/pkg/cannon/cannon.go index 74bf4e5f..e9623904 100644 --- a/pkg/cannon/cannon.go +++ b/pkg/cannon/cannon.go @@ -337,8 +337,6 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { return err } - checkpointIteratorMetrics := iterator.NewCheckpointMetrics("xatu_cannon") - backfillingCheckpointIteratorMetrics := iterator.NewBackfillingCheckpointMetrics("xatu_cannon") blockprintIteratorMetrics := iterator.NewBlockprintMetrics("xatu_cannon") @@ -354,16 +352,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewAttesterSlashingDeriver( c.log, &c.Config.Derivers.AttesterSlashingConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_ATTESTER_SLASHING, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -371,16 +370,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewProposerSlashingDeriver( c.log, &c.Config.Derivers.ProposerSlashingConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_PROPOSER_SLASHING, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -388,16 +388,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewVoluntaryExitDeriver( c.log, &c.Config.Derivers.VoluntaryExitConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_VOLUNTARY_EXIT, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -405,16 +406,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewDepositDeriver( c.log, &c.Config.Derivers.DepositConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_DEPOSIT, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -422,16 +424,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewBLSToExecutionChangeDeriver( c.log, &c.Config.Derivers.BLSToExecutionConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_BLS_TO_EXECUTION_CHANGE, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -439,16 +442,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewExecutionTransactionDeriver( c.log, &c.Config.Derivers.ExecutionTransactionConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_EXECUTION_TRANSACTION, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -456,16 +460,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewWithdrawalDeriver( c.log, &c.Config.Derivers.WithdrawalConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_WITHDRAWAL, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -473,16 +478,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v2.NewBeaconBlockDeriver( c.log, &c.Config.Derivers.BeaconBlockConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -506,16 +512,17 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { v1.NewBeaconBlobDeriver( c.log, &c.Config.Derivers.BeaconBlobSidecarConfig, - iterator.NewCheckpointIterator( + iterator.NewBackfillingCheckpoint( c.log, networkName, networkID, xatu.CannonType_BEACON_API_ETH_V1_BEACON_BLOB_SIDECAR, c.coordinatorClient, wallclock, - &checkpointIteratorMetrics, + &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -533,6 +540,7 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -550,6 +558,7 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 3, ), c.beacon, clientMeta, @@ -567,6 +576,7 @@ func (c *Cannon) startBeaconBlockProcessor(ctx context.Context) error { &backfillingCheckpointIteratorMetrics, c.beacon, finalizedCheckpoint, + 2, ), c.beacon, clientMeta, diff --git a/pkg/cannon/deriver/beacon/eth/v1/beacon_blob.go b/pkg/cannon/deriver/beacon/eth/v1/beacon_blob.go index 25835ca4..3e9d1388 100644 --- a/pkg/cannon/deriver/beacon/eth/v1/beacon_blob.go +++ b/pkg/cannon/deriver/beacon/eth/v1/beacon_blob.go @@ -37,13 +37,13 @@ type BeaconBlobDeriverConfig struct { type BeaconBlobDeriver struct { log logrus.FieldLogger cfg *BeaconBlobDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewBeaconBlobDeriver(log logrus.FieldLogger, config *BeaconBlobDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *BeaconBlobDeriver { +func NewBeaconBlobDeriver(log logrus.FieldLogger, config *BeaconBlobDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *BeaconBlobDeriver { return &BeaconBlobDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v1/beacon_blob"), cfg: config, @@ -78,6 +78,10 @@ func (b *BeaconBlobDeriver) Start(ctx context.Context) error { b.log.Info("Beacon blob deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -118,18 +122,16 @@ func (b *BeaconBlobDeriver) run(rctx context.Context) { span.AddEvent("Grabbing next location") - // Get the next slot - location, _, err := b.iterator.Next(ctx) + // Get the next position. + position, err := b.iterator.Next(ctx) if err != nil { span.SetStatus(codes.Error, err.Error()) return err } - span.AddEvent("Obtained next location. Processing epoch...", trace.WithAttributes(attribute.Int64("location", int64(location.GetEthV1BeaconBlobSidecar().GetEpoch())))) - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV1BeaconBlobSidecar().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") @@ -138,8 +140,6 @@ func (b *BeaconBlobDeriver) run(rctx context.Context) { return err } - span.AddEvent("Epoch processing complete. Sending events...") - // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -149,17 +149,13 @@ func (b *BeaconBlobDeriver) run(rctx context.Context) { } } - span.AddEvent("Events sent. Updating location...") - // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { span.SetStatus(codes.Error, err.Error()) return err } - span.AddEvent("Location updated. Done.") - bo.Reset() return nil diff --git a/pkg/cannon/deriver/beacon/eth/v1/beacon_validators.go b/pkg/cannon/deriver/beacon/eth/v1/beacon_validators.go index 6dfbbd96..defe5d9a 100644 --- a/pkg/cannon/deriver/beacon/eth/v1/beacon_validators.go +++ b/pkg/cannon/deriver/beacon/eth/v1/beacon_validators.go @@ -82,6 +82,10 @@ func (b *BeaconValidatorsDeriver) Start(ctx context.Context) error { b.log.Info("Validator states deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -118,71 +122,28 @@ func (b *BeaconValidatorsDeriver) run(rctx context.Context) { return err } - // Get the next location. - location, _, err := b.iterator.Next(ctx) + // Get the next position. + position, err := b.iterator.Next(ctx) if err != nil { span.SetStatus(codes.Error, err.Error()) return err } - finality, err := b.beacon.Node().Finality() - if err != nil { - span.SetStatus(codes.Error, err.Error()) - - return errors.Wrap(err, "failed to get finality") - } - - if finality == nil { - span.SetStatus(codes.Error, "finality is nil") - - return errors.New("finality is nil") - } - - checkpoint := finality.Finalized - - processingFinalizedEpoch := false - epochToProcess := location.GetEthV1BeaconValidators().GetBackfillingCheckpointMarker().GetBackfillEpoch() - 1 - - if checkpoint.Epoch > phase0.Epoch(location.GetEthV1BeaconValidators().BackfillingCheckpointMarker.FinalizedEpoch) { - processingFinalizedEpoch = true - epochToProcess = int64(location.GetEthV1BeaconValidators().BackfillingCheckpointMarker.FinalizedEpoch) + 1 - } - - if !processingFinalizedEpoch && epochToProcess == -1 { - return nil - } - - events, slot, err := b.processEpoch(ctx, phase0.Epoch(epochToProcess)) + events, slot, err := b.processEpoch(ctx, position.Next) if err != nil { - b.log.WithError(err).WithField("epoch", epochToProcess).Error("Failed to process epoch") + b.log.WithError(err).WithField("epoch", position.Next).Error("Failed to process epoch") span.SetStatus(codes.Error, err.Error()) return err } + b.lookAhead(ctx, position.LookAheads) + // Be a good citizen and clean up the validator cache for the current epoch b.beacon.DeleteValidatorsFromCache(xatuethv1.SlotAsString(slot)) - if !processingFinalizedEpoch { - // If we are backfilling we can prewarm the validator cache with the next epoch's validators - spec, err := b.beacon.Node().Spec() - if err != nil { - return errors.Wrap(err, "failed to fetch spec") - } - - nextSlot := slot - spec.SlotsPerEpoch - if nextSlot > 0 { - b.log.WithFields(logrus.Fields{ - "next_state_id": nextSlot, - "current_state_id": slot, - }).Info("Prewarming validators cache") - - b.beacon.LazyLoadValidators(xatuethv1.SlotAsString(nextSlot)) - } - } - for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { span.SetStatus(codes.Error, err.Error()) @@ -191,30 +152,7 @@ func (b *BeaconValidatorsDeriver) run(rctx context.Context) { } } - if processingFinalizedEpoch { - location.Data = &xatu.CannonLocation_EthV1BeaconValidators{ - EthV1BeaconValidators: &xatu.CannonLocationEthV1BeaconValidators{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - BackfillEpoch: location.GetEthV1BeaconValidators().GetBackfillingCheckpointMarker().GetBackfillEpoch(), - FinalizedEpoch: uint64(epochToProcess), - }, - }, - } - } else { - location.Data = &xatu.CannonLocation_EthV1BeaconValidators{ - EthV1BeaconValidators: &xatu.CannonLocationEthV1BeaconValidators{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - BackfillEpoch: epochToProcess, - FinalizedEpoch: location.GetEthV1BeaconValidators().GetBackfillingCheckpointMarker().GetFinalizedEpoch(), - }, - }, - } - } - - span.SetAttributes(attribute.Int64("epoch", epochToProcess)) - span.SetAttributes(attribute.Bool("is_backfill", !processingFinalizedEpoch)) - - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { span.SetStatus(codes.Error, err.Error()) return err @@ -234,6 +172,30 @@ func (b *BeaconValidatorsDeriver) run(rctx context.Context) { } } +// lookAhead takes the upcoming epochs and looks ahead to do any pre-processing that might be required. +func (b *BeaconValidatorsDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { + _, span := observability.Tracer().Start(ctx, + "BeaconValidatorsDeriver.lookAhead", + ) + defer span.End() + + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") + + return + } + + for _, epoch := range epochs { + for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { + slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) + + // Add the state to the preload queue so it's available when we need it + b.beacon.LazyLoadValidators(xatuethv1.SlotAsString(slot)) + } + } +} + func (b *BeaconValidatorsDeriver) processEpoch(ctx context.Context, epoch phase0.Epoch) ([]*xatu.DecoratedEvent, phase0.Slot, error) { ctx, span := observability.Tracer().Start(ctx, "BeaconValidatorsDeriver.processEpoch", diff --git a/pkg/cannon/deriver/beacon/eth/v1/proposer_duty.go b/pkg/cannon/deriver/beacon/eth/v1/proposer_duty.go index f89a4b88..9b0a074b 100644 --- a/pkg/cannon/deriver/beacon/eth/v1/proposer_duty.go +++ b/pkg/cannon/deriver/beacon/eth/v1/proposer_duty.go @@ -77,6 +77,10 @@ func (b *ProposerDutyDeriver) Start(ctx context.Context) error { b.log.Info("Proposer duty deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -113,54 +117,16 @@ func (b *ProposerDutyDeriver) run(rctx context.Context) { return err } - // Get the next location. - location, _, err := b.iterator.Next(ctx) + // Get the next position. + position, err := b.iterator.Next(ctx) if err != nil { span.SetStatus(codes.Error, err.Error()) return err } - /* - Because we are using a backfilling-checkpoint iterator we will - be responsible for deciding which epoch to process, and will update the - location after-the-fact accordingly. - - If the beacon node tells us our finalized_epoch is behind, we'll - process the finalized_epoch. Otherwise we'll process the backfill_epoch - until we are at epoch 0. - */ - - finality, err := b.beacon.Node().Finality() - if err != nil { - span.SetStatus(codes.Error, err.Error()) - - return errors.Wrap(err, "failed to get finality") - } - - if finality == nil { - span.SetStatus(codes.Error, "finality is nil") - - return errors.New("finality is nil") - } - - checkpoint := finality.Finalized - - processingFinalizedEpoch := false - epochToProcess := location.GetEthV1BeaconProposerDuty().GetBackfillingCheckpointMarker().GetBackfillEpoch() - 1 - - if checkpoint.Epoch > phase0.Epoch(location.GetEthV1BeaconProposerDuty().BackfillingCheckpointMarker.FinalizedEpoch) { - processingFinalizedEpoch = true - epochToProcess = int64(location.GetEthV1BeaconProposerDuty().BackfillingCheckpointMarker.FinalizedEpoch) + 1 - } - - if !processingFinalizedEpoch && epochToProcess == -1 { - // We're up to date! We can safely return here and let the iterator sleep us until it thinks we're ready to process again. - return nil - } - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(epochToProcess)) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") @@ -169,6 +135,9 @@ func (b *ProposerDutyDeriver) run(rctx context.Context) { return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -178,31 +147,8 @@ func (b *ProposerDutyDeriver) run(rctx context.Context) { } } - if processingFinalizedEpoch { - location.Data = &xatu.CannonLocation_EthV1BeaconProposerDuty{ - EthV1BeaconProposerDuty: &xatu.CannonLocationEthV1BeaconProposerDuty{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - BackfillEpoch: location.GetEthV1BeaconProposerDuty().GetBackfillingCheckpointMarker().GetBackfillEpoch(), - FinalizedEpoch: uint64(epochToProcess), - }, - }, - } - } else { - location.Data = &xatu.CannonLocation_EthV1BeaconProposerDuty{ - EthV1BeaconProposerDuty: &xatu.CannonLocationEthV1BeaconProposerDuty{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - BackfillEpoch: epochToProcess, - FinalizedEpoch: location.GetEthV1BeaconProposerDuty().GetBackfillingCheckpointMarker().GetFinalizedEpoch(), - }, - }, - } - } - - span.SetAttributes(attribute.Int64("epoch", epochToProcess)) - span.SetAttributes(attribute.Bool("is_backfill", !processingFinalizedEpoch)) - // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { span.SetStatus(codes.Error, err.Error()) return err @@ -255,6 +201,30 @@ func (b *ProposerDutyDeriver) processEpoch(ctx context.Context, epoch phase0.Epo return allEvents, nil } +// lookAhead takes the upcoming epochs and looks ahead to do any pre-processing that might be required. +func (b *ProposerDutyDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { + _, span := observability.Tracer().Start(ctx, + "ProposerDutyDeriver.lookAhead", + ) + defer span.End() + + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") + + return + } + + for _, epoch := range epochs { + for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { + slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) + + // Add the block to the preload queue so it's available when we need it + b.beacon.LazyLoadBeaconBlock(xatuethv1.SlotAsString(slot)) + } + } +} + func (b *ProposerDutyDeriver) createEventFromProposerDuty(ctx context.Context, duty *apiv1.ProposerDuty) (*xatu.DecoratedEvent, error) { // Make a clone of the metadata metadata, ok := proto.Clone(b.clientMeta).(*xatu.ClientMeta) diff --git a/pkg/cannon/deriver/beacon/eth/v2/attester_slashing.go b/pkg/cannon/deriver/beacon/eth/v2/attester_slashing.go index 56a9f28a..d6c65713 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/attester_slashing.go +++ b/pkg/cannon/deriver/beacon/eth/v2/attester_slashing.go @@ -34,13 +34,13 @@ type AttesterSlashingDeriverConfig struct { type AttesterSlashingDeriver struct { log logrus.FieldLogger cfg *AttesterSlashingDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewAttesterSlashingDeriver(log logrus.FieldLogger, config *AttesterSlashingDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *AttesterSlashingDeriver { +func NewAttesterSlashingDeriver(log logrus.FieldLogger, config *AttesterSlashingDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *AttesterSlashingDeriver { return &AttesterSlashingDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/attester_slashing"), cfg: config, @@ -75,6 +75,10 @@ func (a *AttesterSlashingDeriver) Start(ctx context.Context) error { a.log.Info("Attester slashing deriver enabled") + if err := a.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop go a.run(ctx) @@ -109,22 +113,22 @@ func (a *AttesterSlashingDeriver) run(rctx context.Context) { } // Get the next slot - location, lookAhead, err := a.iterator.Next(ctx) + position, err := a.iterator.Next(ctx) if err != nil { return err } - // Look ahead - a.lookAheadAtLocations(ctx, lookAhead) - // Process the epoch - events, err := a.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlockAttesterSlashing().GetEpoch())) + events, err := a.processEpoch(ctx, position.Next) if err != nil { a.log.WithError(err).Error("Failed to process epoch") return err } + // Look ahead + a.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range a.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -133,7 +137,7 @@ func (a *AttesterSlashingDeriver) run(rctx context.Context) { } // Update our location - if err := a.iterator.UpdateLocation(ctx, location); err != nil { + if err := a.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { return err } @@ -151,28 +155,21 @@ func (a *AttesterSlashingDeriver) run(rctx context.Context) { } } -// lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (a *AttesterSlashingDeriver) lookAheadAtLocations(ctx context.Context, locations []*xatu.CannonLocation) { +// lookAhead takes the upcoming epochs and looks ahead to do any pre-processing that might be required. +func (a *AttesterSlashingDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, - "AttesterSlashingDeriver.lookAheadAtLocations", + "AttesterSlashingDeriver.lookAhead", ) defer span.End() - if locations == nil { + sp, err := a.beacon.Node().Spec() + if err != nil { + a.log.WithError(err).Warn("Failed to look ahead at epoch") + return } - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlockAttesterSlashing().GetEpoch()) - - sp, err := a.beacon.Node().Spec() - if err != nil { - a.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") - - return - } - + for _, epoch := range epochs { for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) diff --git a/pkg/cannon/deriver/beacon/eth/v2/beacon_block.go b/pkg/cannon/deriver/beacon/eth/v2/beacon_block.go index 9d223ff3..6d6011af 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/beacon_block.go +++ b/pkg/cannon/deriver/beacon/eth/v2/beacon_block.go @@ -39,13 +39,13 @@ type BeaconBlockDeriverConfig struct { type BeaconBlockDeriver struct { log logrus.FieldLogger cfg *BeaconBlockDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewBeaconBlockDeriver(log logrus.FieldLogger, config *BeaconBlockDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *BeaconBlockDeriver { +func NewBeaconBlockDeriver(log logrus.FieldLogger, config *BeaconBlockDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *BeaconBlockDeriver { return &BeaconBlockDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/beacon_block"), cfg: config, @@ -80,6 +80,10 @@ func (b *BeaconBlockDeriver) Start(ctx context.Context) error { b.log.Info("Beacon block deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -110,33 +114,25 @@ func (b *BeaconBlockDeriver) run(rctx context.Context) { time.Sleep(100 * time.Millisecond) - span.AddEvent("Checking if beacon node is synced") - if err := b.beacon.Synced(ctx); err != nil { span.SetStatus(codes.Error, err.Error()) return err } - span.AddEvent("Grabbing next location") - // Get the next slot - location, lookAhead, err := b.iterator.Next(ctx) + position, err := b.iterator.Next(ctx) if err != nil { span.SetStatus(codes.Error, err.Error()) return err } - span.AddEvent("Obtained next location, looking ahead...", trace.WithAttributes(attribute.Int64("location", int64(location.GetEthV2BeaconBlock().GetEpoch())))) - // Look ahead - b.lookAheadAtLocation(ctx, lookAhead) - - span.AddEvent("Look ahead complete. Processing epoch...") + b.lookAhead(ctx, position.LookAheads) // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlock().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") @@ -159,7 +155,7 @@ func (b *BeaconBlockDeriver) run(rctx context.Context) { span.AddEvent("Events sent. Updating location...") // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { span.SetStatus(codes.Error, err.Error()) return err @@ -172,35 +168,30 @@ func (b *BeaconBlockDeriver) run(rctx context.Context) { return nil } - if err := backoff.Retry(operation, bo); err != nil { - b.log.WithError(err).Error("Failed to process location") + if err := backoff.RetryNotify(operation, bo, func(err error, timer time.Duration) { + b.log.WithError(err).WithField("next_attempt", timer).Warn("Failed to process") + }); err != nil { + b.log.WithError(err).Warn("Failed to process") } } } } -// lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (b *BeaconBlockDeriver) lookAheadAtLocation(ctx context.Context, locations []*xatu.CannonLocation) { +// lookAhead takes the upcoming epochs and looks ahead to do any pre-processing that might be required. +func (b *BeaconBlockDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, - "BeaconBlockDeriver.lookAheadAtLocations", + "BeaconBlockDeriver.lookAhead", ) defer span.End() - if locations == nil { + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") + return } - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlock().GetEpoch()) - - sp, err := b.beacon.Node().Spec() - if err != nil { - b.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") - - return - } - + for _, epoch := range epochs { for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) diff --git a/pkg/cannon/deriver/beacon/eth/v2/bls_to_execution_change.go b/pkg/cannon/deriver/beacon/eth/v2/bls_to_execution_change.go index 9b57ae57..58625bb2 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/bls_to_execution_change.go +++ b/pkg/cannon/deriver/beacon/eth/v2/bls_to_execution_change.go @@ -36,13 +36,13 @@ type BLSToExecutionChangeDeriverConfig struct { type BLSToExecutionChangeDeriver struct { log logrus.FieldLogger cfg *BLSToExecutionChangeDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewBLSToExecutionChangeDeriver(log logrus.FieldLogger, config *BLSToExecutionChangeDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *BLSToExecutionChangeDeriver { +func NewBLSToExecutionChangeDeriver(log logrus.FieldLogger, config *BLSToExecutionChangeDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *BLSToExecutionChangeDeriver { return &BLSToExecutionChangeDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/bls_to_execution_change"), cfg: config, @@ -77,6 +77,10 @@ func (b *BLSToExecutionChangeDeriver) Start(ctx context.Context) error { b.log.Info("BLS to execution change deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -109,23 +113,23 @@ func (b *BLSToExecutionChangeDeriver) run(rctx context.Context) { return err } - // Get the next slot - location, lookAheads, err := b.iterator.Next(ctx) + // Get the next position + position, err := b.iterator.Next(ctx) if err != nil { return err } - // Look ahead - b.lookAheadAtLocation(ctx, lookAheads) - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlockBlsToExecutionChange().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -134,7 +138,7 @@ func (b *BLSToExecutionChangeDeriver) run(rctx context.Context) { } // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { return err } @@ -153,27 +157,20 @@ func (b *BLSToExecutionChangeDeriver) run(rctx context.Context) { } // lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (b *BLSToExecutionChangeDeriver) lookAheadAtLocation(ctx context.Context, locations []*xatu.CannonLocation) { +func (b *BLSToExecutionChangeDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, - "BLSToExecutionChangeDeriver.lookAheadAtLocations", + "BLSToExecutionChangeDeriver.lookAhead", ) defer span.End() - if locations == nil { + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") + return } - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlockBlsToExecutionChange().GetEpoch()) - - sp, err := b.beacon.Node().Spec() - if err != nil { - b.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") - - return - } - + for _, epoch := range epochs { for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) diff --git a/pkg/cannon/deriver/beacon/eth/v2/deposit.go b/pkg/cannon/deriver/beacon/eth/v2/deposit.go index 6c03eea8..5d7ad2af 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/deposit.go +++ b/pkg/cannon/deriver/beacon/eth/v2/deposit.go @@ -34,13 +34,13 @@ type DepositDeriverConfig struct { type DepositDeriver struct { log logrus.FieldLogger cfg *DepositDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewDepositDeriver(log logrus.FieldLogger, config *DepositDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *DepositDeriver { +func NewDepositDeriver(log logrus.FieldLogger, config *DepositDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *DepositDeriver { return &DepositDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/deposit"), cfg: config, @@ -75,6 +75,10 @@ func (b *DepositDeriver) Start(ctx context.Context) error { b.log.Info("Deposit deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -107,23 +111,23 @@ func (b *DepositDeriver) run(rctx context.Context) { return err } - // Get the next slot - location, lookAhead, err := b.iterator.Next(ctx) + // Get the next position + position, err := b.iterator.Next(ctx) if err != nil { return err } - // Look ahead - b.lookAheadAtLocation(ctx, lookAhead) - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlockDeposit().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -132,7 +136,7 @@ func (b *DepositDeriver) run(rctx context.Context) { } // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { return err } @@ -150,28 +154,21 @@ func (b *DepositDeriver) run(rctx context.Context) { } } -// lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (b *DepositDeriver) lookAheadAtLocation(ctx context.Context, locations []*xatu.CannonLocation) { +// lookAhead attempts to pre-load any blocks that might be required for the epochs that are coming up. +func (b *DepositDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, - "DepositDeriver.lookAheadAtLocations", + "DepositDeriver.lookAhead", ) defer span.End() - if locations == nil { + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") + return } - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlockDeposit().GetEpoch()) - - sp, err := b.beacon.Node().Spec() - if err != nil { - b.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") - - return - } - + for _, epoch := range epochs { for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) diff --git a/pkg/cannon/deriver/beacon/eth/v2/elaborated_attestation.go b/pkg/cannon/deriver/beacon/eth/v2/elaborated_attestation.go index 98c165ac..0f8ebab1 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/elaborated_attestation.go +++ b/pkg/cannon/deriver/beacon/eth/v2/elaborated_attestation.go @@ -76,6 +76,10 @@ func (b *ElaboratedAttestationDeriver) Start(ctx context.Context) error { b.log.Info("Elaborated attestation deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -112,54 +116,16 @@ func (b *ElaboratedAttestationDeriver) run(rctx context.Context) { return err } - // Get the next location. - location, _, err := b.iterator.Next(ctx) + // Get the next position. + position, err := b.iterator.Next(ctx) if err != nil { span.SetStatus(codes.Error, err.Error()) return err } - /* - Because we are using a backfilling-checkpoint iterator we will - be responsible for deciding which epoch to process, and will update the - location after-the-fact accordingly. - - If the beacon node tells us our finalized_epoch is behind, we'll - process the finalized_epoch. Otherwise we'll process the backfill_epoch - until we are at epoch 0. - */ - - finality, err := b.beacon.Node().Finality() - if err != nil { - span.SetStatus(codes.Error, err.Error()) - - return errors.Wrap(err, "failed to get finality") - } - - if finality == nil { - span.SetStatus(codes.Error, "finality is nil") - - return errors.New("finality is nil") - } - - checkpoint := finality.Finalized - - processingFinalizedEpoch := false - epochToProcess := location.GetEthV2BeaconBlockElaboratedAttestation().GetBackfillingCheckpointMarker().GetBackfillEpoch() - 1 - - if checkpoint.Epoch > phase0.Epoch(location.GetEthV2BeaconBlockElaboratedAttestation().BackfillingCheckpointMarker.FinalizedEpoch) { - processingFinalizedEpoch = true - epochToProcess = int64(location.GetEthV2BeaconBlockElaboratedAttestation().BackfillingCheckpointMarker.FinalizedEpoch) + 1 - } - - if !processingFinalizedEpoch && epochToProcess == -1 { - // We're up to date! We can safely return here and let the iterator sleep us until it thinks we're ready to process again. - return nil - } - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(epochToProcess)) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") @@ -168,6 +134,9 @@ func (b *ElaboratedAttestationDeriver) run(rctx context.Context) { return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -177,31 +146,8 @@ func (b *ElaboratedAttestationDeriver) run(rctx context.Context) { } } - if processingFinalizedEpoch { - location.Data = &xatu.CannonLocation_EthV2BeaconBlockElaboratedAttestation{ - EthV2BeaconBlockElaboratedAttestation: &xatu.CannonLocationEthV2BeaconBlockElaboratedAttestation{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - BackfillEpoch: location.GetEthV2BeaconBlockElaboratedAttestation().GetBackfillingCheckpointMarker().GetBackfillEpoch(), - FinalizedEpoch: uint64(epochToProcess), - }, - }, - } - } else { - location.Data = &xatu.CannonLocation_EthV2BeaconBlockElaboratedAttestation{ - EthV2BeaconBlockElaboratedAttestation: &xatu.CannonLocationEthV2BeaconBlockElaboratedAttestation{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - BackfillEpoch: epochToProcess, - FinalizedEpoch: location.GetEthV2BeaconBlockElaboratedAttestation().GetBackfillingCheckpointMarker().GetFinalizedEpoch(), - }, - }, - } - } - - span.SetAttributes(attribute.Int64("epoch", epochToProcess)) - span.SetAttributes(attribute.Bool("is_backfill", !processingFinalizedEpoch)) - // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { span.SetStatus(codes.Error, err.Error()) return err @@ -276,6 +222,30 @@ func (b *ElaboratedAttestationDeriver) processSlot(ctx context.Context, slot pha return events, nil } +// lookAhead attempts to pre-load any blocks that might be required for the epochs that are coming up. +func (b *ElaboratedAttestationDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { + _, span := observability.Tracer().Start(ctx, + "ElaboratedAttestationDeriver.lookAhead", + ) + defer span.End() + + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") + + return + } + + for _, epoch := range epochs { + for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { + slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) + + // Add the block to the preload queue so it's available when we need it + b.beacon.LazyLoadBeaconBlock(xatuethv1.SlotAsString(slot)) + } + } +} + func (b *ElaboratedAttestationDeriver) getElaboratedAttestations(ctx context.Context, block *spec.VersionedSignedBeaconBlock) ([]*xatu.DecoratedEvent, error) { blockAttestations, err := block.Attestations() if err != nil { diff --git a/pkg/cannon/deriver/beacon/eth/v2/execution_transaction.go b/pkg/cannon/deriver/beacon/eth/v2/execution_transaction.go index 0ecf83bd..ccfab72b 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/execution_transaction.go +++ b/pkg/cannon/deriver/beacon/eth/v2/execution_transaction.go @@ -31,7 +31,7 @@ import ( type ExecutionTransactionDeriver struct { log logrus.FieldLogger cfg *ExecutionTransactionDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta @@ -45,7 +45,7 @@ const ( ExecutionTransactionDeriverName = xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_EXECUTION_TRANSACTION ) -func NewExecutionTransactionDeriver(log logrus.FieldLogger, config *ExecutionTransactionDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *ExecutionTransactionDeriver { +func NewExecutionTransactionDeriver(log logrus.FieldLogger, config *ExecutionTransactionDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *ExecutionTransactionDeriver { return &ExecutionTransactionDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/execution_transaction"), cfg: config, @@ -80,6 +80,10 @@ func (b *ExecutionTransactionDeriver) Start(ctx context.Context) error { b.log.Info("Execution transaction deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -112,23 +116,23 @@ func (b *ExecutionTransactionDeriver) run(rctx context.Context) { return err } - // Get the next slot - location, lookAhead, err := b.iterator.Next(ctx) + // Get the next position + position, err := b.iterator.Next(ctx) if err != nil { return err } - // Look ahead - b.lookAheadAtLocation(ctx, lookAhead) - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlockExecutionTransaction().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -137,7 +141,7 @@ func (b *ExecutionTransactionDeriver) run(rctx context.Context) { } // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { return err } @@ -183,24 +187,21 @@ func (b *ExecutionTransactionDeriver) processEpoch(ctx context.Context, epoch ph return allEvents, nil } -// lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (b *ExecutionTransactionDeriver) lookAheadAtLocation(ctx context.Context, locations []*xatu.CannonLocation) { +// lookAhead attempts to pre-load any blocks that might be required for the epochs that are coming up. +func (b *ExecutionTransactionDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, - "ExecutionTransactionDeriver.lookAheadAtLocations", + "ExecutionTransactionDeriver.lookAhead", ) defer span.End() - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlockExecutionTransaction().GetEpoch()) - - sp, err := b.beacon.Node().Spec() - if err != nil { - b.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") - return - } + return + } + for _, epoch := range epochs { for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) diff --git a/pkg/cannon/deriver/beacon/eth/v2/proposer_slashing.go b/pkg/cannon/deriver/beacon/eth/v2/proposer_slashing.go index 72aeaf8f..087befce 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/proposer_slashing.go +++ b/pkg/cannon/deriver/beacon/eth/v2/proposer_slashing.go @@ -34,13 +34,13 @@ type ProposerSlashingDeriverConfig struct { type ProposerSlashingDeriver struct { log logrus.FieldLogger cfg *ProposerSlashingDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewProposerSlashingDeriver(log logrus.FieldLogger, config *ProposerSlashingDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *ProposerSlashingDeriver { +func NewProposerSlashingDeriver(log logrus.FieldLogger, config *ProposerSlashingDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *ProposerSlashingDeriver { return &ProposerSlashingDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/proposer_slashing"), cfg: config, @@ -75,6 +75,10 @@ func (b *ProposerSlashingDeriver) Start(ctx context.Context) error { b.log.Info("Proposer slashing deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -107,23 +111,23 @@ func (b *ProposerSlashingDeriver) run(rctx context.Context) { return err } - // Get the next slot - location, lookAhead, err := b.iterator.Next(ctx) + // Get the next position + position, err := b.iterator.Next(ctx) if err != nil { return err } - // Look ahead - b.lookAheadAtLocation(ctx, lookAhead) - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlockProposerSlashing().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -132,7 +136,7 @@ func (b *ProposerSlashingDeriver) run(rctx context.Context) { } // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { return err } @@ -257,28 +261,25 @@ func (b *ProposerSlashingDeriver) getProposerSlashings(ctx context.Context, bloc return slashings, nil } -// lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (b *ProposerSlashingDeriver) lookAheadAtLocation(ctx context.Context, locations []*xatu.CannonLocation) { +// lookAhead attempts to pre-load any blocks that might be required for the epochs that are coming up. +func (b *ProposerSlashingDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, - "ProposerSlashingDeriver.lookAheadAtLocations", + "ProposerSlashingDeriver.lookAhead", ) defer span.End() - if locations == nil { + if epochs == nil { return } - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlockProposerSlashing().GetEpoch()) - - sp, err := b.beacon.Node().Spec() - if err != nil { - b.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") - return - } + return + } + for _, epoch := range epochs { for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) diff --git a/pkg/cannon/deriver/beacon/eth/v2/voluntary_exit.go b/pkg/cannon/deriver/beacon/eth/v2/voluntary_exit.go index 270aa48e..ef9db7c9 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/voluntary_exit.go +++ b/pkg/cannon/deriver/beacon/eth/v2/voluntary_exit.go @@ -34,13 +34,13 @@ type VoluntaryExitDeriverConfig struct { type VoluntaryExitDeriver struct { log logrus.FieldLogger cfg *VoluntaryExitDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewVoluntaryExitDeriver(log logrus.FieldLogger, config *VoluntaryExitDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *VoluntaryExitDeriver { +func NewVoluntaryExitDeriver(log logrus.FieldLogger, config *VoluntaryExitDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *VoluntaryExitDeriver { return &VoluntaryExitDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/voluntary_exit"), cfg: config, @@ -75,6 +75,10 @@ func (b *VoluntaryExitDeriver) Start(ctx context.Context) error { b.log.Info("Voluntary exit deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -107,23 +111,23 @@ func (b *VoluntaryExitDeriver) run(rctx context.Context) { return err } - // Get the next slot - location, lookAhead, err := b.iterator.Next(ctx) + // Get the next position + position, err := b.iterator.Next(ctx) if err != nil { return err } - // Look ahead - b.lookAheadAtLocation(ctx, lookAhead) - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlockVoluntaryExit().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + // Send the events for _, fn := range b.onEventsCallbacks { if err := fn(ctx, events); err != nil { @@ -132,7 +136,7 @@ func (b *VoluntaryExitDeriver) run(rctx context.Context) { } // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { return err } @@ -150,21 +154,18 @@ func (b *VoluntaryExitDeriver) run(rctx context.Context) { } } -// lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (b *VoluntaryExitDeriver) lookAheadAtLocation(ctx context.Context, locations []*xatu.CannonLocation) { +// lookAhead attempts to pre-load any blocks that might be required for the epochs that are coming up. +func (b *VoluntaryExitDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, "VoluntaryExitDeriver.lookAheadAtLocations", ) defer span.End() - if locations == nil { + if epochs == nil { return } - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlockVoluntaryExit().GetEpoch()) - + for _, epoch := range epochs { sp, err := b.beacon.Node().Spec() if err != nil { b.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") diff --git a/pkg/cannon/deriver/beacon/eth/v2/withdrawal.go b/pkg/cannon/deriver/beacon/eth/v2/withdrawal.go index 6ee25042..d45a7774 100644 --- a/pkg/cannon/deriver/beacon/eth/v2/withdrawal.go +++ b/pkg/cannon/deriver/beacon/eth/v2/withdrawal.go @@ -34,13 +34,13 @@ type WithdrawalDeriverConfig struct { type WithdrawalDeriver struct { log logrus.FieldLogger cfg *WithdrawalDeriverConfig - iterator *iterator.CheckpointIterator + iterator *iterator.BackfillingCheckpoint onEventsCallbacks []func(ctx context.Context, events []*xatu.DecoratedEvent) error beacon *ethereum.BeaconNode clientMeta *xatu.ClientMeta } -func NewWithdrawalDeriver(log logrus.FieldLogger, config *WithdrawalDeriverConfig, iter *iterator.CheckpointIterator, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *WithdrawalDeriver { +func NewWithdrawalDeriver(log logrus.FieldLogger, config *WithdrawalDeriverConfig, iter *iterator.BackfillingCheckpoint, beacon *ethereum.BeaconNode, clientMeta *xatu.ClientMeta) *WithdrawalDeriver { return &WithdrawalDeriver{ log: log.WithField("module", "cannon/event/beacon/eth/v2/withdrawal"), cfg: config, @@ -75,6 +75,10 @@ func (b *WithdrawalDeriver) Start(ctx context.Context) error { b.log.Info("Withdrawal deriver enabled") + if err := b.iterator.Start(ctx); err != nil { + return errors.Wrap(err, "failed to start iterator") + } + // Start our main loop b.run(ctx) @@ -107,23 +111,23 @@ func (b *WithdrawalDeriver) run(rctx context.Context) { return err } - // Get the next slot - location, lookAhead, err := b.iterator.Next(ctx) + // Get the next position + position, err := b.iterator.Next(ctx) if err != nil { return err } - // Look ahead - b.lookAheadAtLocation(ctx, lookAhead) - // Process the epoch - events, err := b.processEpoch(ctx, phase0.Epoch(location.GetEthV2BeaconBlockWithdrawal().GetEpoch())) + events, err := b.processEpoch(ctx, position.Next) if err != nil { b.log.WithError(err).Error("Failed to process epoch") return err } + // Look ahead + b.lookAhead(ctx, position.LookAheads) + for _, fn := range b.onEventsCallbacks { if errr := fn(ctx, events); errr != nil { return errors.Wrapf(errr, "failed to send events") @@ -131,7 +135,7 @@ func (b *WithdrawalDeriver) run(rctx context.Context) { } // Update our location - if err := b.iterator.UpdateLocation(ctx, location); err != nil { + if err := b.iterator.UpdateLocation(ctx, position.Next, position.Direction); err != nil { return err } @@ -218,28 +222,21 @@ func (b *WithdrawalDeriver) processSlot(ctx context.Context, slot phase0.Slot) ( return events, nil } -// lookAheadAtLocation takes the upcoming locations and looks ahead to do any pre-processing that might be required. -func (b *WithdrawalDeriver) lookAheadAtLocation(ctx context.Context, locations []*xatu.CannonLocation) { +// lookAhead attempts to pre-load any blocks that might be required for the epochs that are coming up. +func (b *WithdrawalDeriver) lookAhead(ctx context.Context, epochs []phase0.Epoch) { _, span := observability.Tracer().Start(ctx, - "WithdrawalDeriver.lookAheadAtLocations", + "WithdrawalDeriver.lookAhead", ) defer span.End() - if locations == nil { + sp, err := b.beacon.Node().Spec() + if err != nil { + b.log.WithError(err).Warn("Failed to look ahead at epoch") + return } - for _, location := range locations { - // Get the next look ahead epoch - epoch := phase0.Epoch(location.GetEthV2BeaconBlockWithdrawal().GetEpoch()) - - sp, err := b.beacon.Node().Spec() - if err != nil { - b.log.WithError(err).WithField("epoch", epoch).Warn("Failed to look ahead at epoch") - - return - } - + for _, epoch := range epochs { for i := uint64(0); i <= uint64(sp.SlotsPerEpoch-1); i++ { slot := phase0.Slot(i + uint64(epoch)*uint64(sp.SlotsPerEpoch)) diff --git a/pkg/cannon/deriver/blockprint/block_classification.go b/pkg/cannon/deriver/blockprint/block_classification.go index 2f96b70d..1033c875 100644 --- a/pkg/cannon/deriver/blockprint/block_classification.go +++ b/pkg/cannon/deriver/blockprint/block_classification.go @@ -117,7 +117,7 @@ func (b *BlockClassificationDeriver) run(rctx context.Context) { time.Sleep(1000 * time.Millisecond) // Get the next slot - location, _, err := b.iterator.Next(ctx) + location, err := b.iterator.Next(ctx) if err != nil { return err } diff --git a/pkg/cannon/iterator/backfilling_checkpoint_iterator.go b/pkg/cannon/iterator/backfilling_checkpoint_iterator.go index 6a8fd3f7..2dee7d2a 100644 --- a/pkg/cannon/iterator/backfilling_checkpoint_iterator.go +++ b/pkg/cannon/iterator/backfilling_checkpoint_iterator.go @@ -17,38 +17,106 @@ import ( ) type BackfillingCheckpoint struct { - log logrus.FieldLogger - cannonType xatu.CannonType - coordinator coordinator.Client - wallclock *ethwallclock.EthereumBeaconChain - networkID string - networkName string - metrics *BackfillingCheckpointMetrics - beaconNode *ethereum.BeaconNode - checkpointName string + log logrus.FieldLogger + cannonType xatu.CannonType + coordinator coordinator.Client + wallclock *ethwallclock.EthereumBeaconChain + networkID string + networkName string + metrics *BackfillingCheckpointMetrics + beaconNode *ethereum.BeaconNode + checkpointName string + lookAheadDistance int } -func NewBackfillingCheckpoint(log logrus.FieldLogger, networkName, networkID string, cannonType xatu.CannonType, coordinatorClient *coordinator.Client, wallclock *ethwallclock.EthereumBeaconChain, metrics *BackfillingCheckpointMetrics, beacon *ethereum.BeaconNode, checkpoint string) *BackfillingCheckpoint { +type BackfillingCheckpointDirection string + +const ( + BackfillingCheckpointDirectionBackfill BackfillingCheckpointDirection = "backfill" + BackfillingCheckpointDirectionHead BackfillingCheckpointDirection = "head" +) + +type BackFillingCheckpointNextResponse struct { + Next phase0.Epoch + LookAheads []phase0.Epoch + Direction BackfillingCheckpointDirection +} + +func NewBackfillingCheckpoint( + log logrus.FieldLogger, + networkName, networkID string, + cannonType xatu.CannonType, + coordinatorClient *coordinator.Client, + wallclock *ethwallclock.EthereumBeaconChain, + metrics *BackfillingCheckpointMetrics, + beacon *ethereum.BeaconNode, + checkpoint string, + lookAheadDistance int, +) *BackfillingCheckpoint { return &BackfillingCheckpoint{ log: log. WithField("module", "cannon/iterator/backfilling_checkpoint_iterator"). WithField("cannon_type", cannonType.String()), - networkName: networkName, - networkID: networkID, - cannonType: cannonType, - coordinator: *coordinatorClient, - wallclock: wallclock, - beaconNode: beacon, - metrics: metrics, - checkpointName: checkpoint, + networkName: networkName, + networkID: networkID, + cannonType: cannonType, + coordinator: *coordinatorClient, + wallclock: wallclock, + beaconNode: beacon, + metrics: metrics, + checkpointName: checkpoint, + lookAheadDistance: lookAheadDistance, } } -func (c *BackfillingCheckpoint) UpdateLocation(ctx context.Context, location *xatu.CannonLocation) error { - return c.coordinator.UpsertCannonLocationRequest(ctx, location) +func (c *BackfillingCheckpoint) Start(ctx context.Context) error { + return nil +} + +func (c *BackfillingCheckpoint) UpdateLocation(ctx context.Context, epoch phase0.Epoch, direction BackfillingCheckpointDirection) error { + location, err := c.coordinator.GetCannonLocation(ctx, c.cannonType, c.networkID) + if err != nil { + return errors.Wrap(err, "failed to get cannon location") + } + + if location == nil { + location, err = c.createLocationFromEpochNumber(epoch, epoch) + if err != nil { + return errors.Wrap(err, "failed to create fresh location from epoch number") + } + } + + marker, err := c.GetMarker(location) + if err != nil { + return errors.Wrap(err, "failed to get marker from location") + } + + switch direction { + case BackfillingCheckpointDirectionHead: + marker.FinalizedEpoch = uint64(epoch) + case BackfillingCheckpointDirectionBackfill: + marker.BackfillEpoch = int64(epoch) + default: + return errors.Errorf("unknown direction (%s) when updating cannon location", direction) + } + + newLocation, err := c.createLocationFromEpochNumber(phase0.Epoch(marker.FinalizedEpoch), phase0.Epoch(marker.BackfillEpoch)) + if err != nil { + return errors.Wrap(err, "failed to create location from epoch number") + } + + err = c.coordinator.UpsertCannonLocationRequest(ctx, newLocation) + if err != nil { + return errors.Wrap(err, "failed to update cannon location") + } + + c.metrics.SetBackfillEpoch(c.cannonType.String(), c.networkName, c.checkpointName, float64(marker.BackfillEpoch)) + c.metrics.SetFinalizedEpoch(c.cannonType.String(), c.networkName, c.checkpointName, float64(marker.FinalizedEpoch)) + + return nil } -func (c *BackfillingCheckpoint) Next(ctx context.Context) (next *xatu.CannonLocation, lookAhead []*xatu.CannonLocation, err error) { +func (c *BackfillingCheckpoint) Next(ctx context.Context) (rsp *BackFillingCheckpointNextResponse, err error) { ctx, span := observability.Tracer().Start(ctx, "BackfillingCheckpoint.Next", trace.WithAttributes( @@ -60,13 +128,23 @@ func (c *BackfillingCheckpoint) Next(ctx context.Context) (next *xatu.CannonLoca defer func() { if err != nil { span.RecordError(err) - } else { - marker, err := c.getMarker(next) - if err == nil { - span.SetAttributes(attribute.Int64("finalized_epoch", int64(marker.FinalizedEpoch))) - span.SetAttributes(attribute.Int64("backfill_epoch", marker.BackfillEpoch)) - c.metrics.SetBackfillEpoch(c.cannonType.String(), c.networkName, c.checkpointName, float64(marker.BackfillEpoch)) - c.metrics.SetFinalizedEpoch(c.cannonType.String(), c.networkName, c.checkpointName, float64(marker.FinalizedEpoch)) + } else if rsp != nil { + c.log.WithFields(logrus.Fields{ + "next_epoch": rsp.Next, + "direction": rsp.Direction, + "look_aheads": rsp.LookAheads, + }).Info("Returning next epoch") + + span.SetAttributes(attribute.Int64("next_epoch", int64(rsp.Next))) + span.SetAttributes(attribute.String("direction", string(rsp.Direction))) + + if rsp.LookAheads != nil { + lookAheads := make([]int64, len(rsp.LookAheads)) + for i, epoch := range rsp.LookAheads { + lookAheads[i] = int64(epoch) + } + + span.SetAttributes(attribute.Int64Slice("look_aheads", lookAheads)) } } @@ -77,37 +155,97 @@ func (c *BackfillingCheckpoint) Next(ctx context.Context) (next *xatu.CannonLoca // Grab the current checkpoint from the beacon node checkpoint, err := c.fetchLatestCheckpoint(ctx) if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to fetch latest checkpoint") + return nil, errors.Wrap(err, "failed to fetch latest checkpoint") } if checkpoint == nil { - return nil, []*xatu.CannonLocation{}, errors.New("checkpoint is nil") + return nil, errors.New("checkpoint is nil") } + c.metrics.SetFinalizedCheckpointEpoch(c.networkName, float64(checkpoint.Epoch)) + // Check where we are at from the coordinator location, err := c.coordinator.GetCannonLocation(ctx, c.cannonType, c.networkID) if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to get cannon location") + return nil, errors.Wrap(err, "failed to get cannon location") } + earliestEpoch := GetStartingEpochLocation(c.beaconNode.Metadata().Spec.ForkEpochs, c.cannonType) + // If location is empty we haven't started yet, start at the network default for the type. If the network default // is empty, we'll start at the checkpoint. - if location == nil { - location, err = c.createLocationFromEpochNumber(checkpoint.Epoch, checkpoint.Epoch) - if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to create location from slot number 0") - } - return location, c.getLookAheads(ctx, location), nil + if checkpoint.Epoch < earliestEpoch { + // The current finalized checkpoint is before the activation of this cannon, so we should sleep until the next epoch. + epoch := c.wallclock.Epochs().Current() + + sleepFor := time.Until(epoch.TimeWindow().End()) + + c.log.WithFields(logrus.Fields{ + "current_epoch": epoch.Number(), + "sleep_for": sleepFor.String(), + "checkpoint_epoch": checkpoint.Epoch, + "earliest_epoch": earliestEpoch, + }).Info("Sleeping until next epoch as the fork for the iterator is not yet active") + + time.Sleep(sleepFor) + + // Sleep for an additional 5 seconds to give the beacon node time to do epoch processing. + time.Sleep(5 * time.Second) + + continue + } + + if location == nil { + // If the location is empty, we haven't started yet, so we should return the current checkpoint epoch. + return &BackFillingCheckpointNextResponse{ + Next: checkpoint.Epoch, + LookAheads: c.calculateFinalizedLookAheads(checkpoint.Epoch, checkpoint.Epoch), + Direction: BackfillingCheckpointDirectionHead, + }, nil } - // If the backfill is at zero, and the finalized epoch is up to date, we should sleep until the next epoch - marker, err := c.getMarker(location) + marker, err := c.GetMarker(location) if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to get marker from location") + return nil, errors.Wrap(err, "failed to get marker from location") } - if marker.BackfillEpoch == -1 && checkpoint.Epoch == phase0.Epoch(marker.FinalizedEpoch) { + c.metrics.SetLag(c.cannonType.String(), c.networkName, BackfillingCheckpointDirectionHead, float64(checkpoint.Epoch-phase0.Epoch(marker.FinalizedEpoch))) + c.metrics.SetLag(c.cannonType.String(), c.networkName, BackfillingCheckpointDirectionBackfill, float64(phase0.Epoch(marker.BackfillEpoch)-earliestEpoch)) + + if marker.FinalizedEpoch == 0 { + // If the marker is empty, we haven't started yet, so we should return the current checkpoint. + return &BackFillingCheckpointNextResponse{ + Next: checkpoint.Epoch, + LookAheads: c.calculateFinalizedLookAheads(checkpoint.Epoch, checkpoint.Epoch), + Direction: BackfillingCheckpointDirectionHead, + }, nil + } + + // If the head isn't up to date, we can return the next finalized epoch to process. + if marker.FinalizedEpoch < uint64(checkpoint.Epoch) { + next := phase0.Epoch(marker.FinalizedEpoch + 1) + + return &BackFillingCheckpointNextResponse{ + Next: next, + LookAheads: c.calculateFinalizedLookAheads(next, checkpoint.Epoch), + Direction: BackfillingCheckpointDirectionHead, + }, nil + } + + // If the backfill hasn't completed, we can return the next backfill epoch to process. + if marker.BackfillEpoch != int64(earliestEpoch) { + next := phase0.Epoch(marker.BackfillEpoch - 1) + + return &BackFillingCheckpointNextResponse{ + Next: next, + LookAheads: c.calculateBackfillingLookAheads(next), + Direction: BackfillingCheckpointDirectionBackfill, + }, nil + } + + // The backfill is done, and the finalized epoch is up to date - we can sleep until the next epoch. + if marker.BackfillEpoch == int64(earliestEpoch) && checkpoint.Epoch == phase0.Epoch(marker.FinalizedEpoch) { // Sleep until the next epoch epoch := c.wallclock.Epochs().Current() @@ -117,7 +255,7 @@ func (c *BackfillingCheckpoint) Next(ctx context.Context) (next *xatu.CannonLoca "current_epoch": epoch.Number(), "sleep_for": sleepFor.String(), "checkpoint_epoch": checkpoint.Epoch, - }).Trace("Sleeping until next epoch") + }).Info("Sleeping until next epoch") time.Sleep(sleepFor) @@ -127,14 +265,16 @@ func (c *BackfillingCheckpoint) Next(ctx context.Context) (next *xatu.CannonLoca continue } - // Return the current location -- consumers of this iterator will have to update the location themselves. - return location, c.getLookAheads(ctx, location), nil - } -} + // Log the current state for debugging + c.log.WithFields(logrus.Fields{ + "marker_finalized_epoch": marker.FinalizedEpoch, + "marker_backfill_epoch": marker.BackfillEpoch, + "checkpoint_epoch": checkpoint.Epoch, + "earliest_epoch": earliestEpoch, + }).Info("Current state before returning unknown state") -func (c *BackfillingCheckpoint) getLookAheads(ctx context.Context, location *xatu.CannonLocation) []*xatu.CannonLocation { - // Not supported - return []*xatu.CannonLocation{} + return nil, errors.New("unknown state") + } } func (c *BackfillingCheckpoint) fetchLatestCheckpoint(ctx context.Context) (*phase0.Checkpoint, error) { @@ -159,17 +299,76 @@ func (c *BackfillingCheckpoint) fetchLatestCheckpoint(ctx context.Context) (*pha return nil, errors.Errorf("unknown checkpoint name %s", c.checkpointName) } -func (c *BackfillingCheckpoint) getMarker(location *xatu.CannonLocation) (*xatu.BackfillingCheckpointMarker, error) { +func (c *BackfillingCheckpoint) calculateBackfillingLookAheads(epoch phase0.Epoch) []phase0.Epoch { + epochs := []phase0.Epoch{} + + for i := 0; i < c.lookAheadDistance; i++ { + e := epoch - phase0.Epoch(i) + + epochs = append(epochs, e) + } + + return epochs +} + +func (c *BackfillingCheckpoint) calculateFinalizedLookAheads(epoch, finalizedEpoch phase0.Epoch) []phase0.Epoch { + epochs := []phase0.Epoch{} + + for i := 0; i < c.lookAheadDistance; i++ { + e := epoch + phase0.Epoch(i) + if e >= finalizedEpoch { + break + } + + epochs = append(epochs, e) + } + + return epochs +} + +func (c *BackfillingCheckpoint) GetMarker(location *xatu.CannonLocation) (*xatu.BackfillingCheckpointMarker, error) { + if location == nil { + return nil, errors.New("location is nil") + } + + var marker *xatu.BackfillingCheckpointMarker + switch location.Type { case xatu.CannonType_BEACON_API_ETH_V1_PROPOSER_DUTY: - return location.GetEthV1BeaconProposerDuty().GetBackfillingCheckpointMarker(), nil + marker = location.GetEthV1BeaconProposerDuty().GetBackfillingCheckpointMarker() case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_ELABORATED_ATTESTATION: - return location.GetEthV2BeaconBlockElaboratedAttestation().GetBackfillingCheckpointMarker(), nil + marker = location.GetEthV2BeaconBlockElaboratedAttestation().GetBackfillingCheckpointMarker() case xatu.CannonType_BEACON_API_ETH_V1_BEACON_VALIDATORS: - return location.GetEthV1BeaconValidators().GetBackfillingCheckpointMarker(), nil + marker = location.GetEthV1BeaconValidators().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_ATTESTER_SLASHING: + marker = location.GetEthV2BeaconBlockAttesterSlashing().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_PROPOSER_SLASHING: + marker = location.GetEthV2BeaconBlockProposerSlashing().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_BLS_TO_EXECUTION_CHANGE: + marker = location.GetEthV2BeaconBlockBlsToExecutionChange().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_EXECUTION_TRANSACTION: + marker = location.GetEthV2BeaconBlockExecutionTransaction().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_VOLUNTARY_EXIT: + marker = location.GetEthV2BeaconBlockVoluntaryExit().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_DEPOSIT: + marker = location.GetEthV2BeaconBlockDeposit().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_WITHDRAWAL: + marker = location.GetEthV2BeaconBlockWithdrawal().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK: + marker = location.GetEthV2BeaconBlock().GetBackfillingCheckpointMarker() + case xatu.CannonType_BEACON_API_ETH_V1_BEACON_BLOB_SIDECAR: + marker = location.GetEthV1BeaconBlobSidecar().GetBackfillingCheckpointMarker() default: return nil, errors.Errorf("unknown cannon type %s", location.Type) } + + if marker == nil { + marker = &xatu.BackfillingCheckpointMarker{ + BackfillEpoch: -1, + } + } + + return marker, nil } func (c *BackfillingCheckpoint) createLocationFromEpochNumber(finalized, backfill phase0.Epoch) (*xatu.CannonLocation, error) { @@ -178,32 +377,82 @@ func (c *BackfillingCheckpoint) createLocationFromEpochNumber(finalized, backfil Type: c.cannonType, } + marker := &xatu.BackfillingCheckpointMarker{ + FinalizedEpoch: uint64(finalized), + BackfillEpoch: int64(backfill), + } + switch c.cannonType { case xatu.CannonType_BEACON_API_ETH_V1_PROPOSER_DUTY: location.Data = &xatu.CannonLocation_EthV1BeaconProposerDuty{ EthV1BeaconProposerDuty: &xatu.CannonLocationEthV1BeaconProposerDuty{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - FinalizedEpoch: uint64(finalized), - BackfillEpoch: int64(backfill), - }, + BackfillingCheckpointMarker: marker, }, } case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_ELABORATED_ATTESTATION: location.Data = &xatu.CannonLocation_EthV2BeaconBlockElaboratedAttestation{ EthV2BeaconBlockElaboratedAttestation: &xatu.CannonLocationEthV2BeaconBlockElaboratedAttestation{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - FinalizedEpoch: uint64(finalized), - BackfillEpoch: int64(backfill), - }, + BackfillingCheckpointMarker: marker, }, } case xatu.CannonType_BEACON_API_ETH_V1_BEACON_VALIDATORS: location.Data = &xatu.CannonLocation_EthV1BeaconValidators{ EthV1BeaconValidators: &xatu.CannonLocationEthV1BeaconValidators{ - BackfillingCheckpointMarker: &xatu.BackfillingCheckpointMarker{ - FinalizedEpoch: uint64(finalized), - BackfillEpoch: int64(backfill), - }, + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_ATTESTER_SLASHING: + location.Data = &xatu.CannonLocation_EthV2BeaconBlockAttesterSlashing{ + EthV2BeaconBlockAttesterSlashing: &xatu.CannonLocationEthV2BeaconBlockAttesterSlashing{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_PROPOSER_SLASHING: + location.Data = &xatu.CannonLocation_EthV2BeaconBlockProposerSlashing{ + EthV2BeaconBlockProposerSlashing: &xatu.CannonLocationEthV2BeaconBlockProposerSlashing{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_BLS_TO_EXECUTION_CHANGE: + location.Data = &xatu.CannonLocation_EthV2BeaconBlockBlsToExecutionChange{ + EthV2BeaconBlockBlsToExecutionChange: &xatu.CannonLocationEthV2BeaconBlockBlsToExecutionChange{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_EXECUTION_TRANSACTION: + location.Data = &xatu.CannonLocation_EthV2BeaconBlockExecutionTransaction{ + EthV2BeaconBlockExecutionTransaction: &xatu.CannonLocationEthV2BeaconBlockExecutionTransaction{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_VOLUNTARY_EXIT: + location.Data = &xatu.CannonLocation_EthV2BeaconBlockVoluntaryExit{ + EthV2BeaconBlockVoluntaryExit: &xatu.CannonLocationEthV2BeaconBlockVoluntaryExit{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_DEPOSIT: + location.Data = &xatu.CannonLocation_EthV2BeaconBlockDeposit{ + EthV2BeaconBlockDeposit: &xatu.CannonLocationEthV2BeaconBlockDeposit{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_WITHDRAWAL: + location.Data = &xatu.CannonLocation_EthV2BeaconBlockWithdrawal{ + EthV2BeaconBlockWithdrawal: &xatu.CannonLocationEthV2BeaconBlockWithdrawal{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK: + location.Data = &xatu.CannonLocation_EthV2BeaconBlock{ + EthV2BeaconBlock: &xatu.CannonLocationEthV2BeaconBlock{ + BackfillingCheckpointMarker: marker, + }, + } + case xatu.CannonType_BEACON_API_ETH_V1_BEACON_BLOB_SIDECAR: + location.Data = &xatu.CannonLocation_EthV1BeaconBlobSidecar{ + EthV1BeaconBlobSidecar: &xatu.CannonLocationEthV1BeaconBlobSidecar{ + BackfillingCheckpointMarker: marker, }, } default: diff --git a/pkg/cannon/iterator/backfilling_checkpoint_iterator_metrics.go b/pkg/cannon/iterator/backfilling_checkpoint_iterator_metrics.go index adbe81d8..7ba7d1b2 100644 --- a/pkg/cannon/iterator/backfilling_checkpoint_iterator_metrics.go +++ b/pkg/cannon/iterator/backfilling_checkpoint_iterator_metrics.go @@ -3,8 +3,10 @@ package iterator import "github.com/prometheus/client_golang/prometheus" type BackfillingCheckpointMetrics struct { - BackfillEpoch *prometheus.GaugeVec - FinalizedEpoch *prometheus.GaugeVec + BackfillEpoch *prometheus.GaugeVec + FinalizedEpoch *prometheus.GaugeVec + FinalizedCheckpointEpoch *prometheus.GaugeVec + Lag *prometheus.GaugeVec } func NewBackfillingCheckpointMetrics(namespace string) BackfillingCheckpointMetrics { @@ -21,10 +23,22 @@ func NewBackfillingCheckpointMetrics(namespace string) BackfillingCheckpointMetr Name: "finalized_epoch", Help: "The current position of the finalized epoch", }, []string{"cannon_type", "network", "checkpoint"}), + FinalizedCheckpointEpoch: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Name: "finalized_checkpoint_epoch", + Help: "The finalized checkpoint epoch of the network", + }, []string{"network"}), + Lag: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Name: "lag_epochs", + Help: "The lag of the iterator in epochs", + }, []string{"cannon_type", "network", "direction"}), } prometheus.MustRegister(s.BackfillEpoch) prometheus.MustRegister(s.FinalizedEpoch) + prometheus.MustRegister(s.FinalizedCheckpointEpoch) + prometheus.MustRegister(s.Lag) return s } @@ -36,3 +50,11 @@ func (s *BackfillingCheckpointMetrics) SetBackfillEpoch(cannonType, network, che func (s *BackfillingCheckpointMetrics) SetFinalizedEpoch(cannonType, network, checkpoint string, epoch float64) { s.FinalizedEpoch.WithLabelValues(cannonType, network, checkpoint).Set(epoch) } + +func (s *BackfillingCheckpointMetrics) SetFinalizedCheckpointEpoch(network string, epoch float64) { + s.FinalizedCheckpointEpoch.WithLabelValues(network).Set(epoch) +} + +func (s *BackfillingCheckpointMetrics) SetLag(cannonType, network string, direction BackfillingCheckpointDirection, lag float64) { + s.Lag.WithLabelValues(cannonType, network, string(direction)).Set(lag) +} diff --git a/pkg/cannon/iterator/blockprint_iterator.go b/pkg/cannon/iterator/blockprint_iterator.go index e9c5373a..e7bd09fe 100644 --- a/pkg/cannon/iterator/blockprint_iterator.go +++ b/pkg/cannon/iterator/blockprint_iterator.go @@ -47,7 +47,7 @@ func (c *BlockprintIterator) UpdateLocation(ctx context.Context, location *xatu. return c.coordinator.UpsertCannonLocationRequest(ctx, location) } -func (c *BlockprintIterator) Next(ctx context.Context) (next *xatu.CannonLocation, lookAhead []*xatu.CannonLocation, err error) { +func (c *BlockprintIterator) Next(ctx context.Context) (next *xatu.CannonLocation, err error) { ctx, span := observability.Tracer().Start(ctx, "BlockprintIterator.Next", trace.WithAttributes( @@ -77,16 +77,16 @@ func (c *BlockprintIterator) Next(ctx context.Context) (next *xatu.CannonLocatio // Check where we are at from the coordinator location, err := c.coordinator.GetCannonLocation(ctx, c.cannonType, c.networkID) if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to get cannon location") + return nil, errors.Wrap(err, "failed to get cannon location") } status, err := c.blockprintClient.SyncStatus(ctx) if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to fetch sync status") + return nil, errors.Wrap(err, "failed to fetch sync status") } if !status.Synced { - return nil, []*xatu.CannonLocation{}, errors.New("blockprint is not synced") + return nil, errors.New("blockprint is not synced") } // If location is empty we haven't started yet. This means we should set our `target_end_slot` to the latest synced slot. @@ -94,15 +94,15 @@ func (c *BlockprintIterator) Next(ctx context.Context) (next *xatu.CannonLocatio if location == nil { next, errr := c.createLocation(0, phase0.Slot(status.GreatestBlockSlot)) if errr != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(errr, "failed to create location") + return nil, errors.Wrap(errr, "failed to create location") } - return next, c.getLookAheads(ctx, next), nil + return next, nil } slot, _, err := c.getSlotsFromLocation(location) if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to get slots from location") + return nil, errors.Wrap(err, "failed to get slots from location") } if slot >= phase0.Slot(status.GreatestBlockSlot) { @@ -114,18 +114,13 @@ func (c *BlockprintIterator) Next(ctx context.Context) (next *xatu.CannonLocatio next, err := c.createLocation(slot, phase0.Slot(status.GreatestBlockSlot)) if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to create location") + return nil, errors.Wrap(err, "failed to create location") } - return next, c.getLookAheads(ctx, next), nil + return next, nil } } -func (c *BlockprintIterator) getLookAheads(ctx context.Context, location *xatu.CannonLocation) []*xatu.CannonLocation { - // Not supported for blockprint - return []*xatu.CannonLocation{} -} - func (c *BlockprintIterator) getSlotsFromLocation(location *xatu.CannonLocation) (slot, target phase0.Slot, err error) { switch location.Type { case xatu.CannonType_BLOCKPRINT_BLOCK_CLASSIFICATION: diff --git a/pkg/cannon/iterator/checkpoint_iterator.go b/pkg/cannon/iterator/checkpoint_iterator.go deleted file mode 100644 index 2b5018b8..00000000 --- a/pkg/cannon/iterator/checkpoint_iterator.go +++ /dev/null @@ -1,287 +0,0 @@ -package iterator - -import ( - "context" - "time" - - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethpandaops/ethwallclock" - "github.com/ethpandaops/xatu/pkg/cannon/coordinator" - "github.com/ethpandaops/xatu/pkg/cannon/ethereum" - "github.com/ethpandaops/xatu/pkg/observability" - "github.com/ethpandaops/xatu/pkg/proto/xatu" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -type CheckpointIterator struct { - log logrus.FieldLogger - cannonType xatu.CannonType - coordinator coordinator.Client - wallclock *ethwallclock.EthereumBeaconChain - networkID string - networkName string - metrics *CheckpointMetrics - beaconNode *ethereum.BeaconNode - checkpointName string -} - -func NewCheckpointIterator(log logrus.FieldLogger, networkName, networkID string, cannonType xatu.CannonType, coordinatorClient *coordinator.Client, wallclock *ethwallclock.EthereumBeaconChain, metrics *CheckpointMetrics, beacon *ethereum.BeaconNode, checkpoint string) *CheckpointIterator { - return &CheckpointIterator{ - log: log. - WithField("module", "cannon/iterator/checkpoint_iterator"). - WithField("cannon_type", cannonType.String()), - networkName: networkName, - networkID: networkID, - cannonType: cannonType, - coordinator: *coordinatorClient, - wallclock: wallclock, - beaconNode: beacon, - metrics: metrics, - checkpointName: checkpoint, - } -} - -func (c *CheckpointIterator) UpdateLocation(ctx context.Context, location *xatu.CannonLocation) error { - return c.coordinator.UpsertCannonLocationRequest(ctx, location) -} - -func (c *CheckpointIterator) Next(ctx context.Context) (next *xatu.CannonLocation, lookAhead []*xatu.CannonLocation, err error) { - ctx, span := observability.Tracer().Start(ctx, - "CheckpointIterator.Next", - trace.WithAttributes( - attribute.String("network", c.networkName), - attribute.String("cannon_type", c.cannonType.String()), - attribute.String("network_id", c.networkID), - ), - ) - defer func() { - if err != nil { - span.RecordError(err) - } else { - epoch, err := c.getEpochFromLocation(next) - if err == nil { - span.SetAttributes(attribute.Int64("next", int64(epoch))) - } - } - - span.End() - }() - - for { - // Grab the current checkpoint from the beacon node - checkpoint, err := c.fetchLatestEpoch(ctx) - if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to fetch latest checkpoint") - } - - if checkpoint == nil { - return nil, []*xatu.CannonLocation{}, errors.New("checkpoint is nil") - } - - // Check where we are at from the coordinator - location, err := c.coordinator.GetCannonLocation(ctx, c.cannonType, c.networkID) - if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to get cannon location") - } - - // If location is empty we haven't started yet, start at the network default for the type. If the network default - // is empty, we'll start at epoch 0. - if location == nil { - location, err = c.createLocationFromEpochNumber(phase0.Epoch(GetDefaultSlotLocation(c.beaconNode.Metadata().Spec.ForkEpochs, c.cannonType) / 32)) - if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to create location from slot number 0") - } - - return location, c.getLookAheads(ctx, location), nil - } - - // If the location is the same as the current checkpoint, we should sleep until the next epoch - locationEpoch, err := c.getEpochFromLocation(location) - if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to get epoch from location") - } - - c.metrics.SetTrailingEpochs(c.cannonType.String(), c.networkName, c.checkpointName, float64(checkpoint.Epoch-locationEpoch)) - - if locationEpoch >= checkpoint.Epoch { - // Sleep until the next epoch - epoch := c.wallclock.Epochs().Current() - - sleepFor := time.Until(epoch.TimeWindow().End()) - - c.log.WithFields(logrus.Fields{ - "current_epoch": epoch.Number(), - "sleep_for": sleepFor.String(), - "checkpoint_epoch": checkpoint.Epoch, - }).Trace("Sleeping until next epoch") - - time.Sleep(sleepFor) - - // Sleep for an additional 5 seconds to give the beacon node time to do epoch processing. - time.Sleep(5 * time.Second) - - continue - } - - nextEpoch := locationEpoch + 1 - - current, err := c.createLocationFromEpochNumber(nextEpoch) - if err != nil { - return nil, []*xatu.CannonLocation{}, errors.Wrap(err, "failed to create location from epoch number") - } - - c.metrics.SetCurrentEpoch(c.cannonType.String(), c.networkName, c.checkpointName, float64(nextEpoch)) - - return current, c.getLookAheads(ctx, current), nil - } -} - -func (c *CheckpointIterator) getLookAheads(ctx context.Context, location *xatu.CannonLocation) []*xatu.CannonLocation { - // Calculate if we should look ahead - epoch, err := c.getEpochFromLocation(location) - if err != nil { - return []*xatu.CannonLocation{} - } - - latestCheckpoint, err := c.fetchLatestEpoch(ctx) - if err != nil { - return []*xatu.CannonLocation{} - } - - lookAheads := make([]*xatu.CannonLocation, 0) - - for _, i := range []int{1, 2, 3} { - lookAheadEpoch := epoch + phase0.Epoch(i) - - if lookAheadEpoch > latestCheckpoint.Epoch { - continue - } - - loc, err := c.createLocationFromEpochNumber(lookAheadEpoch) - if err != nil { - return []*xatu.CannonLocation{} - } - - lookAheads = append(lookAheads, loc) - } - - return lookAheads -} - -func (c *CheckpointIterator) fetchLatestEpoch(ctx context.Context) (*phase0.Checkpoint, error) { - _, span := observability.Tracer().Start(ctx, - "CheckpointIterator.FetchLatestEpoch", - ) - defer span.End() - - finality, err := c.beaconNode.Node().Finality() - if err != nil { - return nil, errors.Wrap(err, "failed to fetch finality") - } - - if c.checkpointName == "justified" { - return finality.Justified, nil - } - - if c.checkpointName == "finalized" { - return finality.Finalized, nil - } - - return nil, errors.Errorf("unknown checkpoint name %s", c.checkpointName) -} - -func (c *CheckpointIterator) getEpochFromLocation(location *xatu.CannonLocation) (phase0.Epoch, error) { - switch location.Type { - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_ATTESTER_SLASHING: - return phase0.Epoch(location.GetEthV2BeaconBlockAttesterSlashing().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_PROPOSER_SLASHING: - return phase0.Epoch(location.GetEthV2BeaconBlockProposerSlashing().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_BLS_TO_EXECUTION_CHANGE: - return phase0.Epoch(location.GetEthV2BeaconBlockBlsToExecutionChange().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_EXECUTION_TRANSACTION: - return phase0.Epoch(location.GetEthV2BeaconBlockExecutionTransaction().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_VOLUNTARY_EXIT: - return phase0.Epoch(location.GetEthV2BeaconBlockVoluntaryExit().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_DEPOSIT: - return phase0.Epoch(location.GetEthV2BeaconBlockDeposit().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_WITHDRAWAL: - return phase0.Epoch(location.GetEthV2BeaconBlockWithdrawal().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK: - return phase0.Epoch(location.GetEthV2BeaconBlock().Epoch), nil - case xatu.CannonType_BEACON_API_ETH_V1_BEACON_BLOB_SIDECAR: - return phase0.Epoch(location.GetEthV1BeaconBlobSidecar().Epoch), nil - default: - return 0, errors.Errorf("unknown cannon type %s", location.Type) - } -} - -func (c *CheckpointIterator) createLocationFromEpochNumber(epoch phase0.Epoch) (*xatu.CannonLocation, error) { - location := &xatu.CannonLocation{ - NetworkId: c.networkID, - Type: c.cannonType, - } - - switch c.cannonType { - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_ATTESTER_SLASHING: - location.Data = &xatu.CannonLocation_EthV2BeaconBlockAttesterSlashing{ - EthV2BeaconBlockAttesterSlashing: &xatu.CannonLocationEthV2BeaconBlockAttesterSlashing{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_PROPOSER_SLASHING: - location.Data = &xatu.CannonLocation_EthV2BeaconBlockProposerSlashing{ - EthV2BeaconBlockProposerSlashing: &xatu.CannonLocationEthV2BeaconBlockProposerSlashing{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_BLS_TO_EXECUTION_CHANGE: - location.Data = &xatu.CannonLocation_EthV2BeaconBlockBlsToExecutionChange{ - EthV2BeaconBlockBlsToExecutionChange: &xatu.CannonLocationEthV2BeaconBlockBlsToExecutionChange{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_EXECUTION_TRANSACTION: - location.Data = &xatu.CannonLocation_EthV2BeaconBlockExecutionTransaction{ - EthV2BeaconBlockExecutionTransaction: &xatu.CannonLocationEthV2BeaconBlockExecutionTransaction{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_VOLUNTARY_EXIT: - location.Data = &xatu.CannonLocation_EthV2BeaconBlockVoluntaryExit{ - EthV2BeaconBlockVoluntaryExit: &xatu.CannonLocationEthV2BeaconBlockVoluntaryExit{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_DEPOSIT: - location.Data = &xatu.CannonLocation_EthV2BeaconBlockDeposit{ - EthV2BeaconBlockDeposit: &xatu.CannonLocationEthV2BeaconBlockDeposit{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK_WITHDRAWAL: - location.Data = &xatu.CannonLocation_EthV2BeaconBlockWithdrawal{ - EthV2BeaconBlockWithdrawal: &xatu.CannonLocationEthV2BeaconBlockWithdrawal{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V2_BEACON_BLOCK: - location.Data = &xatu.CannonLocation_EthV2BeaconBlock{ - EthV2BeaconBlock: &xatu.CannonLocationEthV2BeaconBlock{ - Epoch: uint64(epoch), - }, - } - case xatu.CannonType_BEACON_API_ETH_V1_BEACON_BLOB_SIDECAR: - location.Data = &xatu.CannonLocation_EthV1BeaconBlobSidecar{ - EthV1BeaconBlobSidecar: &xatu.CannonLocationEthV1BeaconBlobSidecar{ - Epoch: uint64(epoch), - }, - } - default: - return location, errors.Errorf("unknown cannon type %s", location.Type) - } - - return location, nil -} diff --git a/pkg/cannon/iterator/checkpoint_metrics.go b/pkg/cannon/iterator/checkpoint_metrics.go deleted file mode 100644 index 7433c8cf..00000000 --- a/pkg/cannon/iterator/checkpoint_metrics.go +++ /dev/null @@ -1,38 +0,0 @@ -package iterator - -import "github.com/prometheus/client_golang/prometheus" - -type CheckpointMetrics struct { - Trailingepochs *prometheus.GaugeVec - Currentepoch *prometheus.GaugeVec -} - -func NewCheckpointMetrics(namespace string) CheckpointMetrics { - namespace += "_epoch_iterator" - - s := CheckpointMetrics{ - Trailingepochs: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: namespace, - Name: "trailing_epochs", - Help: "The number of epochs that the iterator is trailing behind the latest checkpoint epoch", - }, []string{"cannon_type", "network", "checkpoint"}), - Currentepoch: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: namespace, - Name: "current_epoch", - Help: "The current epoch", - }, []string{"cannon_type", "network", "checkpoint"}), - } - - prometheus.MustRegister(s.Trailingepochs) - prometheus.MustRegister(s.Currentepoch) - - return s -} - -func (s *CheckpointMetrics) SetTrailingEpochs(cannonType, network, checkpoint string, trailing float64) { - s.Trailingepochs.WithLabelValues(cannonType, network, checkpoint).Set(trailing) -} - -func (s *CheckpointMetrics) SetCurrentEpoch(cannonType, network, checkpoint string, current float64) { - s.Currentepoch.WithLabelValues(cannonType, network, checkpoint).Set(current) -} diff --git a/pkg/cannon/iterator/iterator.go b/pkg/cannon/iterator/iterator.go index de4fb457..e58eacba 100644 --- a/pkg/cannon/iterator/iterator.go +++ b/pkg/cannon/iterator/iterator.go @@ -1,7 +1,6 @@ package iterator import ( - "context" "errors" "github.com/attestantio/go-eth2-client/spec/phase0" @@ -9,14 +8,6 @@ import ( "github.com/ethpandaops/xatu/pkg/proto/xatu" ) -type Iterator interface { - UpdateLocation(ctx context.Context, location *xatu.CannonLocation) error - Next(ctx context.Context) (next *xatu.CannonLocation, lookAhead []*xatu.CannonLocation, err error) -} - -// Ensure that derivers implements the EventDeriver interface -var _ Iterator = &CheckpointIterator{} - var ( ErrLocationUpToDate = errors.New("location up to date") @@ -31,3 +22,12 @@ func GetDefaultSlotLocation(forkEpochs state.ForkEpochs, cannonType xatu.CannonT return SlotZero } + +func GetStartingEpochLocation(forkEpochs state.ForkEpochs, cannonType xatu.CannonType) phase0.Epoch { + defaults := NewSlotDefaultsFromForkEpochs(forkEpochs) + if slot, exists := defaults[cannonType]; exists { + return phase0.Epoch(slot / 32) + } + + return 0 +} diff --git a/pkg/proto/xatu/coordinator.pb.go b/pkg/proto/xatu/coordinator.pb.go index fa55b731..32e9eefd 100644 --- a/pkg/proto/xatu/coordinator.pb.go +++ b/pkg/proto/xatu/coordinator.pb.go @@ -841,7 +841,8 @@ type CannonLocationEthV2BeaconBlockVoluntaryExit struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlockVoluntaryExit) Reset() { @@ -883,12 +884,20 @@ func (x *CannonLocationEthV2BeaconBlockVoluntaryExit) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlockVoluntaryExit) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV2BeaconBlockProposerSlashing struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlockProposerSlashing) Reset() { @@ -930,12 +939,20 @@ func (x *CannonLocationEthV2BeaconBlockProposerSlashing) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlockProposerSlashing) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV2BeaconBlockDeposit struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlockDeposit) Reset() { @@ -977,12 +994,20 @@ func (x *CannonLocationEthV2BeaconBlockDeposit) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlockDeposit) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV2BeaconBlockAttesterSlashing struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlockAttesterSlashing) Reset() { @@ -1024,12 +1049,20 @@ func (x *CannonLocationEthV2BeaconBlockAttesterSlashing) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlockAttesterSlashing) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV2BeaconBlockBlsToExecutionChange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlockBlsToExecutionChange) Reset() { @@ -1071,12 +1104,20 @@ func (x *CannonLocationEthV2BeaconBlockBlsToExecutionChange) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlockBlsToExecutionChange) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV2BeaconBlockExecutionTransaction struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlockExecutionTransaction) Reset() { @@ -1118,12 +1159,20 @@ func (x *CannonLocationEthV2BeaconBlockExecutionTransaction) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlockExecutionTransaction) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV2BeaconBlockWithdrawal struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlockWithdrawal) Reset() { @@ -1165,12 +1214,20 @@ func (x *CannonLocationEthV2BeaconBlockWithdrawal) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlockWithdrawal) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV2BeaconBlock struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV2BeaconBlock) Reset() { @@ -1212,6 +1269,13 @@ func (x *CannonLocationEthV2BeaconBlock) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV2BeaconBlock) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationBlockprintBlockClassification struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1272,7 +1336,8 @@ type CannonLocationEthV1BeaconBlobSidecar struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` // Marked for deprecation + BackfillingCheckpointMarker *BackfillingCheckpointMarker `protobuf:"bytes,2,opt,name=backfilling_checkpoint_marker,json=backfillingCheckpointMarker,proto3" json:"backfilling_checkpoint_marker,omitempty"` } func (x *CannonLocationEthV1BeaconBlobSidecar) Reset() { @@ -1314,6 +1379,13 @@ func (x *CannonLocationEthV1BeaconBlobSidecar) GetEpoch() uint64 { return 0 } +func (x *CannonLocationEthV1BeaconBlobSidecar) GetBackfillingCheckpointMarker() *BackfillingCheckpointMarker { + if x != nil { + return x.BackfillingCheckpointMarker + } + return nil +} + type CannonLocationEthV1BeaconProposerDuty struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2111,309 +2183,367 @@ var file_pkg_proto_xatu_coordinator_proto_rawDesc = []byte{ 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x43, - 0x0a, 0x2b, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x14, 0x0a, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x22, 0x46, 0x0a, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, + 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0xaa, + 0x01, 0x0a, 0x2b, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, + 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, + 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, + 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, + 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0xad, 0x01, 0x0a, 0x2e, + 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, + 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, + 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, + 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, + 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, + 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0xa4, 0x01, 0x0a, 0x25, + 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, + 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, 0x0a, 0x1d, 0x62, + 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, + 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, + 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, + 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, + 0x65, 0x72, 0x22, 0xad, 0x01, 0x0a, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x3d, 0x0a, 0x25, 0x43, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, 0x0a, 0x1d, 0x62, + 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, + 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, + 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, + 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, + 0x65, 0x72, 0x22, 0xb1, 0x01, 0x0a, 0x32, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, + 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, + 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, + 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0xb1, 0x01, 0x0a, 0x32, 0x43, 0x61, 0x6e, 0x6e, 0x6f, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, + 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x12, 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, + 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, + 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, + 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, + 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0xa7, 0x01, 0x0a, 0x28, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, - 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x46, 0x0a, 0x2e, 0x43, 0x61, - 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, - 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x22, 0x4a, 0x0a, 0x32, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x4a, - 0x0a, 0x32, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x40, 0x0a, 0x28, 0x43, 0x61, - 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, - 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x36, 0x0a, 0x1e, - 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, - 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x22, 0x69, 0x0a, 0x2b, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, + 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, 0x0a, + 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, + 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, + 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, + 0x72, 0x6b, 0x65, 0x72, 0x22, 0x9d, 0x01, 0x0a, 0x1e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, 0x0a, + 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, + 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, + 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, + 0x72, 0x6b, 0x65, 0x72, 0x22, 0x69, 0x0a, 0x2b, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x45, 0x6e, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x22, - 0x3c, 0x0a, 0x24, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x62, - 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x8e, 0x01, - 0x0a, 0x25, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, 0x79, 0x12, 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, - 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, - 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, - 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0x9c, - 0x01, 0x0a, 0x33, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x45, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, - 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, - 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0x8c, 0x01, - 0x0a, 0x23, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, - 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, - 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, - 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, - 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0xe3, 0x0e, 0x0a, - 0x0e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x24, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x78, - 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x22, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, - 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x76, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x31, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, - 0x45, 0x78, 0x69, 0x74, 0x48, 0x00, 0x52, 0x2d, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, - 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, - 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x56, 0x4f, 0x4c, 0x55, 0x4e, 0x54, 0x41, 0x52, 0x59, - 0x5f, 0x45, 0x58, 0x49, 0x54, 0x12, 0x97, 0x01, 0x0a, 0x25, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, - 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, - 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x30, 0x42, - 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, - 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, - 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x12, - 0x7a, 0x0a, 0x1b, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, - 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x48, 0x00, 0x52, 0x26, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, - 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x12, 0x97, 0x01, 0x0a, 0x25, - 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, 0x61, - 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x48, 0x00, 0x52, 0x30, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, - 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x5f, 0x41, 0x54, 0x54, 0x45, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x53, 0x4c, 0x41, - 0x53, 0x48, 0x49, 0x4e, 0x47, 0x12, 0xa7, 0x01, 0x0a, 0x2b, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, - 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x62, 0x6c, - 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x61, - 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x42, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x36, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, - 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, - 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x42, 0x4c, 0x53, 0x5f, 0x54, 0x4f, 0x5f, 0x45, - 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x12, - 0xa3, 0x01, 0x0a, 0x29, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, + 0xa3, 0x01, 0x0a, 0x24, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, + 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, + 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, + 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, + 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0x8e, 0x01, 0x0a, 0x25, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, 0x79, 0x12, + 0x65, 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, + 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, + 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0x9c, 0x01, 0x0a, 0x33, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, - 0x34, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, - 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, - 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x83, 0x01, 0x0a, 0x1e, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, - 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x48, 0x00, - 0x52, 0x29, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, - 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, - 0x5f, 0x57, 0x49, 0x54, 0x48, 0x44, 0x52, 0x41, 0x57, 0x41, 0x4c, 0x12, 0x63, 0x0a, 0x13, 0x65, - 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, - 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, - 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, - 0x52, 0x1e, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, - 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, - 0x12, 0x7d, 0x0a, 0x1f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x78, 0x61, 0x74, 0x75, - 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6c, - 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x1f, - 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, - 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x12, - 0x77, 0x0a, 0x1a, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x31, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x48, - 0x00, 0x52, 0x25, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, - 0x48, 0x5f, 0x56, 0x31, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x42, - 0x5f, 0x53, 0x49, 0x44, 0x45, 0x43, 0x41, 0x52, 0x12, 0x73, 0x0a, 0x1b, 0x65, 0x74, 0x68, 0x5f, - 0x76, 0x31, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x5f, 0x64, 0x75, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, + 0x0a, 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, + 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, + 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, + 0x61, 0x72, 0x6b, 0x65, 0x72, 0x22, 0x8c, 0x01, 0x0a, 0x23, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x65, 0x0a, + 0x1d, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x42, 0x61, 0x63, 0x6b, + 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x1b, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, + 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, + 0x72, 0x6b, 0x65, 0x72, 0x22, 0xe3, 0x0e, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, + 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x8e, 0x01, 0x0a, + 0x22, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, + 0x78, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x78, 0x61, 0x74, 0x75, + 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, + 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x48, 0x00, 0x52, 0x2d, + 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, + 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x56, + 0x4f, 0x4c, 0x55, 0x4e, 0x54, 0x41, 0x52, 0x59, 0x5f, 0x45, 0x58, 0x49, 0x54, 0x12, 0x97, 0x01, + 0x0a, 0x25, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, 0x79, 0x48, 0x00, 0x52, 0x1f, 0x42, 0x45, - 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, 0x5f, - 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, 0x5f, 0x44, 0x55, 0x54, 0x59, 0x12, 0xa6, 0x01, - 0x0a, 0x2a, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x65, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, - 0x35, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, - 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, - 0x45, 0x4c, 0x41, 0x42, 0x4f, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x54, 0x54, 0x45, 0x53, - 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x72, 0x0a, 0x18, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x31, - 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, - 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, - 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x73, 0x48, 0x00, 0x52, 0x23, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, - 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, - 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x4f, 0x52, 0x53, 0x42, 0x06, 0x0a, 0x04, 0x44, 0x61, - 0x74, 0x61, 0x22, 0x5f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x24, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x78, 0x61, - 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x4d, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x30, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x4f, 0x0a, 0x1b, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, 0x6e, - 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x1e, 0x0a, 0x1c, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, - 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2a, 0xf9, 0x04, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x31, 0x0a, 0x2d, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, - 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, - 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x56, 0x4f, 0x4c, 0x55, 0x4e, 0x54, 0x41, 0x52, 0x59, 0x5f, 0x45, - 0x58, 0x49, 0x54, 0x10, 0x00, 0x12, 0x34, 0x0a, 0x30, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, - 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, - 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, - 0x5f, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x42, - 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, - 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x44, 0x45, - 0x50, 0x4f, 0x53, 0x49, 0x54, 0x10, 0x02, 0x12, 0x34, 0x0a, 0x30, 0x42, 0x45, 0x41, 0x43, 0x4f, - 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, - 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x41, 0x54, 0x54, 0x45, 0x53, 0x54, - 0x45, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x3a, 0x0a, + 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x30, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, + 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, + 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, 0x5f, 0x53, + 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x12, 0x7a, 0x0a, 0x1b, 0x65, 0x74, 0x68, 0x5f, 0x76, + 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, + 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x48, 0x00, 0x52, 0x26, 0x42, 0x45, 0x41, + 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, + 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x44, 0x45, 0x50, 0x4f, + 0x53, 0x49, 0x54, 0x12, 0x97, 0x01, 0x0a, 0x25, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x30, 0x42, 0x45, 0x41, + 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, + 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x41, 0x54, 0x54, 0x45, + 0x53, 0x54, 0x45, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x12, 0xa7, 0x01, + 0x0a, 0x2b, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x36, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x42, 0x4c, 0x53, 0x5f, 0x54, 0x4f, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x04, 0x12, 0x38, 0x0a, 0x34, 0x42, 0x45, 0x41, - 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, - 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x45, 0x58, 0x45, 0x43, - 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x10, 0x05, 0x12, 0x2d, 0x0a, 0x29, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, - 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, - 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x44, 0x52, 0x41, 0x57, 0x41, 0x4c, - 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, - 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, - 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x07, 0x12, 0x23, 0x0a, 0x1f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x50, - 0x52, 0x49, 0x4e, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, - 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x29, 0x0a, 0x25, 0x42, + 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x12, 0xa3, 0x01, 0x0a, 0x29, 0x65, 0x74, 0x68, 0x5f, + 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x61, + 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x34, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, + 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, + 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x83, 0x01, + 0x0a, 0x1e, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, + 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, + 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x29, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, + 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, + 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x44, 0x52, 0x41, + 0x57, 0x41, 0x4c, 0x12, 0x63, 0x0a, 0x13, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, 0x5f, 0x62, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x1e, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, + 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, + 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x12, 0x7d, 0x0a, 0x1f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x61, + 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x70, 0x72, 0x69, 0x6e, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x1f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x50, 0x52, 0x49, + 0x4e, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x49, 0x46, + 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x77, 0x0a, 0x1a, 0x65, 0x74, 0x68, 0x5f, 0x76, + 0x31, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x73, 0x69, + 0x64, 0x65, 0x63, 0x61, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x61, + 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x62, + 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x48, 0x00, 0x52, 0x25, 0x42, 0x45, 0x41, 0x43, 0x4f, + 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, 0x5f, 0x42, 0x45, 0x41, + 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x42, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x43, 0x41, 0x52, + 0x12, 0x73, 0x0a, 0x1b, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x31, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x75, 0x74, 0x79, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, + 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, + 0x74, 0x79, 0x48, 0x00, 0x52, 0x1f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, + 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, + 0x5f, 0x44, 0x55, 0x54, 0x59, 0x12, 0xa6, 0x01, 0x0a, 0x2a, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x32, + 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x65, 0x6c, + 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x78, 0x61, 0x74, + 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x74, 0x68, 0x56, 0x32, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x45, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x35, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, + 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, + 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x45, 0x4c, 0x41, 0x42, 0x4f, 0x52, 0x41, 0x54, + 0x45, 0x44, 0x5f, 0x41, 0x54, 0x54, 0x45, 0x53, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x72, + 0x0a, 0x18, 0x65, 0x74, 0x68, 0x5f, 0x76, 0x31, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x74, 0x68, 0x56, 0x31, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x48, 0x00, 0x52, 0x23, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, - 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x42, 0x5f, 0x53, 0x49, 0x44, - 0x45, 0x43, 0x41, 0x52, 0x10, 0x09, 0x12, 0x23, 0x0a, 0x1f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, - 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, 0x5f, 0x50, 0x52, 0x4f, 0x50, - 0x4f, 0x53, 0x45, 0x52, 0x5f, 0x44, 0x55, 0x54, 0x59, 0x10, 0x0a, 0x12, 0x39, 0x0a, 0x35, 0x42, - 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, - 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x45, 0x4c, - 0x41, 0x42, 0x4f, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x54, 0x54, 0x45, 0x53, 0x54, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0b, 0x12, 0x27, 0x0a, 0x23, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, - 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, 0x5f, 0x42, 0x45, 0x41, 0x43, - 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x4f, 0x52, 0x53, 0x10, 0x0c, 0x32, - 0x8a, 0x06, 0x0a, 0x0b, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, - 0x56, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1e, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x78, 0x61, - 0x74, 0x75, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x61, 0x74, 0x75, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x1f, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, - 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, - 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7d, 0x0a, - 0x1e, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, - 0x2b, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, - 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x78, - 0x61, 0x74, 0x75, 0x2e, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x16, - 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x23, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x47, 0x65, - 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x78, 0x61, - 0x74, 0x75, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x4e, - 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x14, 0x55, - 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, + 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x4f, + 0x52, 0x53, 0x42, 0x06, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x22, 0x5f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x55, 0x70, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x4d, 0x0a, 0x19, 0x47, + 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x78, 0x61, 0x74, + 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4f, 0x0a, 0x1b, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x70, 0x61, - 0x6e, 0x64, 0x61, 0x6f, 0x70, 0x73, 0x2f, 0x78, 0x61, 0x74, 0x75, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x78, 0x61, 0x74, 0x75, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x78, 0x61, + 0x74, 0x75, 0x2e, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1e, 0x0a, 0x1c, 0x55, + 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0xf9, 0x04, 0x0a, 0x0a, + 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, 0x2d, 0x42, 0x45, + 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, + 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x56, 0x4f, 0x4c, + 0x55, 0x4e, 0x54, 0x41, 0x52, 0x59, 0x5f, 0x45, 0x58, 0x49, 0x54, 0x10, 0x00, 0x12, 0x34, 0x0a, + 0x30, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, + 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, + 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, + 0x47, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, + 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, + 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x10, 0x02, 0x12, + 0x34, 0x0a, 0x30, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, + 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, + 0x4b, 0x5f, 0x41, 0x54, 0x54, 0x45, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x53, 0x48, + 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x3a, 0x0a, 0x36, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, + 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, + 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x42, 0x4c, 0x53, 0x5f, 0x54, 0x4f, 0x5f, 0x45, + 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, + 0x04, 0x12, 0x38, 0x0a, 0x34, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, + 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, + 0x4f, 0x43, 0x4b, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x52, + 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x2d, 0x0a, 0x29, 0x42, + 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, + 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x57, 0x49, + 0x54, 0x48, 0x44, 0x52, 0x41, 0x57, 0x41, 0x4c, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x42, 0x45, + 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, + 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x07, 0x12, 0x23, + 0x0a, 0x1f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x5f, 0x42, 0x4c, 0x4f, + 0x43, 0x4b, 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x10, 0x08, 0x12, 0x29, 0x0a, 0x25, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, + 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x31, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, + 0x42, 0x4c, 0x4f, 0x42, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x43, 0x41, 0x52, 0x10, 0x09, 0x12, 0x23, + 0x0a, 0x1f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, + 0x5f, 0x56, 0x31, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, 0x5f, 0x44, 0x55, 0x54, + 0x59, 0x10, 0x0a, 0x12, 0x39, 0x0a, 0x35, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, + 0x49, 0x5f, 0x45, 0x54, 0x48, 0x5f, 0x56, 0x32, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, + 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x45, 0x4c, 0x41, 0x42, 0x4f, 0x52, 0x41, 0x54, 0x45, 0x44, + 0x5f, 0x41, 0x54, 0x54, 0x45, 0x53, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0b, 0x12, 0x27, + 0x0a, 0x23, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x45, 0x54, 0x48, + 0x5f, 0x56, 0x31, 0x5f, 0x42, 0x45, 0x41, 0x43, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, + 0x41, 0x54, 0x4f, 0x52, 0x53, 0x10, 0x0c, 0x32, 0x8a, 0x06, 0x0a, 0x0b, 0x43, 0x6f, 0x6f, 0x72, + 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x56, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1e, 0x2e, 0x78, + 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x78, + 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x80, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, + 0x6c, 0x6c, 0x65, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7d, 0x0a, 0x1e, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, + 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x2b, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, + 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x43, 0x6f, 0x6f, 0x72, + 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x23, + 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x1e, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x14, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, + 0x6e, 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x78, 0x61, + 0x74, 0x75, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x2e, 0x78, 0x61, 0x74, 0x75, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x61, 0x6e, 0x6e, + 0x6f, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x70, 0x73, 0x2f, 0x78, + 0x61, 0x74, 0x75, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x78, 0x61, + 0x74, 0x75, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2471,45 +2601,54 @@ var file_pkg_proto_xatu_coordinator_proto_depIdxs = []int32{ 33, // 1: xatu.ExecutionNodeStatus.fork_id:type_name -> xatu.ExecutionNodeStatus.ForkID 5, // 2: xatu.CreateExecutionNodeRecordStatusRequest.status:type_name -> xatu.ExecutionNodeStatus 8, // 3: xatu.CoordinateExecutionNodeRecordsRequest.node_records:type_name -> xatu.CoordinatedNodeRecord - 13, // 4: xatu.CannonLocationEthV1BeaconProposerDuty.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker - 13, // 5: xatu.CannonLocationEthV2BeaconBlockElaboratedAttestation.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker - 13, // 6: xatu.CannonLocationEthV1BeaconValidators.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker - 0, // 7: xatu.CannonLocation.type:type_name -> xatu.CannonType - 14, // 8: xatu.CannonLocation.eth_v2_beacon_block_voluntary_exit:type_name -> xatu.CannonLocationEthV2BeaconBlockVoluntaryExit - 15, // 9: xatu.CannonLocation.eth_v2_beacon_block_proposer_slashing:type_name -> xatu.CannonLocationEthV2BeaconBlockProposerSlashing - 16, // 10: xatu.CannonLocation.eth_v2_beacon_block_deposit:type_name -> xatu.CannonLocationEthV2BeaconBlockDeposit - 17, // 11: xatu.CannonLocation.eth_v2_beacon_block_attester_slashing:type_name -> xatu.CannonLocationEthV2BeaconBlockAttesterSlashing - 18, // 12: xatu.CannonLocation.eth_v2_beacon_block_bls_to_execution_change:type_name -> xatu.CannonLocationEthV2BeaconBlockBlsToExecutionChange - 19, // 13: xatu.CannonLocation.eth_v2_beacon_block_execution_transaction:type_name -> xatu.CannonLocationEthV2BeaconBlockExecutionTransaction - 20, // 14: xatu.CannonLocation.eth_v2_beacon_block_withdrawal:type_name -> xatu.CannonLocationEthV2BeaconBlockWithdrawal - 21, // 15: xatu.CannonLocation.eth_v2_beacon_block:type_name -> xatu.CannonLocationEthV2BeaconBlock - 22, // 16: xatu.CannonLocation.blockprint_block_classification:type_name -> xatu.CannonLocationBlockprintBlockClassification - 23, // 17: xatu.CannonLocation.eth_v1_beacon_blob_sidecar:type_name -> xatu.CannonLocationEthV1BeaconBlobSidecar - 24, // 18: xatu.CannonLocation.eth_v1_beacon_proposer_duty:type_name -> xatu.CannonLocationEthV1BeaconProposerDuty - 25, // 19: xatu.CannonLocation.eth_v2_beacon_block_elaborated_attestation:type_name -> xatu.CannonLocationEthV2BeaconBlockElaboratedAttestation - 26, // 20: xatu.CannonLocation.eth_v1_beacon_validators:type_name -> xatu.CannonLocationEthV1BeaconValidators - 0, // 21: xatu.GetCannonLocationRequest.type:type_name -> xatu.CannonType - 27, // 22: xatu.GetCannonLocationResponse.location:type_name -> xatu.CannonLocation - 27, // 23: xatu.UpsertCannonLocationRequest.location:type_name -> xatu.CannonLocation - 1, // 24: xatu.Coordinator.CreateNodeRecords:input_type -> xatu.CreateNodeRecordsRequest - 3, // 25: xatu.Coordinator.ListStalledExecutionNodeRecords:input_type -> xatu.ListStalledExecutionNodeRecordsRequest - 6, // 26: xatu.Coordinator.CreateExecutionNodeRecordStatus:input_type -> xatu.CreateExecutionNodeRecordStatusRequest - 9, // 27: xatu.Coordinator.CoordinateExecutionNodeRecords:input_type -> xatu.CoordinateExecutionNodeRecordsRequest - 11, // 28: xatu.Coordinator.GetDiscoveryNodeRecord:input_type -> xatu.GetDiscoveryNodeRecordRequest - 28, // 29: xatu.Coordinator.GetCannonLocation:input_type -> xatu.GetCannonLocationRequest - 30, // 30: xatu.Coordinator.UpsertCannonLocation:input_type -> xatu.UpsertCannonLocationRequest - 2, // 31: xatu.Coordinator.CreateNodeRecords:output_type -> xatu.CreateNodeRecordsResponse - 4, // 32: xatu.Coordinator.ListStalledExecutionNodeRecords:output_type -> xatu.ListStalledExecutionNodeRecordsResponse - 7, // 33: xatu.Coordinator.CreateExecutionNodeRecordStatus:output_type -> xatu.CreateExecutionNodeRecordStatusResponse - 10, // 34: xatu.Coordinator.CoordinateExecutionNodeRecords:output_type -> xatu.CoordinateExecutionNodeRecordsResponse - 12, // 35: xatu.Coordinator.GetDiscoveryNodeRecord:output_type -> xatu.GetDiscoveryNodeRecordResponse - 29, // 36: xatu.Coordinator.GetCannonLocation:output_type -> xatu.GetCannonLocationResponse - 31, // 37: xatu.Coordinator.UpsertCannonLocation:output_type -> xatu.UpsertCannonLocationResponse - 31, // [31:38] is the sub-list for method output_type - 24, // [24:31] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 13, // 4: xatu.CannonLocationEthV2BeaconBlockVoluntaryExit.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 5: xatu.CannonLocationEthV2BeaconBlockProposerSlashing.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 6: xatu.CannonLocationEthV2BeaconBlockDeposit.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 7: xatu.CannonLocationEthV2BeaconBlockAttesterSlashing.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 8: xatu.CannonLocationEthV2BeaconBlockBlsToExecutionChange.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 9: xatu.CannonLocationEthV2BeaconBlockExecutionTransaction.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 10: xatu.CannonLocationEthV2BeaconBlockWithdrawal.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 11: xatu.CannonLocationEthV2BeaconBlock.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 12: xatu.CannonLocationEthV1BeaconBlobSidecar.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 13: xatu.CannonLocationEthV1BeaconProposerDuty.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 14: xatu.CannonLocationEthV2BeaconBlockElaboratedAttestation.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 13, // 15: xatu.CannonLocationEthV1BeaconValidators.backfilling_checkpoint_marker:type_name -> xatu.BackfillingCheckpointMarker + 0, // 16: xatu.CannonLocation.type:type_name -> xatu.CannonType + 14, // 17: xatu.CannonLocation.eth_v2_beacon_block_voluntary_exit:type_name -> xatu.CannonLocationEthV2BeaconBlockVoluntaryExit + 15, // 18: xatu.CannonLocation.eth_v2_beacon_block_proposer_slashing:type_name -> xatu.CannonLocationEthV2BeaconBlockProposerSlashing + 16, // 19: xatu.CannonLocation.eth_v2_beacon_block_deposit:type_name -> xatu.CannonLocationEthV2BeaconBlockDeposit + 17, // 20: xatu.CannonLocation.eth_v2_beacon_block_attester_slashing:type_name -> xatu.CannonLocationEthV2BeaconBlockAttesterSlashing + 18, // 21: xatu.CannonLocation.eth_v2_beacon_block_bls_to_execution_change:type_name -> xatu.CannonLocationEthV2BeaconBlockBlsToExecutionChange + 19, // 22: xatu.CannonLocation.eth_v2_beacon_block_execution_transaction:type_name -> xatu.CannonLocationEthV2BeaconBlockExecutionTransaction + 20, // 23: xatu.CannonLocation.eth_v2_beacon_block_withdrawal:type_name -> xatu.CannonLocationEthV2BeaconBlockWithdrawal + 21, // 24: xatu.CannonLocation.eth_v2_beacon_block:type_name -> xatu.CannonLocationEthV2BeaconBlock + 22, // 25: xatu.CannonLocation.blockprint_block_classification:type_name -> xatu.CannonLocationBlockprintBlockClassification + 23, // 26: xatu.CannonLocation.eth_v1_beacon_blob_sidecar:type_name -> xatu.CannonLocationEthV1BeaconBlobSidecar + 24, // 27: xatu.CannonLocation.eth_v1_beacon_proposer_duty:type_name -> xatu.CannonLocationEthV1BeaconProposerDuty + 25, // 28: xatu.CannonLocation.eth_v2_beacon_block_elaborated_attestation:type_name -> xatu.CannonLocationEthV2BeaconBlockElaboratedAttestation + 26, // 29: xatu.CannonLocation.eth_v1_beacon_validators:type_name -> xatu.CannonLocationEthV1BeaconValidators + 0, // 30: xatu.GetCannonLocationRequest.type:type_name -> xatu.CannonType + 27, // 31: xatu.GetCannonLocationResponse.location:type_name -> xatu.CannonLocation + 27, // 32: xatu.UpsertCannonLocationRequest.location:type_name -> xatu.CannonLocation + 1, // 33: xatu.Coordinator.CreateNodeRecords:input_type -> xatu.CreateNodeRecordsRequest + 3, // 34: xatu.Coordinator.ListStalledExecutionNodeRecords:input_type -> xatu.ListStalledExecutionNodeRecordsRequest + 6, // 35: xatu.Coordinator.CreateExecutionNodeRecordStatus:input_type -> xatu.CreateExecutionNodeRecordStatusRequest + 9, // 36: xatu.Coordinator.CoordinateExecutionNodeRecords:input_type -> xatu.CoordinateExecutionNodeRecordsRequest + 11, // 37: xatu.Coordinator.GetDiscoveryNodeRecord:input_type -> xatu.GetDiscoveryNodeRecordRequest + 28, // 38: xatu.Coordinator.GetCannonLocation:input_type -> xatu.GetCannonLocationRequest + 30, // 39: xatu.Coordinator.UpsertCannonLocation:input_type -> xatu.UpsertCannonLocationRequest + 2, // 40: xatu.Coordinator.CreateNodeRecords:output_type -> xatu.CreateNodeRecordsResponse + 4, // 41: xatu.Coordinator.ListStalledExecutionNodeRecords:output_type -> xatu.ListStalledExecutionNodeRecordsResponse + 7, // 42: xatu.Coordinator.CreateExecutionNodeRecordStatus:output_type -> xatu.CreateExecutionNodeRecordStatusResponse + 10, // 43: xatu.Coordinator.CoordinateExecutionNodeRecords:output_type -> xatu.CoordinateExecutionNodeRecordsResponse + 12, // 44: xatu.Coordinator.GetDiscoveryNodeRecord:output_type -> xatu.GetDiscoveryNodeRecordResponse + 29, // 45: xatu.Coordinator.GetCannonLocation:output_type -> xatu.GetCannonLocationResponse + 31, // 46: xatu.Coordinator.UpsertCannonLocation:output_type -> xatu.UpsertCannonLocationResponse + 40, // [40:47] is the sub-list for method output_type + 33, // [33:40] is the sub-list for method input_type + 33, // [33:33] is the sub-list for extension type_name + 33, // [33:33] is the sub-list for extension extendee + 0, // [0:33] is the sub-list for field type_name } func init() { file_pkg_proto_xatu_coordinator_proto_init() } diff --git a/pkg/proto/xatu/coordinator.proto b/pkg/proto/xatu/coordinator.proto index 383c82a5..257c7e7f 100644 --- a/pkg/proto/xatu/coordinator.proto +++ b/pkg/proto/xatu/coordinator.proto @@ -108,28 +108,55 @@ message BackfillingCheckpointMarker { int64 backfill_epoch = 2; } -message CannonLocationEthV2BeaconBlockVoluntaryExit { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlockVoluntaryExit { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} -message CannonLocationEthV2BeaconBlockProposerSlashing { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlockProposerSlashing{ + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} -message CannonLocationEthV2BeaconBlockDeposit { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlockDeposit { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} -message CannonLocationEthV2BeaconBlockAttesterSlashing { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlockAttesterSlashing { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} -message CannonLocationEthV2BeaconBlockBlsToExecutionChange { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlockBlsToExecutionChange { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} -message CannonLocationEthV2BeaconBlockExecutionTransaction { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlockExecutionTransaction { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} -message CannonLocationEthV2BeaconBlockWithdrawal { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlockWithdrawal { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} -message CannonLocationEthV2BeaconBlock { uint64 epoch = 1; } +message CannonLocationEthV2BeaconBlock { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} message CannonLocationBlockprintBlockClassification { uint64 slot = 1; uint64 target_end_slot = 2; } -message CannonLocationEthV1BeaconBlobSidecar { uint64 epoch = 1; } +message CannonLocationEthV1BeaconBlobSidecar { + uint64 epoch = 1; // Marked for deprecation + BackfillingCheckpointMarker backfilling_checkpoint_marker = 2; +} message CannonLocationEthV1BeaconProposerDuty { BackfillingCheckpointMarker backfilling_checkpoint_marker = 1;