Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command to fetch validator statuses + MultipleValidatorStatus #5784

Conversation

michaelhly
Copy link
Contributor

@michaelhly michaelhly commented May 8, 2020

What type of PR is this?

Feature

What does this PR do? Why is it needed?
Add validator accounts status command to fetch validator statuses from the Beacon Node.

Which issues(s) does this PR fix?
Resolves #5578

Other notes for review
Summary of changes:

  • MultipleValidatorStatus endpoint
  • Update beacon_node_validator_service_mock.go
  • status command for the validator client
    • Status fetcher
    • Status sorter
  • Tests for the above

TODO:

  • Sorting
  • Bulk status fetching
  • Properly format statuses before printing
  • Better tests
  • Test runtime

Runtime Demos:
Connected to syncing node

> bazel run validator accounts status
2020/05/12 15:12:45 maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[2020-05-13 08:24:57]  INFO accounts: Please specify the keystore path for your private keys (default: "/Users/username/Library/Eth2Validators"):

[2020-05-13 08:24:59]  INFO accounts: Please enter the password for your private keys
[2020-05-13 08:24:59]  INFO node: Enter a password:
[2020-05-13 08:25:01]  WARN validator: You are using an insecure gRPC connection! Please provide a certificate and key to use a secure connection.
[2020-05-13 08:25:01] FATAL main: Could not fetch account statuses from the beacon node. error=rpc error: code = Unavailable desc = Syncing to latest head, not ready to respond
Failed to fetch validator statuses for 1 key(s)

Node offline

> bazel run validator accounts status
2020/05/12 15:15:09 maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[2020-05-12 15:15:09]  INFO accounts: Please specify the keystore path for your private keys (default: "/Users/username/Library/Eth2Validators"):

[2020-05-12 15:15:15]  INFO accounts: Please enter the password for your private keys
[2020-05-12 15:15:15]  INFO node: Enter a password:
[2020-05-12 15:15:21]  WARN validator: You are using an insecure gRPC connection! Please provide a certificate and key to use a secure connection.

// Waits for 10 seconds

[2020-05-12 15:15:31] FATAL main: Failed to dial beacon node endpoint at localhost:4000 error=context deadline exceeded

Connected to synced node
https://gist.github.com/michaelhly/cc00d4329974582abcbbbb19dbed66a0

@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from 91ce0fc to fdc668b Compare May 8, 2020 19:10
@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from fdc668b to 3c357a1 Compare May 8, 2020 19:13
@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from 5ea8600 to 1294fdf Compare May 8, 2020 19:28
@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from 3e9e770 to 7b7efef Compare May 10, 2020 00:07
}

req := &ethpb.ValidatorStatusRequest{
PublicKey: pubKey,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if we have N keys then it's N requests to the beacon node. Can we batch this to just 1 request?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Right now it's like this so I can avoid compile errors.

I'm waiting for prysmaticlabs/ethereumapis#148 to get merged. Once the API for ValidatorStatus is updated, we'll batch public keys into slices of at most C keys. So we'll make k=N/C requests.

And after receiving the responses from the node, we'll run a k-way merge sort and then print the results.

@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from 3bc7daf to 2ab3a6b Compare May 10, 2020 23:30
@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from 2ab3a6b to 9635895 Compare May 11, 2020 00:05
@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from 6a4f56f to 8096b80 Compare May 11, 2020 03:43
@michaelhly michaelhly force-pushed the validator-client-account-statuses branch from 8096b80 to 74c315b Compare May 11, 2020 03:47
@codecov
Copy link

codecov bot commented May 11, 2020

Codecov Report

Merging #5784 into master will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##           master    #5784   +/-   ##
=======================================
  Coverage   59.60%   59.60%           
=======================================
  Files         315      315           
  Lines       26570    26570           
=======================================
  Hits        15836    15836           
  Misses       8590     8590           
  Partials     2144     2144           

@michaelhly michaelhly marked this pull request as ready for review May 11, 2020 14:59
@michaelhly michaelhly force-pushed the validator-client-account-statuses branch 3 times, most recently from dc8e385 to f7237cf Compare May 17, 2020 00:41
grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
grpc.WithBlock(),
grpc.WithTimeout(
10 * time.Second /* Block for 10 seconds to see if we can connect to beacon node */),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecated: use DialContext instead of Dial and context.WithTimeout instead. Will be supported throughout 1.x.

https://godoc.org/google.golang.org/grpc#WithTimeout

validator/accounts/status.go Outdated Show resolved Hide resolved
validator/accounts/status.go Show resolved Hide resolved
@rauljordan
Copy link
Contributor

PTAL @terencechain

terencechain
terencechain previously approved these changes May 19, 2020
Copy link
Member

@terencechain terencechain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm. Thanks Michael!

filtered := make(map[[48]byte]bool)
filtered[[48]byte{}] = true // Filter out keys with all zeros.
// Filter out duplicate public keys.
for _, pubKey := range req.GetPublicKeys() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to copy here, you can access the field directly

}
}
// Convert indices to public keys.
for _, idx := range req.GetIndices() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same over here

validator/accounts/account.go Show resolved Hide resolved

// MaxRequestLimit specifies the max concurrent grpc requests allowed
// to fetch account statuses.
const MaxRequestLimit = 5 // XXX: Should create flag to make parameter configurable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the XXX comment, or open up an issue in the repo for this as a todo. We use
TODO(#Num) where Num represents the issue number.


// MaxRequestKeys specifies the max amount of public keys allowed
// in a single grpc request, when fetching account statuses.
const MaxRequestKeys = 2000 // XXX: This is an arbitrary number. Used to limit time complexity
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here remove XXX

maxCallRecvMsgSize int,
grpcRetries uint,
grpcHeaders []string) error {
dialOpts, err := constructDialOptions(maxCallRecvMsgSize, withCert, grpcHeaders, grpcRetries)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you not construct the GRPC client in this command, this should be done on the outside of the method.

errorChannel := make(chan error, MaxRequestLimit)
statusChannel := make(chan []ValidatorStatusMetadata, MaxRequestLimit)
// Launch routines to fetch statuses.
i, numBatches := 0, 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use scatter from mputils for parallelized requests.
https://github.com/prysmaticlabs/prysm/blob/master/shared/mputil/scatter.go#L21

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nisdas do you think that is going to help here? This isn't doing any computation really, just fetching the requests from the server.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly because it looks like its doing a lot of repeat work which is done by Scatter, its also just splitting up the requests into separate goroutines using a fixed request size.

errorChannel := make(chan error, MaxRequestLimit)
statusChannel := make(chan []ValidatorStatusMetadata, MaxRequestLimit)
// Launch routines to fetch statuses.
i, numBatches := 0, 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nisdas do you think that is going to help here? This isn't doing any computation really, just fetching the requests from the server.

validator/accounts/status.go Outdated Show resolved Hide resolved
validator/accounts/status.go Outdated Show resolved Hide resolved
"Eth1DepositBlockNumber": fieldToString(m.Eth1DepositBlockNumber),
"PositionInActivationQueue": fieldToString(m.PositionInActivationQueue),
},
).Infof("Status=%v\n PublicKey=0x%s\n", m.Status, hex.EncodeToString(key))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pubkey should be above under logrus.Fields . You should be only logging the status here, with the status being an enum type, you can simple represent it using %s

Copy link
Member

@nisdas nisdas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM !

@prylabs-bulldozer prylabs-bulldozer bot merged commit 62b617f into prysmaticlabs:master May 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show STATUS when running ./validator accounts keys
6 participants