Skip to content

Commit 2ff7011

Browse files
authored
[graphql-alt] Handle transaction execution/simulation errors as BAD_USER_INPUT (#25261)
## Description - gRPC `InvalidArgument` and `NotFound` errors from `executeTransaction` and `simulateTransaction` now return GraphQL `BAD_USER_INPUT` errors instead of being returned in an `error`/`errors` field - Added `InvalidArgument` variant to `TransactionInputError` with message prefix "Invalid argument:" - Removed `error` field from `SimulationResult` and `errors` field from `ExecutionResult` ## Example error: ``` { "data": null, "errors": [ { "message": "Invalid argument: Invalid user signature: Signature is not valid: Fail to verify user sig Invalid signature was given to the function", "locations": [ { "line": 3, "column": 17 } ], "path": [ "executeTransaction" ], "extensions": { "code": "BAD_USER_INPUT" } } ] } ``` ## Test plan - test_execute_transaction_grpc_errors verifies BAD_USER_INPUT code and ServerValidation message - Existing e2e tests updated to remove error/errors field references --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] gRPC: - [ ] JSON-RPC: - [x] GraphQL: Error field is no longer available in simulateResult and ExecutionResult. They will be propagated in GraphQL errors - [ ] CLI: - [ ] Rust SDK: - [ ] Indexing Framework:
1 parent 87665b0 commit 2ff7011

16 files changed

+69
-161
lines changed

crates/sui-indexer-alt-e2e-tests/tests/graphql_execute_transaction_tests.rs

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@ async fn test_execute_transaction_mutation_schema() {
207207
}
208208
}
209209
}
210-
errors
211210
}
212211
}
213212
"#,
@@ -225,11 +224,9 @@ async fn test_execute_transaction_mutation_schema() {
225224
.clone(),
226225
)
227226
.unwrap();
228-
let errors = result.pointer("/data/executeTransaction/errors");
229227

230228
assert_eq!(effects.status, "SUCCESS");
231229
assert_eq!(effects.checkpoint, None); // ExecutedTransaction has no checkpoint yet
232-
assert_eq!(errors, Some(&serde_json::Value::Null));
233230

234231
// Verify transaction data matches original
235232
let transaction = effects.transaction.unwrap();
@@ -259,7 +256,6 @@ async fn test_execute_transaction_input_validation() {
259256
mutation($txData: Base64!, $sigs: [Base64!]!) {
260257
executeTransaction(transactionDataBcs: $txData, signatures: $sigs) {
261258
effects { digest }
262-
errors
263259
}
264260
}
265261
"#,
@@ -309,7 +305,6 @@ async fn test_execute_transaction_with_events() {
309305
}
310306
}
311307
}
312-
errors
313308
}
314309
}
315310
"#,
@@ -327,10 +322,8 @@ async fn test_execute_transaction_with_events() {
327322
.clone(),
328323
)
329324
.unwrap();
330-
let errors = result.pointer("/data/executeTransaction/errors");
331325

332326
assert_eq!(effects.status, "SUCCESS");
333-
assert_eq!(errors, Some(&serde_json::Value::Null));
334327

335328
let events = effects.events.unwrap();
336329
assert!(
@@ -360,7 +353,7 @@ async fn test_execute_transaction_grpc_errors() {
360353
.await;
361354
let graphql_cluster = GraphQlTestCluster::new(&validator_cluster).await;
362355

363-
// Create signature mismatch scenario: use transaction data from one tx with signatures from another
356+
// Create signature mismatch: use transaction data from one tx with signatures from another
364357
let recipient1 = SuiAddress::random_for_testing_only();
365358
let recipient2 = SuiAddress::random_for_testing_only();
366359

@@ -374,7 +367,6 @@ async fn test_execute_transaction_grpc_errors() {
374367
let (tx1_bytes, _) = signed_tx1.to_tx_bytes_and_signatures();
375368
let (_, tx2_signatures) = signed_tx2.to_tx_bytes_and_signatures();
376369

377-
// This will pass GraphQL validation but fail at gRPC execution due to signature mismatch
378370
let result = graphql_cluster
379371
.execute_graphql(
380372
r#"
@@ -384,7 +376,6 @@ async fn test_execute_transaction_grpc_errors() {
384376
digest
385377
status
386378
}
387-
errors
388379
}
389380
}
390381
"#,
@@ -394,17 +385,10 @@ async fn test_execute_transaction_grpc_errors() {
394385
}),
395386
)
396387
.await
397-
.expect("GraphQL request failed");
398-
let effects = result.pointer("/data/executeTransaction/effects");
399-
let errors = result.pointer("/data/executeTransaction/errors").unwrap();
388+
.unwrap();
400389

