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

feat: gRPC server #8

Merged
merged 24 commits into from
Aug 21, 2024
Merged

feat: gRPC server #8

merged 24 commits into from
Aug 21, 2024

Conversation

Reecepbcups
Copy link
Contributor

@Reecepbcups Reecepbcups commented Aug 16, 2024

Summary

A gRPC server implementation for Gordian. This way we can add interchaintest support. Then wrap gRPC in the HTTP server instead for Comet compatibility.

Keep scoped to gcosmos only

Future

  • TxHash -> tx retrieval from the store
  • support extending the gRPC interface as other modules are added / removed, specifically allowing rust crypto libraries (similar to the Signer interface)
  • Migrate http handler -> a gRPC client wrapper for request (feat: wrap gRPC client within http handler #14)

@jackzampolin jackzampolin mentioned this pull request Aug 16, 2024
8 tasks
@Reecepbcups Reecepbcups changed the title feat: gRPC feat: gRPC server Aug 19, 2024
#!/bin/sh
# sh ./scripts/protocgen.sh
#
# TODO: migrate to buf?
Copy link
Contributor Author

@Reecepbcups Reecepbcups Aug 19, 2024

Choose a reason for hiding this comment

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

Given the simplicity atm with proto I feel protoc is fine until it is not?

I have attempted the buf work & the cosmos/gogoproto is not happy with duplicate definitions on v1.7.0. I think this should be scoped to its own PR in coordination with #15.

Ref buf attempt here: 4d4c9be

Copy link
Member

Choose a reason for hiding this comment

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

That's really unfortunate.

Copy link
Contributor Author

@Reecepbcups Reecepbcups Aug 20, 2024

Choose a reason for hiding this comment

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

update: I finally got it to register properly (required cosmos proto with their buf container) but then it still breaks gRPC url despite list showing that service method. 😞

Standard Go clients work but not working with grpcurl seems really wrong. I think future scope

https://github.com/rollchains/gordian/tree/reece/grpc-buf-attempt

@Reecepbcups Reecepbcups marked this pull request as ready for review August 19, 2024 20:52
gcosmos/gserver/internal/ggrpc/server.go Outdated Show resolved Hide resolved
@@ -1,4 +1,4 @@
package gsi
package txmanager
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was needed for the gRPC server as well. So sharing within the txmanager package instead of gsi (http only)

Copy link
Contributor

Choose a reason for hiding this comment

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

cc @mark-rushakoff for rationale on moving the txmanager to its own package

Copy link
Contributor Author

@Reecepbcups Reecepbcups Aug 19, 2024

Choose a reason for hiding this comment

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

my reply from slack for ctx:

GRPC server needs access to the SDKTxBuf for the server_debug.go commands (SubmitTransaction, PendingTransactions). Importing gsi from within ggrpc would result in an import cycle not allowed (since HTTPServerConfig will depend on ggrpc.GordianGRPCClient)

This was a proactive change in prep for the next iteration. Happy to undo for the context of this PR, but is required in the http gRPC wrapped PR

Copy link
Member

Choose a reason for hiding this comment

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

Due to the volume of other comments -- and the general size of the PR -- don't include this change in this PR. Removing it will reduce the number of touched files by four, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

reverted txmanager -> gsi here: a01a380

message TxResultResponse {
// TODO: tx hash?
repeated Event events = 1 [json_name="events"];
// bytes resp = 2; // []transaction.Msg
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is an interface on the SDK side

Copy link
Member

@mark-rushakoff mark-rushakoff left a comment

Choose a reason for hiding this comment

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

I have a lot of comments.

The narrower we can get these PRs, the faster we can get individual pieces through.

@@ -3,3 +3,5 @@

# go build . will make a binary named gcosmos, which we never want to commit.
gcosmos

Copy link
Member

Choose a reason for hiding this comment

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

Include a comment noting what this is and why it's ignored.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added context b369490


# Interact
```bash
# go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest GOBIN="$PWD" go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest so as to not pollute anything else on the user's system. Maybe @v1 would even be better so we don't get unexpected breakage upon a v2 release.

Then we can just git-ignore grpcurl and change the rest of the commands in this list to ./grpcurl instead of whatever is on $PATH.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call:
handled and added to gitignore with comment: b369490#diff-62120d6b326ed1a40891671df851b595805cc273ecb5ba7cf3c34ccd194d0465R60

Comment on lines 76 to 78
grpcurl -plaintext -emit-defaults -d '{"tx":"'$(cat example-tx-signed.json | base64 -w 0)'"}' localhost:9092 server.GordianGRPC/SimulateTransaction

grpcurl -plaintext -emit-defaults -d '{"tx":"'$(cat example-tx-signed.json | base64 -w 0)'"}' localhost:9092 server.GordianGRPC/SubmitTransaction
Copy link
Member

Choose a reason for hiding this comment

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

base64 -w does not work by default on macOS. Is there another, portable way to express this?

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, migrated to use tr -d '\n' instead. Tested on my Mac and works as expected

22fed16

gcosmos/gserver/internal/ggrpc/server.go Outdated Show resolved Hide resolved
@@ -415,6 +464,7 @@ func (c *Component) StartCmdFlags() *pflag.FlagSet {
flags := pflag.NewFlagSet("gserver", pflag.ExitOnError)

flags.String(httpAddrFlag, "", "TCP address of Gordian's introspective HTTP server; if blank, server will not be started")
flags.String(grpcAddrFlag, "", "GRPC address of Gordian's introspective GRPC server; if blank, server will not be started")
Copy link
Member

Choose a reason for hiding this comment

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

This would be another TCP address (of the gRPC server), not a gRPC address.

TCP address is a little more clear that it is of form HOST:PORT, as opposed to SCHEME://HOST:PORT or something else.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

am := g.cfg.AppManager

if req.Address == "" {
return nil, fmt.Errorf("BUG: address field is required")
Copy link
Member

Choose a reason for hiding this comment

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

If this is a programmer bug (e.g. they didn't fully configure the gRPC server) then a panic is appropriate. If this could be blank due to user input then the BUG prefix is probably not appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

User facing issue, removed BUG ce439ab

@@ -1,4 +1,4 @@
package gsi
package txmanager
Copy link
Member

Choose a reason for hiding this comment

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

Due to the volume of other comments -- and the general size of the PR -- don't include this change in this PR. Removing it will reduce the number of touched files by four, I think.

#!/bin/sh
# sh ./scripts/protocgen.sh
#
# TODO: migrate to buf?
Copy link
Member

Choose a reason for hiding this comment

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

That's really unfortunate.

Comment on lines +8 to +9
cp -r ./github.com/rollchains/gordian/gcosmos/* .
rm -rf ./github.com
Copy link
Member

Choose a reason for hiding this comment

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

What is this supposed to be doing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

protoc generates the code in this relative directory format
image

So we copy the changed files -> their path. Then remove the relative temp generated directory.

Copy link
Member

Choose a reason for hiding this comment

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

That's far from obvious, reading this script in isolation. It should be commented.

go run . genesis add-genesis-account val 1000000stake --keyring-backend=test
go run . genesis gentx val 1000000stake --keyring-backend=test --chain-id=gcosmos
go run . genesis collect-gentxs
# cosmos1r5v5srda7xfth3hn2s26txvrcrntldjumt8mhl
Copy link
Member

Choose a reason for hiding this comment

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

This comment is missing some words.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

@mark-rushakoff mark-rushakoff left a comment

Choose a reason for hiding this comment

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

I left a few more comments, but all of those we can address separately. I'm going to merge this.

./gcosmos genesis gentx val 1000000stake --keyring-backend=test --chain-id=gcosmos
./gcosmos genesis collect-gentxs

# rm -rf ~/.simappv2/data/application.db/
Copy link
Member

Choose a reason for hiding this comment

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

Help the reader out -- why is this commented code here? Would they want to run it? If so, when?

Same on the next section at L60.


grpcServer *grpc.Server

cfg GRPCServerConfig
Copy link
Member

Choose a reason for hiding this comment

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

I think there is only one other place in Gordian where we retain a reference to a config object (and that was a hack that needs to be cleaned up).

Sometimes it's because the config object contains some values that the parent only needs to pass through to sub-components, or the parent only composes some of the values into a different inner type.

It's a little more verbose to copy the config fields into the target type, but again as a reader, I don't want to have to make two jumps to figure out what fields my type has.

I think there is also some subtlety in having several plain unexported fields as opposed to a single unexported field that itself has many exported fields. Furthermore, while we use fully written names for exported fields like in the config object, we conventionally go towards standard shorthand notation for unexported fields, like ln instead of Listener, fs instead of FinalizationStore, etc.

I think we can clean that up in a separate PR anyway.

Comment on lines +78 to +79
var opts []grpc.ServerOption
g.grpcServer = grpc.NewServer(opts...)
Copy link
Member

Choose a reason for hiding this comment

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

The previous // TODO comment here was fine. Otherwise, why declare the opts slice at all?

RegisterGordianGRPCServer(g.grpcServer, g)
reflection.Register(g.grpcServer)

if err := g.grpcServer.Serve(g.cfg.Listener); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

There is probably an expected error or two that we can swallow here, but we'll adjust that later.

func convertEvent(e []event.Event) []*Event {
events := make([]*Event, len(e))
for i, ev := range e {

Copy link
Member

Choose a reason for hiding this comment

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

Avoid leading blank lines in new indentation.

Comment on lines +8 to +9
cp -r ./github.com/rollchains/gordian/gcosmos/* .
rm -rf ./github.com
Copy link
Member

Choose a reason for hiding this comment

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

That's far from obvious, reading this script in isolation. It should be commented.

}

message Validator {
bytes pub_key = 1;
Copy link
Member

Choose a reason for hiding this comment

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

The public key field is subtle because, it looks like it would contain raw public key bytes. But it doesn't because that would not contain the type of the key.

So, maybe renaming this to encoded_pub_key would make things a little more clear?

Or we could adjust the gcrypto public key interface to make it easier to get the Gordian name for the key type, and encode the key type field separately from the raw key bytes.

I think the single byte slice containing both the type and the key bytes is generally a good fit when staying internal to Gordian, but a separated type and raw key bytes is probably easier to consume from the outside, as there is no special parsing -- the gcrypto registry just prefixes the raw bytes with a fixed 8-byte header.


option go_package = "github.com/rollchains/gordian/gcosmos/gserver/internal/ggrpc";

package server;
Copy link
Member

Choose a reason for hiding this comment

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

I'm not too sure about the location of the file (the bare proto directory), and I feel like there is a more specific name than server that we can use here. But we can adjust both of those later.

@mark-rushakoff mark-rushakoff merged commit 53020d6 into main Aug 21, 2024
0 of 2 checks passed
@mark-rushakoff mark-rushakoff deleted the reece/grpc branch August 21, 2024 13:39
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.

3 participants