Skip to content

Commit

Permalink
grpc: introduce FieldMasks for partial responses
Browse files Browse the repository at this point in the history
Instead of defining custom "options" types for each endpoint to control
the amount of data being returned, leverage the standard
google.protobuf.FieldMask type and inspiration from
https://google.aip.dev/157 in order to provide users fine-grained
control over what fields are returned.

Initially the provided field masks will support parity with the existing
options and in the future provided field masks may support more
fine-grained control over nested fields.
  • Loading branch information
bmwill committed Feb 12, 2025
1 parent 9cd0e7e commit 6886e5f
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 79 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/sui-e2e-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ shared-crypto.workspace = true
sui-sdk-types.workspace = true
sui-sdk-transaction-builder.workspace = true
tonic.workspace = true
prost-types.workspace = true

passkey-types.workspace = true
passkey-client.workspace = true
Expand Down
2 changes: 2 additions & 0 deletions crates/sui-e2e-tests/tests/rpc/checkpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ async fn get_checkpoint() {
sequence_number: Some(sequence_number.unwrap()),
digest: Some(digest.clone().unwrap()),
options: None,
read_mask: None,
})
.await
.unwrap_err();
Expand Down Expand Up @@ -401,6 +402,7 @@ async fn get_full_checkpoint() {
sequence_number: Some(sequence_number.unwrap()),
digest: Some(digest.clone().unwrap()),
options: None,
read_mask: None,
})
.await
.unwrap_err();
Expand Down
11 changes: 9 additions & 2 deletions crates/sui-e2e-tests/tests/rpc/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use prost_types::FieldMask;
use shared_crypto::intent::Intent;
use sui_keys::keystore::AccountKeystore;
use sui_macros::sim_test;
Expand All @@ -20,10 +21,16 @@ fn build_resolve_request(
transaction: &unresolved::Transaction,
simulate: bool,
) -> ResolveTransactionRequest {
let read_mask = if simulate {
Some(FieldMask {
paths: vec!["simulation".to_string()],
})
} else {
None
};
ResolveTransactionRequest {
unresolved_transaction: Some(serde_json::to_string(transaction).unwrap()),
simulate: Some(simulate),
simulate_options: None,
read_mask,
}
}

Expand Down
42 changes: 28 additions & 14 deletions crates/sui-rpc-api/proto/sui/node/v2/node_service.proto
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
// The sui.node.v2 package contains API definitions for services that are
// expected to run on Full nodes.
// expected to run on Fullnodes.
syntax = "proto3";

package sui.node.v2;

import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "sui/types/types.proto";

//
// RPC Node interface
//

