Compare commits

...

8 Commits

Author SHA1 Message Date
james-prysm
2c21b379f6 fixing changelog conflict, put in the wrong spot 2024-11-22 14:06:48 -06:00
james-prysm
1a5d92ea03 gaz 2024-11-22 13:47:38 -06:00
james-prysm
3ab92a1036 undoing some reverts for useful helper functions 2024-11-22 13:38:47 -06:00
james-prysm
ff5df53bad undoing some reverts, validator count api should not be called and should remain removed 2024-11-22 13:27:37 -06:00
james-prysm
13417acb54 missed something on changelog conflict 2024-11-22 12:14:21 -06:00
james-prysm
461c5ff127 Merge branch 'develop' into revert-wait-for-activation 2024-11-22 12:11:22 -06:00
james-prysm
775a694318 Revert "Replace validator wait for activation stream with polling (#14514)"
This reverts commit 6c22edeecc.
2024-11-22 12:07:55 -06:00
james-prysm
470581ec6c Revert "Remove validator count log (#14600)"
This reverts commit f2ade3caff.
2024-11-22 12:06:05 -06:00
18 changed files with 1198 additions and 437 deletions

View File

@@ -69,7 +69,6 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
### Removed
- Removed finalized validator index cache, no longer needed.
- Removed validator queue position log on key reload and wait for activation.
- Removed outdated spectest exclusions for EIP-6110.
### Fixed
@@ -92,6 +91,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- temporary solution to handling electra attesation and attester_slashing events. [pr](14655)
### Security
## [v5.1.2](https://github.com/prysmaticlabs/prysm/compare/v5.1.1...v5.1.2) - 2024-10-16

View File

