From 9a865a0848b3dd171ae411e06b831170885596d8 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 16 Apr 2024 19:57:00 +0200 Subject: [PATCH 1/2] Obtain simulation protocol version dynamically --- cmd/soroban-rpc/internal/jsonrpc.go | 2 +- .../internal/methods/simulate_transaction.go | 27 ++++++++++++++++++- cmd/soroban-rpc/internal/preflight/pool.go | 1 + .../internal/preflight/preflight.go | 4 ++- .../internal/preflight/preflight_test.go | 1 + 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index b0ceb372..59d83420 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -208,7 +208,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { }, { methodName: "simulateTransaction", - underlyingHandler: methods.NewSimulateTransactionHandler(params.Logger, params.LedgerEntryReader, params.LedgerReader, params.PreflightGetter), + underlyingHandler: methods.NewSimulateTransactionHandler(params.Logger, params.LedgerEntryReader, params.LedgerReader, params.Daemon, params.PreflightGetter), longName: "simulate_transaction", queueLimit: cfg.RequestBacklogSimulateTransactionQueueLimit, requestDurationLimit: cfg.MaxSimulateTransactionExecutionDuration, diff --git a/cmd/soroban-rpc/internal/methods/simulate_transaction.go b/cmd/soroban-rpc/internal/methods/simulate_transaction.go index 6edc37d7..f8bdfad4 100644 --- a/cmd/soroban-rpc/internal/methods/simulate_transaction.go +++ b/cmd/soroban-rpc/internal/methods/simulate_transaction.go @@ -7,11 +7,13 @@ import ( "errors" "fmt" "strings" + "sync/atomic" "github.com/creachadair/jrpc2" "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/preflight" ) @@ -156,7 +158,7 @@ type PreflightGetter interface { } // NewSimulateTransactionHandler returns a json rpc handler to run preflight simulations -func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntryReader, ledgerReader db.LedgerReader, getter PreflightGetter) jrpc2.Handler { +func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntryReader, ledgerReader db.LedgerReader, daemon interfaces.Daemon, getter PreflightGetter) jrpc2.Handler { return NewHandler(func(ctx context.Context, request SimulateTransactionRequest) SimulateTransactionResponse { var txEnvelope xdr.TransactionEnvelope @@ -223,6 +225,12 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge if request.ResourceConfig != nil { resource_config = *request.ResourceConfig } + protocolVersion, err := getProtocolVersion(ctx, daemon.CoreClient()) + if err != nil { + return SimulateTransactionResponse{ + Error: fmt.Sprintf("cannot obtain protocol version from core: %s", err), + } + } params := preflight.PreflightGetterParameters{ LedgerEntryReadTx: readTx, BucketListSize: bucketListSize, @@ -230,6 +238,7 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge OperationBody: op.Body, Footprint: footprint, ResourceConfig: resource_config, + ProtocolVersion: protocolVersion, } result, err := getter.GetPreflight(ctx, params) if err != nil { @@ -298,3 +307,19 @@ func getBucketListSize(ctx context.Context, ledgerReader db.LedgerReader, latest } return uint64(closeMeta.V1.TotalByteSizeOfBucketList), nil } + +var cachedCoreProtocolVersion atomic.Int32 + +// getProtocolVersion obtains the memoized protocol version from a core client +func getProtocolVersion(ctx context.Context, client interfaces.CoreClient) (int, error) { + version := cachedCoreProtocolVersion.Load() + if version != 0 { + return int(version), nil + } + info, err := client.Info(ctx) + if err != nil { + return 0, err + } + cachedCoreProtocolVersion.CompareAndSwap(0, int32(info.Info.ProtocolVersion)) + return info.Info.ProtocolVersion, nil +} diff --git a/cmd/soroban-rpc/internal/preflight/pool.go b/cmd/soroban-rpc/internal/preflight/pool.go index 4eeddb53..3ea704d8 100644 --- a/cmd/soroban-rpc/internal/preflight/pool.go +++ b/cmd/soroban-rpc/internal/preflight/pool.go @@ -156,6 +156,7 @@ func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, params Preflig Footprint: params.Footprint, ResourceConfig: params.ResourceConfig, EnableDebug: pwp.enableDebug, + ProtocolVersion: params.ProtocolVersion, } resultC := make(chan workerResult) select { diff --git a/cmd/soroban-rpc/internal/preflight/preflight.go b/cmd/soroban-rpc/internal/preflight/preflight.go index 9a0fb94f..7c689519 100644 --- a/cmd/soroban-rpc/internal/preflight/preflight.go +++ b/cmd/soroban-rpc/internal/preflight/preflight.go @@ -91,6 +91,7 @@ type PreflightGetterParameters struct { OperationBody xdr.OperationBody Footprint xdr.LedgerFootprint ResourceConfig ResourceConfig + ProtocolVersion int } type PreflightParameters struct { @@ -103,6 +104,7 @@ type PreflightParameters struct { BucketListSize uint64 ResourceConfig ResourceConfig EnableDebug bool + ProtocolVersion int } type XDRDiff struct { @@ -174,7 +176,7 @@ func getLedgerInfo(params PreflightParameters) (C.ledger_info_t, error) { li := C.ledger_info_t{ network_passphrase: C.CString(params.NetworkPassphrase), sequence_number: C.uint32_t(simulationLedgerSeq), - protocol_version: 20, + protocol_version: C.uint32_t(params.ProtocolVersion), timestamp: C.uint64_t(time.Now().Unix()), // Current base reserve is 0.5XLM (in stroops) base_reserve: 5_000_000, diff --git a/cmd/soroban-rpc/internal/preflight/preflight_test.go b/cmd/soroban-rpc/internal/preflight/preflight_test.go index 4b164212..c7787bc5 100644 --- a/cmd/soroban-rpc/internal/preflight/preflight_test.go +++ b/cmd/soroban-rpc/internal/preflight/preflight_test.go @@ -361,6 +361,7 @@ func getPreflightParameters(t testing.TB, dbConfig *preflightParametersDBConfig) NetworkPassphrase: "foo", LedgerEntryReadTx: ledgerEntryReadTx, BucketListSize: 200, + ProtocolVersion: 20, } return params } From c59009e70286a406f763ef9555f3427b672c2806 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 16 Apr 2024 21:03:49 +0200 Subject: [PATCH 2/2] Address review feedback --- .../internal/methods/simulate_transaction.go | 35 ++++--------------- .../internal/preflight/preflight.go | 4 +-- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/simulate_transaction.go b/cmd/soroban-rpc/internal/methods/simulate_transaction.go index f8bdfad4..9ad98d80 100644 --- a/cmd/soroban-rpc/internal/methods/simulate_transaction.go +++ b/cmd/soroban-rpc/internal/methods/simulate_transaction.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "strings" - "sync/atomic" "github.com/creachadair/jrpc2" "github.com/stellar/go/support/log" @@ -214,7 +213,7 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge Error: err.Error(), } } - bucketListSize, err := getBucketListSize(ctx, ledgerReader, latestLedger) + bucketListSize, protocolVersion, err := getBucketListSizeAndProtocolVersion(ctx, ledgerReader, latestLedger) if err != nil { return SimulateTransactionResponse{ Error: err.Error(), @@ -225,12 +224,6 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge if request.ResourceConfig != nil { resource_config = *request.ResourceConfig } - protocolVersion, err := getProtocolVersion(ctx, daemon.CoreClient()) - if err != nil { - return SimulateTransactionResponse{ - Error: fmt.Sprintf("cannot obtain protocol version from core: %s", err), - } - } params := preflight.PreflightGetterParameters{ LedgerEntryReadTx: readTx, BucketListSize: bucketListSize, @@ -293,33 +286,17 @@ func base64EncodeSlice(in [][]byte) []string { return result } -func getBucketListSize(ctx context.Context, ledgerReader db.LedgerReader, latestLedger uint32) (uint64, error) { +func getBucketListSizeAndProtocolVersion(ctx context.Context, ledgerReader db.LedgerReader, latestLedger uint32) (uint64, uint32, error) { // obtain bucket size var closeMeta, ok, err = ledgerReader.GetLedger(ctx, latestLedger) if err != nil { - return 0, err + return 0, 0, err } if !ok { - return 0, fmt.Errorf("missing meta for latest ledger (%d)", latestLedger) + return 0, 0, fmt.Errorf("missing meta for latest ledger (%d)", latestLedger) } if closeMeta.V != 1 { - return 0, fmt.Errorf("latest ledger (%d) meta has unexpected verion (%d)", latestLedger, closeMeta.V) - } - return uint64(closeMeta.V1.TotalByteSizeOfBucketList), nil -} - -var cachedCoreProtocolVersion atomic.Int32 - -// getProtocolVersion obtains the memoized protocol version from a core client -func getProtocolVersion(ctx context.Context, client interfaces.CoreClient) (int, error) { - version := cachedCoreProtocolVersion.Load() - if version != 0 { - return int(version), nil - } - info, err := client.Info(ctx) - if err != nil { - return 0, err + return 0, 0, fmt.Errorf("latest ledger (%d) meta has unexpected verion (%d)", latestLedger, closeMeta.V) } - cachedCoreProtocolVersion.CompareAndSwap(0, int32(info.Info.ProtocolVersion)) - return info.Info.ProtocolVersion, nil + return uint64(closeMeta.V1.TotalByteSizeOfBucketList), uint32(closeMeta.V1.LedgerHeader.Header.LedgerVersion), nil } diff --git a/cmd/soroban-rpc/internal/preflight/preflight.go b/cmd/soroban-rpc/internal/preflight/preflight.go index 7c689519..ec0d8fd3 100644 --- a/cmd/soroban-rpc/internal/preflight/preflight.go +++ b/cmd/soroban-rpc/internal/preflight/preflight.go @@ -91,7 +91,7 @@ type PreflightGetterParameters struct { OperationBody xdr.OperationBody Footprint xdr.LedgerFootprint ResourceConfig ResourceConfig - ProtocolVersion int + ProtocolVersion uint32 } type PreflightParameters struct { @@ -104,7 +104,7 @@ type PreflightParameters struct { BucketListSize uint64 ResourceConfig ResourceConfig EnableDebug bool - ProtocolVersion int + ProtocolVersion uint32 } type XDRDiff struct {