From 3ac050d516c92eafc6197c9e7eb5f06265e26eab Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 10 Jun 2026 15:09:10 -0700 Subject: [PATCH 1/4] Add AuthV2 support for preflight operations --- cmd/stellar-rpc/internal/preflight/pool.go | 2 ++ .../internal/preflight/preflight.go | 2 ++ .../internal/preflight/preflight_test.go | 15 +++++++++++ cmd/stellar-rpc/lib/preflight.h | 3 ++- cmd/stellar-rpc/lib/preflight/src/lib.rs | 26 +++++++++++++------ cmd/stellar-rpc/lib/preflight/src/shared.rs | 5 ++-- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/cmd/stellar-rpc/internal/preflight/pool.go b/cmd/stellar-rpc/internal/preflight/pool.go index 21456deed..54ede4b9d 100644 --- a/cmd/stellar-rpc/internal/preflight/pool.go +++ b/cmd/stellar-rpc/internal/preflight/pool.go @@ -164,6 +164,7 @@ type GetterParameters struct { Footprint xdr.LedgerFootprint ResourceConfig protocol.ResourceConfig AuthMode string + AuthV2 bool ProtocolVersion uint32 LedgerEntryGetter ledgerentries.LedgerEntryGetter LedgerSeq uint32 @@ -188,6 +189,7 @@ func (pwp *WorkerPool) GetPreflight(ctx context.Context, params GetterParameters ResourceConfig: params.ResourceConfig, EnableDebug: pwp.enableDebug, AuthMode: params.AuthMode, + AuthV2: params.AuthV2, ProtocolVersion: params.ProtocolVersion, } resultC := make(chan workerResult) diff --git a/cmd/stellar-rpc/internal/preflight/preflight.go b/cmd/stellar-rpc/internal/preflight/preflight.go index e69935c89..4b32f8b70 100644 --- a/cmd/stellar-rpc/internal/preflight/preflight.go +++ b/cmd/stellar-rpc/internal/preflight/preflight.go @@ -107,6 +107,7 @@ type Parameters struct { ResourceConfig protocol.ResourceConfig EnableDebug bool AuthMode string + AuthV2 bool ProtocolVersion uint32 } @@ -268,6 +269,7 @@ func getInvokeHostFunctionPreflight(ctx context.Context, params Parameters) (Pre resourceConfig, C.bool(params.EnableDebug), C.uint32_t(authMode), + C.bool(params.AuthV2), ) return GoPreflight(res), nil diff --git a/cmd/stellar-rpc/internal/preflight/preflight_test.go b/cmd/stellar-rpc/internal/preflight/preflight_test.go index 029b99b28..782421826 100644 --- a/cmd/stellar-rpc/internal/preflight/preflight_test.go +++ b/cmd/stellar-rpc/internal/preflight/preflight_test.go @@ -302,3 +302,18 @@ func BenchmarkGetPreflight(b *testing.B) { require.Empty(b, result.Error) } } + +// TestGetPreflightAuthV2SilentlyIgnoredOnPrevProtocol locks in the agreed +// behavior that requesting v2 (AddressV2) credentials on a protocol served by +// the prev soroban-env host -- which predates v2 credentials -- is silently +// ignored rather than rejected: v1 behavior is used and no error is returned. +// getPreflightParameters runs at ProtocolVersion 25, which routes to the prev +// host. (Asserting the credential version itself requires an auth-recording +// contract on the curr host; that is covered by the integration tests.) +func TestGetPreflightAuthV2SilentlyIgnoredOnPrevProtocol(t *testing.T) { + params := getPreflightParameters(t) + params.AuthV2 = true + result, err := GetPreflight(t.Context(), params) + require.NoError(t, err) + require.Empty(t, result.Error) +} diff --git a/cmd/stellar-rpc/lib/preflight.h b/cmd/stellar-rpc/lib/preflight.h index 897fe59ec..2febed5d7 100644 --- a/cmd/stellar-rpc/lib/preflight.h +++ b/cmd/stellar-rpc/lib/preflight.h @@ -53,7 +53,8 @@ preflight_result_t *preflight_invoke_hf_op(uintptr_t handle, // Go Handle to for const ledger_info_t ledger_info, const resource_config_t resource_config, bool enable_debug, - const uint32_t auth_mode); + const uint32_t auth_mode, + bool auth_v2); // emit AddressV2 ("v2") credentials when recording auth preflight_result_t *preflight_footprint_ttl_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet const xdr_t op_body, // OperationBody XDR diff --git a/cmd/stellar-rpc/lib/preflight/src/lib.rs b/cmd/stellar-rpc/lib/preflight/src/lib.rs index 376a1f1e7..dca5f7c4c 100644 --- a/cmd/stellar-rpc/lib/preflight/src/lib.rs +++ b/cmd/stellar-rpc/lib/preflight/src/lib.rs @@ -42,18 +42,16 @@ mod curr { pub(crate) const PROTOCOL: u32 = soroban_env_host::meta::INTERFACE_VERSION.protocol; - // Builds the recording auth mode for this protocol version. The shape of - // `RecordingInvocationAuthMode::Recording` differs between soroban versions, - // so each version-specific module provides its own constructor and - // `shared.rs` calls into it via `super::`. From protocol 27 - // the recording params also carry `use_address_v2`, which we leave `false` - // at this layer until v28. - pub(crate) fn recording_auth_mode( + // Constructs the recording auth mode for this protocol version. The current + // protocol's soroban-env can emit either v1 (`Address`) or v2 (`AddressV2`) + // credentials, selected by `use_address_v2`. + pub(crate) fn make_recording_auth_mode( disable_non_root_auth: bool, + use_address_v2: bool, ) -> soroban_env_host::e2e_invoke::RecordingInvocationAuthMode { soroban_env_host::e2e_invoke::RecordingInvocationAuthMode::recording( disable_non_root_auth, - false, + use_address_v2, ) } } @@ -75,6 +73,15 @@ mod prev { ) -> soroban_env_host::e2e_invoke::RecordingInvocationAuthMode { soroban_env_host::e2e_invoke::RecordingInvocationAuthMode::Recording(disable_non_root_auth) } + + // The previous protocol's soroban-env predates v2 Address credentials, so + // `use_address_v2` is ignored and v1 `Address` credentials are always used. + pub(crate) fn make_recording_auth_mode( + disable_non_root_auth: bool, + _use_address_v2: bool, + ) -> soroban_env_host::e2e_invoke::RecordingInvocationAuthMode { + soroban_env_host::e2e_invoke::RecordingInvocationAuthMode::Recording(disable_non_root_auth) + } } use std::cell::RefCell; @@ -203,6 +210,7 @@ pub extern "C" fn preflight_invoke_hf_op( resource_config: CResourceConfig, enable_debug: bool, auth_mode: u32, + auth_v2: bool, ) -> *mut CPreflightResult { let proto = ledger_info.protocol_version; catch_preflight_panic(&move || { @@ -215,6 +223,7 @@ pub extern "C" fn preflight_invoke_hf_op( resource_config, enable_debug, auth_mode.into(), + auth_v2, ) } else if proto == curr::PROTOCOL { curr::shared::preflight_invoke_hf_op_or_maybe_panic( @@ -225,6 +234,7 @@ pub extern "C" fn preflight_invoke_hf_op( resource_config, enable_debug, auth_mode.into(), + auth_v2, ) } else { bail!("unsupported protocol version: {proto}") diff --git a/cmd/stellar-rpc/lib/preflight/src/shared.rs b/cmd/stellar-rpc/lib/preflight/src/shared.rs index 6881600cb..02257941b 100644 --- a/cmd/stellar-rpc/lib/preflight/src/shared.rs +++ b/cmd/stellar-rpc/lib/preflight/src/shared.rs @@ -121,6 +121,7 @@ pub(crate) fn preflight_invoke_hf_op_or_maybe_panic( resource_config: CResourceConfig, enable_debug: bool, auth_mode: AuthMode, + use_address_v2: bool, ) -> Result { let invoke_hf_op = InvokeHostFunctionOp::from_xdr(unsafe { from_c_xdr(invoke_hf_op) }, DEFAULT_XDR_RW_LIMITS) @@ -149,8 +150,8 @@ pub(crate) fn preflight_invoke_hf_op_or_maybe_panic( // ignore the list entirely even if it's present. let auth_mode = match auth_mode { AuthMode::Enforce => RecordingInvocationAuthMode::Enforcing(auth_entries), - AuthMode::Record => super::recording_auth_mode(true), - AuthMode::RecordAllowNonroot => super::recording_auth_mode(false), + AuthMode::Record => super::make_recording_auth_mode(true, use_address_v2), + AuthMode::RecordAllowNonroot => super::make_recording_auth_mode(false, use_address_v2), }; preflight_invoke_hf_op_post_autorestore_or_maybe_panic( From a3c75e9922d4ad799d6577b6375b0ebfc17a3d99 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 10 Jun 2026 15:09:42 -0700 Subject: [PATCH 2/4] Add AuthV2 support for related tests --- .../simulate_transaction_test.go | 78 ++++++++++++ .../internal/methods/simulate_transaction.go | 1 + .../methods/simulate_transaction_test.go | 113 ++++++++++++++++++ 3 files changed, 192 insertions(+) diff --git a/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go b/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go index 802f2cea7..a73efc811 100644 --- a/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go +++ b/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go @@ -267,6 +267,84 @@ func TestSimulateInvokeContractTransactionSucceeds(t *testing.T) { require.Equal(t, xdr.ScString("auth"), *event.Event.Body.V0.Topics[0].Str) } +// TestSimulateInvokeContractTransactionAuthV2 verifies that setting AuthV2 on the +// simulate request causes recorded authorization entries to use AddressV2 ("v2") +// credentials instead of Address ("v1"). v2 credentials are only emitted by the +// curr soroban-env host, so this requires a protocol that routes to it. +func TestSimulateInvokeContractTransactionAuthV2(t *testing.T) { + test := infrastructure.NewTest(t, nil) + if test.GetProtocolVersion() < 27 { + t.Skip("AddressV2 credentials require protocol >= 27 (curr soroban-env host)") + } + + _, contractID, _ := test.CreateHelloWorldContract() + + contractFnParameterSym := xdr.ScSymbol("world") + authAddrArg := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" + authAccountIDArg := xdr.MustAddress(authAddrArg) + test.SendMasterOperation(&txnbuild.CreateAccount{ + Destination: authAddrArg, + Amount: "100000", + SourceAccount: test.MasterAccount().GetAccountID(), + }) + params := infrastructure.CreateTransactionParams( + test.MasterAccount(), + infrastructure.CreateInvokeHostOperation( + test.MasterAccount().GetAccountID(), + contractID, + "auth", + xdr.ScVal{ + Type: xdr.ScValTypeScvAddress, + Address: &xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeAccount, + AccountId: &authAccountIDArg, + }, + }, + xdr.ScVal{ + Type: xdr.ScValTypeScvSymbol, + Sym: &contractFnParameterSym, + }, + ), + ) + tx, err := txnbuild.NewTransaction(params) + require.NoError(t, err) + txB64, err := tx.Base64() + require.NoError(t, err) + + // Baseline: without AuthV2, the recorded credential is v1 (Address). + v1Resp, err := test.GetRPCLient().SimulateTransaction(t.Context(), + protocol.SimulateTransactionRequest{Transaction: txB64}) + require.NoError(t, err) + require.Empty(t, v1Resp.Error) + v1Auth := firstSimulateAuthEntry(t, v1Resp) + require.Equal(t, xdr.SorobanCredentialsTypeSorobanCredentialsAddress, v1Auth.Credentials.Type) + + // With AuthV2, the same recorded entry uses v2 (AddressV2) credentials. + v2Resp, err := test.GetRPCLient().SimulateTransaction(t.Context(), + protocol.SimulateTransactionRequest{Transaction: txB64, AuthV2: true}) + require.NoError(t, err) + require.Empty(t, v2Resp.Error) + v2Auth := firstSimulateAuthEntry(t, v2Resp) + require.Equal(t, xdr.SorobanCredentialsTypeSorobanCredentialsAddressV2, v2Auth.Credentials.Type) + require.NotNil(t, v2Auth.Credentials.AddressV2) + require.Nil(t, v2Auth.Credentials.Address) + // The authorized invocation itself is unchanged -- only the credential format differs. + require.Equal(t, xdr.ScSymbol("auth"), v2Auth.RootInvocation.Function.ContractFn.FunctionName) +} + +func firstSimulateAuthEntry( + t *testing.T, + resp protocol.SimulateTransactionResponse, +) xdr.SorobanAuthorizationEntry { + t.Helper() + require.Len(t, resp.Results, 1) + require.NotNil(t, resp.Results[0].AuthXDR) + require.Len(t, *resp.Results[0].AuthXDR, 1) + var auth xdr.SorobanAuthorizationEntry + require.NoError(t, xdr.SafeUnmarshalBase64((*resp.Results[0].AuthXDR)[0], &auth)) + return auth +} + func TestSimulateTransactionError(t *testing.T) { test := infrastructure.NewTest(t, nil) diff --git a/cmd/stellar-rpc/internal/methods/simulate_transaction.go b/cmd/stellar-rpc/internal/methods/simulate_transaction.go index ba97c95b2..f6e971b53 100644 --- a/cmd/stellar-rpc/internal/methods/simulate_transaction.go +++ b/cmd/stellar-rpc/internal/methods/simulate_transaction.go @@ -370,6 +370,7 @@ func NewSimulateTransactionHandler(logger *log.Entry, Footprint: footprint, ResourceConfig: resourceConfig, AuthMode: request.AuthMode, + AuthV2: request.AuthV2, ProtocolVersion: protocolVersion, LedgerEntryGetter: ledgerEntryGetter, LedgerSeq: latestLedger, diff --git a/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go b/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go index 5d7177763..17f58696a 100644 --- a/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go +++ b/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/creachadair/jrpc2" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" protocol "github.com/stellar/go-stellar-sdk/protocols/rpc" @@ -234,3 +235,115 @@ func feeBumpExtendFootprintMissingSorobanData(t *testing.T) xdr.TransactionEnvel FeeBump: &feeBumpEnvelope, } } + +// capturingPreflightGetter records the GetterParameters it receives so tests can +// assert on how the handler populates them, and returns an empty (but valid) +// Preflight result. +type capturingPreflightGetter struct { + called bool + params preflight.GetterParameters +} + +func (c *capturingPreflightGetter) GetPreflight( + _ context.Context, + params preflight.GetterParameters, +) (preflight.Preflight, error) { + c.called = true + c.params = params + return preflight.Preflight{}, nil +} + +func invokeHostFunctionEnvelope(t *testing.T) xdr.TransactionEnvelope { + t.Helper() + + sourceAccountID := xdr.MustAddress("GBXGQJWVLWOYHFLVTKWV5FGHA3LNYY2JQKM7OAJAUEQFU6LPCSEFVXON") + source := (&sourceAccountID).ToMuxedAccount() + contractID := xdr.ContractId{0xa, 0xb, 0xc} + argSymbol := xdr.ScSymbol("world") + + op := xdr.Operation{ + Body: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, + InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, + InvokeContract: &xdr.InvokeContractArgs{ + ContractAddress: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &contractID, + }, + FunctionName: "hello", + Args: []xdr.ScVal{{Type: xdr.ScValTypeScvSymbol, Sym: &argSymbol}}, + }, + }, + }, + }, + } + + tx := xdr.Transaction{ + SourceAccount: source, + Fee: xdr.Uint32(100), + SeqNum: xdr.SequenceNumber(1), + Cond: xdr.Preconditions{Type: xdr.PreconditionTypePrecondNone}, + Memo: xdr.Memo{Type: xdr.MemoTypeMemoNone}, + Operations: []xdr.Operation{op}, + Ext: xdr.TransactionExt{V: 0}, + } + + return xdr.TransactionEnvelope{ + Type: xdr.EnvelopeTypeEnvelopeTypeTx, + V1: &xdr.TransactionV1Envelope{Tx: tx}, + } +} + +// TestSimulateTransactionThreadsAuthV2 verifies that the request's authV2 flag is +// forwarded into the preflight GetterParameters (and defaults to false when omitted). +func TestSimulateTransactionThreadsAuthV2(t *testing.T) { + closeMeta := xdr.LedgerCloseMeta{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Header: xdr.LedgerHeader{LedgerVersion: 23}, + }, + TotalByteSizeOfLiveSorobanState: 100, + }, + } + + txB64, err := xdr.MarshalBase64(invokeHostFunctionEnvelope(t)) + require.NoError(t, err) + + for _, tc := range []struct { + name string + paramsField string + expected bool + }{ + {name: "authV2 true is forwarded", paramsField: `, "authV2": true`, expected: true}, + {name: "authV2 false is forwarded", paramsField: `, "authV2": false`, expected: false}, + {name: "authV2 omitted defaults to false", paramsField: "", expected: false}, + } { + t.Run(tc.name, func(t *testing.T) { + ledgerReader := &MockLedgerReader{} + ledgerReader.On("GetLatestLedgerSequence", mock.Anything).Return(uint32(2), nil) + ledgerReader.On("GetLedger", mock.Anything, uint32(2)).Return(closeMeta, true, nil) + + getter := &capturingPreflightGetter{} + handler := NewSimulateTransactionHandler(log.New(), ledgerReader, nil, getter, xdr.DecodeOptions{}) + + requestJSON := fmt.Sprintf(`{ +"jsonrpc": "2.0", +"id": 1, +"method": "simulateTransaction", +"params": { "transaction": "%s"%s } +}`, txB64, tc.paramsField) + requests, err := jrpc2.ParseRequests([]byte(requestJSON)) + require.NoError(t, err) + require.Len(t, requests, 1) + + _, err = handler(t.Context(), requests[0].ToRequest()) + require.NoError(t, err) + + require.True(t, getter.called, "GetPreflight should have been called") + require.Equal(t, tc.expected, getter.params.AuthV2) + }) + } +} From c298b6c0b436f2fd2a228e79b226a7ad9dfce73a Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 10 Jun 2026 15:33:46 -0700 Subject: [PATCH 3/4] Remove obsolete recording_auth_mode function for previous soroban version --- cmd/stellar-rpc/lib/preflight/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cmd/stellar-rpc/lib/preflight/src/lib.rs b/cmd/stellar-rpc/lib/preflight/src/lib.rs index dca5f7c4c..7246ccb44 100644 --- a/cmd/stellar-rpc/lib/preflight/src/lib.rs +++ b/cmd/stellar-rpc/lib/preflight/src/lib.rs @@ -66,14 +66,6 @@ mod prev { pub(crate) const PROTOCOL: u32 = soroban_env_host::meta::INTERFACE_VERSION.protocol; - // See the matching `curr::recording_auth_mode`. The previous soroban version - // models the recording auth mode as a bare `disable_non_root_auth` bool. - pub(crate) fn recording_auth_mode( - disable_non_root_auth: bool, - ) -> soroban_env_host::e2e_invoke::RecordingInvocationAuthMode { - soroban_env_host::e2e_invoke::RecordingInvocationAuthMode::Recording(disable_non_root_auth) - } - // The previous protocol's soroban-env predates v2 Address credentials, so // `use_address_v2` is ignored and v1 `Address` credentials are always used. pub(crate) fn make_recording_auth_mode( From 270e772bad847a9ed0382c2724b860326bd3f802 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Mon, 15 Jun 2026 18:02:46 -0700 Subject: [PATCH 4/4] Refactor AuthV2 to UseUpgradedAuth across preflight and simulation components --- .../integrationtest/simulate_transaction_test.go | 10 +++++----- .../internal/methods/simulate_transaction.go | 2 +- .../methods/simulate_transaction_test.go | 12 ++++++------ cmd/stellar-rpc/internal/preflight/pool.go | 4 ++-- cmd/stellar-rpc/internal/preflight/preflight.go | 4 ++-- .../internal/preflight/preflight_test.go | 15 ++++++++------- cmd/stellar-rpc/lib/preflight.h | 2 +- cmd/stellar-rpc/lib/preflight/src/lib.rs | 16 ++++++++-------- cmd/stellar-rpc/lib/preflight/src/shared.rs | 6 +++--- 9 files changed, 36 insertions(+), 35 deletions(-) diff --git a/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go b/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go index a73efc811..3ca088198 100644 --- a/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go +++ b/cmd/stellar-rpc/internal/integrationtest/simulate_transaction_test.go @@ -267,11 +267,11 @@ func TestSimulateInvokeContractTransactionSucceeds(t *testing.T) { require.Equal(t, xdr.ScString("auth"), *event.Event.Body.V0.Topics[0].Str) } -// TestSimulateInvokeContractTransactionAuthV2 verifies that setting AuthV2 on the +// TestSimulateInvokeContractTransactionUseUpgradedAuth verifies that setting UseUpgradedAuth on the // simulate request causes recorded authorization entries to use AddressV2 ("v2") // credentials instead of Address ("v1"). v2 credentials are only emitted by the // curr soroban-env host, so this requires a protocol that routes to it. -func TestSimulateInvokeContractTransactionAuthV2(t *testing.T) { +func TestSimulateInvokeContractTransactionUseUpgradedAuth(t *testing.T) { test := infrastructure.NewTest(t, nil) if test.GetProtocolVersion() < 27 { t.Skip("AddressV2 credentials require protocol >= 27 (curr soroban-env host)") @@ -311,7 +311,7 @@ func TestSimulateInvokeContractTransactionAuthV2(t *testing.T) { txB64, err := tx.Base64() require.NoError(t, err) - // Baseline: without AuthV2, the recorded credential is v1 (Address). + // Baseline: without UseUpgradedAuth, the recorded credential is v1 (Address). v1Resp, err := test.GetRPCLient().SimulateTransaction(t.Context(), protocol.SimulateTransactionRequest{Transaction: txB64}) require.NoError(t, err) @@ -319,9 +319,9 @@ func TestSimulateInvokeContractTransactionAuthV2(t *testing.T) { v1Auth := firstSimulateAuthEntry(t, v1Resp) require.Equal(t, xdr.SorobanCredentialsTypeSorobanCredentialsAddress, v1Auth.Credentials.Type) - // With AuthV2, the same recorded entry uses v2 (AddressV2) credentials. + // With UseUpgradedAuth, the same recorded entry uses v2 (AddressV2) credentials. v2Resp, err := test.GetRPCLient().SimulateTransaction(t.Context(), - protocol.SimulateTransactionRequest{Transaction: txB64, AuthV2: true}) + protocol.SimulateTransactionRequest{Transaction: txB64, UseUpgradedAuth: true}) require.NoError(t, err) require.Empty(t, v2Resp.Error) v2Auth := firstSimulateAuthEntry(t, v2Resp) diff --git a/cmd/stellar-rpc/internal/methods/simulate_transaction.go b/cmd/stellar-rpc/internal/methods/simulate_transaction.go index f6e971b53..a30a30acb 100644 --- a/cmd/stellar-rpc/internal/methods/simulate_transaction.go +++ b/cmd/stellar-rpc/internal/methods/simulate_transaction.go @@ -370,7 +370,7 @@ func NewSimulateTransactionHandler(logger *log.Entry, Footprint: footprint, ResourceConfig: resourceConfig, AuthMode: request.AuthMode, - AuthV2: request.AuthV2, + UseUpgradedAuth: request.UseUpgradedAuth, ProtocolVersion: protocolVersion, LedgerEntryGetter: ledgerEntryGetter, LedgerSeq: latestLedger, diff --git a/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go b/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go index 17f58696a..648e5f023 100644 --- a/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go +++ b/cmd/stellar-rpc/internal/methods/simulate_transaction_test.go @@ -296,9 +296,9 @@ func invokeHostFunctionEnvelope(t *testing.T) xdr.TransactionEnvelope { } } -// TestSimulateTransactionThreadsAuthV2 verifies that the request's authV2 flag is +// TestSimulateTransactionThreadsUseUpgradedAuth verifies that the request's useUpgradedAuth flag is // forwarded into the preflight GetterParameters (and defaults to false when omitted). -func TestSimulateTransactionThreadsAuthV2(t *testing.T) { +func TestSimulateTransactionThreadsUseUpgradedAuth(t *testing.T) { closeMeta := xdr.LedgerCloseMeta{ V: 1, V1: &xdr.LedgerCloseMetaV1{ @@ -317,9 +317,9 @@ func TestSimulateTransactionThreadsAuthV2(t *testing.T) { paramsField string expected bool }{ - {name: "authV2 true is forwarded", paramsField: `, "authV2": true`, expected: true}, - {name: "authV2 false is forwarded", paramsField: `, "authV2": false`, expected: false}, - {name: "authV2 omitted defaults to false", paramsField: "", expected: false}, + {name: "useUpgradedAuth true is forwarded", paramsField: `, "useUpgradedAuth": true`, expected: true}, + {name: "useUpgradedAuth false is forwarded", paramsField: `, "useUpgradedAuth": false`, expected: false}, + {name: "useUpgradedAuth omitted defaults to false", paramsField: "", expected: false}, } { t.Run(tc.name, func(t *testing.T) { ledgerReader := &MockLedgerReader{} @@ -343,7 +343,7 @@ func TestSimulateTransactionThreadsAuthV2(t *testing.T) { require.NoError(t, err) require.True(t, getter.called, "GetPreflight should have been called") - require.Equal(t, tc.expected, getter.params.AuthV2) + require.Equal(t, tc.expected, getter.params.UseUpgradedAuth) }) } } diff --git a/cmd/stellar-rpc/internal/preflight/pool.go b/cmd/stellar-rpc/internal/preflight/pool.go index 54ede4b9d..bc5a944a6 100644 --- a/cmd/stellar-rpc/internal/preflight/pool.go +++ b/cmd/stellar-rpc/internal/preflight/pool.go @@ -164,7 +164,7 @@ type GetterParameters struct { Footprint xdr.LedgerFootprint ResourceConfig protocol.ResourceConfig AuthMode string - AuthV2 bool + UseUpgradedAuth bool ProtocolVersion uint32 LedgerEntryGetter ledgerentries.LedgerEntryGetter LedgerSeq uint32 @@ -189,7 +189,7 @@ func (pwp *WorkerPool) GetPreflight(ctx context.Context, params GetterParameters ResourceConfig: params.ResourceConfig, EnableDebug: pwp.enableDebug, AuthMode: params.AuthMode, - AuthV2: params.AuthV2, + UseUpgradedAuth: params.UseUpgradedAuth, ProtocolVersion: params.ProtocolVersion, } resultC := make(chan workerResult) diff --git a/cmd/stellar-rpc/internal/preflight/preflight.go b/cmd/stellar-rpc/internal/preflight/preflight.go index 4b32f8b70..ce85b0816 100644 --- a/cmd/stellar-rpc/internal/preflight/preflight.go +++ b/cmd/stellar-rpc/internal/preflight/preflight.go @@ -107,7 +107,7 @@ type Parameters struct { ResourceConfig protocol.ResourceConfig EnableDebug bool AuthMode string - AuthV2 bool + UseUpgradedAuth bool ProtocolVersion uint32 } @@ -269,7 +269,7 @@ func getInvokeHostFunctionPreflight(ctx context.Context, params Parameters) (Pre resourceConfig, C.bool(params.EnableDebug), C.uint32_t(authMode), - C.bool(params.AuthV2), + C.bool(params.UseUpgradedAuth), ) return GoPreflight(res), nil diff --git a/cmd/stellar-rpc/internal/preflight/preflight_test.go b/cmd/stellar-rpc/internal/preflight/preflight_test.go index 782421826..5218c30cd 100644 --- a/cmd/stellar-rpc/internal/preflight/preflight_test.go +++ b/cmd/stellar-rpc/internal/preflight/preflight_test.go @@ -303,16 +303,17 @@ func BenchmarkGetPreflight(b *testing.B) { } } -// TestGetPreflightAuthV2SilentlyIgnoredOnPrevProtocol locks in the agreed +// TestGetPreflightUseUpgradedAuthSilentlyIgnoredOnPrevProtocol locks in the agreed // behavior that requesting v2 (AddressV2) credentials on a protocol served by // the prev soroban-env host -- which predates v2 credentials -- is silently // ignored rather than rejected: v1 behavior is used and no error is returned. -// getPreflightParameters runs at ProtocolVersion 25, which routes to the prev -// host. (Asserting the credential version itself requires an auth-recording -// contract on the curr host; that is covered by the integration tests.) -func TestGetPreflightAuthV2SilentlyIgnoredOnPrevProtocol(t *testing.T) { - params := getPreflightParameters(t) - params.AuthV2 = true +// It runs at protocol 26, which routes to the prev host. (Asserting the +// credential version itself requires an auth-recording contract on the curr +// host; that is covered by the integration tests.) +func TestGetPreflightUseUpgradedAuthSilentlyIgnoredOnPrevProtocol(t *testing.T) { + const prevHostProtocol = 26 + params := getPreflightParameters(t, prevHostProtocol) + params.UseUpgradedAuth = true result, err := GetPreflight(t.Context(), params) require.NoError(t, err) require.Empty(t, result.Error) diff --git a/cmd/stellar-rpc/lib/preflight.h b/cmd/stellar-rpc/lib/preflight.h index 2febed5d7..100c82602 100644 --- a/cmd/stellar-rpc/lib/preflight.h +++ b/cmd/stellar-rpc/lib/preflight.h @@ -54,7 +54,7 @@ preflight_result_t *preflight_invoke_hf_op(uintptr_t handle, // Go Handle to for const resource_config_t resource_config, bool enable_debug, const uint32_t auth_mode, - bool auth_v2); // emit AddressV2 ("v2") credentials when recording auth + bool use_upgraded_auth); // record AddressV2 ("upgraded") credentials preflight_result_t *preflight_footprint_ttl_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet const xdr_t op_body, // OperationBody XDR diff --git a/cmd/stellar-rpc/lib/preflight/src/lib.rs b/cmd/stellar-rpc/lib/preflight/src/lib.rs index 7246ccb44..150523c6c 100644 --- a/cmd/stellar-rpc/lib/preflight/src/lib.rs +++ b/cmd/stellar-rpc/lib/preflight/src/lib.rs @@ -44,14 +44,14 @@ mod curr { // Constructs the recording auth mode for this protocol version. The current // protocol's soroban-env can emit either v1 (`Address`) or v2 (`AddressV2`) - // credentials, selected by `use_address_v2`. + // credentials, selected by `use_upgraded_auth`. pub(crate) fn make_recording_auth_mode( disable_non_root_auth: bool, - use_address_v2: bool, + use_upgraded_auth: bool, ) -> soroban_env_host::e2e_invoke::RecordingInvocationAuthMode { soroban_env_host::e2e_invoke::RecordingInvocationAuthMode::recording( disable_non_root_auth, - use_address_v2, + use_upgraded_auth, ) } } @@ -67,10 +67,10 @@ mod prev { pub(crate) const PROTOCOL: u32 = soroban_env_host::meta::INTERFACE_VERSION.protocol; // The previous protocol's soroban-env predates v2 Address credentials, so - // `use_address_v2` is ignored and v1 `Address` credentials are always used. + // `use_upgraded_auth` is ignored and v1 `Address` credentials are always used. pub(crate) fn make_recording_auth_mode( disable_non_root_auth: bool, - _use_address_v2: bool, + _use_upgraded_auth: bool, ) -> soroban_env_host::e2e_invoke::RecordingInvocationAuthMode { soroban_env_host::e2e_invoke::RecordingInvocationAuthMode::Recording(disable_non_root_auth) } @@ -202,7 +202,7 @@ pub extern "C" fn preflight_invoke_hf_op( resource_config: CResourceConfig, enable_debug: bool, auth_mode: u32, - auth_v2: bool, + use_upgraded_auth: bool, ) -> *mut CPreflightResult { let proto = ledger_info.protocol_version; catch_preflight_panic(&move || { @@ -215,7 +215,7 @@ pub extern "C" fn preflight_invoke_hf_op( resource_config, enable_debug, auth_mode.into(), - auth_v2, + use_upgraded_auth, ) } else if proto == curr::PROTOCOL { curr::shared::preflight_invoke_hf_op_or_maybe_panic( @@ -226,7 +226,7 @@ pub extern "C" fn preflight_invoke_hf_op( resource_config, enable_debug, auth_mode.into(), - auth_v2, + use_upgraded_auth, ) } else { bail!("unsupported protocol version: {proto}") diff --git a/cmd/stellar-rpc/lib/preflight/src/shared.rs b/cmd/stellar-rpc/lib/preflight/src/shared.rs index 02257941b..2cfc2f868 100644 --- a/cmd/stellar-rpc/lib/preflight/src/shared.rs +++ b/cmd/stellar-rpc/lib/preflight/src/shared.rs @@ -121,7 +121,7 @@ pub(crate) fn preflight_invoke_hf_op_or_maybe_panic( resource_config: CResourceConfig, enable_debug: bool, auth_mode: AuthMode, - use_address_v2: bool, + use_upgraded_auth: bool, ) -> Result { let invoke_hf_op = InvokeHostFunctionOp::from_xdr(unsafe { from_c_xdr(invoke_hf_op) }, DEFAULT_XDR_RW_LIMITS) @@ -150,8 +150,8 @@ pub(crate) fn preflight_invoke_hf_op_or_maybe_panic( // ignore the list entirely even if it's present. let auth_mode = match auth_mode { AuthMode::Enforce => RecordingInvocationAuthMode::Enforcing(auth_entries), - AuthMode::Record => super::make_recording_auth_mode(true, use_address_v2), - AuthMode::RecordAllowNonroot => super::make_recording_auth_mode(false, use_address_v2), + AuthMode::Record => super::make_recording_auth_mode(true, use_upgraded_auth), + AuthMode::RecordAllowNonroot => super::make_recording_auth_mode(false, use_upgraded_auth), }; preflight_invoke_hf_op_post_autorestore_or_maybe_panic(