@@ -83,7 +83,6 @@ type Server struct {
// WaitForActivation checks if a validator public key exists in the active validator registry of the current
// beacon state, if not, then it creates a stream which listens for canonical states which contain
// the validator with the public key as an active validator record.
// Deprecated: do not use, just poll validator status every epoch.
func (vs *Server) WaitForActivation(req *ethpb.ValidatorActivationRequest, stream ethpb.BeaconNodeValidator_WaitForActivationServer) error {
activeValidatorExists, validatorStatuses, err := vs.activationStatus(stream.Context(), req.PublicKeys)
if err != nil {

View File

@@ -3728,7 +3728,7 @@ var file_proto_prysm_v1alpha1_validator_proto_rawDesc = []byte{
0x0a, 0x0a, 0x06, 0x45, 0x58, 0x49, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x49,
0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x41, 0x52, 0x54,
0x49, 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x44, 0x10,
0x08, 0x32, 0xf5, 0x28, 0x0a, 0x13, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65,
0x08, 0x32, 0xf2, 0x28, 0x0a, 0x13, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x80, 0x01, 0x0a, 0x09, 0x47, 0x65,
0x74, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
@@ -3755,317 +3755,317 @@ var file_proto_prysm_v1alpha1_validator_proto_rawDesc = []byte{
0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e,
0x73, 0x74, 0x61, 0x72, 0x74, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x88, 0x02, 0x01, 0x30,
0x01, 0x12, 0xb2, 0x01, 0x0a, 0x11, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74,
0x01, 0x12, 0xaf, 0x01, 0x0a, 0x11, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74,
0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69,
0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34,
0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f,
0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61,
0x6d, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x94, 0x01, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d,
0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x98, 0x01,
0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61,
0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0xb2, 0x01, 0x0a, 0x17, 0x4d, 0x75, 0x6c,
0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x75, 0x6c,
0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x65, 0x74,
0x6d, 0x30, 0x01, 0x12, 0x94, 0x01, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c,
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x87, 0x01,
0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x12, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65,
0x6e, 0x65, 0x72, 0x69, 0x63, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x97, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70,
0x6f, 0x73, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f,
0x61, 0x74, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x98, 0x01, 0x0a, 0x0f, 0x56,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x1a,
0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a,
0x01, 0x2a, 0x22, 0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x12, 0xa0, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61,
0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f,
0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34,
0x3a, 0x01, 0x2a, 0x22, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x65,
0x70, 0x61, 0x72, 0x65, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70,
0x6f, 0x73, 0x65, 0x72, 0x12, 0xbf, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52,
0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79,
0x12, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69,
0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65,
0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65,
0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x35, 0x3a, 0x01, 0x2a, 0x22, 0x30, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x66, 0x65,
0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x70,
0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x98, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x74,
0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x2e,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x44, 0x61, 0x74, 0x61, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x65,
0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x8f, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, 0x74,
0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53,
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73,
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0xb2, 0x01, 0x0a, 0x17, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70,
0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70,
0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x25, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x3a, 0x01, 0x2a, 0x22, 0x23,
0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0xa5, 0x01, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41,
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72,
0x61, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x1a, 0x25, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x3a, 0x01, 0x2a, 0x22, 0x2b,
0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xb2, 0x01, 0x0a, 0x1d,
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x30, 0x2e,
0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x0e, 0x47,
0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74,
0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72,
0x69, 0x63, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x25, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x97, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, 0x65,
0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, 0x26, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x22,
0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2f, 0x76,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0xa0,
0x01, 0x0a, 0x15, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e,
0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72,
0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x3a, 0x01, 0x2a,
0x22, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f,
0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72,
0x65, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
0x72, 0x12, 0xbf, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69,
0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x32, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65,
0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63,
0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x3a, 0x01,
0x2a, 0x22, 0x30, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x66, 0x65, 0x65, 0x5f, 0x72,
0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x75, 0x62, 0x5f,
0x6b, 0x65, 0x79, 0x12, 0x98, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73,
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61,
0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74,
0x61, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x8f,
0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74,
0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x3a, 0x01, 0x2a, 0x22, 0x23, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0xa5, 0x01, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, 0x74, 0x65,
0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x29,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x3a, 0x01, 0x2a, 0x22, 0x2b, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xb2, 0x01, 0x0a, 0x1d, 0x53, 0x75, 0x62,
0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65,
0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xc8, 0x01,
0x0a, 0x24, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74,
0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45,
0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41,
0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c,
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65,
0x12, 0xc8, 0x01, 0x0a, 0x24, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65,
0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f,
0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a,
0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f,
0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67,
0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xbe, 0x01, 0x0a, 0x23,
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72,
0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e,
0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69,
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xbe, 0x01, 0x0a, 0x23, 0x53, 0x75, 0x62,
0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66,
0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41,
0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62,
0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f,
0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xd4, 0x01, 0x0a, 0x2a, 0x53, 0x75,
0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67,
0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f,
0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65,
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xd4, 0x01, 0x0a,
0x2a, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67,
0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50,
0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3a, 0x2e, 0x65, 0x74,
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67,
0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d,
0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61,
0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61,
0x12, 0x8e, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, 0x74,
0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56,
0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a, 0x2a, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21,
0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x65, 0x78, 0x69,
0x74, 0x12, 0xa1, 0x01, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x12,
0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65,
0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x75, 0x62, 0x73,
0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x9a, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44,
0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67,
0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53,
0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x72, 0x61, 0x12, 0x8e, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45,
0x78, 0x69, 0x74, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e,
0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a,
0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45,
0x78, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f,
0x65, 0x78, 0x69, 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
0x62, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65,
0x74, 0x73, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63,
0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28,
0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x2f, 0x73,
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x9a, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x65,
0x63, 0x6b, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x2a,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e,
0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12,
0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x67,
0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x9f, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e,
0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f,
0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f,
0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x6c, 0x6f,
0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d,
0x69, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c,
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x12, 0xb4, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x53,
0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78,
0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62,
0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79,
0x6e, 0x63, 0x53, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e,
0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0xc4, 0x01, 0x0a, 0x1c, 0x47,
0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65,
0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e,
0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69,
0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01,
0x2a, 0x22, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f,
0x66, 0x12, 0xaf, 0x01, 0x0a, 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e,
0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e,
0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53,
0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x22, 0x40, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x3a, 0x01, 0x2a, 0x22, 0x35, 0x2f, 0x65,
0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72,
0x6f, 0x6f, 0x66, 0x12, 0x9e, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c,
0x6f, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65,
0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x2d, 0x12, 0x2b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x88,
0x02, 0x01, 0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73,
0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65,
0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x65,
0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x9e, 0x01, 0x0a, 0x1c, 0x53, 0x75, 0x62,
0x6d, 0x69, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69,
0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65,
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31,
0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29,
0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x72, 0x65, 0x67,
0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xae, 0x01, 0x0a, 0x17, 0x41, 0x73,
0x73, 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53,
0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x73,
0x73, 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53,
0x75, 0x62, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
0x6d, 0x70, 0x74, 0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x3a, 0x01, 0x2a, 0x22,
0x39, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f,
0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0xec, 0x01, 0x0a, 0x1f, 0x41,
0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41,
0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3d,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65,
0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x67, 0x61, 0x6e, 0x67,
0x65, 0x72, 0x12, 0x9f, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x16,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53,
0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52,
0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e,
0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53,
0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22,
0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x12, 0xb4, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, 0x63,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x33, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x44, 0x12, 0x42, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
0x5f, 0x73, 0x69, 0x67, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x42, 0x93, 0x01, 0x0a, 0x19, 0x6f, 0x72,
0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c,
0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53,
0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27,
0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f,
0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65,
0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0xc4, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53,
0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f,
0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
0x69, 0x6f, 0x6e, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, 0x2a, 0x22, 0x2e,
0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0xaf,
0x01, 0x0a, 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e,
0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e,
0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x40,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x3a, 0x01, 0x2a, 0x22, 0x35, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69,
0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66,
0x12, 0x9e, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73,
0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53,
0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x12,
0x2b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f,
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x88, 0x02, 0x01, 0x30,
0x01, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x73, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x9e, 0x01, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53,
0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31, 0x1a, 0x16, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a,
0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f,
0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xae, 0x01, 0x0a, 0x17, 0x41, 0x73, 0x73, 0x69, 0x67,
0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, 0x6e,
0x65, 0x74, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67,
0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, 0x6e,
0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x3a, 0x01, 0x2a, 0x22, 0x39, 0x2f, 0x65,
0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x61, 0x73, 0x73,
0x69, 0x67, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x6f,
0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0xec, 0x01, 0x0a, 0x1f, 0x41, 0x67, 0x67, 0x72,
0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72,
0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3d, 0x2e, 0x65, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69,
0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42,
0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67,
0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x44, 0x12, 0x42, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x73, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x69,
0x67, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x42, 0x93, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73,
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65,
0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74,
0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c,
0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -4906,7 +4906,6 @@ type BeaconNodeValidatorClient interface {
DomainData(ctx context.Context, in *DomainRequest, opts ...grpc.CallOption) (*DomainResponse, error)
// Deprecated: Do not use.
WaitForChainStart(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForChainStartClient, error)
// Deprecated: Do not use.
WaitForActivation(ctx context.Context, in *ValidatorActivationRequest, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForActivationClient, error)
ValidatorIndex(ctx context.Context, in *ValidatorIndexRequest, opts ...grpc.CallOption) (*ValidatorIndexResponse, error)
ValidatorStatus(ctx context.Context, in *ValidatorStatusRequest, opts ...grpc.CallOption) (*ValidatorStatusResponse, error)
@@ -4998,7 +4997,6 @@ func (x *beaconNodeValidatorWaitForChainStartClient) Recv() (*ChainStartResponse
return m, nil
}
// Deprecated: Do not use.
func (c *beaconNodeValidatorClient) WaitForActivation(ctx context.Context, in *ValidatorActivationRequest, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForActivationClient, error) {
stream, err := c.cc.NewStream(ctx, &_BeaconNodeValidator_serviceDesc.Streams[1], "/ethereum.eth.v1alpha1.BeaconNodeValidator/WaitForActivation", opts...)
if err != nil {
@@ -5328,7 +5326,6 @@ type BeaconNodeValidatorServer interface {
DomainData(context.Context, *DomainRequest) (*DomainResponse, error)
// Deprecated: Do not use.
WaitForChainStart(*emptypb.Empty, BeaconNodeValidator_WaitForChainStartServer) error
// Deprecated: Do not use.
WaitForActivation(*ValidatorActivationRequest, BeaconNodeValidator_WaitForActivationServer) error
ValidatorIndex(context.Context, *ValidatorIndexRequest) (*ValidatorIndexResponse, error)
ValidatorStatus(context.Context, *ValidatorStatusRequest) (*ValidatorStatusResponse, error)

View File

@@ -87,7 +87,6 @@ service BeaconNodeValidator {
option (google.api.http) = {
get: "/eth/v1alpha1/validator/activation/stream"
};
option deprecated = true;
}
// ValidatorIndex retrieves a validator's index location in the beacon state's

View File

@@ -786,6 +786,129 @@ func (mr *MockBeaconNodeValidator_WaitForChainStartClientMockRecorder) Trailer()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockBeaconNodeValidator_WaitForChainStartClient)(nil).Trailer))
}
// MockBeaconNodeValidator_WaitForActivationClient is a mock of BeaconNodeValidator_WaitForActivationClient interface.
type MockBeaconNodeValidator_WaitForActivationClient struct {
ctrl *gomock.Controller
recorder *MockBeaconNodeValidator_WaitForActivationClientMockRecorder
}
// MockBeaconNodeValidator_WaitForActivationClientMockRecorder is the mock recorder for MockBeaconNodeValidator_WaitForActivationClient.
type MockBeaconNodeValidator_WaitForActivationClientMockRecorder struct {
mock *MockBeaconNodeValidator_WaitForActivationClient
}
// NewMockBeaconNodeValidator_WaitForActivationClient creates a new mock instance.
func NewMockBeaconNodeValidator_WaitForActivationClient(ctrl *gomock.Controller) *MockBeaconNodeValidator_WaitForActivationClient {
mock := &MockBeaconNodeValidator_WaitForActivationClient{ctrl: ctrl}
mock.recorder = &MockBeaconNodeValidator_WaitForActivationClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockBeaconNodeValidator_WaitForActivationClient) EXPECT() *MockBeaconNodeValidator_WaitForActivationClientMockRecorder {
return m.recorder
}
// CloseSend mocks base method.
func (m *MockBeaconNodeValidator_WaitForActivationClient) CloseSend() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CloseSend")
ret0, _ := ret[0].(error)
return ret0
}
// CloseSend indicates an expected call of CloseSend.
func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) CloseSend() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).CloseSend))
}
// Context mocks base method.
func (m *MockBeaconNodeValidator_WaitForActivationClient) Context() context.Context {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context.
func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Context() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Context))
}
// Header mocks base method.
func (m *MockBeaconNodeValidator_WaitForActivationClient) Header() (metadata.MD, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Header")
ret0, _ := ret[0].(metadata.MD)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Header indicates an expected call of Header.
func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Header() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Header))
}
// Recv mocks base method.
func (m *MockBeaconNodeValidator_WaitForActivationClient) Recv() (*eth.ValidatorActivationResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Recv")
ret0, _ := ret[0].(*eth.ValidatorActivationResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Recv indicates an expected call of Recv.
func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Recv() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recv", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Recv))
}
// RecvMsg mocks base method.
func (m *MockBeaconNodeValidator_WaitForActivationClient) RecvMsg(arg0 any) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RecvMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg.
func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) RecvMsg(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).RecvMsg), arg0)
}
// SendMsg mocks base method.
func (m *MockBeaconNodeValidator_WaitForActivationClient) SendMsg(arg0 any) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendMsg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg.
func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) SendMsg(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).SendMsg), arg0)
}
// Trailer mocks base method.
func (m *MockBeaconNodeValidator_WaitForActivationClient) Trailer() metadata.MD {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Trailer")
ret0, _ := ret[0].(metadata.MD)
return ret0
}
// Trailer indicates an expected call of Trailer.
func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Trailer() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Trailer))
}
// MockBeaconNodeValidator_StreamSlotsClient is a mock of BeaconNodeValidator_StreamSlotsClient interface.
type MockBeaconNodeValidator_StreamSlotsClient struct {
ctrl *gomock.Controller

View File

@@ -630,5 +630,4 @@ func TestSecondsUntilNextEpochStart(t *testing.T) {
newGenesisTime := uint64(n.Add(time.Duration(-1*int(waitTime)) * time.Second).Unix())
currentSlot := CurrentSlot(newGenesisTime)
require.Equal(t, true, IsEpochStart(currentSlot))
}

View File

@@ -143,6 +143,7 @@ go_test(
"//runtime:go_default_library",
"//runtime/version:go_default_library",
"//testing/assert:go_default_library",
"//testing/mock:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"//testing/validator-mock:go_default_library",
@@ -167,6 +168,7 @@ go_test(
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@com_github_stretchr_testify//mock:go_default_library",
"@com_github_tyler_smith_go_bip39//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
"@com_github_wealdtech_go_eth2_util//:go_default_library",

View File

@@ -3,6 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"activation.go",
"attestation_data.go",
"beacon_api_beacon_chain_client.go",
"beacon_api_helpers.go",
@@ -74,6 +75,7 @@ go_test(
name = "go_default_test",
size = "small",
srcs = [
"activation_test.go",
"attestation_data_test.go",
"beacon_api_beacon_chain_client_test.go",
"beacon_api_helpers_test.go",

View File

@@ -0,0 +1,121 @@
package beacon_api
import (
"context"
"strconv"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"google.golang.org/grpc"
)
func (c *beaconApiValidatorClient) waitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) {
return &waitForActivationClient{
ctx: ctx,
beaconApiValidatorClient: c,
ValidatorActivationRequest: in,
}, nil
}
type waitForActivationClient struct {
grpc.ClientStream
ctx context.Context
*beaconApiValidatorClient
*ethpb.ValidatorActivationRequest
lastRecvTime time.Time
}
func computeWaitElements(now, lastRecvTime time.Time) (time.Duration, time.Time) {
nextRecvTime := lastRecvTime.Add(time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
if lastRecvTime.IsZero() {
nextRecvTime = now
}
if nextRecvTime.Before(now) {
return time.Duration(0), now
}
return nextRecvTime.Sub(now), nextRecvTime
}
func (c *waitForActivationClient) Recv() (*ethpb.ValidatorActivationResponse, error) {
waitDuration, nextRecvTime := computeWaitElements(time.Now(), c.lastRecvTime)
select {
case <-time.After(waitDuration):
c.lastRecvTime = nextRecvTime
// Represents the target set of keys
stringTargetPubKeysToPubKeys := make(map[string][]byte, len(c.ValidatorActivationRequest.PublicKeys))
stringTargetPubKeys := make([]string, len(c.ValidatorActivationRequest.PublicKeys))
// Represents the set of keys actually returned by the beacon node
stringRetrievedPubKeys := make(map[string]struct{})
// Contains all keys in targetPubKeys but not in retrievedPubKeys
var missingPubKeys [][]byte
var statuses []*ethpb.ValidatorActivationResponse_Status
for index, publicKey := range c.ValidatorActivationRequest.PublicKeys {
stringPubKey := hexutil.Encode(publicKey)
stringTargetPubKeysToPubKeys[stringPubKey] = publicKey
stringTargetPubKeys[index] = stringPubKey
}
stateValidators, err := c.stateValidatorsProvider.StateValidators(c.ctx, stringTargetPubKeys, nil, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to get state validators")
}
for _, data := range stateValidators.Data {
pubkey, err := hexutil.Decode(data.Validator.Pubkey)
if err != nil {
return nil, errors.Wrap(err, "failed to parse validator public key")
}
stringRetrievedPubKeys[data.Validator.Pubkey] = struct{}{}
index, err := strconv.ParseUint(data.Index, 10, 64)
if err != nil {
return nil, errors.Wrap(err, "failed to parse validator index")
}
validatorStatus, ok := beaconAPITogRPCValidatorStatus[data.Status]
if !ok {
return nil, errors.New("invalid validator status: " + data.Status)
}
statuses = append(statuses, &ethpb.ValidatorActivationResponse_Status{
PublicKey: pubkey,
Index: primitives.ValidatorIndex(index),
Status: &ethpb.ValidatorStatusResponse{Status: validatorStatus},
})
}
for stringTargetPubKey, targetPubKey := range stringTargetPubKeysToPubKeys {
if _, ok := stringRetrievedPubKeys[stringTargetPubKey]; !ok {
missingPubKeys = append(missingPubKeys, targetPubKey)
}
}
for _, missingPubKey := range missingPubKeys {
statuses = append(statuses, &ethpb.ValidatorActivationResponse_Status{
PublicKey: missingPubKey,
Index: primitives.ValidatorIndex(^uint64(0)),
Status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS},
})
}
return &ethpb.ValidatorActivationResponse{
Statuses: statuses,
}, nil
case <-c.ctx.Done():
return nil, errors.New("context canceled")
}
}

View File

@@ -0,0 +1,315 @@
package beacon_api
import (
"bytes"
"context"
"encoding/json"
"testing"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
"github.com/prysmaticlabs/prysm/v5/config/params"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
"go.uber.org/mock/gomock"
)
func TestComputeWaitElements_LastRecvTimeZero(t *testing.T) {
now := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
lastRecvTime := time.Time{}
waitDuration, nextRecvTime := computeWaitElements(now, lastRecvTime)
assert.Equal(t, time.Duration(0), waitDuration)
assert.Equal(t, now, nextRecvTime)
}
func TestComputeWaitElements_LastRecvTimeNotZero(t *testing.T) {
delay := 10
now := time.Date(2022, 1, 1, 0, 0, delay, 0, time.UTC)
lastRecvTime := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
secondsPerSlot := params.BeaconConfig().SecondsPerSlot
waitDuration, nextRecvTime := computeWaitElements(now, lastRecvTime)
assert.Equal(t, time.Duration(secondsPerSlot-uint64(delay))*time.Second, waitDuration)
assert.Equal(t, time.Date(2022, 1, 1, 0, 0, int(secondsPerSlot), 0, time.UTC), nextRecvTime)
}
func TestComputeWaitElements_Longest(t *testing.T) {
now := time.Date(2022, 1, 1, 0, 0, 20, 0, time.UTC)
lastRecvTime := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
waitDuration, nextRecvTime := computeWaitElements(now, lastRecvTime)
assert.Equal(t, 0*time.Second, waitDuration)
assert.Equal(t, now, nextRecvTime)
}
func TestActivation_Nominal(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
stringPubKeys := []string{
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
"0x80000e851c0f53c3246ff726d7ff7766661ca5e12a07c45c114d208d54f0f8233d4380b2e9aff759d69795d1df905526", // active_exiting
"0x424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", // does not exist
"0x800015473bdc3a7f45ef8eb8abc598bc20021e55ad6e6ad1d745aaef9730dd2c28ec08bf42df18451de94dd4a6d24ec5", // exited_slashed
}
pubKeys := make([][]byte, len(stringPubKeys))
for i, stringPubKey := range stringPubKeys {
pubKey, err := hexutil.Decode(stringPubKey)
require.NoError(t, err)
pubKeys[i] = pubKey
}
wantedStatuses := []*ethpb.ValidatorActivationResponse_Status{
{
PublicKey: pubKeys[0],
Index: 55293,
Status: &ethpb.ValidatorStatusResponse{
Status: ethpb.ValidatorStatus_ACTIVE,
},
},
{
PublicKey: pubKeys[1],
Index: 11877,
Status: &ethpb.ValidatorStatusResponse{
Status: ethpb.ValidatorStatus_EXITING,
},
},
{
PublicKey: pubKeys[3],
Index: 210439,
Status: &ethpb.ValidatorStatusResponse{
Status: ethpb.ValidatorStatus_EXITED,
},
},
{
PublicKey: pubKeys[2],
Index: 18446744073709551615,
Status: &ethpb.ValidatorStatusResponse{
Status: ethpb.ValidatorStatus_UNKNOWN_STATUS,
},
},
}
stateValidatorsResponseJson := structs.GetValidatorsResponse{}
// Instantiate a cancellable context.
ctx, cancel := context.WithCancel(context.Background())
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
req := &structs.GetValidatorsRequest{
Ids: stringPubKeys,
Statuses: []string{},
}
reqBytes, err := json.Marshal(req)
require.NoError(t, err)
// Get does not return any result for non existing key
jsonRestHandler.EXPECT().Post(
gomock.Any(),
"/eth/v1/beacon/states/head/validators",
nil,
bytes.NewBuffer(reqBytes),
&stateValidatorsResponseJson,
).Return(
nil,
).SetArg(
4,
structs.GetValidatorsResponse{
Data: []*structs.ValidatorContainer{
{
Index: "55293",
Status: "active_ongoing",
Validator: &structs.Validator{
Pubkey: stringPubKeys[0],
},
},
{
Index: "11877",
Status: "active_exiting",
Validator: &structs.Validator{
Pubkey: stringPubKeys[1],
},
},
{
Index: "210439",
Status: "exited_slashed",
Validator: &structs.Validator{
Pubkey: stringPubKeys[3],
},
},
},
},
).Times(1)
validatorClient := beaconApiValidatorClient{
stateValidatorsProvider: beaconApiStateValidatorsProvider{
jsonRestHandler: jsonRestHandler,
},
}
waitForActivation, err := validatorClient.WaitForActivation(
ctx,
&ethpb.ValidatorActivationRequest{
PublicKeys: pubKeys,
},
)
assert.NoError(t, err)
// This first call to `Recv` should return immediately
resp, err := waitForActivation.Recv()
require.NoError(t, err)
assert.DeepEqual(t, wantedStatuses, resp.Statuses)
// Cancel the context after 1 second
go func(ctx context.Context) {
time.Sleep(time.Second)
cancel()
}(ctx)
// This second call to `Recv` should return after ~12 seconds, but is interrupted by the cancel
_, err = waitForActivation.Recv()
assert.ErrorContains(t, "context canceled", err)
}
func TestActivation_InvalidData(t *testing.T) {
testCases := []struct {
name string
data []*structs.ValidatorContainer
expectedErrorMessage string
}{
{
name: "bad validator public key",
data: []*structs.ValidatorContainer{
{
Index: "55293",
Status: "active_ongoing",
Validator: &structs.Validator{
Pubkey: "NotAPubKey",
},
},
},
expectedErrorMessage: "failed to parse validator public key",
},
{
name: "bad validator index",
data: []*structs.ValidatorContainer{
{
Index: "NotAnIndex",
Status: "active_ongoing",
Validator: &structs.Validator{
Pubkey: stringPubKey,
},
},
},
expectedErrorMessage: "failed to parse validator index",
},
{
name: "invalid validator status",
data: []*structs.ValidatorContainer{
{
Index: "12345",
Status: "NotAStatus",
Validator: &structs.Validator{
Pubkey: stringPubKey,
},
},
},
expectedErrorMessage: "invalid validator status: NotAStatus",
},
}
for _, testCase := range testCases {
t.Run(testCase.name,
func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
).Return(
nil,
).SetArg(
4,
structs.GetValidatorsResponse{
Data: testCase.data,
},
).Times(1)
validatorClient := beaconApiValidatorClient{
stateValidatorsProvider: beaconApiStateValidatorsProvider{
jsonRestHandler: jsonRestHandler,
},
}
waitForActivation, err := validatorClient.WaitForActivation(
ctx,
&ethpb.ValidatorActivationRequest{},
)
assert.NoError(t, err)
_, err = waitForActivation.Recv()
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
},
)
}
}
func TestActivation_JsonResponseError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
).Return(
errors.New("some specific json error"),
).Times(1)
jsonRestHandler.EXPECT().Get(
gomock.Any(),
gomock.Any(),
gomock.Any(),
).Return(
errors.New("some specific json error"),
).Times(1)
validatorClient := beaconApiValidatorClient{
stateValidatorsProvider: beaconApiStateValidatorsProvider{
jsonRestHandler: jsonRestHandler,
},
}
waitForActivation, err := validatorClient.WaitForActivation(
ctx,
&ethpb.ValidatorActivationRequest{},
)
assert.NoError(t, err)
_, err = waitForActivation.Recv()
assert.ErrorContains(t, "failed to get state validators", err)
}

