Skip to content

Commit

Permalink
Add get_version_info endpoint (#132)
Browse files Browse the repository at this point in the history
* Add get_version endpoint

* Add CaptiveCoreVersion Info

* Add integration tests

* update integration tests

* remove protocol version

* fetch captive core version from info endpoint

* Add protocol version in response

* Remove captive-core-info from makefile

* Cache captive core version during bootup and add retry logic

* Revert retry logic in daemon and call /info endpoint directly in handler

* Fix integration tests

* Isolate version population in its own test

* Fix review comments
  • Loading branch information
psheth9 authored May 2, 2024
1 parent 587a229 commit c7b8ddc
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cmd/soroban-rpc/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Config struct {
RequestBacklogGetHealthQueueLimit uint
RequestBacklogGetEventsQueueLimit uint
RequestBacklogGetNetworkQueueLimit uint
RequestBacklogGetVersionInfoQueueLimit uint
RequestBacklogGetLatestLedgerQueueLimit uint
RequestBacklogGetLedgerEntriesQueueLimit uint
RequestBacklogGetTransactionQueueLimit uint
Expand All @@ -54,6 +55,7 @@ type Config struct {
MaxGetHealthExecutionDuration time.Duration
MaxGetEventsExecutionDuration time.Duration
MaxGetNetworkExecutionDuration time.Duration
MaxGetVersionInfoExecutionDuration time.Duration
MaxGetLatestLedgerExecutionDuration time.Duration
MaxGetLedgerEntriesExecutionDuration time.Duration
MaxGetTransactionExecutionDuration time.Duration
Expand Down
13 changes: 13 additions & 0 deletions cmd/soroban-rpc/internal/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,13 @@ func (cfg *Config) options() ConfigOptions {
DefaultValue: uint(1000),
Validate: positive,
},
{
TomlKey: strutils.KebabToConstantCase("request-backlog-get-version-info-queue-limit"),
Usage: "Maximum number of outstanding GetVersionInfo requests",
ConfigKey: &cfg.RequestBacklogGetVersionInfoQueueLimit,
DefaultValue: uint(1000),
Validate: positive,
},
{
TomlKey: strutils.KebabToConstantCase("request-backlog-get-latest-ledger-queue-limit"),
Usage: "Maximum number of outstanding GetLatestsLedger requests",
Expand Down Expand Up @@ -367,6 +374,12 @@ func (cfg *Config) options() ConfigOptions {
ConfigKey: &cfg.MaxGetNetworkExecutionDuration,
DefaultValue: 5 * time.Second,
},
{
TomlKey: strutils.KebabToConstantCase("max-get-version-info-execution-duration"),
Usage: "The maximum duration of time allowed for processing a getVersionInfo request. When that time elapses, the rpc server would return -32001 and abort the request's execution",
ConfigKey: &cfg.MaxGetVersionInfoExecutionDuration,
DefaultValue: 5 * time.Second,
},
{
TomlKey: strutils.KebabToConstantCase("max-get-latest-ledger-execution-duration"),
Usage: "The maximum duration of time allowed for processing a getLatestLedger request. When that time elapses, the rpc server would return -32001 and abort the request's execution",
Expand Down
7 changes: 7 additions & 0 deletions cmd/soroban-rpc/internal/jsonrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler {
queueLimit: cfg.RequestBacklogGetNetworkQueueLimit,
requestDurationLimit: cfg.MaxGetNetworkExecutionDuration,
},
{
methodName: "getVersionInfo",
underlyingHandler: methods.NewGetVersionInfoHandler(params.Logger, params.LedgerEntryReader, params.LedgerReader, params.Daemon),
longName: "get_version_info",
queueLimit: cfg.RequestBacklogGetVersionInfoQueueLimit,
requestDurationLimit: cfg.MaxGetVersionInfoExecutionDuration,
},
{
methodName: "getLatestLedger",
underlyingHandler: methods.NewGetLatestLedgerHandler(params.LedgerEntryReader, params.LedgerReader),
Expand Down
61 changes: 61 additions & 0 deletions cmd/soroban-rpc/internal/methods/get_version_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package methods

import (
"context"
"github.com/creachadair/jrpc2"
"github.com/creachadair/jrpc2/handler"
"github.com/stellar/go/support/log"
"github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/config"
"github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces"
"github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db"
)

type GetVersionInfoResponse struct {
Version string `json:"version"`
CommitHash string `json:"commit_hash"`
BuildTimestamp string `json:"build_time_stamp"`
CaptiveCoreVersion string `json:"captive_core_version"`
ProtocolVersion uint32 `json:"protocol_version"`
}

func NewGetVersionInfoHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntryReader, ledgerReader db.LedgerReader, daemon interfaces.Daemon) jrpc2.Handler {
coreClient := daemon.CoreClient()
return handler.New(func(ctx context.Context) (GetVersionInfoResponse, error) {

var captiveCoreVersion string
info, err := coreClient.Info(ctx)
if err != nil {
logger.WithError(err).Info("error occurred while calling Info endpoint of core")
} else {
captiveCoreVersion = info.Info.Build
}

// Fetch Protocol version
var protocolVersion uint32
readTx, err := ledgerEntryReader.NewCachedTx(ctx)
if err != nil {
logger.WithError(err).Info("Cannot create read transaction")
}
defer func() {
_ = readTx.Done()
}()

latestLedger, err := readTx.GetLatestLedgerSequence()
if err != nil {
logger.WithError(err).Info("error occurred while getting latest ledger")
}

_, protocolVersion, err = getBucketListSizeAndProtocolVersion(ctx, ledgerReader, latestLedger)
if err != nil {
logger.WithError(err).Info("error occurred while fetching protocol version")
}

return GetVersionInfoResponse{
Version: config.Version,
CommitHash: config.CommitHash,
BuildTimestamp: config.BuildTimestamp,
CaptiveCoreVersion: captiveCoreVersion,
ProtocolVersion: protocolVersion,
}, nil
})
}
67 changes: 67 additions & 0 deletions cmd/soroban-rpc/internal/test/get_version_info_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package test

import (
"context"
"fmt"
"github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/config"
"os/exec"
"testing"

"github.com/creachadair/jrpc2"
"github.com/creachadair/jrpc2/jhttp"
"github.com/stretchr/testify/assert"

"github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods"
)

func TestGetVersionInfoSucceeds(t *testing.T) {
test := NewTest(t, nil)

version, commitHash, buildTimeStamp := config.Version, config.CommitHash, config.BuildTimestamp

populateVersionInfo(test)

// reset to previous config values
t.Cleanup(func() {
config.Version = version
config.CommitHash = commitHash
config.BuildTimestamp = buildTimeStamp
})

ch := jhttp.NewChannel(test.sorobanRPCURL(), nil)
client := jrpc2.NewClient(ch, nil)

var result methods.GetVersionInfoResponse
err := client.CallResult(context.Background(), "getVersionInfo", nil, &result)
assert.NoError(t, err)

assert.Equal(t, config.Version, result.Version)
assert.Equal(t, config.BuildTimestamp, result.BuildTimestamp)
assert.Equal(t, config.CommitHash, result.CommitHash)
assert.Equal(t, test.protocolVersion, result.ProtocolVersion)
assert.NotEmpty(t, result.CaptiveCoreVersion)

}

// Runs git commands to fetch version information
func populateVersionInfo(test *Test) {

execFunction := func(command string, args ...string) string {
cmd := exec.Command(command, args...)
test.t.Log("Running", cmd.Env, cmd.Args)
out, innerErr := cmd.Output()
if exitErr, ok := innerErr.(*exec.ExitError); ok {
fmt.Printf("stdout:\n%s\n", string(out))
fmt.Printf("stderr:\n%s\n", string(exitErr.Stderr))
}

if innerErr != nil {
test.t.Fatalf("Command %s failed: %v", cmd.Env, innerErr)
}
return string(out)
}

config.Version = execFunction("git", "describe", "--tags", "--always", "--abbrev=0", "--match='v[0-9]*.[0-9]*.[0-9]*'")
config.CommitHash = execFunction("git", "rev-parse", "HEAD")
config.BuildTimestamp = execFunction("date", "+%Y-%m-%dT%H:%M:%S")
}

0 comments on commit c7b8ddc

Please sign in to comment.