Skip to content

Commit

Permalink
feat: gRPC server (#8)
Browse files Browse the repository at this point in the history
Add initial gRPC server matching the existing HTTP server's functionality. This
provides a basis for simpler integration with other typical Cosmos tooling.
  • Loading branch information
Reecepbcups authored Aug 21, 2024
1 parent adf25c1 commit 53020d6
Show file tree
Hide file tree
Showing 10 changed files with 2,008 additions and 8 deletions.
7 changes: 7 additions & 0 deletions gcosmos/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@

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

# grpcurl is a local binary downloaded as to not polute the user's system.
grpcurl

# example-tx are the default json Tx and signed json Tx from the test case found in the README.
# This is unique every generation and will be overriden frequently.
example-tx*
42 changes: 35 additions & 7 deletions gcosmos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,42 @@ but sometimes a local patch makes more sense.
Begin running the updated siampp commands from the `gcosmos` directory.

```bash
go run . init moniker
echo -n "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" > $HOME/.simappv2/mnemonic.txt
rm -rf ~/.simappv2/
go build -o gcosmos .

go run . keys add val --recover --source $HOME/.simappv2/mnemonic.txt
./gcosmos init moniker

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
# example-mnemonic address: cosmos1r5v5srda7xfth3hn2s26txvrcrntldjumt8mhl
echo -n "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" > example-mnemonic.txt

go run . start
./gcosmos keys add val --recover --source example-mnemonic.txt
./gcosmos genesis add-genesis-account val 10000000stake --keyring-backend=test
./gcosmos genesis gentx val 1000000stake --keyring-backend=test --chain-id=gcosmos
./gcosmos genesis collect-gentxs

# rm -rf ~/.simappv2/data/application.db/
./gcosmos start --g-http-addr 127.0.0.1:26657 --g-grpc-addr 127.0.0.1:9092
```

# Interact
```bash
# GOBIN="$PWD" go install github.com/fullstorydev/grpcurl/cmd/grpcurl@v1

./grpcurl -plaintext localhost:9092 list
./grpcurl -plaintext localhost:9092 server.GordianGRPC/GetBlocksWatermark
./grpcurl -plaintext localhost:9092 server.GordianGRPC/GetValidators

./grpcurl -plaintext -d '{"address":"cosmos1r5v5srda7xfth3hn2s26txvrcrntldjumt8mhl","denom":"stake"}' localhost:9092 server.GordianGRPC/QueryAccountBalance
```

# Transaction Testing
```bash
./gcosmos tx bank send val cosmos10r39fueph9fq7a6lgswu4zdsg8t3gxlqvvvyvn 1stake --chain-id=TODO:TEMPORARY_CHAIN_ID --generate-only > example-tx.json

# TODO: get account number
./gcosmos tx sign ./example-tx.json --offline --from=val --sequence=1 --account-number=1 --chain-id=TODO:TEMPORARY_CHAIN_ID --keyring-backend=test > example-tx-signed.json

./grpcurl -plaintext -emit-defaults -d '{"tx":"'$(cat example-tx-signed.json | base64 | tr -d '\n')'"}' localhost:9092 server.GordianGRPC/SimulateTransaction

./grpcurl -plaintext -emit-defaults -d '{"tx":"'$(cat example-tx-signed.json | base64 | tr -d '\n')'"}' localhost:9092 server.GordianGRPC/SubmitTransaction
```
1 change: 1 addition & 0 deletions gcosmos/example-mnemonic.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art
51 changes: 50 additions & 1 deletion gcosmos/gserver/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/libp2p/go-libp2p"
libp2ppeer "github.com/libp2p/go-libp2p/core/peer"
"github.com/rollchains/gordian/gcosmos/gserver/internal/ggrpc"
"github.com/rollchains/gordian/gcosmos/gserver/internal/gsbd"
"github.com/rollchains/gordian/gcosmos/gserver/internal/gsi"
"github.com/rollchains/gordian/gcrypto"
Expand Down Expand Up @@ -70,10 +71,13 @@ type Component struct {

seedAddrs string

httpLn net.Listener
httpLn net.Listener
grpcLn net.Listener

ms tmstore.MirrorStore
fs tmstore.FinalizationStore
httpServer *gsi.HTTPServer
grpcServer *ggrpc.GordianGRPC
}

// NewComponent returns a new server component
Expand Down Expand Up @@ -247,6 +251,25 @@ func (c *Component) Start(ctx context.Context) error {
Handler: e,
})

if c.grpcLn != nil {
// TODO; share this with the http server as a wrapper.
// https://github.com/rollchains/gordian/pull/14
c.grpcServer = ggrpc.NewGordianGRPCServer(ctx, c.log.With("sys", "grpc"), ggrpc.GRPCServerConfig{
Listener: c.grpcLn,

FinalizationStore: c.fs,
MirrorStore: c.ms,

CryptoRegistry: reg,

// debug:
TxCodec: c.txc,
AppManager: am,
TxBuf: txBuf,
Codec: c.codec,
})
}

if c.httpLn != nil {
c.httpServer = gsi.NewHTTPServer(ctx, c.log.With("sys", "http"), gsi.HTTPServerConfig{
Listener: c.httpLn,
Expand Down Expand Up @@ -303,6 +326,20 @@ func (c *Component) Stop(_ context.Context) error {
c.httpServer.Wait()
}
}
if c.grpcLn != nil {
if err := c.grpcLn.Close(); err != nil {
// If the GRPC server is closed directly,
// it will close the underlying listener,
// which will probably happen before our call to close the listener here.
// Don't log if the error already indicated the network connection was closed.
if !errors.Is(err, net.ErrClosed) {
c.log.Warn("Error closing gRPC listener", "err", err)
}
}
if c.grpcServer != nil {
c.grpcServer.Wait()
}
}
return nil
}

Expand Down Expand Up @@ -333,6 +370,16 @@ func (c *Component) Init(app serverv2.AppI[transaction.Tx], v *viper.Viper, log
c.httpLn = ln
}

// Maybe set up the GRPC server.
if grpcAddrFlag := v.GetString(grpcAddrFlag); grpcAddrFlag != "" {
ln, err := net.Listen("tcp", grpcAddrFlag)
if err != nil {
return fmt.Errorf("failed to listen for gRPC on %q: %w", grpcAddrFlag, err)
}

c.grpcLn = ln
}

c.seedAddrs = v.GetString(seedAddrsFlag)
if c.seedAddrs == "" {
c.log.Warn("No seed addresses provided; relying on incoming connections to discover peers")
Expand Down Expand Up @@ -407,6 +454,7 @@ func (c *Component) Init(app serverv2.AppI[transaction.Tx], v *viper.Viper, log

const (
httpAddrFlag = "g-http-addr"
grpcAddrFlag = "g-grpc-addr"
httpAddrFileFlag = "g-http-addr-file"

seedAddrsFlag = "g-seed-addrs"
Expand All @@ -416,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, "", "TCP address of Gordian's introspective GRPC server; if blank, server will not be started")
flags.String(httpAddrFileFlag, "", "Write the actual Gordian HTTP listen address to the given file (useful for tests when configured to listen on :0)")

flags.String(seedAddrsFlag, "", "Newline-separated multiaddrs to connect to; if omitted, relies on incoming connections to discover peers")
Expand Down
Loading

0 comments on commit 53020d6

Please sign in to comment.