401-
assert_eq!(
402-
effects,
403-
Some(&serde_json::Value::Null),
404-
"Should have null effects on gRPC error"
405-
);
406-
let error_array = errors.as_array().unwrap();
407-
assert!(!error_array.is_empty());
390+
// Verify the error response structure with a snapshot
391+
insta::assert_json_snapshot!("execute_transaction_grpc_error", &result);
408392
}
409393

410394
#[sim_test]
@@ -462,7 +446,6 @@ async fn test_execute_transaction_unchanged_consensus_objects() {
462446
}
463447
}
464448
}
465-
errors
466449
}
467450
}
468451
"#,
@@ -481,11 +464,8 @@ async fn test_execute_transaction_unchanged_consensus_objects() {
481464
.clone(),
482465
)
483466
.unwrap();
484-
let errors = result.pointer("/data/executeTransaction/errors");
485467

486-
// Verify the transaction succeeded
487468
assert_eq!(effects.status, "SUCCESS");
488-
assert_eq!(errors, Some(&serde_json::Value::Null));
489469

490470
// Verify unchanged consensus objects are returned
491471
let consensus_objects = effects.unchanged_consensus_objects.unwrap();
@@ -550,7 +530,6 @@ async fn test_execute_transaction_object_changes_input_output() {
550530
}
551531
}
552532
}
553-
errors
554533
}
555534
}
556535
"#,
@@ -672,7 +651,6 @@ async fn test_execute_transaction_effects_json() {
672651
effectsJson
673652
balanceChangesJson
674653
}
675-
errors
676654
}
677655
}
678656
"#,
@@ -729,7 +707,6 @@ async fn test_execute_transaction_payload_bypasses_query_limit() {
729707
mutation($txData: Base64!, $sigs: [Base64!]!) {
730708
executeTransaction(transactionDataBcs: $txData, signatures: $sigs) {
731709
effects { status }
732-
errors
733710
}
734711
}
735712
"#,
@@ -753,10 +730,6 @@ async fn test_execute_transaction_payload_bypasses_query_limit() {
753730
.is_some(),
754731
"Expected executeTransaction status to be populated"
755732
);
756-
assert_eq!(
757-
result.pointer("/data/executeTransaction/errors"),
758-
Some(&serde_json::Value::Null)
759-
);
760733
}
761734

762735
#[sim_test]
@@ -785,7 +758,6 @@ async fn test_execute_transaction_transaction_json() {
785758
transactionJson
786759
}
787760
}
788-
errors
789761
}
790762
}
791763
"#,

crates/sui-indexer-alt-e2e-tests/tests/graphql_simulate_transaction_tests.rs

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ enum ArgumentKind {
8989
struct SimulationResult {
9090
effects: Option<TransactionEffects>,
9191
outputs: Option<Vec<CommandResult>>,
92-
error: Option<String>,
9392
}
9493

9594
// Reuse TransactionEffects from execute_transaction tests
@@ -270,7 +269,6 @@ async fn test_simulate_transaction_basic() {
270269
}
271270
}
272271
}
273-
error
274272
}
275273
}
276274
"#,
@@ -292,7 +290,6 @@ async fn test_simulate_transaction_basic() {
292290
// Verify simulation was successful
293291
let effects = simulation_result.effects.unwrap();
294292
assert_eq!(effects.status, "SUCCESS");
295-
assert!(simulation_result.error.is_none());
296293

297294
// Verify transaction data matches original
298295
let transaction = effects.transaction.unwrap();
@@ -349,7 +346,6 @@ async fn test_simulate_transaction_with_events() {
349346
}
350347
}
351348
}
352-
error
353349
}
354350
}
355351
"#,
@@ -395,8 +391,7 @@ async fn test_simulate_transaction_with_events() {
395391
}
396392
]
397393
}
398-
},
399-
"error": null
394+
}
400395
}
401396
"#);
402397
}
@@ -413,7 +408,6 @@ async fn test_simulate_transaction_input_validation() {
413408
query($txData: JSON!) {
414409
simulateTransaction(transaction: $txData) {
415410
effects { digest }
416-
error
417411
}
418412
}
419413
"#,
@@ -479,7 +473,6 @@ async fn test_simulate_transaction_object_changes() {
479473
}
480474
}
481475
}
482-
error
483476
}
484477
}
485478
"#,
@@ -844,7 +837,6 @@ async fn test_simulate_transaction_json_transfer() {
844837
}
845838
}
846839
}
847-
error
848840
}
849841
}
850842
"#,
@@ -862,7 +854,6 @@ async fn test_simulate_transaction_json_transfer() {
862854
// Verify simulation was successful
863855
let effects = simulation_result.effects.unwrap();
864856
assert_eq!(effects.status, "SUCCESS");
865-
assert!(simulation_result.error.is_none());
866857

867858
// Verify transaction data matches original
868859
let transaction = effects.transaction.unwrap();
@@ -1020,7 +1011,6 @@ async fn test_simulate_transaction_balance_changes() {
10201011
}
10211012
}
10221013
}
1023-
error
10241014
}
10251015
}
10261016
"#,
@@ -1122,7 +1112,6 @@ async fn test_simulate_transaction_with_gas_selection() {
11221112
transactionBcs
11231113
}
11241114
}
1125-
error
11261115
}
11271116
}
11281117
"#,
@@ -1155,7 +1144,6 @@ async fn test_simulate_transaction_with_gas_selection() {
11551144
mutation($txData: Base64!, $sigs: [Base64!]!) {
11561145
executeTransaction(transactionDataBcs: $txData, signatures: $sigs) {
11571146
effects { status }
1158-
errors
11591147
}
11601148
}
11611149
"#,
@@ -1171,10 +1159,6 @@ async fn test_simulate_transaction_with_gas_selection() {
11711159
execute_result.pointer("/data/executeTransaction/effects/status"),
11721160
Some(&json!("SUCCESS"))
11731161
);
1174-
assert_eq!(
1175-
execute_result.pointer("/data/executeTransaction/errors"),
1176-
Some(&serde_json::Value::Null)
1177-
);
11781162
}
11791163