View File

@@ -273,6 +273,13 @@ func (c *beaconApiValidatorClient) ValidatorStatus(ctx context.Context, in *ethp
return c.validatorStatus(ctx, in)
}
func (c *beaconApiValidatorClient) WaitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) {
ctx, span := trace.StartSpan(ctx, "beacon-api.WaitForActivation")
defer span.End()
return c.waitForActivation(ctx, in)
}
// Deprecated: Do not use.
func (c *beaconApiValidatorClient) WaitForChainStart(ctx context.Context, _ *empty.Empty) (*ethpb.ChainStartResponse, error) {
return c.waitForChainStart(ctx)

View File

@@ -127,6 +127,10 @@ func (c *grpcValidatorClient) ValidatorStatus(ctx context.Context, in *ethpb.Val
return c.beaconNodeValidatorClient.ValidatorStatus(ctx, in)
}
func (c *grpcValidatorClient) WaitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) {
return c.beaconNodeValidatorClient.WaitForActivation(ctx, in)
}
// Deprecated: Do not use.
func (c *grpcValidatorClient) WaitForChainStart(ctx context.Context, in *empty.Empty) (*ethpb.ChainStartResponse, error) {
stream, err := c.beaconNodeValidatorClient.WaitForChainStart(ctx, in)

View File

@@ -124,6 +124,7 @@ type ValidatorClient interface {
Duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error)
DomainData(ctx context.Context, in *ethpb.DomainRequest) (*ethpb.DomainResponse, error)
WaitForChainStart(ctx context.Context, in *empty.Empty) (*ethpb.ChainStartResponse, error)
WaitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error)
ValidatorIndex(ctx context.Context, in *ethpb.ValidatorIndexRequest) (*ethpb.ValidatorIndexResponse, error)
ValidatorStatus(ctx context.Context, in *ethpb.ValidatorStatusRequest) (*ethpb.ValidatorStatusResponse, error)
MultipleValidatorStatus(ctx context.Context, in *ethpb.MultipleValidatorStatusRequest) (*ethpb.MultipleValidatorStatusResponse, error)

