Skip to content

Commit 7e0fa86

Browse files
authored
feat: add support for non-root authorization in SorobanServer#simulateTransaction. (#708)
1 parent 97955e3 commit 7e0fa86

File tree

4 files changed

+103
-5
lines changed

4 files changed

+103
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- feat: add `destinationMuxedId` and `destinationMuxedIdType` to `InvokeHostFunctionOperationResponse.AssetContractBalanceChange`.
1212
- feat: add `events` field to `GetTransactionsResponse.Transaction` and `GetTransactionResponse`, see [stellar-rpc#455](https://github.com/stellar/stellar-rpc/pull/455) for more details.
1313
- feat: add `oldestLedger`, `latestLedgerCloseTime` and `oldestLedgerCloseTime` fields to `GetEventsResponse`, and add `transactionIndex` and `operationIndex` fields to `GetEventsResponse.EventInfo`, check [Stellar RPC release log](https://github.com/stellar/stellar-rpc/releases/tag/v23.0.0-rc.1) for more information.
14+
- feat: add support for non-root authorization in `SorobanServer#simulateTransaction`.
1415

1516
### Breaking changes:
1617
- refactor!: the following functions in `StrKey` are marked as deprecated, they will be removed in the next major release; please refer to the documentation for each function to see the corresponding replacement functions:

src/main/java/org/stellar/sdk/SorobanServer.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ public GetLatestLedgerResponse getLatestLedger() {
489489
* org.stellar.sdk.operations.RestoreFootprintOperation}. Any provided footprint will be
490490
* ignored.
491491
* @param resourceConfig Additional resource include in the simulation.
492+
* @param authMode Explicitly allows users to opt-in to non-root authorization in recording mode.
492493
* @return A {@link SimulateTransactionResponse} object containing the cost, footprint,
493494
* result/auth requirements (if applicable), and error of the transaction.
494495
* @throws org.stellar.sdk.exception.NetworkException All the exceptions below are subclasses of
@@ -502,10 +503,12 @@ public GetLatestLedgerResponse getLatestLedger() {
502503
* target="_blank">simulateTransaction documentation</a>
503504
*/
504505
public SimulateTransactionResponse simulateTransaction(
505-
Transaction transaction, @Nullable SimulateTransactionRequest.ResourceConfig resourceConfig) {
506+
Transaction transaction,
507+
@Nullable SimulateTransactionRequest.ResourceConfig resourceConfig,
508+
@Nullable SimulateTransactionRequest.AuthMode authMode) {
506509
// TODO: In the future, it may be necessary to consider FeeBumpTransaction.
507510
SimulateTransactionRequest params =
508-
new SimulateTransactionRequest(transaction.toEnvelopeXdrBase64(), resourceConfig);
511+
new SimulateTransactionRequest(transaction.toEnvelopeXdrBase64(), resourceConfig, authMode);
509512
return this.sendRequest(
510513
"simulateTransaction",
511514
params,
@@ -514,10 +517,11 @@ public SimulateTransactionResponse simulateTransaction(
514517

515518
/**
516519
* An alias for {@link #simulateTransaction(Transaction,
517-
* SimulateTransactionRequest.ResourceConfig)} with no resource leeway.
520+
* SimulateTransactionRequest.ResourceConfig, SimulateTransactionRequest.AuthMode)} with no
521+
* resource leeway, and no auth mode set.
518522
*/
519523
public SimulateTransactionResponse simulateTransaction(Transaction transaction) {
520-
return simulateTransaction(transaction, null);
524+
return simulateTransaction(transaction, null, null);
521525
}
522526

523527
/**

src/main/java/org/stellar/sdk/requests/sorobanrpc/SimulateTransactionRequest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.stellar.sdk.requests.sorobanrpc;
22

3+
import com.google.gson.annotations.SerializedName;
34
import java.math.BigInteger;
45
import lombok.AllArgsConstructor;
56
import lombok.Builder;
@@ -18,6 +19,26 @@ public class SimulateTransactionRequest {
1819

1920
ResourceConfig resourceConfig;
2021

22+
/**
23+
* Explicitly allows users to opt-in to non-root authorization in recording mode.
24+
*
25+
* <p>Leaving this field unset will default to {@link AuthMode#ENFORCE} if auth entries are
26+
* present, {@link AuthMode#RECORD} otherwise.
27+
*/
28+
AuthMode authMode;
29+
30+
public enum AuthMode {
31+
/** Always enforce mode, even with an empty list. */
32+
@SerializedName("enforce")
33+
ENFORCE,
34+
/** Always recording mode, failing if any auth exists. */
35+
@SerializedName("record")
36+
RECORD,
37+
/** Like {@code RECORD}, but allowing non-root authorization. */
38+
@SerializedName("record_allow_nonroot")
39+
RECORD_ALLOW_NONROOT;
40+
}
41+
2142
@Value
2243
@AllArgsConstructor
2344
@Builder

src/test/java/org/stellar/sdk/SorobanServerTest.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,79 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest)
997997

998998
SimulateTransactionRequest.ResourceConfig resourceConfig =
999999
new SimulateTransactionRequest.ResourceConfig(cpuInstructions);
1000-
SimulateTransactionResponse resp = server.simulateTransaction(transaction, resourceConfig);
1000+
SimulateTransactionResponse resp =
1001+
server.simulateTransaction(transaction, resourceConfig, null);
1002+
assertEquals(resp.getLatestLedger().longValue(), 14245L);
1003+
assertEquals(
1004+
resp.getTransactionData(),
1005+
"AAAAAAAAAAIAAAAGAAAAAem354u9STQWq5b3Ed1j9tOemvL7xV0NPwhn4gXg0AP8AAAAFAAAAAEAAAAH8dTe2OoI0BnhlDbH0fWvXmvprkBvBAgKIcL9busuuMEAAAABAAAABgAAAAHpt+eLvUk0FquW9xHdY/bTnpry+8VdDT8IZ+IF4NAD/AAAABAAAAABAAAAAgAAAA8AAAAHQ291bnRlcgAAAAASAAAAAAAAAABYt8SiyPKXqo89JHEoH9/M7K/kjlZjMT7BjhKnPsqYoQAAAAEAHifGAAAFlAAAAIgAAAAAAAAAAg==");
1006+
assertEquals(resp.getEvents().size(), 2);
1007+
assertEquals(
1008+
resp.getEvents().get(0),
1009+
"AAAAAQAAAAAAAAAAAAAAAgAAAAAAAAADAAAADwAAAAdmbl9jYWxsAAAAAA0AAAAg6bfni71JNBarlvcR3WP2056a8vvFXQ0/CGfiBeDQA/wAAAAPAAAACWluY3JlbWVudAAAAAAAABAAAAABAAAAAgAAABIAAAAAAAAAAFi3xKLI8peqjz0kcSgf38zsr+SOVmMxPsGOEqc+ypihAAAAAwAAAAo=");
1010+
assertEquals(
1011+
resp.getEvents().get(1),
1012+
"AAAAAQAAAAAAAAAB6bfni71JNBarlvcR3WP2056a8vvFXQ0/CGfiBeDQA/wAAAACAAAAAAAAAAIAAAAPAAAACWZuX3JldHVybgAAAAAAAA8AAAAJaW5jcmVtZW50AAAAAAAAAwAAABQ=");
1013+
assertEquals(resp.getMinResourceFee().longValue(), 58181L);
1014+
assertEquals(resp.getResults().size(), 1);
1015+
assertEquals(resp.getResults().get(0).getAuth().size(), 1);
1016+
assertEquals(
1017+
resp.getResults().get(0).getAuth().get(0),
1018+
"AAAAAAAAAAAAAAAB6bfni71JNBarlvcR3WP2056a8vvFXQ0/CGfiBeDQA/wAAAAJaW5jcmVtZW50AAAAAAAAAgAAABIAAAAAAAAAAFi3xKLI8peqjz0kcSgf38zsr+SOVmMxPsGOEqc+ypihAAAAAwAAAAoAAAAA");
1019+
assertEquals(resp.getResults().get(0).getXdr(), "AAAAAwAAABQ=");
1020+
server.close();
1021+
mockWebServer.close();
1022+
}
1023+
1024+
@Test
1025+
public void testSimulateTransactionWithAuthMode() throws IOException, SorobanRpcException {
1026+
String filePath =
1027+
"src/test/resources/soroban_server/simulate_transaction_with_resource_leeway.json";
1028+
String json = new String(Files.readAllBytes(Paths.get(filePath)));
1029+
Transaction transaction = buildSorobanTransaction(null, null);
1030+
BigInteger cpuInstructions = BigInteger.valueOf(20000L);
1031+
MockWebServer mockWebServer = new MockWebServer();
1032+
Dispatcher dispatcher =
1033+
new Dispatcher() {
1034+
@NotNull
1035+
@Override
1036+
public MockResponse dispatch(@NotNull RecordedRequest recordedRequest)
1037+
throws InterruptedException {
1038+
SorobanRpcRequest<SimulateTransactionRequest> sorobanRpcRequest =
1039+
gson.fromJson(
1040+
recordedRequest.getBody().readUtf8(),
1041+
new TypeToken<SorobanRpcRequest<SimulateTransactionRequest>>() {}.getType());
1042+
if ("POST".equals(recordedRequest.getMethod())
1043+
&& sorobanRpcRequest.getMethod().equals("simulateTransaction")
1044+
&& sorobanRpcRequest
1045+
.getParams()
1046+
.getTransaction()
1047+
.equals(transaction.toEnvelopeXdrBase64())
1048+
&& sorobanRpcRequest
1049+
.getParams()
1050+
.getResourceConfig()
1051+
.getInstructionLeeway()
1052+
.equals(cpuInstructions)
1053+
&& sorobanRpcRequest
1054+
.getParams()
1055+
.getAuthMode()
1056+
.equals(SimulateTransactionRequest.AuthMode.RECORD_ALLOW_NONROOT)) {
1057+
return new MockResponse().setResponseCode(200).setBody(json);
1058+
}
1059+
return new MockResponse().setResponseCode(404);
1060+
}
1061+
};
1062+
mockWebServer.setDispatcher(dispatcher);
1063+
mockWebServer.start();
1064+
1065+
HttpUrl baseUrl = mockWebServer.url("");
1066+
SorobanServer server = new SorobanServer(baseUrl.toString());
1067+
1068+
SimulateTransactionRequest.ResourceConfig resourceConfig =
1069+
new SimulateTransactionRequest.ResourceConfig(cpuInstructions);
1070+
SimulateTransactionResponse resp =
1071+
server.simulateTransaction(
1072+
transaction, resourceConfig, SimulateTransactionRequest.AuthMode.RECORD_ALLOW_NONROOT);
10011073
assertEquals(resp.getLatestLedger().longValue(), 14245L);
10021074
assertEquals(
10031075
resp.getTransactionData(),

0 commit comments

Comments
 (0)