11801164
#[tokio::test]
@@ -1199,7 +1183,6 @@ async fn test_simulate_transaction_effects_json() {
11991183
effectsJson
12001184
balanceChangesJson
12011185
}
1202-
error
12031186
}
12041187
}
12051188
"#,
@@ -1258,7 +1241,6 @@ async fn test_simulate_transaction_payload_bypasses_query_limit() {
12581241
query($txData: JSON!) {
12591242
simulateTransaction(transaction: $txData) {
12601243
effects { status }
1261-
error
12621244
}
12631245
}
12641246
"#,
@@ -1277,10 +1259,6 @@ async fn test_simulate_transaction_payload_bypasses_query_limit() {
12771259
result.pointer("/data/simulateTransaction/effects/status"),
12781260
Some(&json!("SUCCESS"))
12791261
);
1280-
assert_eq!(
1281-
result.pointer("/data/simulateTransaction/error"),
1282-
Some(&serde_json::Value::Null)
1283-
);
12841262
}
12851263

12861264
#[tokio::test]
@@ -1306,7 +1284,6 @@ async fn test_simulate_transaction_transaction_json() {
13061284
transactionJson
13071285
}
13081286
}
1309-
error
13101287
}
13111288
}
13121289
"#,

crates/sui-indexer-alt-e2e-tests/tests/snapshots/graphql_execute_transaction_tests__execute_transaction_effects_json.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,5 @@ expression: "result.pointer(\"/data/executeTransaction\")"
8888
"amount": "1000000"
8989
}
9090
]
91-
},
92-
"errors": null
91+
}
9392
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
source: crates/sui-indexer-alt-e2e-tests/tests/graphql_execute_transaction_tests.rs
3+
expression: "&result"
4+
---
5+
{
6+
"data": null,
7+
"errors": [
8+
{
9+
"message": "Invalid argument: Invalid user signature: Signature is not valid: Fail to verify user sig Invalid signature was given to the function",
10+
"locations": [
11+
{
12+
"line": 3,
13+
"column": 17
14+
}
15+
],
16+
"path": [
17+
"executeTransaction"
18+
],
19+
"extensions": {
20+
"code": "BAD_USER_INPUT"
21+
}
22+
}
23+
]
24+
}

crates/sui-indexer-alt-e2e-tests/tests/snapshots/graphql_execute_transaction_tests__execute_transaction_transaction_json.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,5 @@ expression: "result.pointer(\"/data/executeTransaction\")"
7171
}
7272
}
7373
}
74-
},
75-
"errors": null
74+
}
7675
}

crates/sui-indexer-alt-e2e-tests/tests/snapshots/graphql_simulate_transaction_tests__simulate_transaction_effects_json.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,5 @@ expression: "result.pointer(\"/data/simulateTransaction\")"
8888
"amount": "1000000"
8989
}
9090
]
91-
},
92-
"error": null
91+
}
9392
}

crates/sui-indexer-alt-e2e-tests/tests/snapshots/graphql_simulate_transaction_tests__simulate_transaction_transaction_json.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,5 @@ expression: "result.pointer(\"/data/simulateTransaction\")"
7171
}
7272
}
7373
}
74-
},
75-
"error": null
74+
}
7675
}

0 commit comments

Comments
 (0)