// Service for reading data from a Sui Full node.
// Service for reading data from a Sui Fullnode.
service NodeService {
// Query a node for information about its current state.
rpc GetNodeInfo(GetNodeInfoRequest) returns (GetNodeInfoResponse);
Expand Down Expand Up @@ -138,12 +139,14 @@ message GetTransactionRequest {
// Required. The digest of the requested transaction.
optional sui.types.Digest digest = 1;

// Optional. Options for specifying which parts of the `GetTransactionResponse`
// should be returned.
// DEPRECATED To be removed in the next release
optional GetTransactionOptions options = 3;
// Optional. Mask for specifying which parts of the `GetTransactionResponse`
// should be returned.
optional google.protobuf.FieldMask read_mask = 4;
}

// Options for which parts of the `GetTransactionResponse` should be returned.
// DEPRECATED To be removed in the next release
message GetTransactionOptions {
// Include the `sui.types.Transaction` message in the response.
//
Expand Down Expand Up @@ -239,10 +242,14 @@ message GetObjectRequest {
// the object is returned.
optional uint64 version = 2;

// Optional. Options for specifying which parts of the `GetObjectResponse` should be returned.
// DEPRECATED To be removed in the next release
optional GetObjectOptions options = 3;
// Optional. Mask for specifying which parts of the `GetObjectResponse`
// should be returned.
optional google.protobuf.FieldMask read_mask = 4;
}

// DEPRECATED To be removed in the next release
message GetObjectOptions {
// Include the `sui.types.Object` message in the response.
//
Expand Down Expand Up @@ -287,12 +294,14 @@ message GetCheckpointRequest {
// Optional. The digest of the requested checkpoint.
optional sui.types.Digest digest = 2;

// Optional. Options for specifying which parts of the `GetCheckpointResponse`
// should be returned.
// DEPRECATED To be removed in the next release
optional GetCheckpointOptions options = 3;
// Optional. Mask for specifying which parts of the `GetCheckpointResponse`
// should be returned.
optional google.protobuf.FieldMask read_mask = 4;
}

// Options for which parts of the `GetCheckpointResponse` should be returned.
// DEPRECATED To be removed in the next release
message GetCheckpointOptions {
// Include the `sui.types.CheckpointSummary` in the response.
//
Expand Down Expand Up @@ -361,12 +370,14 @@ message GetFullCheckpointRequest {
// Optional. The digest of the requested checkpoint.
optional sui.types.Digest digest = 2;

// Optional. Options for specifying which parts of the
// `GetFullCheckpointResponse` should be returned.
// DEPRECATED To be removed in the next release
optional GetFullCheckpointOptions options = 3;
// Optional. Mask for specifying which parts of the `GetFullCheckpointResponse`
// should be returned.
optional google.protobuf.FieldMask read_mask = 4;
}

// Options for which parts of the `GetFullCheckpointResponse` should be returned.
// DEPRECATED To be removed in the next release
message GetFullCheckpointOptions {
// Include the `sui.types.CheckpointSummary` in the response.
//
Expand Down Expand Up @@ -566,11 +577,14 @@ message ExecuteTransactionRequest {
// transaction, encoded as bytes.
repeated bytes signatures_bytes = 4;

// Optional. Options for specifying which parts of the
// `ExecuteTransactionResponse` should be returned.
// DEPRECATED To be removed in the next release
optional ExecuteTransactionOptions options = 5;
// Optional. Mask for specifying which parts of the
// `ExecuteTransactionResponse` should be returned.
optional google.protobuf.FieldMask read_mask = 6;
}

// DEPRECATED To be removed in the next release
message ExecuteTransactionOptions {
// Include the `sui.types.TransactionEffects` message in the response.
//
Expand Down
13 changes: 3 additions & 10 deletions crates/sui-rpc-api/proto/sui/node/v2alpha/node_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ syntax = "proto3";

package sui.node.v2alpha;

import "google/protobuf/field_mask.proto";
import "sui/node/v2/node_service.proto";
import "sui/types/types.proto";

Expand Down Expand Up @@ -160,14 +161,7 @@ message GetGasInfoResponse {

message SimulateTransactionRequest {
optional sui.types.Bcs transaction_bcs = 2;
optional SimulateTransactionOptions options = 3;
}

message SimulateTransactionOptions {
// Include the `BalanceChange`s in the response.
//
// Defaults to `false` if not included.
optional bool balance_changes = 8;
optional google.protobuf.FieldMask read_mask = 3;
}

message SimulateTransactionResponse {
Expand All @@ -180,8 +174,7 @@ message ResolveTransactionRequest {
// TODO FIX TYPE
// Json unresolved transaction type
optional string unresolved_transaction = 1;
optional bool simulate = 2;
optional SimulateTransactionOptions simulate_options = 3;
optional google.protobuf.FieldMask read_mask = 3;
}

message ResolveTransactionResponse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ syntax = "proto3";

package sui.node.v2alpha;

import "google/protobuf/field_mask.proto";
import "sui/node/v2/node_service.proto";

// Service for subscribing to data from a Sui Fullnode
Expand All @@ -21,16 +22,16 @@ service SubscriptionService {
// event the subscription terminates (either by the client/server or by the
// connection breaking), clients will be able to reinitailize a subscription
// and then leverage other APIs (e.g.
// sui.node.v1.NodeService.GetFullCheckpoint) in order to request data for
// sui.node.v2.NodeService.GetFullCheckpoint) in order to request data for
// the checkpoints they missed.
rpc SubscribeCheckpoints(SubscribeCheckpointsRequest) returns (stream SubscribeCheckpointsResponse);
}

// Request message for SubscriptionService.SubscribeCheckpoints
message SubscribeCheckpointsRequest {
// Optional. Options for specifiying which parts of the
// Optional. Mask for specifiying which parts of the
// SubscribeCheckpointsResponse should be returned.
optional sui.node.v2.GetFullCheckpointOptions options = 1;
optional google.protobuf.FieldMask read_mask = 3;
}

// Response message for SubscriptionService.SubscribeCheckpoints
Expand Down
4 changes: 4 additions & 0 deletions crates/sui-rpc-api/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ impl Client {
contents: Some(false),
contents_bcs: Some(false),
}),
read_mask: None,
};

let (
Expand Down Expand Up @@ -143,6 +144,7 @@ impl Client {
object: Some(false),
object_bcs: Some(true),
}),
read_mask: None,
};

let (metadata, response, _extentions) = self
Expand Down Expand Up @@ -181,6 +183,7 @@ impl Client {
object: Some(false),
object_bcs: Some(true),
}),
read_mask: None,
};

let (metadata, GetObjectResponse { object_bcs, .. }, _extentions) =
Expand Down Expand Up @@ -217,6 +220,7 @@ impl Client {
events_bcs: Some(true),
..(parameters.to_owned().into())
}),
read_mask: None,
};

let (metadata, response, _extentions) = self
Expand Down
39 changes: 21 additions & 18 deletions crates/sui-rpc-api/src/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,10 @@ impl crate::proto::node::v2alpha::subscription_service_server::SubscriptionServi

async fn subscribe_checkpoints(
&self,
request: tonic::Request<crate::proto::node::v2alpha::SubscribeCheckpointsRequest>,
_request: tonic::Request<crate::proto::node::v2alpha::SubscribeCheckpointsRequest>,
) -> Result<tonic::Response<Self::SubscribeCheckpointsStream>, tonic::Status> {
let options = request.into_inner().options.unwrap_or_default();
// TODO use provided read_mask
let options = crate::proto::node::v2::GetFullCheckpointOptions::default();

let Some(mut receiver) = self.register_subscription().await else {
return Err(tonic::Status::unavailable(
Expand Down Expand Up @@ -466,11 +467,9 @@ impl crate::proto::node::v2alpha::node_service_server::NodeService for crate::Rp
tonic::Status,
> {
let request = request.into_inner();
//TODO use provided read_mask
let parameters = crate::types::SimulateTransactionQueryParameters {
balance_changes: request
.options
.and_then(|options| options.balance_changes)
.unwrap_or(false),
balance_changes: false,
input_objects: false,
output_objects: false,
};
Expand Down Expand Up @@ -511,25 +510,29 @@ impl crate::proto::node::v2alpha::node_service_server::NodeService for crate::Rp
tonic::Status,
> {
let request = request.into_inner();
let read_mask = request.read_mask.unwrap_or_default();
//TODO use provided read_mask
let simulate_parameters = crate::types::SimulateTransactionQueryParameters {
balance_changes: request
.simulate_options
.and_then(|options| options.balance_changes)
.unwrap_or(false),
balance_changes: false,
input_objects: false,
output_objects: false,
};
let parameters = crate::types::ResolveTransactionQueryParameters {
simulate: request.simulate.unwrap_or(false),
simulate: read_mask
.paths
.iter()
.any(|path| path.starts_with("simulation")),
simulate_transaction_parameters: simulate_parameters,
};
let unresolved_transaction = serde_json::from_str(request.unresolved_transaction())
.map_err(|_| {
tonic::Status::new(
tonic::Code::InvalidArgument,
"invalid unresolved_transaction",
)
})?;
let unresolved_transaction = serde_json::from_str(
&request.unresolved_transaction.unwrap_or_default(),
)
.map_err(|_| {
tonic::Status::new(
tonic::Code::InvalidArgument,
"invalid unresolved_transaction",
)
})?;

let response = self.resolve_transaction(parameters, unresolved_transaction)?;

Expand Down
Binary file modified crates/sui-rpc-api/src/proto/generated/sui.node.v2.fds.bin
Binary file not shown.
Loading

0 comments on commit 6886e5f

Please sign in to comment.