Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/stellar-rpc/internal/daemon/interfaces/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Daemon interface {

type CoreClient interface {
Info(ctx context.Context) (*proto.InfoResponse, error)
SorobanInfo(ctx context.Context) (*proto.SorobanInfoResponse, error)
SubmitTransaction(ctx context.Context, txBase64 string) (*proto.TXResponse, error)
}

Expand Down
4 changes: 4 additions & 0 deletions cmd/stellar-rpc/internal/daemon/interfaces/noOpDaemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func (s noOpCoreClient) Info(context.Context) (*proto.InfoResponse, error) {
return &proto.InfoResponse{}, nil
}

func (s noOpCoreClient) SorobanInfo(context.Context) (*proto.SorobanInfoResponse, error) {
return &proto.SorobanInfoResponse{}, nil
}

func (s noOpCoreClient) SubmitTransaction(context.Context, string) (*proto.TXResponse, error) {
return &proto.TXResponse{Status: proto.PreflightStatusOk}, nil
}
Expand Down
10 changes: 9 additions & 1 deletion cmd/stellar-rpc/internal/integrationtest/get_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,13 @@ func TestGetNetworkSucceeds(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, infrastructure.FriendbotURL, result.FriendbotURL)
assert.Equal(t, infrastructure.StandaloneNetworkPassphrase, result.Passphrase)
assert.GreaterOrEqual(t, result.ProtocolVersion, 20)
assert.GreaterOrEqual(t, result.ProtocolVersions.MaxSupportedProtocolVersion, 24)
assert.Positive(t, result.Limits.MaxContractSize)
assert.Positive(t, result.Limits.Tx.MaxInstructions)
assert.Positive(t, result.Limits.Ledger.MaxInstructions)
assert.Positive(t, result.Limits.FeeTransactionSize1KB)
assert.Positive(t, result.Limits.StateArchival.PersistentRentRateDenominator)
// Core should refuse to boot if the following doesn't hold
assert.Equal(t, result.ProtocolVersions.MaxSupportedProtocolVersion,
result.ProtocolVersions.CoreSupportedProtocolVersion)
}
3 changes: 2 additions & 1 deletion cmd/stellar-rpc/internal/jsonrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler {
underlyingHandler: methods.NewGetNetworkHandler(
cfg.NetworkPassphrase,
cfg.FriendbotURL,
params.LedgerReader,
params.Daemon.CoreClient(),
cfg.StellarCoreBinaryPath,
),
longName: toSnakeCase(protocol.GetNetworkMethodName),
queueLimit: cfg.RequestBacklogGetNetworkQueueLimit,
Expand Down
79 changes: 72 additions & 7 deletions cmd/stellar-rpc/internal/methods/get_network.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,99 @@
package methods

import (
"bytes"
"context"
"os/exec"
"regexp"
"slices"
"strconv"

"github.com/creachadair/jrpc2"

protocol "github.com/stellar/go-stellar-sdk/protocols/rpc"

"github.com/stellar/stellar-rpc/cmd/stellar-rpc/internal/db"
"github.com/stellar/stellar-rpc/cmd/stellar-rpc/internal/daemon/interfaces"
)

// NewGetNetworkHandler returns a json rpc handler to for the getNetwork method
func NewGetNetworkHandler(
networkPassphrase string,
friendbotURL string,
ledgerReader db.LedgerReader,
coreClient interfaces.CoreClient,
coreBinaryPath string,
) jrpc2.Handler {
return NewHandler(func(ctx context.Context, _ protocol.GetNetworkRequest) (protocol.GetNetworkResponse, error) {
protocolVersion, err := getProtocolVersion(ctx, ledgerReader)
infoResponse, err := coreClient.Info(ctx)
if err != nil {
return protocol.GetNetworkResponse{}, &jrpc2.Error{
Code: jrpc2.InternalError,
Message: err.Error(),
}
}

versionInfoResponse, err := getSupportedProtocolVersions(ctx, coreBinaryPath)
if err != nil {
return protocol.GetNetworkResponse{}, &jrpc2.Error{
Code: jrpc2.InternalError,
Message: "failed to get supported protocol versions: " + err.Error(),
}
}

sorobanInfoResponse, err := coreClient.SorobanInfo(ctx)
if err != nil {
return protocol.GetNetworkResponse{}, &jrpc2.Error{
Code: jrpc2.InternalError,
Message: "failed to get soroban info: " + err.Error(),
}
}

return protocol.GetNetworkResponse{
FriendbotURL: friendbotURL,
Passphrase: networkPassphrase,
ProtocolVersion: int(protocolVersion),
FriendbotURL: friendbotURL,
Passphrase: networkPassphrase,
Build: infoResponse.Info.Build,
ProtocolVersions: versionInfoResponse,
Limits: *sorobanInfoResponse,
}, nil
})
}

func getSupportedProtocolVersions(ctx context.Context, coreBinaryPath string) (protocol.GetProtocolVersions, error) {
// Exec `stellar-core version` to get supported protocol versions
cmd := exec.CommandContext(ctx, coreBinaryPath, "version")
var out, stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return protocol.GetProtocolVersions{}, &jrpc2.Error{
Code: jrpc2.InternalError,
Message: "failed to exec `stellar-core version`: " + err.Error() + " stderr: " + stderr.String(),
}
}

// Find all matches for protocol versions across hosts in stdout
outStr := out.String()
re := regexp.MustCompile(`ledger protocol version:\s*(\d+)`)
matches := re.FindAllStringSubmatch(outStr, -1)
if matches == nil {
return protocol.GetProtocolVersions{}, &jrpc2.Error{
Code: jrpc2.InternalError,
Message: "failed to parse protocol versions from `stellar-core version` output: " + outStr,
}
}

versions := make([]int, len(matches))
for i, match := range matches {
version, err := strconv.Atoi(match[1])
if err != nil {
return protocol.GetProtocolVersions{}, &jrpc2.Error{
Code: jrpc2.InternalError,
Message: "failed to parse protocol version from `stellar-core version` output: " + err.Error(),
}
}
versions[i] = version
}
return protocol.GetProtocolVersions{
MinSupportedProtocolVersion: slices.Min(versions), // min supported ledger protocol version
MaxSupportedProtocolVersion: slices.Max(versions), // max supported ledger protocol version
CoreSupportedProtocolVersion: versions[0], // core's protocol version. Should == MaxSupportedProtocolVersion
}, nil
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
github.com/stellar/go-stellar-sdk v0.0.0-20251203191521-a04f63bf3455
github.com/stellar/go-stellar-sdk v0.0.0-20251208214900-1d112ac18173
github.com/stretchr/testify v1.11.1
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,8 @@ github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo=
github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs=
github.com/stellar/go-stellar-sdk v0.0.0-20251203191521-a04f63bf3455 h1:cP/z5b8FF0PcMhnRxAq6AECCRgWhENTjgw5tHVWcZcs=
github.com/stellar/go-stellar-sdk v0.0.0-20251203191521-a04f63bf3455/go.mod h1:fZPcxQZw1I0zZ+X76uFcVPqmQCaYbWc87lDFW/kQJaY=
github.com/stellar/go-stellar-sdk v0.0.0-20251208214900-1d112ac18173 h1:AOo12Cj6yDdM2PZS3SXlw6bUBrJ1xqrtoqfEFIlahcM=
github.com/stellar/go-stellar-sdk v0.0.0-20251208214900-1d112ac18173/go.mod h1:fZPcxQZw1I0zZ+X76uFcVPqmQCaYbWc87lDFW/kQJaY=
github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 h1:OzCVd0SV5qE3ZcDeSFCmOWLZfEWZ3Oe8KtmSOYKEVWE=
github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
Loading