Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 additions & 0 deletions .github/workflows/golang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@ jobs:
version: v2.1.6 # this is the golangci-lint version
github-token: ${{ secrets.GITHUB_TOKEN }}
only-new-issues: true

- name: Run golangci-lint with XDR build tags
uses: golangci/golangci-lint-action@v7
with:
version: v2.1.6
github-token: ${{ secrets.GITHUB_TOKEN }}
only-new-issues: true
args: --build-tags xdr_hello_world,xdr_ledger_entry_ext_v2,xdr_transaction_meta_v5
11 changes: 9 additions & 2 deletions .github/workflows/stellar-rpc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ concurrency:

jobs:
test:
name: Unit tests
name: Unit tests${{ matrix.go_build_tags && ' (xdr tags)' || '' }}
strategy:
matrix:
os: [ ubuntu-22.04 ]
go_build_tags: [ '', 'xdr_hello_world,xdr_ledger_entry_ext_v2,xdr_transaction_meta_v5' ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand All @@ -32,7 +33,7 @@ jobs:
- run: rustup update
- uses: stellar/actions/rust-cache@main
- run: make build-libs
- run: go test -race -timeout 25m ./cmd/stellar-rpc/...
- run: go test -race -timeout 25m ${{ matrix.go_build_tags && format('-tags {0}', matrix.go_build_tags) || '' }} ./cmd/stellar-rpc/...

build:
name: Build
Expand Down Expand Up @@ -84,6 +85,12 @@ jobs:
CGO_ENABLED: 1
GOARCH: ${{ matrix.go_arch }}

- name: Verify build with XDR build tags
run: go vet -tags xdr_hello_world,xdr_ledger_entry_ext_v2,xdr_transaction_meta_v5 ./cmd/stellar-rpc/...
env:
CGO_ENABLED: 1
GOARCH: ${{ matrix.go_arch }}

integration:
name: Integration tests
continue-on-error: true
Expand Down
23 changes: 16 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,25 @@ CARGO_BUILD_TARGET ?= $(shell rustc -vV | sed -n 's|host: ||p')

STELLAR_RPC_BINARY := stellar-rpc

# XDR build tags for enabling gated XDR types from go-stellar-sdk.
# Set GO_BUILD_TAGS to a comma-separated list of tags, or use
# "make GO_BUILD_TAGS=$(XDR_BUILD_TAGS_ALL) build" to enable all.
XDR_BUILD_TAGS_ALL := xdr_hello_world,xdr_ledger_entry_ext_v2,xdr_transaction_meta_v5
GO_BUILD_TAGS ?=
ifneq ($(strip $(GO_BUILD_TAGS)),)
GOTAGS := -tags $(GO_BUILD_TAGS)
GOLANGCI_LINT_TAGS := --build-tags $(GO_BUILD_TAGS)
endif

# update the Cargo.lock every time the Cargo.toml changes.
Cargo.lock: Cargo.toml
cargo update --workspace

install: build-libs
go install -ldflags="${GOLDFLAGS}" ./...
go install $(GOTAGS) -ldflags="${GOLDFLAGS}" ./...

build: build-libs
go build -ldflags="${GOLDFLAGS}" ./...
go build $(GOTAGS) -ldflags="${GOLDFLAGS}" ./...

build-libs: Cargo.lock
cd cmd/stellar-rpc/lib/preflight && \
Expand All @@ -93,12 +102,12 @@ rust-test:
cargo test

go-test: build-libs
go test ./...
go test $(GOTAGS) ./...

test: go-test rust-test

bench:
go test -run=None -bench=. ./...
go test $(GOTAGS) -run=None -bench=. ./...

clean:
cargo clean
Expand All @@ -108,13 +117,13 @@ clean:
# https://github.com/stellar/pipelines/blob/master/stellar-rpc/Jenkinsfile-stellar-rpc-package-builder
# as part of the package building.
build-stellar-rpc: build-libs
go build -ldflags="${GOLDFLAGS}" ${MACOS_MIN_VER} -o ${STELLAR_RPC_BINARY} -trimpath -v ./cmd/stellar-rpc
go build $(GOTAGS) -ldflags="${GOLDFLAGS}" ${MACOS_MIN_VER} -o ${STELLAR_RPC_BINARY} -trimpath -v ./cmd/stellar-rpc

go-check-branch:
golangci-lint run ./... --new-from-rev $$(git rev-parse origin/main)
golangci-lint run $(GOLANGCI_LINT_TAGS) ./... --new-from-rev $$(git rev-parse origin/main)

go-check:
golangci-lint run ./...
golangci-lint run $(GOLANGCI_LINT_TAGS) ./...

# PHONY lists all the targets that aren't file names, so that make would skip the timestamp based check.
.PHONY: clean fmt watch test rust-test go-test check rust-check go-check install build build-stellar-rpc build-libs lint lint-changes
30 changes: 8 additions & 22 deletions cmd/stellar-rpc/internal/feewindow/feewindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,30 +172,16 @@
// should not happen
continue
}
if len(ops) == 1 {
switch ops[0].Body.Type { //nolint:exhaustive
case xdr.OperationTypeInvokeHostFunction, xdr.OperationTypeExtendFootprintTtl, xdr.OperationTypeRestoreFootprint:
var sorobanFees xdr.SorobanTransactionMetaExtV1
switch tx.UnsafeMeta.V {
case 3:
if tx.UnsafeMeta.V3.SorobanMeta == nil || tx.UnsafeMeta.V3.SorobanMeta.Ext.V != 1 {
continue
}
sorobanFees = *tx.UnsafeMeta.V3.SorobanMeta.Ext.V1
case 4:
if tx.UnsafeMeta.V4.SorobanMeta == nil || tx.UnsafeMeta.V4.SorobanMeta.Ext.V != 1 {
continue
}
sorobanFees = *tx.UnsafeMeta.V4.SorobanMeta.Ext.V1
default:
continue
}
resourceFeeCharged := sorobanFees.TotalNonRefundableResourceFeeCharged +
sorobanFees.TotalRefundableResourceFeeCharged
inclusionFee := feeCharged - uint64(resourceFeeCharged)
sorobanInclusionFees = append(sorobanInclusionFees, inclusionFee)
if len(ops) == 1 && isSorobanOperation(ops[0].Body.Type) {
sorobanFees, ok := extractSorobanFees(tx.UnsafeMeta)
if !ok {
continue
}
resourceFeeCharged := sorobanFees.TotalNonRefundableResourceFeeCharged +
sorobanFees.TotalRefundableResourceFeeCharged
inclusionFee := feeCharged - uint64(resourceFeeCharged)

Check failure on line 182 in cmd/stellar-rpc/internal/feewindow/feewindow.go

View workflow job for this annotation

GitHub Actions / golangci-lint

G115: integer overflow conversion int64 -> uint64 (gosec)
sorobanInclusionFees = append(sorobanInclusionFees, inclusionFee)
continue
}
feePerOp := feeCharged / uint64(len(ops))
classicFees = append(classicFees, feePerOp)
Expand Down
18 changes: 18 additions & 0 deletions cmd/stellar-rpc/internal/feewindow/feewindow_no_xdr_hello_world.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//go:build !xdr_hello_world

package feewindow

import "github.com/stellar/go-stellar-sdk/xdr"

// isSorobanOperation returns true if the operation type is a Soroban
// operation that incurs Soroban-specific resource fees.
func isSorobanOperation(opType xdr.OperationType) bool {
switch opType { //nolint:exhaustive

Check failure on line 10 in cmd/stellar-rpc/internal/feewindow/feewindow_no_xdr_hello_world.go

View workflow job for this annotation

GitHub Actions / golangci-lint

directive `//nolint:exhaustive` is unused for linter "exhaustive" (nolintlint)
case xdr.OperationTypeInvokeHostFunction,
xdr.OperationTypeExtendFootprintTtl,
xdr.OperationTypeRestoreFootprint:
return true
default:
return false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//go:build !xdr_transaction_meta_v5

package feewindow

import "github.com/stellar/go-stellar-sdk/xdr"

func extractSorobanFees(meta xdr.TransactionMeta) (xdr.SorobanTransactionMetaExtV1, bool) {
switch meta.V {
case 3:
if meta.V3.SorobanMeta == nil || meta.V3.SorobanMeta.Ext.V != 1 {
return xdr.SorobanTransactionMetaExtV1{}, false
}
return *meta.V3.SorobanMeta.Ext.V1, true
case 4:
if meta.V4.SorobanMeta == nil || meta.V4.SorobanMeta.Ext.V != 1 {
return xdr.SorobanTransactionMetaExtV1{}, false
}
return *meta.V4.SorobanMeta.Ext.V1, true
default:
return xdr.SorobanTransactionMetaExtV1{}, false
}
}
22 changes: 22 additions & 0 deletions cmd/stellar-rpc/internal/feewindow/feewindow_xdr_hello_world.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//go:build xdr_hello_world

package feewindow

import "github.com/stellar/go-stellar-sdk/xdr"

// isSorobanOperation returns true if the operation type is a Soroban
// operation that incurs Soroban-specific resource fees.
// OperationTypeHelloWorld is a classic operation and does not incur
// Soroban fees.
func isSorobanOperation(opType xdr.OperationType) bool {
switch opType { //nolint:exhaustive
case xdr.OperationTypeInvokeHostFunction,
xdr.OperationTypeExtendFootprintTtl,
xdr.OperationTypeRestoreFootprint:
return true
case xdr.OperationTypeHelloWorld:
return false
default:
return false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//go:build xdr_transaction_meta_v5

package feewindow

import "github.com/stellar/go-stellar-sdk/xdr"

func extractSorobanFees(meta xdr.TransactionMeta) (xdr.SorobanTransactionMetaExtV1, bool) {
switch meta.V {
case 3:
if meta.V3.SorobanMeta == nil || meta.V3.SorobanMeta.Ext.V != 1 {
return xdr.SorobanTransactionMetaExtV1{}, false
}
return *meta.V3.SorobanMeta.Ext.V1, true
case 4:
if meta.V4.SorobanMeta == nil || meta.V4.SorobanMeta.Ext.V != 1 {
return xdr.SorobanTransactionMetaExtV1{}, false
}
return *meta.V4.SorobanMeta.Ext.V1, true
case 5:
if meta.V5.SorobanMeta == nil || meta.V5.SorobanMeta.Ext.V != 1 {
return xdr.SorobanTransactionMetaExtV1{}, false
}
return *meta.V5.SorobanMeta.Ext.V1, true
default:
return xdr.SorobanTransactionMetaExtV1{}, false
}
}
10 changes: 1 addition & 9 deletions cmd/stellar-rpc/internal/integrationtest/get_fee_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,7 @@ func TestGetFeeStats(t *testing.T) {
sorobanTotalFee := sorobanTxResult.FeeCharged
var sorobanTxMeta xdr.TransactionMeta
require.NoError(t, xdr.SafeUnmarshalBase64(sorobanTxResponse.ResultMetaXDR, &sorobanTxMeta))
var sorobanFees xdr.SorobanTransactionMetaExtV1
switch sorobanTxMeta.V {
case 3:
sorobanFees = *sorobanTxMeta.V3.SorobanMeta.Ext.V1
case 4:
sorobanFees = *sorobanTxMeta.V4.SorobanMeta.Ext.V1
default:
t.Fatalf("Unexpected meta version: %d", sorobanTxMeta.V)
}
sorobanFees := extractSorobanFeesFromMeta(t, sorobanTxMeta)
sorobanResourceFeeCharged := sorobanFees.TotalRefundableResourceFeeCharged + sorobanFees.TotalNonRefundableResourceFeeCharged
sorobanInclusionFee := uint64(sorobanTotalFee - sorobanResourceFeeCharged)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//go:build !xdr_transaction_meta_v5

package integrationtest

import (
"testing"

"github.com/stellar/go-stellar-sdk/xdr"
)

func extractReturnValue(t *testing.T, meta xdr.TransactionMeta) xdr.ScVal {
t.Helper()
switch meta.V {
case 3:
return meta.V3.SorobanMeta.ReturnValue
case 4:
return *meta.V4.SorobanMeta.ReturnValue
default:
t.Fatalf("Unexpected meta version: %d", meta.V)
return xdr.ScVal{}
}
}

func extractSorobanFeesFromMeta(t *testing.T, meta xdr.TransactionMeta) xdr.SorobanTransactionMetaExtV1 {
t.Helper()
switch meta.V {
case 3:
return *meta.V3.SorobanMeta.Ext.V1
case 4:
return *meta.V4.SorobanMeta.Ext.V1
default:
t.Fatalf("Unexpected meta version: %d", meta.V)
return xdr.SorobanTransactionMetaExtV1{}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//go:build xdr_transaction_meta_v5

package integrationtest

import (
"testing"

"github.com/stellar/go-stellar-sdk/xdr"
)

func extractReturnValue(t *testing.T, meta xdr.TransactionMeta) xdr.ScVal {
t.Helper()
switch meta.V {
case 3:
return meta.V3.SorobanMeta.ReturnValue
case 4:
return *meta.V4.SorobanMeta.ReturnValue
case 5:
return *meta.V5.SorobanMeta.ReturnValue
default:
t.Fatalf("Unexpected meta version: %d", meta.V)
return xdr.ScVal{}
}
}

func extractSorobanFeesFromMeta(t *testing.T, meta xdr.TransactionMeta) xdr.SorobanTransactionMetaExtV1 {
t.Helper()
switch meta.V {
case 3:
return *meta.V3.SorobanMeta.Ext.V1
case 4:
return *meta.V4.SorobanMeta.Ext.V1
case 5:
return *meta.V5.SorobanMeta.Ext.V1
default:
t.Fatalf("Unexpected meta version: %d", meta.V)
return xdr.SorobanTransactionMetaExtV1{}
}
}
10 changes: 1 addition & 9 deletions cmd/stellar-rpc/internal/integrationtest/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,7 @@ func TestSendTransactionSucceedsWithResults(t *testing.T) {
expectedScVal := xdr.ScVal{Type: xdr.ScValTypeScvBytes, Bytes: &contractHashBytes}
var transactionMeta xdr.TransactionMeta
require.NoError(t, xdr.SafeUnmarshalBase64(response.ResultMetaXDR, &transactionMeta))
var retVal xdr.ScVal
switch transactionMeta.V {
case 3:
retVal = transactionMeta.V3.SorobanMeta.ReturnValue
case 4:
retVal = *transactionMeta.V4.SorobanMeta.ReturnValue
default:
t.Fatalf("Unexpected protocol version: %d", transactionMeta.V)
}
retVal := extractReturnValue(t, transactionMeta)
require.True(t, expectedScVal.Equals(retVal))
var resultXdr xdr.TransactionResult
require.NoError(t, xdr.SafeUnmarshalBase64(response.ResultXDR, &resultXdr))
Expand Down
22 changes: 12 additions & 10 deletions cmd/stellar-rpc/internal/methods/simulate_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,14 @@ func NewSimulateTransactionHandler(logger *log.Entry,
sourceAccount = txEnvelope.SourceAccount().ToAccountId()
}

if !isSorobanSimulationOp(op.Body.Type) {
return protocol.SimulateTransactionResponse{
Error: "Transaction contains unsupported operation type: " + op.Body.Type.String(),
}
}

footprint := xdr.LedgerFootprint{}
switch op.Body.Type {
switch op.Body.Type { //nolint:exhaustive
case xdr.OperationTypeInvokeHostFunction: // no-op
case xdr.OperationTypeExtendFootprintTtl, xdr.OperationTypeRestoreFootprint:
if txEnvelope.Type != xdr.EnvelopeTypeEnvelopeTypeTx && txEnvelope.V1.Tx.Ext.V != 1 {
Expand All @@ -304,11 +310,6 @@ func NewSimulateTransactionHandler(logger *log.Entry,
}
}
footprint = txEnvelope.V1.Tx.Ext.SorobanData.Resources.Footprint

default:
return protocol.SimulateTransactionResponse{
Error: "Transaction contains unsupported operation type: " + op.Body.Type.String(),
}
}

latestLedger, err := ledgerReader.GetLatestLedgerSequence(ctx)
Expand Down Expand Up @@ -386,7 +387,11 @@ func validateAuthMode(opBody xdr.OperationBody, authModeRef *string) error {
)
}

switch opBody.Type {
if !isSorobanSimulationOp(opBody.Type) {
return fmt.Errorf("transaction contains unsupported operation type: %s", opBody.Type.String())
}

switch opBody.Type { //nolint:exhaustive
case xdr.OperationTypeInvokeHostFunction:
hasAuth := len(opBody.MustInvokeHostFunctionOp().Auth) > 0

Expand Down Expand Up @@ -414,9 +419,6 @@ func validateAuthMode(opBody xdr.OperationBody, authModeRef *string) error {
if authMode != "" {
return errors.New("cannot set authMode with non-InvokeHostFunction operations")
}

default:
return fmt.Errorf("transaction contains unsupported operation type: %s", opBody.Type.String())
}

return nil
Expand Down
Loading
Loading