View File

@@ -12,6 +12,7 @@ import (
func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldparams.BLSPubkeyLength]byte) (bool, error) {
ctx, span := trace.StartSpan(ctx, "validator.HandleKeyReload")
defer span.End()
if err := v.updateValidatorStatusCache(ctx, currentKeys); err != nil {
return false, err
}

View File

@@ -1247,7 +1247,6 @@ func (v *validator) updateValidatorStatusCache(ctx context.Context, pubkeys [][f
if len(resp.Statuses) != len(resp.Indices) {
return fmt.Errorf("expected %d indices in status, received %d", len(resp.Statuses), len(resp.Indices))
}
pubkeyToStatus := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus, len(resp.Statuses))
for i, s := range resp.Statuses {
pubkeyToStatus[bytesutil.ToBytes48(resp.PublicKeys[i])] = &validatorStatus{

View File

@@ -33,6 +33,7 @@ import (
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
mock2 "github.com/prysmaticlabs/prysm/v5/testing/mock"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util"
validatormock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock"
@@ -157,6 +158,19 @@ func (*mockKeymanager) DeleteKeystores(context.Context, [][]byte,
return nil, nil
}
func generateMockStatusResponse(pubkeys [][]byte) *ethpb.ValidatorActivationResponse {
multipleStatus := make([]*ethpb.ValidatorActivationResponse_Status, len(pubkeys))
for i, key := range pubkeys {
multipleStatus[i] = &ethpb.ValidatorActivationResponse_Status{
PublicKey: key,
Status: &ethpb.ValidatorStatusResponse{
Status: ethpb.ValidatorStatus_UNKNOWN_STATUS,
},
}
}
return &ethpb.ValidatorActivationResponse{Statuses: multipleStatus}
}
func TestWaitForChainStart_SetsGenesisInfo(t *testing.T) {
for _, isSlashingProtectionMinimal := range [...]bool{false, true} {
t.Run(fmt.Sprintf("SlashingProtectionMinimal:%v", isSlashingProtectionMinimal), func(t *testing.T) {
@@ -327,6 +341,41 @@ func TestCanonicalHeadSlot_OK(t *testing.T) {
assert.Equal(t, primitives.Slot(0), headSlot, "Mismatch slots")
}
func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
ctx := context.Background()
hook := logTest.NewGlobal()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
client := validatormock.NewMockValidatorClient(ctrl)
chainClient := validatormock.NewMockChainClient(ctrl)
prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl)
kp := randKeypair(t)
v := validator{
validatorClient: client,
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
clientStream := mock2.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
client.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{kp.pub[:]},
},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
resp,
nil,
)
require.NoError(t, v.WaitForActivation(ctx, nil), "Could not wait for activation")
require.LogsContain(t, hook, "Validator activated")
}
func TestWaitSync_ContextCanceled(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

View File

@@ -2,14 +2,16 @@ package client
import (
"context"
"io"
"time"
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/math"
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing"
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
"github.com/prysmaticlabs/prysm/v5/time/slots"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
octrace "go.opentelemetry.io/otel/trace"
)
@@ -37,46 +39,68 @@ func (v *validator) WaitForActivation(ctx context.Context, accountsChangedChan c
return v.internalWaitForActivation(ctx, accountsChangedChan)
}
// internalWaitForActivation recursively waits for at least one active validator key
// internalWaitForActivation performs the following:
// 1) While the key manager is empty, subscribe to keymanager changes until some validator keys exist.
// 2) Open a server side stream for activation events against the given keys.
// 3) In another go routine, the key manager is monitored for updates and emits an update event on
// the accountsChangedChan. When an event signal is received, restart the internalWaitForActivation routine.
// 4) If the stream is reset in error, restart the routine.
// 5) If the stream returns a response indicating one or more validators are active, exit the routine.
func (v *validator) internalWaitForActivation(ctx context.Context, accountsChangedChan <-chan [][fieldparams.BLSPubkeyLength]byte) error {
ctx, span := trace.StartSpan(ctx, "validator.WaitForActivation")
defer span.End()
// Step 1: Fetch validating public keys.
validatingKeys, err := v.km.FetchValidatingPublicKeys(ctx)
if err != nil {
return errors.Wrap(err, msgCouldNotFetchKeys)
}
// Step 2: If no keys, wait for accounts change or context cancellation.
// if there are no validating keys, wait for some
if len(validatingKeys) == 0 {
log.Warn(msgNoKeysFetched)
return v.waitForAccountsChange(ctx, accountsChangedChan)
}
// Step 3: update validator statuses in cache.
if err := v.updateValidatorStatusCache(ctx, validatingKeys); err != nil {
stream, err := v.validatorClient.WaitForActivation(ctx, &ethpb.ValidatorActivationRequest{
PublicKeys: bytesutil.FromBytes48Array(validatingKeys),
})
if err != nil {
return v.retryWaitForActivation(ctx, span, err, "Connection broken while waiting for activation. Reconnecting...", accountsChangedChan)
}
// Step 4: Check and log validator statuses.
someAreActive := v.checkAndLogValidatorStatus()
if !someAreActive {
// Step 6: If no active validators, wait for accounts change, context cancellation, or next epoch.
someAreActive := false
for !someAreActive {
select {
case <-ctx.Done():
log.Debug("Context closed, exiting WaitForActivation")
log.Debug("Context closed, exiting fetching validating keys")
return ctx.Err()
case <-accountsChangedChan:
// Accounts (keys) changed, restart the process.
return v.internalWaitForActivation(ctx, accountsChangedChan)
default:
if err := v.waitForNextEpoch(ctx, v.genesisTime, accountsChangedChan); err != nil {
return v.retryWaitForActivation(ctx, span, err, "Failed to wait for next epoch. Reconnecting...", accountsChangedChan)
res, err := (stream).Recv() // retrieve from stream one loop at a time
// If the stream is closed, we stop the loop.
if errors.Is(err, io.EOF) {
break
}
return v.internalWaitForActivation(incrementRetries(ctx), accountsChangedChan)
// If context is canceled we return from the function.
if errors.Is(ctx.Err(), context.Canceled) {
return errors.Wrap(ctx.Err(), "context has been canceled so shutting down the loop")
}
if err != nil {
return v.retryWaitForActivation(ctx, span, err, "Connection broken while waiting for activation. Reconnecting...", accountsChangedChan)
}
for _, s := range res.Statuses {
v.pubkeyToStatus[bytesutil.ToBytes48(s.PublicKey)] = &validatorStatus{
publicKey: s.PublicKey,
status: s.Status,
index: s.Index,
}
}
someAreActive = v.checkAndLogValidatorStatus()
}
}
return nil
}
@@ -101,27 +125,6 @@ func (v *validator) waitForAccountsChange(ctx context.Context, accountsChangedCh
}
}
// waitForNextEpoch creates a blocking function to wait until the next epoch start given the current slot
func (v *validator) waitForNextEpoch(ctx context.Context, genesisTimeSec uint64, accountsChangedChan <-chan [][fieldparams.BLSPubkeyLength]byte) error {
waitTime, err := slots.SecondsUntilNextEpochStart(genesisTimeSec)
if err != nil {
return err
}
log.WithField("seconds_until_next_epoch", waitTime).Warn("No active validator keys provided. Waiting until next epoch to check again...")
select {
case <-ctx.Done():
log.Debug("Context closed, exiting waitForNextEpoch")
return ctx.Err()
case <-accountsChangedChan:
// Accounts (keys) changed, restart the process.
return v.internalWaitForActivation(ctx, accountsChangedChan)
case <-time.After(time.Duration(waitTime) * time.Second):
log.Debug("Done waiting for epoch start")
// The ticker has ticked, indicating we've reached the next epoch
return nil
}
}
// Preferred way to use context keys is with a non built-in type. See: RVV-B0003
type waitForActivationContextKey string

View File

@@ -1,6 +1,7 @@
package client
import (
"bytes"
"context"
"fmt"
"testing"
@@ -11,19 +12,47 @@ import (
"github.com/prysmaticlabs/prysm/v5/config/params"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/mock"
"github.com/prysmaticlabs/prysm/v5/testing/require"
validatormock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock"
walletMock "github.com/prysmaticlabs/prysm/v5/validator/accounts/testing"
"github.com/prysmaticlabs/prysm/v5/validator/client/testutil"
"github.com/prysmaticlabs/prysm/v5/validator/keymanager/derived"
constant "github.com/prysmaticlabs/prysm/v5/validator/testing"
logTest "github.com/sirupsen/logrus/hooks/test"
mock2 "github.com/stretchr/testify/mock"
"github.com/tyler-smith/go-bip39"
util "github.com/wealdtech/go-eth2-util"
"go.uber.org/mock/gomock"
)
func TestWaitActivation_Exiting_OK(t *testing.T) {
func TestWaitActivation_ContextCanceled(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
validatorClient := validatormock.NewMockValidatorClient(ctrl)
chainClient := validatormock.NewMockChainClient(ctrl)
kp := randKeypair(t)
v := validator{
validatorClient: validatorClient,
km: newMockKeymanager(t, kp),
chainClient: chainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
ctx, cancel := context.WithCancel(context.Background())
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{kp.pub[:]},
},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
&ethpb.ValidatorActivationResponse{},
nil,
).Do(func() { cancel() })
assert.ErrorContains(t, cancelledCtx, v.WaitForActivation(ctx, nil))
}
func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
validatorClient := validatormock.NewMockValidatorClient(ctrl)
@@ -35,19 +64,113 @@ func TestWaitActivation_Exiting_OK(t *testing.T) {
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
ctx := context.Background()
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status = ethpb.ValidatorStatus_EXITING
validatorClient.EXPECT().MultipleValidatorStatus(
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.MultipleValidatorStatusRequest{
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{kp.pub[:]},
},
).Return(resp, nil)
).Return(clientStream, errors.New("failed stream")).Return(clientStream, nil)
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
clientStream.EXPECT().Recv().Return(resp, nil)
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
}
require.NoError(t, v.WaitForActivation(ctx, nil))
require.Equal(t, 1, len(v.pubkeyToStatus))
func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
validatorClient := validatormock.NewMockValidatorClient(ctrl)
chainClient := validatormock.NewMockChainClient(ctrl)
prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl)
kp := randKeypair(t)
v := validator{
validatorClient: validatorClient,
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{kp.pub[:]},
},
).Return(clientStream, nil)
// A stream fails the first time, but succeeds the second time.
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
clientStream.EXPECT().Recv().Return(
nil,
errors.New("fails"),
).Return(resp, nil)
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
}
func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
hook := logTest.NewGlobal()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
validatorClient := validatormock.NewMockValidatorClient(ctrl)
chainClient := validatormock.NewMockChainClient(ctrl)
prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl)
kp := randKeypair(t)
v := validator{
validatorClient: validatorClient,
km: newMockKeymanager(t, kp),
genesisTime: 1,
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{kp.pub[:]},
},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
resp,
nil,
)
assert.NoError(t, v.WaitForActivation(context.Background(), nil), "Could not wait for activation")
assert.LogsContain(t, hook, "Validator activated")
}
func TestWaitForActivation_Exiting(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
validatorClient := validatormock.NewMockValidatorClient(ctrl)
chainClient := validatormock.NewMockChainClient(ctrl)
prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl)
kp := randKeypair(t)
v := validator{
validatorClient: validatorClient,
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{kp.pub[:]},
},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
resp,
nil,
)
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
}
func TestWaitForActivation_RefetchKeys(t *testing.T) {
@@ -73,25 +196,27 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status = ethpb.ValidatorStatus_ACTIVE
validatorClient.EXPECT().MultipleValidatorStatus(
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.MultipleValidatorStatusRequest{
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{kp.pub[:]},
},
).Return(resp, nil)
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
resp,
nil)
accountChan := make(chan [][fieldparams.BLSPubkeyLength]byte)
sub := km.SubscribeAccountChanges(accountChan)
defer func() {
sub.Unsubscribe()
close(accountChan)
}()
// update the accounts from 0 to 1 after a delay
// update the accounts after a delay
go func() {
time.Sleep(1 * time.Second)
time.Sleep(2 * time.Second)
require.NoError(t, km.add(kp))
km.SimulateAccountChanges([][48]byte{kp.pub})
}()
@@ -100,11 +225,12 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
assert.LogsContain(t, hook, "Validator activated")
}
// Regression test for a scenario where you start with an inactive key and then import an active key.
func TestWaitForActivation_AccountsChanged(t *testing.T) {
params.SetupTestConfigCleanup(t)
hook := logTest.NewGlobal()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
t.Run("Imported keymanager", func(t *testing.T) {
inactive := randKeypair(t)
active := randKeypair(t)
@@ -119,36 +245,52 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
inactiveResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:]})
inactiveResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
activeResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]})
activeResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
activeResp.Statuses[1].Status = ethpb.ValidatorStatus_ACTIVE
gomock.InOrder(
validatorClient.EXPECT().MultipleValidatorStatus(
gomock.Any(),
&ethpb.MultipleValidatorStatusRequest{
PublicKeys: [][]byte{inactive.pub[:]},
},
).Return(inactiveResp, nil).Do(func(arg0, arg1 interface{}) {
require.NoError(t, km.add(active))
km.SimulateAccountChanges([][fieldparams.BLSPubkeyLength]byte{inactive.pub, active.pub})
}),
validatorClient.EXPECT().MultipleValidatorStatus(
gomock.Any(),
&ethpb.MultipleValidatorStatusRequest{
PublicKeys: [][]byte{inactive.pub[:], active.pub[:]},
},
).Return(activeResp, nil))
chainClient.EXPECT().ChainHead(
inactiveResp := generateMockStatusResponse([][]byte{inactive.pub[:]})
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
inactiveClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
gomock.Any(),
).Return(
&ethpb.ChainHead{HeadEpoch: 0},
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{inactive.pub[:]},
},
).DoAndReturn(func(ctx context.Context, in *ethpb.ValidatorActivationRequest) (*mock.MockBeaconNodeValidator_WaitForActivationClient, error) {
//delay a bit so that other key can be added
time.Sleep(time.Second * 2)
return inactiveClientStream, nil
})
inactiveClientStream.EXPECT().Recv().Return(
inactiveResp,
nil,
).AnyTimes()
activeResp := generateMockStatusResponse([][]byte{inactive.pub[:], active.pub[:]})
activeResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
activeResp.Statuses[1].Status.Status = ethpb.ValidatorStatus_ACTIVE
activeClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
mock2.MatchedBy(func(req *ethpb.ValidatorActivationRequest) bool {
found := 0
for _, pk := range req.PublicKeys {
if bytes.Equal(pk, active.pub[:]) || bytes.Equal(pk, inactive.pub[:]) {
found++
}
}
return found == 2
}),
).Return(activeClientStream, nil)
activeClientStream.EXPECT().Recv().Return(
activeResp,
nil,
)
go func() {
// We add the active key into the keymanager and simulate a key refresh.
time.Sleep(time.Second * 1)
require.NoError(t, km.add(active))
km.SimulateAccountChanges(make([][fieldparams.BLSPubkeyLength]byte, 0))
}()
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node")
assert.LogsContain(t, hook, "Validator activated")
@@ -191,59 +333,61 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
inactiveResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactivePubKey[:]})
inactiveResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
activeResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]})
activeResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
activeResp.Statuses[1].Status = ethpb.ValidatorStatus_ACTIVE
channel := make(chan [][fieldparams.BLSPubkeyLength]byte, 1)
km.SubscribeAccountChanges(channel)
gomock.InOrder(
validatorClient.EXPECT().MultipleValidatorStatus(
gomock.Any(),
&ethpb.MultipleValidatorStatusRequest{
PublicKeys: [][]byte{inactivePubKey[:]},
},
).Return(inactiveResp, nil).Do(func(arg0, arg1 interface{}) {
err = km.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, derived.DefaultMnemonicLanguage, "", 2)
require.NoError(t, err)
pks, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
require.DeepEqual(t, pks, [][fieldparams.BLSPubkeyLength]byte{inactivePubKey, activePubKey})
channel <- [][fieldparams.BLSPubkeyLength]byte{inactivePubKey, activePubKey}
}),
validatorClient.EXPECT().MultipleValidatorStatus(
gomock.Any(),
&ethpb.MultipleValidatorStatusRequest{
PublicKeys: [][]byte{inactivePubKey[:], activePubKey[:]},
},
).Return(activeResp, nil))
chainClient.EXPECT().ChainHead(
inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]})
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
inactiveClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
gomock.Any(),
).Return(
&ethpb.ChainHead{HeadEpoch: 0},
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{inactivePubKey[:]},
},
).DoAndReturn(func(ctx context.Context, in *ethpb.ValidatorActivationRequest) (*mock.MockBeaconNodeValidator_WaitForActivationClient, error) {
//delay a bit so that other key can be added
time.Sleep(time.Second * 2)
return inactiveClientStream, nil
})
inactiveClientStream.EXPECT().Recv().Return(
inactiveResp,
nil,
).AnyTimes()
activeResp := generateMockStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]})
activeResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
activeResp.Statuses[1].Status.Status = ethpb.ValidatorStatus_ACTIVE
activeClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
&ethpb.ValidatorActivationRequest{
PublicKeys: [][]byte{inactivePubKey[:], activePubKey[:]},
},
).Return(activeClientStream, nil)
activeClientStream.EXPECT().Recv().Return(
activeResp,
nil,
)
channel := make(chan [][fieldparams.BLSPubkeyLength]byte)
go func() {
// We add the active key into the keymanager and simulate a key refresh.
time.Sleep(time.Second * 1)
err = km.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, derived.DefaultMnemonicLanguage, "", 2)
require.NoError(t, err)
channel <- [][fieldparams.BLSPubkeyLength]byte{}
}()
assert.NoError(t, v.internalWaitForActivation(context.Background(), channel))
assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node")
assert.LogsContain(t, hook, "Validator activated")
})
}
func TestWaitForActivation_AttemptsReconnectionOnFailure(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.MainnetConfig().Copy()
cfg.ConfigName = "test"
cfg.SecondsPerSlot = 1
params.OverrideBeaconConfig(cfg)
func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
validatorClient := validatormock.NewMockValidatorClient(ctrl)
chainClient := validatormock.NewMockChainClient(ctrl)
prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl)
kp := randKeypair(t)
v := validator{
validatorClient: validatorClient,
@@ -252,24 +396,20 @@ func TestWaitForActivation_AttemptsReconnectionOnFailure(t *testing.T) {
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
active := randKeypair(t)
activeResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{active.pub[:]})
activeResp.Statuses[0].Status = ethpb.ValidatorStatus_ACTIVE
gomock.InOrder(
validatorClient.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any(),
).Return(nil, errors.New("some random connection error")),
validatorClient.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any(),
).Return(activeResp, nil))
chainClient.EXPECT().ChainHead(
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
gomock.Any(),
gomock.Any(),
).Return(
&ethpb.ChainHead{HeadEpoch: 0},
).Return(clientStream, nil)
clientStream.EXPECT().Recv().Return(
&ethpb.ValidatorActivationResponse{},
nil,
).AnyTimes()
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
)
clientStream.EXPECT().Recv().Return(
resp,
nil,
)
assert.NoError(t, v.WaitForActivation(context.Background(), nil), "Could not wait for activation")
}