From bc7d229a17f04bce2164ad8f0e668ab05385d48a Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Wed, 20 Nov 2024 15:08:32 -0800 Subject: [PATCH 01/28] chore: update sui-sdk-types --- Cargo.lock | 2 +- Cargo.toml | 2 +- crates/sui-e2e-tests/tests/rest/resolve.rs | 52 ++- crates/sui-rest-api/openapi/openapi.json | 36 +- crates/sui-rest-api/src/client/sdk.rs | 2 +- .../src/transactions/resolve/literal.rs | 310 ++++++++---------- .../src/transactions/resolve/mod.rs | 63 ++-- 7 files changed, 207 insertions(+), 260 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8d3a59dc2da0..d48e3310c8266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15289,7 +15289,7 @@ dependencies = [ [[package]] name = "sui-sdk-types" version = "0.0.1" -source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=31bd9da32a8057edc45da8f5e6a8f25b83919b93#31bd9da32a8057edc45da8f5e6a8f25b83919b93" +source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=24c34933c421319e9aa1c48b3b7108c756e1422f#24c34933c421319e9aa1c48b3b7108c756e1422f" dependencies = [ "base64ct", "bcs", diff --git a/Cargo.toml b/Cargo.toml index 9962f7cd9ea9b..8c4c87ad986b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -605,7 +605,7 @@ anemo-tower = { git = "https://github.com/mystenlabs/anemo.git", rev = "e609f769 # core-types with json format for REST api # sui-sdk-types = { version = "0.0.1", features = ["hash", "serde", "schemars"] } -sui-sdk-types = { git = "https://github.com/MystenLabs/sui-rust-sdk.git", rev = "31bd9da32a8057edc45da8f5e6a8f25b83919b93", features = ["hash", "serde", "schemars"] } +sui-sdk-types = { git = "https://github.com/MystenLabs/sui-rust-sdk.git", rev = "24c34933c421319e9aa1c48b3b7108c756e1422f", features = ["hash", "serde", "schemars"] } ### Workspace Members ### anemo-benchmark = { path = "crates/anemo-benchmark" } diff --git a/crates/sui-e2e-tests/tests/rest/resolve.rs b/crates/sui-e2e-tests/tests/rest/resolve.rs index 482b022e52a6e..5ad8b6d7e7ec5 100644 --- a/crates/sui-e2e-tests/tests/rest/resolve.rs +++ b/crates/sui-e2e-tests/tests/rest/resolve.rs @@ -8,14 +8,10 @@ use sui_rest_api::client::reqwest::StatusCode; use sui_rest_api::transactions::ResolveTransactionQueryParameters; use sui_rest_api::Client; use sui_rest_api::ExecuteTransactionQueryParameters; +use sui_sdk_types::types::unresolved; use sui_sdk_types::types::Argument; use sui_sdk_types::types::Command; use sui_sdk_types::types::TransactionExpiration; -use sui_sdk_types::types::UnresolvedGasPayment; -use sui_sdk_types::types::UnresolvedInputArgument; -use sui_sdk_types::types::UnresolvedProgrammableTransaction; -use sui_sdk_types::types::UnresolvedTransaction; -use sui_sdk_types::types::UnresolvedValue; use sui_types::base_types::SuiAddress; use sui_types::effects::TransactionEffectsAPI; use test_cluster::TestClusterBuilder; @@ -31,15 +27,15 @@ async fn resolve_transaction_simple_transfer() { gas.sort_by_key(|object_ref| object_ref.0); let obj_to_send = gas.first().unwrap().0; - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { + let unresolved_transaction = unresolved::Transaction { + ptb: unresolved::ProgrammableTransaction { inputs: vec![ - UnresolvedInputArgument { + unresolved::Input { object_id: Some(obj_to_send.into()), ..Default::default() }, - UnresolvedInputArgument { - value: Some(UnresolvedValue::String(recipient.to_string())), + unresolved::Input { + value: Some(unresolved::Value::String(recipient.to_string())), ..Default::default() }, ], @@ -98,15 +94,15 @@ async fn resolve_transaction_transfer_with_sponsor() { let obj_to_send = gas.first().unwrap().0; let sponsor = test_cluster.wallet.get_addresses()[1]; - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { + let unresolved_transaction = unresolved::Transaction { + ptb: unresolved::ProgrammableTransaction { inputs: vec![ - UnresolvedInputArgument { + unresolved::Input { object_id: Some(obj_to_send.into()), ..Default::default() }, - UnresolvedInputArgument { - value: Some(UnresolvedValue::String(recipient.to_string())), + unresolved::Input { + value: Some(unresolved::Value::String(recipient.to_string())), ..Default::default() }, ], @@ -118,7 +114,7 @@ async fn resolve_transaction_transfer_with_sponsor() { )], }, sender: sender.into(), - gas_payment: Some(UnresolvedGasPayment { + gas_payment: Some(unresolved::GasPayment { objects: vec![], owner: sponsor.into(), price: None, @@ -182,9 +178,9 @@ async fn resolve_transaction_borrowed_shared_object() { let sender = test_cluster.wallet.get_addresses()[0]; - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { - inputs: vec![UnresolvedInputArgument { + let unresolved_transaction = unresolved::Transaction { + ptb: unresolved::ProgrammableTransaction { + inputs: vec![unresolved::Input { object_id: Some("0x6".parse().unwrap()), ..Default::default() }], @@ -249,19 +245,19 @@ async fn resolve_transaction_mutable_shared_object() { .unwrap() .address; - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { + let unresolved_transaction = unresolved::Transaction { + ptb: unresolved::ProgrammableTransaction { inputs: vec![ - UnresolvedInputArgument { + unresolved::Input { object_id: Some("0x5".parse().unwrap()), ..Default::default() }, - UnresolvedInputArgument { + unresolved::Input { object_id: Some(obj_to_stake.into()), ..Default::default() }, - UnresolvedInputArgument { - value: Some(UnresolvedValue::String(validator_address.to_string())), + unresolved::Input { + value: Some(unresolved::Value::String(validator_address.to_string())), ..Default::default() }, ], @@ -316,9 +312,9 @@ async fn resolve_transaction_insufficient_gas() { let client = Client::new(test_cluster.rpc_url()); // Test the case where we don't have enough coins/gas for the required budget - let unresolved_transaction = UnresolvedTransaction { - ptb: UnresolvedProgrammableTransaction { - inputs: vec![UnresolvedInputArgument { + let unresolved_transaction = unresolved::Transaction { + ptb: unresolved::ProgrammableTransaction { + inputs: vec![unresolved::Input { object_id: Some("0x6".parse().unwrap()), ..Default::default() }], diff --git a/crates/sui-rest-api/openapi/openapi.json b/crates/sui-rest-api/openapi/openapi.json index c1f4484b1ca4e..3aa3badcc70b6 100644 --- a/crates/sui-rest-api/openapi/openapi.json +++ b/crates/sui-rest-api/openapi/openapi.json @@ -2259,12 +2259,12 @@ { "type": "object", "required": [ - "authenticator_obj_initial_shared_version", + "authenticator_object_initial_shared_version", "kind", "min_epoch" ], "properties": { - "authenticator_obj_initial_shared_version": { + "authenticator_object_initial_shared_version": { "description": "The initial version of the authenticator object that it was shared at.", "type": "string", "format": "u64" @@ -3207,7 +3207,7 @@ "type": "string", "pattern": "(?:[a-zA-Z][a-zA-Z0-9_]{0,127})|(?:_[a-zA-Z0-9_]{0,127})" }, - "InputArgument": { + "Input": { "oneOf": [ { "type": "object", @@ -4911,7 +4911,7 @@ "description": "Input objects or primitive values", "type": "array", "items": { - "$ref": "#/components/schemas/InputArgument" + "$ref": "#/components/schemas/Input" } }, "kind": { @@ -5506,40 +5506,50 @@ } } }, - "UnresolvedInputArgument": { + "UnresolvedInput": { + "description": "A potentially unresolved transaction input. Note that one can construct a fully resolved input using the provided constructors, but this struct is also useful when the input data is not complete.\n\nIf used in the context of transaction builder, make sure to call `tx.resolve` function on the transaction builder to resolve all unresolved inputs.", "type": "object", "properties": { "digest": { - "$ref": "#/components/schemas/ObjectDigest" + "description": "The digest of this object. This field is only relevant for owned/immutable/receiving inputs.", + "allOf": [ + { + "$ref": "#/components/schemas/ObjectDigest" + } + ] }, "kind": { - "$ref": "#/components/schemas/UnresolvedInputArgumentKind" + "$ref": "#/components/schemas/UnresolvedInputKind" }, "mutable": { + "description": "Whether this object is mutable. This field is only relevant for shared objects.", "type": "boolean" }, "object_id": { - "$ref": "#/components/schemas/ObjectId" + "description": "Unique identifier for this object.", + "allOf": [ + { + "$ref": "#/components/schemas/ObjectId" + } + ] }, "value": { "$ref": "#/components/schemas/UnresolvedValue" }, "version": { - "description": "Either the `initial_shared_version` if object is a shared object, or the `version` if this is an owned object", + "description": "Either the `initial_shared_version` if object is a shared object, or the `version` if this is an owned object. The semantics of version can change depending on whether the object is shared or not. For shared objects, this is the initial version the object was shared at. For all other objects, this is the version of the object.", "type": "string", "format": "u64" } } }, - "UnresolvedInputArgumentKind": { + "UnresolvedInputKind": { "type": "string", "enum": [ "pure", "shared", "receiving", "immutable_or_owned", - "immutable", - "owned", "literal" ] }, @@ -5586,7 +5596,7 @@ "inputs": { "type": "array", "items": { - "$ref": "#/components/schemas/UnresolvedInputArgument" + "$ref": "#/components/schemas/UnresolvedInput" } }, "sender": { diff --git a/crates/sui-rest-api/src/client/sdk.rs b/crates/sui-rest-api/src/client/sdk.rs index 76d6227f0215f..c249e4f34fa41 100644 --- a/crates/sui-rest-api/src/client/sdk.rs +++ b/crates/sui-rest-api/src/client/sdk.rs @@ -4,6 +4,7 @@ use reqwest::header::HeaderValue; use reqwest::StatusCode; use reqwest::Url; +use sui_sdk_types::types::unresolved::Transaction as UnresolvedTransaction; use sui_sdk_types::types::Address; use sui_sdk_types::types::CheckpointData; use sui_sdk_types::types::CheckpointDigest; @@ -16,7 +17,6 @@ use sui_sdk_types::types::SignedTransaction; use sui_sdk_types::types::StructTag; use sui_sdk_types::types::Transaction; use sui_sdk_types::types::TransactionDigest; -use sui_sdk_types::types::UnresolvedTransaction; use sui_sdk_types::types::ValidatorCommittee; use sui_sdk_types::types::Version; use tap::Pipe; diff --git a/crates/sui-rest-api/src/transactions/resolve/literal.rs b/crates/sui-rest-api/src/transactions/resolve/literal.rs index 6b25013faae3a..156dac7c16817 100644 --- a/crates/sui-rest-api/src/transactions/resolve/literal.rs +++ b/crates/sui-rest-api/src/transactions/resolve/literal.rs @@ -7,9 +7,9 @@ use super::NormalizedPackage; use crate::RestError; use crate::Result; use move_binary_format::normalized::Type; +use sui_sdk_types::types::unresolved::Value; use sui_sdk_types::types::Command; use sui_sdk_types::types::ObjectId; -use sui_sdk_types::types::UnresolvedValue; use sui_types::base_types::ObjectID; use sui_types::base_types::STD_ASCII_MODULE_NAME; use sui_types::base_types::STD_ASCII_STRUCT_NAME; @@ -23,7 +23,7 @@ pub(super) fn resolve_literal( called_packages: &HashMap, commands: &[Command], arg_idx: usize, - value: UnresolvedValue, + value: Value, ) -> Result> { let literal_type = determine_literal_type(called_packages, commands, arg_idx)?; @@ -116,7 +116,7 @@ fn determine_literal_type( }) } -fn resolve_literal_to_type(buf: &mut Vec, type_: &Type, value: &UnresolvedValue) -> Result<()> { +fn resolve_literal_to_type(buf: &mut Vec, type_: &Type, value: &Value) -> Result<()> { match type_ { Type::Bool => resolve_as_bool(buf, value), Type::U8 => resolve_as_number::(buf, value), @@ -177,16 +177,16 @@ fn resolve_literal_to_type(buf: &mut Vec, type_: &Type, value: &UnresolvedVa } } -fn resolve_as_bool(buf: &mut Vec, value: &UnresolvedValue) -> Result<()> { +fn resolve_as_bool(buf: &mut Vec, value: &Value) -> Result<()> { let b: bool = match value { - UnresolvedValue::Bool(b) => *b, - UnresolvedValue::String(s) => s.parse().map_err(|e| { + Value::Bool(b) => *b, + Value::String(s) => s.parse().map_err(|e| { RestError::new( axum::http::StatusCode::BAD_REQUEST, format!("literal cannot be resolved as bool: {e}"), ) })?, - UnresolvedValue::Null | UnresolvedValue::Number(_) | UnresolvedValue::Array(_) => { + Value::Null | Value::Number(_) | Value::Array(_) => { return Err(RestError::new( axum::http::StatusCode::BAD_REQUEST, "literal cannot be resolved into type bool", @@ -199,14 +199,14 @@ fn resolve_as_bool(buf: &mut Vec, value: &UnresolvedValue) -> Result<()> { Ok(()) } -fn resolve_as_number(buf: &mut Vec, value: &UnresolvedValue) -> Result<()> +fn resolve_as_number(buf: &mut Vec, value: &Value) -> Result<()> where T: std::str::FromStr + TryFrom + serde::Serialize, ::Err: std::fmt::Display, >::Error: std::fmt::Display, { let n: T = match value { - UnresolvedValue::Number(n) => T::try_from(*n).map_err(|e| { + Value::Number(n) => T::try_from(*n).map_err(|e| { RestError::new( axum::http::StatusCode::BAD_REQUEST, format!( @@ -216,7 +216,7 @@ where ) })?, - UnresolvedValue::String(s) => s.parse().map_err(|e| { + Value::String(s) => s.parse().map_err(|e| { RestError::new( axum::http::StatusCode::BAD_REQUEST, format!( @@ -226,7 +226,7 @@ where ) })?, - UnresolvedValue::Null | UnresolvedValue::Bool(_) | UnresolvedValue::Array(_) => { + Value::Null | Value::Bool(_) | Value::Array(_) => { return Err(RestError::new( axum::http::StatusCode::BAD_REQUEST, format!( @@ -242,19 +242,16 @@ where Ok(()) } -fn resolve_as_address(buf: &mut Vec, value: &UnresolvedValue) -> Result<()> { +fn resolve_as_address(buf: &mut Vec, value: &Value) -> Result<()> { let address = match value { // parse as ObjectID to handle the case where 0x is present or missing - UnresolvedValue::String(s) => s.parse::().map_err(|e| { + Value::String(s) => s.parse::().map_err(|e| { RestError::new( axum::http::StatusCode::BAD_REQUEST, format!("literal cannot be resolved as bool: {e}"), ) })?, - UnresolvedValue::Null - | UnresolvedValue::Bool(_) - | UnresolvedValue::Number(_) - | UnresolvedValue::Array(_) => { + Value::Null | Value::Bool(_) | Value::Number(_) | Value::Array(_) => { return Err(RestError::new( axum::http::StatusCode::BAD_REQUEST, "literal cannot be resolved into type address", @@ -267,15 +264,12 @@ fn resolve_as_address(buf: &mut Vec, value: &UnresolvedValue) -> Result<()> Ok(()) } -fn resolve_as_string(buf: &mut Vec, value: &UnresolvedValue) -> Result<()> { +fn resolve_as_string(buf: &mut Vec, value: &Value) -> Result<()> { match value { - UnresolvedValue::String(s) => { + Value::String(s) => { bcs::serialize_into(buf, s)?; } - UnresolvedValue::Bool(_) - | UnresolvedValue::Null - | UnresolvedValue::Number(_) - | UnresolvedValue::Array(_) => { + Value::Bool(_) | Value::Null | Value::Number(_) | Value::Array(_) => { return Err(RestError::new( axum::http::StatusCode::BAD_REQUEST, "literal cannot be resolved into string", @@ -286,15 +280,12 @@ fn resolve_as_string(buf: &mut Vec, value: &UnresolvedValue) -> Result<()> { Ok(()) } -fn resolve_as_option(buf: &mut Vec, type_: &Type, value: &UnresolvedValue) -> Result<()> { +fn resolve_as_option(buf: &mut Vec, type_: &Type, value: &Value) -> Result<()> { match value { - UnresolvedValue::Null => { + Value::Null => { buf.push(0); } - UnresolvedValue::Bool(_) - | UnresolvedValue::Number(_) - | UnresolvedValue::String(_) - | UnresolvedValue::Array(_) => { + Value::Bool(_) | Value::Number(_) | Value::String(_) | Value::Array(_) => { buf.push(1); resolve_literal_to_type(buf, type_, value)?; } @@ -303,7 +294,7 @@ fn resolve_as_option(buf: &mut Vec, type_: &Type, value: &UnresolvedValue) - Ok(()) } -fn resolve_as_vector(buf: &mut Vec, type_: &Type, value: &UnresolvedValue) -> Result<()> { +fn resolve_as_vector(buf: &mut Vec, type_: &Type, value: &Value) -> Result<()> { fn write_u32_as_uleb128(buf: &mut Vec, mut value: u32) { while value >= 0x80 { // Write 7 (lowest) bits of data and set the 8th bit to 1. @@ -316,16 +307,13 @@ fn resolve_as_vector(buf: &mut Vec, type_: &Type, value: &UnresolvedValue) - } match value { - UnresolvedValue::Array(array) => { + Value::Array(array) => { write_u32_as_uleb128(buf, array.len() as u32); for value in array { resolve_literal_to_type(buf, type_, value)?; } } - UnresolvedValue::Bool(_) - | UnresolvedValue::Number(_) - | UnresolvedValue::String(_) - | UnresolvedValue::Null => { + Value::Bool(_) | Value::Number(_) | Value::String(_) | Value::Null => { return Err(RestError::new( axum::http::StatusCode::BAD_REQUEST, format!("literal cannot be resolved into type Vector<{type_}>"), @@ -342,7 +330,7 @@ mod test { use move_binary_format::normalized::Type; use move_core_types::{account_address::AccountAddress, u256::U256}; - fn test_resolve_literal(ty: Type, value: UnresolvedValue, expected: Option>) { + fn test_resolve_literal(ty: Type, value: Value, expected: Option>) { let mut buf = Vec::new(); match (resolve_literal_to_type(&mut buf, &ty, &value), expected) { (Ok(_), None) => { @@ -359,22 +347,14 @@ mod test { #[test] fn resolve_bool() { let test_cases = [ - (Type::Bool, UnresolvedValue::Bool(true), Some(vec![1])), - (Type::Bool, UnresolvedValue::Bool(false), Some(vec![0])), - ( - Type::Bool, - UnresolvedValue::String("true".into()), - Some(vec![1]), - ), - ( - Type::Bool, - UnresolvedValue::String("false".into()), - Some(vec![0]), - ), - (Type::Bool, UnresolvedValue::Null, None), - (Type::Bool, UnresolvedValue::Number(0), None), - (Type::Bool, UnresolvedValue::Array(vec![]), None), - (Type::Bool, UnresolvedValue::String("foo".into()), None), + (Type::Bool, Value::Bool(true), Some(vec![1])), + (Type::Bool, Value::Bool(false), Some(vec![0])), + (Type::Bool, Value::String("true".into()), Some(vec![1])), + (Type::Bool, Value::String("false".into()), Some(vec![0])), + (Type::Bool, Value::Null, None), + (Type::Bool, Value::Number(0), None), + (Type::Bool, Value::Array(vec![]), None), + (Type::Bool, Value::String("foo".into()), None), ]; for (ty, value, expected) in test_cases { @@ -388,187 +368,171 @@ mod test { // U8 Successful cases ( Type::U8, - UnresolvedValue::Number(u8::MAX.into()), + Value::Number(u8::MAX.into()), Some(bcs::to_bytes(&u8::MAX).unwrap()), ), ( Type::U8, - UnresolvedValue::Number(u8::MIN.into()), + Value::Number(u8::MIN.into()), Some(bcs::to_bytes(&u8::MIN).unwrap()), ), ( Type::U8, - UnresolvedValue::String(u8::MAX.to_string()), + Value::String(u8::MAX.to_string()), Some(bcs::to_bytes(&u8::MAX).unwrap()), ), ( Type::U8, - UnresolvedValue::String(u8::MIN.to_string()), + Value::String(u8::MIN.to_string()), Some(bcs::to_bytes(&u8::MIN).unwrap()), ), // U8 failure cases - (Type::U8, UnresolvedValue::Bool(true), None), - (Type::U8, UnresolvedValue::Array(vec![]), None), - (Type::U8, UnresolvedValue::Null, None), - (Type::U8, UnresolvedValue::String("foo".into()), None), - ( - Type::U8, - UnresolvedValue::String(u64::MAX.to_string()), - None, - ), - (Type::U8, UnresolvedValue::Number(u64::MAX), None), + (Type::U8, Value::Bool(true), None), + (Type::U8, Value::Array(vec![]), None), + (Type::U8, Value::Null, None), + (Type::U8, Value::String("foo".into()), None), + (Type::U8, Value::String(u64::MAX.to_string()), None), + (Type::U8, Value::Number(u64::MAX), None), // U16 Successful cases ( Type::U16, - UnresolvedValue::Number(u16::MAX.into()), + Value::Number(u16::MAX.into()), Some(bcs::to_bytes(&u16::MAX).unwrap()), ), ( Type::U16, - UnresolvedValue::Number(u16::MIN.into()), + Value::Number(u16::MIN.into()), Some(bcs::to_bytes(&u16::MIN).unwrap()), ), ( Type::U16, - UnresolvedValue::String(u16::MAX.to_string()), + Value::String(u16::MAX.to_string()), Some(bcs::to_bytes(&u16::MAX).unwrap()), ), ( Type::U16, - UnresolvedValue::String(u16::MIN.to_string()), + Value::String(u16::MIN.to_string()), Some(bcs::to_bytes(&u16::MIN).unwrap()), ), // U16 failure cases - (Type::U16, UnresolvedValue::Bool(true), None), - (Type::U16, UnresolvedValue::Array(vec![]), None), - (Type::U16, UnresolvedValue::Null, None), - (Type::U16, UnresolvedValue::String("foo".into()), None), - ( - Type::U16, - UnresolvedValue::String(u64::MAX.to_string()), - None, - ), - (Type::U16, UnresolvedValue::Number(u64::MAX), None), + (Type::U16, Value::Bool(true), None), + (Type::U16, Value::Array(vec![]), None), + (Type::U16, Value::Null, None), + (Type::U16, Value::String("foo".into()), None), + (Type::U16, Value::String(u64::MAX.to_string()), None), + (Type::U16, Value::Number(u64::MAX), None), // U32 Successful cases ( Type::U32, - UnresolvedValue::Number(u32::MAX.into()), + Value::Number(u32::MAX.into()), Some(bcs::to_bytes(&u32::MAX).unwrap()), ), ( Type::U32, - UnresolvedValue::Number(u32::MIN.into()), + Value::Number(u32::MIN.into()), Some(bcs::to_bytes(&u32::MIN).unwrap()), ), ( Type::U32, - UnresolvedValue::String(u32::MAX.to_string()), + Value::String(u32::MAX.to_string()), Some(bcs::to_bytes(&u32::MAX).unwrap()), ), ( Type::U32, - UnresolvedValue::String(u32::MIN.to_string()), + Value::String(u32::MIN.to_string()), Some(bcs::to_bytes(&u32::MIN).unwrap()), ), // U32 failure cases - (Type::U32, UnresolvedValue::Bool(true), None), - (Type::U32, UnresolvedValue::Array(vec![]), None), - (Type::U32, UnresolvedValue::Null, None), - (Type::U32, UnresolvedValue::String("foo".into()), None), - ( - Type::U32, - UnresolvedValue::String(u64::MAX.to_string()), - None, - ), - (Type::U32, UnresolvedValue::Number(u64::MAX), None), + (Type::U32, Value::Bool(true), None), + (Type::U32, Value::Array(vec![]), None), + (Type::U32, Value::Null, None), + (Type::U32, Value::String("foo".into()), None), + (Type::U32, Value::String(u64::MAX.to_string()), None), + (Type::U32, Value::Number(u64::MAX), None), // U64 Successful cases ( Type::U64, - UnresolvedValue::Number(u64::MAX), + Value::Number(u64::MAX), Some(bcs::to_bytes(&u64::MAX).unwrap()), ), ( Type::U64, - UnresolvedValue::Number(u64::MIN), + Value::Number(u64::MIN), Some(bcs::to_bytes(&u64::MIN).unwrap()), ), ( Type::U64, - UnresolvedValue::String(u64::MAX.to_string()), + Value::String(u64::MAX.to_string()), Some(bcs::to_bytes(&u64::MAX).unwrap()), ), ( Type::U64, - UnresolvedValue::String(u64::MIN.to_string()), + Value::String(u64::MIN.to_string()), Some(bcs::to_bytes(&u64::MIN).unwrap()), ), // U64 failure cases - (Type::U64, UnresolvedValue::Bool(true), None), - (Type::U64, UnresolvedValue::Array(vec![]), None), - (Type::U64, UnresolvedValue::Null, None), - (Type::U64, UnresolvedValue::String("foo".into()), None), - ( - Type::U64, - UnresolvedValue::String(u128::MAX.to_string()), - None, - ), + (Type::U64, Value::Bool(true), None), + (Type::U64, Value::Array(vec![]), None), + (Type::U64, Value::Null, None), + (Type::U64, Value::String("foo".into()), None), + (Type::U64, Value::String(u128::MAX.to_string()), None), // U128 Successful cases ( Type::U128, - UnresolvedValue::Number(u64::MAX), + Value::Number(u64::MAX), Some(bcs::to_bytes(&u128::from(u64::MAX)).unwrap()), ), ( Type::U128, - UnresolvedValue::Number(u64::MIN), + Value::Number(u64::MIN), Some(bcs::to_bytes(&u128::MIN).unwrap()), ), ( Type::U128, - UnresolvedValue::String(u128::MAX.to_string()), + Value::String(u128::MAX.to_string()), Some(bcs::to_bytes(&u128::MAX).unwrap()), ), ( Type::U128, - UnresolvedValue::String(u128::MIN.to_string()), + Value::String(u128::MIN.to_string()), Some(bcs::to_bytes(&u128::MIN).unwrap()), ), // U128 failure cases - (Type::U128, UnresolvedValue::Bool(true), None), - (Type::U128, UnresolvedValue::Array(vec![]), None), - (Type::U128, UnresolvedValue::Null, None), - (Type::U128, UnresolvedValue::String("foo".into()), None), + (Type::U128, Value::Bool(true), None), + (Type::U128, Value::Array(vec![]), None), + (Type::U128, Value::Null, None), + (Type::U128, Value::String("foo".into()), None), ( Type::U128, - UnresolvedValue::String(U256::max_value().to_string()), + Value::String(U256::max_value().to_string()), None, ), // U256 Successful cases ( Type::U256, - UnresolvedValue::Number(u64::MAX), + Value::Number(u64::MAX), Some(bcs::to_bytes(&U256::from(u64::MAX)).unwrap()), ), ( Type::U256, - UnresolvedValue::Number(u64::MIN), + Value::Number(u64::MIN), Some(bcs::to_bytes(&U256::zero()).unwrap()), ), ( Type::U256, - UnresolvedValue::String(U256::max_value().to_string()), + Value::String(U256::max_value().to_string()), Some(bcs::to_bytes(&U256::max_value()).unwrap()), ), ( Type::U256, - UnresolvedValue::String(U256::zero().to_string()), + Value::String(U256::zero().to_string()), Some(bcs::to_bytes(&U256::zero()).unwrap()), ), // U256 failure cases - (Type::U256, UnresolvedValue::Bool(true), None), - (Type::U256, UnresolvedValue::Array(vec![]), None), - (Type::U256, UnresolvedValue::Null, None), - (Type::U256, UnresolvedValue::String("foo".into()), None), + (Type::U256, Value::Bool(true), None), + (Type::U256, Value::Array(vec![]), None), + (Type::U256, Value::Null, None), + (Type::U256, Value::String("foo".into()), None), ]; for (ty, value, expected) in test_cases { @@ -583,31 +547,31 @@ mod test { ( Type::Address, // with 0x prefix - UnresolvedValue::String(AccountAddress::TWO.to_canonical_string(true)), + Value::String(AccountAddress::TWO.to_canonical_string(true)), Some(bcs::to_bytes(&AccountAddress::TWO).unwrap()), ), ( Type::Address, // without 0x prefix - UnresolvedValue::String(AccountAddress::TWO.to_canonical_string(false)), + Value::String(AccountAddress::TWO.to_canonical_string(false)), Some(bcs::to_bytes(&AccountAddress::TWO).unwrap()), ), ( Type::Address, // with 0x prefix and trimmed 0s - UnresolvedValue::String(AccountAddress::TWO.to_hex_literal()), + Value::String(AccountAddress::TWO.to_hex_literal()), Some(bcs::to_bytes(&AccountAddress::TWO).unwrap()), ), // Address failure cases - (Type::Address, UnresolvedValue::Bool(true), None), - (Type::Address, UnresolvedValue::Array(vec![]), None), - (Type::Address, UnresolvedValue::Null, None), - (Type::Address, UnresolvedValue::String("foo".into()), None), - (Type::Address, UnresolvedValue::Number(0), None), + (Type::Address, Value::Bool(true), None), + (Type::Address, Value::Array(vec![]), None), + (Type::Address, Value::Null, None), + (Type::Address, Value::String("foo".into()), None), + (Type::Address, Value::Number(0), None), ( Type::Address, // without 0x prefix and with trimmed 0s - UnresolvedValue::String(AccountAddress::TWO.short_str_lossless()), + Value::String(AccountAddress::TWO.short_str_lossless()), None, ), ]; @@ -640,33 +604,33 @@ mod test { // string Successful cases ( utf8(), - UnresolvedValue::String("foo".into()), + Value::String("foo".into()), Some(bcs::to_bytes(&"foo").unwrap()), ), ( ascii(), - UnresolvedValue::String("foo".into()), + Value::String("foo".into()), Some(bcs::to_bytes(&"foo").unwrap()), ), ( utf8(), - UnresolvedValue::String("".into()), + Value::String("".into()), Some(bcs::to_bytes(&"").unwrap()), ), ( ascii(), - UnresolvedValue::String("".into()), + Value::String("".into()), Some(bcs::to_bytes(&"").unwrap()), ), // String failure cases - (utf8(), UnresolvedValue::Bool(true), None), - (utf8(), UnresolvedValue::Array(vec![]), None), - (utf8(), UnresolvedValue::Null, None), - (utf8(), UnresolvedValue::Number(0), None), - (ascii(), UnresolvedValue::Bool(true), None), - (ascii(), UnresolvedValue::Array(vec![]), None), - (ascii(), UnresolvedValue::Null, None), - (ascii(), UnresolvedValue::Number(0), None), + (utf8(), Value::Bool(true), None), + (utf8(), Value::Array(vec![]), None), + (utf8(), Value::Null, None), + (utf8(), Value::Number(0), None), + (ascii(), Value::Bool(true), None), + (ascii(), Value::Array(vec![]), None), + (ascii(), Value::Null, None), + (ascii(), Value::Number(0), None), ]; for (ty, value, expected) in test_cases { @@ -689,36 +653,28 @@ mod test { // Option Successful cases ( option_type(Type::Address), - UnresolvedValue::String(AccountAddress::TWO.to_canonical_string(true)), + Value::String(AccountAddress::TWO.to_canonical_string(true)), Some(bcs::to_bytes(&Some(AccountAddress::TWO)).unwrap()), ), - ( - option_type(Type::Address), - UnresolvedValue::Null, - Some(vec![0]), - ), + (option_type(Type::Address), Value::Null, Some(vec![0])), ( option_type(Type::U64), - UnresolvedValue::Number(u64::MIN), + Value::Number(u64::MIN), Some(bcs::to_bytes(&Some(u64::MIN)).unwrap()), ), ( option_type(Type::U64), - UnresolvedValue::String(u64::MAX.to_string()), + Value::String(u64::MAX.to_string()), Some(bcs::to_bytes(&Some(u64::MAX)).unwrap()), ), ( option_type(Type::Bool), - UnresolvedValue::Bool(true), + Value::Bool(true), Some(bcs::to_bytes(&Some(true)).unwrap()), ), - ( - option_type(Type::Bool), - UnresolvedValue::Null, - Some(vec![0]), - ), + (option_type(Type::Bool), Value::Null, Some(vec![0])), // Option failure cases - (option_type(Type::Bool), UnresolvedValue::Number(0), None), + (option_type(Type::Bool), Value::Number(0), None), ]; for (ty, value, expected) in test_cases { @@ -736,45 +692,39 @@ mod test { // Vector Successful cases ( vector_type(Type::Address), - UnresolvedValue::Array(vec![ - UnresolvedValue::String(AccountAddress::TWO.to_canonical_string(true)), - UnresolvedValue::String(AccountAddress::ONE.to_canonical_string(true)), + Value::Array(vec![ + Value::String(AccountAddress::TWO.to_canonical_string(true)), + Value::String(AccountAddress::ONE.to_canonical_string(true)), ]), Some(bcs::to_bytes(&vec![AccountAddress::TWO, AccountAddress::ONE]).unwrap()), ), ( vector_type(Type::U8), - UnresolvedValue::Array(vec![UnresolvedValue::Number(9)]), + Value::Array(vec![Value::Number(9)]), Some(vec![1, 9]), ), - ( - vector_type(Type::U8), - UnresolvedValue::Array(vec![]), - Some(vec![0]), - ), + (vector_type(Type::U8), Value::Array(vec![]), Some(vec![0])), ( vector_type(vector_type(Type::U8)), - UnresolvedValue::Array(vec![UnresolvedValue::Array(vec![ - UnresolvedValue::Number(9), - ])]), + Value::Array(vec![Value::Array(vec![Value::Number(9)])]), Some(bcs::to_bytes(&vec![vec![9u8]]).unwrap()), ), ( vector_type(Type::Bool), // verify we handle uleb128 encoding of length properly - UnresolvedValue::Array(vec![UnresolvedValue::Bool(true); 256]), + Value::Array(vec![Value::Bool(true); 256]), Some(bcs::to_bytes(&vec![true; 256]).unwrap()), ), // Vector failure cases - (vector_type(Type::U64), UnresolvedValue::Bool(true), None), - (vector_type(Type::U64), UnresolvedValue::Number(0), None), - (vector_type(Type::U64), UnresolvedValue::Null, None), - (vector_type(Type::U64), UnresolvedValue::Number(0), None), + (vector_type(Type::U64), Value::Bool(true), None), + (vector_type(Type::U64), Value::Number(0), None), + (vector_type(Type::U64), Value::Null, None), + (vector_type(Type::U64), Value::Number(0), None), ( vector_type(Type::Address), - UnresolvedValue::Array(vec![ - UnresolvedValue::String(AccountAddress::TWO.to_canonical_string(true)), - UnresolvedValue::Number(5), + Value::Array(vec![ + Value::String(AccountAddress::TWO.to_canonical_string(true)), + Value::Number(5), ]), None, ), diff --git a/crates/sui-rest-api/src/transactions/resolve/mod.rs b/crates/sui-rest-api/src/transactions/resolve/mod.rs index b3045f81b1309..3e359d46e0e95 100644 --- a/crates/sui-rest-api/src/transactions/resolve/mod.rs +++ b/crates/sui-rest-api/src/transactions/resolve/mod.rs @@ -26,15 +26,11 @@ use itertools::Itertools; use move_binary_format::normalized; use schemars::JsonSchema; use sui_protocol_config::ProtocolConfig; +use sui_sdk_types::types::unresolved; use sui_sdk_types::types::Argument; use sui_sdk_types::types::Command; use sui_sdk_types::types::ObjectId; use sui_sdk_types::types::Transaction; -use sui_sdk_types::types::UnresolvedInputArgument; -use sui_sdk_types::types::UnresolvedObjectReference; -use sui_sdk_types::types::UnresolvedProgrammableTransaction; -use sui_sdk_types::types::UnresolvedTransaction; -use sui_sdk_types::types::UnresolvedValue; use sui_types::base_types::ObjectID; use sui_types::base_types::ObjectRef; use sui_types::base_types::SuiAddress; @@ -73,7 +69,7 @@ impl ApiEndpoint for ResolveTransaction { .query_parameters::(generator) .request_body( RequestBodyBuilder::new() - .json_content::(generator) + .json_content::(generator) .build(), ) .response( @@ -96,7 +92,7 @@ async fn resolve_transaction( State(state): State, Query(parameters): Query, accept: AcceptJsonProtobufBcs, - Json(unresolved_transaction): Json, + Json(unresolved_transaction): Json, ) -> Result< JsonProtobufBcs< ResolveTransactionResponse, @@ -224,7 +220,7 @@ struct NormalizedPackage { fn called_packages( reader: &StateReader, protocol_config: &ProtocolConfig, - unresolved_transaction: &UnresolvedTransaction, + unresolved_transaction: &unresolved::Transaction, ) -> Result> { let binary_config = sui_types::execution_config_utils::to_binary_config(protocol_config); let mut packages = HashMap::new(); @@ -283,7 +279,7 @@ fn resolve_unresolved_transaction( called_packages: &HashMap, reference_gas_price: u64, max_gas_budget: u64, - unresolved_transaction: UnresolvedTransaction, + unresolved_transaction: unresolved::Transaction, ) -> Result { let sender = unresolved_transaction.sender.into(); let gas_data = if let Some(unresolved_gas_payment) = unresolved_transaction.gas_payment { @@ -327,7 +323,7 @@ pub struct ResolveTransactionResponse { fn resolve_object_reference( reader: &StateReader, - unresolved_object_reference: UnresolvedObjectReference, + unresolved_object_reference: unresolved::ObjectReference, ) -> Result { let object_id = unresolved_object_reference.object_id; let object = reader @@ -343,9 +339,9 @@ fn resolve_object_reference( // before calling. fn resolve_object_reference_with_object( object: &sui_types::object::Object, - unresolved_object_reference: UnresolvedObjectReference, + unresolved_object_reference: unresolved::ObjectReference, ) -> Result { - let UnresolvedObjectReference { + let unresolved::ObjectReference { object_id, version, digest, @@ -393,7 +389,7 @@ fn resolve_object_reference_with_object( fn resolve_ptb( reader: &StateReader, called_packages: &HashMap, - unresolved_ptb: UnresolvedProgrammableTransaction, + unresolved_ptb: unresolved::ProgrammableTransaction, ) -> Result { let inputs = unresolved_ptb .inputs @@ -425,14 +421,14 @@ fn resolve_arg( reader: &StateReader, called_packages: &HashMap, commands: &[Command], - arg: UnresolvedInputArgument, + arg: unresolved::Input, arg_idx: usize, ) -> Result { use fastcrypto::encoding::Base64; use fastcrypto::encoding::Encoding; - use sui_sdk_types::types::UnresolvedInputArgumentKind::*; + use sui_sdk_types::types::unresolved::InputKind::*; - let UnresolvedInputArgument { + let unresolved::Input { kind, value, object_id, @@ -443,7 +439,7 @@ fn resolve_arg( match (kind, value, object_id, version, digest, mutable) { // pre serialized BCS input encoded as a base64 string - (Some(Pure), Some(UnresolvedValue::String(v)), None, None, None, None) => { + (Some(Pure), Some(unresolved::Value::String(v)), None, None, None, None) => { let value = Base64::decode(&v).map_err(|e| { RestError::new( axum::http::StatusCode::BAD_REQUEST, @@ -453,7 +449,7 @@ fn resolve_arg( CallArg::Pure(value) } // pre serialized BCS input encoded as a a JSON array of u8s - (Some(Pure), Some(array @ UnresolvedValue::Array(_)), None, None, None, None) => { + (Some(Pure), Some(array @ unresolved::Value::Array(_)), None, None, None, None) => { let value = serde_json::from_value(serde_json::Value::from(array)).map_err(|e| { RestError::new( axum::http::StatusCode::BAD_REQUEST, @@ -473,21 +469,16 @@ fn resolve_arg( )?), // Immutable or owned - ( - Some(ImmutableOrOwned | Immutable | Owned), - None, - Some(object_id), - version, - digest, - None, - ) => CallArg::Object(ObjectArg::ImmOrOwnedObject(resolve_object_reference( - reader, - UnresolvedObjectReference { - object_id, - version, - digest, - }, - )?)), + (Some(ImmutableOrOwned), None, Some(object_id), version, digest, None) => { + CallArg::Object(ObjectArg::ImmOrOwnedObject(resolve_object_reference( + reader, + unresolved::ObjectReference { + object_id, + version, + digest, + }, + )?)) + } // Shared object (Some(Shared), None, Some(object_id), _version, None, _mutable) => CallArg::Object( @@ -498,7 +489,7 @@ fn resolve_arg( (Some(Receiving), None, Some(object_id), version, digest, None) => { CallArg::Object(ObjectArg::Receiving(resolve_object_reference( reader, - UnresolvedObjectReference { + unresolved::ObjectReference { object_id, version, digest, @@ -547,7 +538,7 @@ fn resolve_object( match object.owner() { sui_types::object::Owner::Immutable => resolve_object_reference_with_object( &object, - UnresolvedObjectReference { + unresolved::ObjectReference { object_id, version, digest, @@ -558,7 +549,7 @@ fn resolve_object( sui_types::object::Owner::AddressOwner(_) => { let object_ref = resolve_object_reference_with_object( &object, - UnresolvedObjectReference { + unresolved::ObjectReference { object_id, version, digest, From 5126b54f4594e8d2db507b504f0d8a338439aceb Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 25 Nov 2024 10:43:58 -0600 Subject: [PATCH 02/28] config: rename 'rest' config to 'rpc' --- crates/sui-config/src/node.rs | 2 +- crates/sui-node/src/lib.rs | 2 +- crates/sui-swarm-config/src/node_config_builder.rs | 4 ++-- ...hot_tests__network_config_snapshot_matches.snap | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/sui-config/src/node.rs b/crates/sui-config/src/node.rs index 947f08f8361ad..12f307ac3729c 100644 --- a/crates/sui-config/src/node.rs +++ b/crates/sui-config/src/node.rs @@ -67,7 +67,7 @@ pub struct NodeConfig { #[serde(default)] pub enable_experimental_rest_api: bool, #[serde(skip_serializing_if = "Option::is_none")] - pub rest: Option, + pub rpc: Option, #[serde(default = "default_metrics_address")] pub metrics_address: SocketAddr, diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index c337b483a7d56..ea1addf09cec2 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -2099,7 +2099,7 @@ pub async fn build_http_server( software_version, ); - if let Some(config) = config.rest.clone() { + if let Some(config) = config.rpc.clone() { rest_service.with_config(config); } diff --git a/crates/sui-swarm-config/src/node_config_builder.rs b/crates/sui-swarm-config/src/node_config_builder.rs index 3bf1a4901eebb..19ea5ce07dd78 100644 --- a/crates/sui-swarm-config/src/node_config_builder.rs +++ b/crates/sui-swarm-config/src/node_config_builder.rs @@ -233,7 +233,7 @@ impl ValidatorConfigBuilder { transaction_kv_store_read_config: Default::default(), transaction_kv_store_write_config: None, enable_experimental_rest_api: true, - rest: Some(sui_rest_api::Config { + rpc: Some(sui_rest_api::Config { enable_unstable_apis: Some(true), ..Default::default() }), @@ -535,7 +535,7 @@ impl FullnodeConfigBuilder { transaction_kv_store_read_config: Default::default(), transaction_kv_store_write_config: Default::default(), enable_experimental_rest_api: true, - rest: Some(sui_rest_api::Config { + rpc: Some(sui_rest_api::Config { enable_unstable_apis: Some(true), ..Default::default() }), diff --git a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap index 44ab14c3ebb4c..72acabc91c600 100644 --- a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap +++ b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap @@ -15,7 +15,7 @@ validator_configs: network-address: "" json-rpc-address: "0.0.0.0:1" enable-experimental-rest-api: true - rest: + rpc: enable-unstable-apis: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 @@ -196,7 +196,7 @@ validator_configs: network-address: "" json-rpc-address: "0.0.0.0:1" enable-experimental-rest-api: true - rest: + rpc: enable-unstable-apis: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 @@ -377,7 +377,7 @@ validator_configs: network-address: "" json-rpc-address: "0.0.0.0:1" enable-experimental-rest-api: true - rest: + rpc: enable-unstable-apis: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 @@ -558,7 +558,7 @@ validator_configs: network-address: "" json-rpc-address: "0.0.0.0:1" enable-experimental-rest-api: true - rest: + rpc: enable-unstable-apis: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 @@ -739,7 +739,7 @@ validator_configs: network-address: "" json-rpc-address: "0.0.0.0:1" enable-experimental-rest-api: true - rest: + rpc: enable-unstable-apis: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 @@ -920,7 +920,7 @@ validator_configs: network-address: "" json-rpc-address: "0.0.0.0:1" enable-experimental-rest-api: true - rest: + rpc: enable-unstable-apis: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 @@ -1101,7 +1101,7 @@ validator_configs: network-address: "" json-rpc-address: "0.0.0.0:1" enable-experimental-rest-api: true - rest: + rpc: enable-unstable-apis: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 From 6b3870deb50357d6195823be86bca71f4c3c4801 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 25 Nov 2024 14:48:31 -0600 Subject: [PATCH 03/28] storage: rename RestStateReader to RpcStateReader --- crates/simulacrum/src/lib.rs | 4 ++-- crates/sui-core/src/storage.rs | 4 ++-- crates/sui-graphql-rpc/src/test_infra/cluster.rs | 4 ++-- crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs | 4 ++-- crates/sui-rest-api/src/lib.rs | 6 +++--- crates/sui-rest-api/src/reader.rs | 8 ++++---- .../src/simulator_persisted_store.rs | 4 ++-- crates/sui-types/src/storage/mod.rs | 2 +- crates/sui-types/src/storage/read_store.rs | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/simulacrum/src/lib.rs b/crates/simulacrum/src/lib.rs index 636803ade7522..954a710d4b494 100644 --- a/crates/simulacrum/src/lib.rs +++ b/crates/simulacrum/src/lib.rs @@ -29,7 +29,7 @@ use sui_types::base_types::{AuthorityName, ObjectID, VersionNumber}; use sui_types::crypto::AuthoritySignature; use sui_types::digests::ConsensusCommitDigest; use sui_types::object::Object; -use sui_types::storage::{ObjectStore, ReadStore, RestStateReader}; +use sui_types::storage::{ObjectStore, ReadStore, RpcStateReader}; use sui_types::sui_system_state::epoch_start_sui_system_state::EpochStartSystemState; use sui_types::transaction::EndOfEpochTransactionKind; use sui_types::{ @@ -549,7 +549,7 @@ impl ReadStore for Simulacrum { } } -impl RestStateReader for Simulacrum { +impl RpcStateReader for Simulacrum { fn get_transaction_checkpoint( &self, _digest: &sui_types::digests::TransactionDigest, diff --git a/crates/sui-core/src/storage.rs b/crates/sui-core/src/storage.rs index 413ea5e4854e8..4dc3e25107621 100644 --- a/crates/sui-core/src/storage.rs +++ b/crates/sui-core/src/storage.rs @@ -26,7 +26,7 @@ use sui_types::storage::CoinInfo; use sui_types::storage::DynamicFieldIndexInfo; use sui_types::storage::DynamicFieldKey; use sui_types::storage::ObjectStore; -use sui_types::storage::RestStateReader; +use sui_types::storage::RpcStateReader; use sui_types::storage::WriteStore; use sui_types::storage::{ObjectKey, ReadStore}; use sui_types::transaction::VerifiedTransaction; @@ -445,7 +445,7 @@ impl ReadStore for RestReadStore { } } -impl RestStateReader for RestReadStore { +impl RpcStateReader for RestReadStore { fn get_transaction_checkpoint( &self, digest: &TransactionDigest, diff --git a/crates/sui-graphql-rpc/src/test_infra/cluster.rs b/crates/sui-graphql-rpc/src/test_infra/cluster.rs index b023997515412..de2b45c5cc7f6 100644 --- a/crates/sui-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/sui-graphql-rpc/src/test_infra/cluster.rs @@ -21,7 +21,7 @@ use sui_indexer::store::PgIndexerStore; use sui_indexer::test_utils::start_indexer_writer_for_testing; use sui_pg_temp_db::{get_available_port, TempDb}; use sui_swarm_config::genesis_config::{AccountConfig, DEFAULT_GAS_AMOUNT}; -use sui_types::storage::RestStateReader; +use sui_types::storage::RpcStateReader; use tempfile::tempdir; use tempfile::TempDir; use test_cluster::TestCluster; @@ -150,7 +150,7 @@ pub async fn start_network_cluster() -> NetworkCluster { /// Takes in a simulated instantiation of a Sui blockchain and builds a cluster around it. This /// cluster is typically used in e2e tests to emulate and test behaviors. pub async fn serve_executor( - executor: Arc, + executor: Arc, snapshot_config: Option, retention_config: Option, data_ingestion_path: PathBuf, diff --git a/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs b/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs index 606097093366c..f54de2dddfb26 100644 --- a/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs @@ -21,7 +21,7 @@ use sui_indexer::store::PgIndexerStore; use sui_indexer::test_utils::start_indexer_writer_for_testing_with_mvr_mode; use sui_pg_temp_db::{get_available_port, TempDb}; use sui_swarm_config::genesis_config::{AccountConfig, DEFAULT_GAS_AMOUNT}; -use sui_types::storage::RestStateReader; +use sui_types::storage::RpcStateReader; use tempfile::tempdir; use tempfile::TempDir; use test_cluster::TestCluster; @@ -151,7 +151,7 @@ pub async fn start_network_cluster() -> NetworkCluster { /// Takes in a simulated instantiation of a Sui blockchain and builds a cluster around it. This /// cluster is typically used in e2e tests to emulate and test behaviors. pub async fn serve_executor( - executor: Arc, + executor: Arc, snapshot_config: Option, retention_config: Option, data_ingestion_path: PathBuf, diff --git a/crates/sui-rest-api/src/lib.rs b/crates/sui-rest-api/src/lib.rs index c2151b5f554a2..82fd98b0b4461 100644 --- a/crates/sui-rest-api/src/lib.rs +++ b/crates/sui-rest-api/src/lib.rs @@ -10,7 +10,7 @@ use mysten_network::callback::CallbackLayer; use openapi::ApiEndpoint; use reader::StateReader; use std::sync::Arc; -use sui_types::storage::RestStateReader; +use sui_types::storage::RpcStateReader; use sui_types::transaction_executor::TransactionExecutor; use tap::Pipe; @@ -151,7 +151,7 @@ impl axum::extract::FromRef for Option } impl RestService { - pub fn new(reader: Arc, software_version: &'static str) -> Self { + pub fn new(reader: Arc, software_version: &'static str) -> Self { let chain_id = reader.get_chain_identifier().unwrap(); Self { reader: StateReader::new(reader), @@ -163,7 +163,7 @@ impl RestService { } } - pub fn new_without_version(reader: Arc) -> Self { + pub fn new_without_version(reader: Arc) -> Self { Self::new(reader, "unknown") } diff --git a/crates/sui-rest-api/src/reader.rs b/crates/sui-rest-api/src/reader.rs index b3d3f038029ef..a586614cd37f4 100644 --- a/crates/sui-rest-api/src/reader.rs +++ b/crates/sui-rest-api/src/reader.rs @@ -9,22 +9,22 @@ use sui_sdk_types::types::{ use sui_sdk_types::types::{Object, ObjectId, Version}; use sui_types::storage::error::{Error as StorageError, Result}; use sui_types::storage::ObjectStore; -use sui_types::storage::RestStateReader; +use sui_types::storage::RpcStateReader; use tap::Pipe; use crate::Direction; #[derive(Clone)] pub struct StateReader { - inner: Arc, + inner: Arc, } impl StateReader { - pub fn new(inner: Arc) -> Self { + pub fn new(inner: Arc) -> Self { Self { inner } } - pub fn inner(&self) -> &Arc { + pub fn inner(&self) -> &Arc { &self.inner } diff --git a/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs b/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs index b77b62a094de6..c0b42e57a3d1d 100644 --- a/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs +++ b/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs @@ -13,7 +13,7 @@ use sui_config::genesis; use sui_protocol_config::ProtocolVersion; use sui_swarm_config::genesis_config::AccountConfig; use sui_swarm_config::network_config_builder::ConfigBuilder; -use sui_types::storage::{ReadStore, RestStateReader}; +use sui_types::storage::{ReadStore, RpcStateReader}; use sui_types::{ base_types::{ObjectID, SequenceNumber, SuiAddress, VersionNumber}, committee::{Committee, EpochId}, @@ -657,7 +657,7 @@ impl ReadStore for PersistedStoreInnerReadOnlyWrapper { } } -impl RestStateReader for PersistedStoreInnerReadOnlyWrapper { +impl RpcStateReader for PersistedStoreInnerReadOnlyWrapper { fn get_transaction_checkpoint( &self, _digest: &TransactionDigest, diff --git a/crates/sui-types/src/storage/mod.rs b/crates/sui-types/src/storage/mod.rs index 8e2add785336e..fa8ea24464687 100644 --- a/crates/sui-types/src/storage/mod.rs +++ b/crates/sui-types/src/storage/mod.rs @@ -27,7 +27,7 @@ pub use read_store::CoinInfo; pub use read_store::DynamicFieldIndexInfo; pub use read_store::DynamicFieldKey; pub use read_store::ReadStore; -pub use read_store::RestStateReader; +pub use read_store::RpcStateReader; use serde::{Deserialize, Serialize}; use serde_with::serde_as; pub use shared_in_memory_store::SharedInMemoryStore; diff --git a/crates/sui-types/src/storage/read_store.rs b/crates/sui-types/src/storage/read_store.rs index 16adb77ae2b03..893c76515fe02 100644 --- a/crates/sui-types/src/storage/read_store.rs +++ b/crates/sui-types/src/storage/read_store.rs @@ -598,7 +598,7 @@ impl ReadStore for Arc { /// /// It extends both ObjectStore and ReadStore by adding functionality that may require more /// detailed underlying databases or indexes to support. -pub trait RestStateReader: ObjectStore + ReadStore + Send + Sync { +pub trait RpcStateReader: ObjectStore + ReadStore + Send + Sync { fn get_transaction_checkpoint( &self, digest: &TransactionDigest, From 5401098d03b46d485177dca30e6ea2f42eb88378 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 25 Nov 2024 15:06:22 -0600 Subject: [PATCH 04/28] core: rename rest_index to rpc_index --- crates/sui-core/src/authority.rs | 12 +++--- .../sui-core/src/authority/authority_store.rs | 6 +-- .../src/authority/authority_store_pruner.rs | 32 +++++++------- .../src/authority/test_authority_builder.rs | 10 ++--- .../checkpoints/checkpoint_executor/mod.rs | 6 +-- crates/sui-core/src/db_checkpoint_handler.rs | 6 +-- crates/sui-core/src/lib.rs | 2 +- .../src/{rest_index.rs => rpc_index.rs} | 43 +++++++++++-------- crates/sui-core/src/storage.rs | 12 +++--- crates/sui-e2e-tests/tests/full_node_tests.rs | 2 +- crates/sui-node/src/lib.rs | 10 ++--- crates/sui-tool/src/db_tool/db_dump.rs | 10 ++--- 12 files changed, 80 insertions(+), 71 deletions(-) rename crates/sui-core/src/{rest_index.rs => rpc_index.rs} (95%) diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index 4b3a4e5dd7863..6c539bf5b7792 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -6,7 +6,7 @@ use crate::consensus_adapter::ConsensusOverloadChecker; use crate::execution_cache::ExecutionCacheTraitPointers; use crate::execution_cache::TransactionCacheRead; use crate::jsonrpc_index::CoinIndexKey2; -use crate::rest_index::RestIndexStore; +use crate::rpc_index::RpcIndexStore; use crate::transaction_outputs::TransactionOutputs; use crate::verify_indexes::verify_indexes; use anyhow::anyhow; @@ -792,7 +792,7 @@ pub struct AuthorityState { execution_lock: RwLock, pub indexes: Option>, - pub rest_index: Option>, + pub rpc_index: Option>, pub subscription_handler: Arc, checkpoint_store: Arc, @@ -2834,7 +2834,7 @@ impl AuthorityState { epoch_store: Arc, committee_store: Arc, indexes: Option>, - rest_index: Option>, + rpc_index: Option>, checkpoint_store: Arc, prometheus_registry: &Registry, genesis_objects: &[Object], @@ -2866,7 +2866,7 @@ impl AuthorityState { let _pruner = AuthorityStorePruner::new( store.perpetual_tables.clone(), checkpoint_store.clone(), - rest_index.clone(), + rpc_index.clone(), store.objects_lock_table.clone(), config.authority_store_pruning_config.clone(), epoch_store.committee().authority_exists(&name), @@ -2886,7 +2886,7 @@ impl AuthorityState { input_loader, execution_cache_trait_pointers, indexes, - rest_index, + rpc_index, subscription_handler: Arc::new(SubscriptionHandler::new(prometheus_registry)), checkpoint_store, committee_store, @@ -2978,7 +2978,7 @@ impl AuthorityState { AuthorityStorePruner::prune_checkpoints_for_eligible_epochs( &self.database_for_testing().perpetual_tables, &self.checkpoint_store, - self.rest_index.as_deref(), + self.rpc_index.as_deref(), &self.database_for_testing().objects_lock_table, config.authority_store_pruning_config, metrics, diff --git a/crates/sui-core/src/authority/authority_store.rs b/crates/sui-core/src/authority/authority_store.rs index fade6814056f4..795f238fee257 100644 --- a/crates/sui-core/src/authority/authority_store.rs +++ b/crates/sui-core/src/authority/authority_store.rs @@ -13,7 +13,7 @@ use crate::authority::authority_store_types::{ get_store_object_pair, ObjectContentDigest, StoreObject, StoreObjectPair, StoreObjectWrapper, }; use crate::authority::epoch_start_configuration::{EpochFlag, EpochStartConfiguration}; -use crate::rest_index::RestIndexStore; +use crate::rpc_index::RpcIndexStore; use crate::state_accumulator::AccumulatorStore; use crate::transaction_outputs::TransactionOutputs; use either::Either; @@ -1791,7 +1791,7 @@ impl AuthorityStore { pub async fn prune_objects_and_compact_for_testing( &self, checkpoint_store: &Arc, - rest_index: Option<&RestIndexStore>, + rpc_index: Option<&RpcIndexStore>, ) { let pruning_config = AuthorityStorePruningConfig { num_epochs_to_retain: 0, @@ -1800,7 +1800,7 @@ impl AuthorityStore { let _ = AuthorityStorePruner::prune_objects_for_eligible_epochs( &self.perpetual_tables, checkpoint_store, - rest_index, + rpc_index, &self.objects_lock_table, pruning_config, AuthorityStorePruningMetrics::new_for_test(), diff --git a/crates/sui-core/src/authority/authority_store_pruner.rs b/crates/sui-core/src/authority/authority_store_pruner.rs index 17f34f5755f89..e622ef39e1858 100644 --- a/crates/sui-core/src/authority/authority_store_pruner.rs +++ b/crates/sui-core/src/authority/authority_store_pruner.rs @@ -3,7 +3,7 @@ use crate::authority::authority_store_types::{ObjectContentDigest, StoreData, StoreObject}; use crate::checkpoints::{CheckpointStore, CheckpointWatermark}; -use crate::rest_index::RestIndexStore; +use crate::rpc_index::RpcIndexStore; use anyhow::anyhow; use mysten_metrics::{monitored_scope, spawn_monitored_task}; use once_cell::sync::Lazy; @@ -233,7 +233,7 @@ impl AuthorityStorePruner { fn prune_checkpoints( perpetual_db: &Arc, checkpoint_db: &Arc, - rest_index: Option<&RestIndexStore>, + rpc_index: Option<&RpcIndexStore>, checkpoint_number: CheckpointSequenceNumber, checkpoints_to_prune: Vec, checkpoint_content_to_prune: Vec, @@ -297,8 +297,8 @@ impl AuthorityStorePruner { )], )?; - if let Some(rest_index) = rest_index { - rest_index.prune(&checkpoint_content_to_prune)?; + if let Some(rpc_index) = rpc_index { + rpc_index.prune(&checkpoint_content_to_prune)?; } perpetual_batch.write()?; checkpoints_batch.write()?; @@ -312,7 +312,7 @@ impl AuthorityStorePruner { pub async fn prune_objects_for_eligible_epochs( perpetual_db: &Arc, checkpoint_store: &Arc, - rest_index: Option<&RestIndexStore>, + rpc_index: Option<&RpcIndexStore>, objects_lock_table: &Arc>, config: AuthorityStorePruningConfig, metrics: Arc, @@ -338,7 +338,7 @@ impl AuthorityStorePruner { Self::prune_for_eligible_epochs( perpetual_db, checkpoint_store, - rest_index, + rpc_index, PruningMode::Objects, config.num_epochs_to_retain, pruned_checkpoint_number, @@ -354,7 +354,7 @@ impl AuthorityStorePruner { pub async fn prune_checkpoints_for_eligible_epochs( perpetual_db: &Arc, checkpoint_store: &Arc, - rest_index: Option<&RestIndexStore>, + rpc_index: Option<&RpcIndexStore>, objects_lock_table: &Arc>, config: AuthorityStorePruningConfig, metrics: Arc, @@ -396,7 +396,7 @@ impl AuthorityStorePruner { Self::prune_for_eligible_epochs( perpetual_db, checkpoint_store, - rest_index, + rpc_index, PruningMode::Checkpoints, config .num_epochs_to_retain_for_checkpoints() @@ -415,7 +415,7 @@ impl AuthorityStorePruner { pub async fn prune_for_eligible_epochs( perpetual_db: &Arc, checkpoint_store: &Arc, - rest_index: Option<&RestIndexStore>, + rpc_index: Option<&RpcIndexStore>, mode: PruningMode, num_epochs_to_retain: u64, starting_checkpoint_number: CheckpointSequenceNumber, @@ -492,7 +492,7 @@ impl AuthorityStorePruner { PruningMode::Checkpoints => Self::prune_checkpoints( perpetual_db, checkpoint_store, - rest_index, + rpc_index, checkpoint_number, checkpoints_to_prune, checkpoint_content_to_prune, @@ -525,7 +525,7 @@ impl AuthorityStorePruner { PruningMode::Checkpoints => Self::prune_checkpoints( perpetual_db, checkpoint_store, - rest_index, + rpc_index, checkpoint_number, checkpoints_to_prune, checkpoint_content_to_prune, @@ -623,7 +623,7 @@ impl AuthorityStorePruner { epoch_duration_ms: u64, perpetual_db: Arc, checkpoint_store: Arc, - rest_index: Option>, + rpc_index: Option>, objects_lock_table: Arc>, metrics: Arc, indirect_objects_threshold: usize, @@ -685,12 +685,12 @@ impl AuthorityStorePruner { loop { tokio::select! { _ = objects_prune_interval.tick(), if config.num_epochs_to_retain != u64::MAX => { - if let Err(err) = Self::prune_objects_for_eligible_epochs(&perpetual_db, &checkpoint_store, rest_index.as_deref(), &objects_lock_table, config.clone(), metrics.clone(), indirect_objects_threshold, epoch_duration_ms).await { + if let Err(err) = Self::prune_objects_for_eligible_epochs(&perpetual_db, &checkpoint_store, rpc_index.as_deref(), &objects_lock_table, config.clone(), metrics.clone(), indirect_objects_threshold, epoch_duration_ms).await { error!("Failed to prune objects: {:?}", err); } }, _ = checkpoints_prune_interval.tick(), if !matches!(config.num_epochs_to_retain_for_checkpoints(), None | Some(u64::MAX) | Some(0)) => { - if let Err(err) = Self::prune_checkpoints_for_eligible_epochs(&perpetual_db, &checkpoint_store, rest_index.as_deref(), &objects_lock_table, config.clone(), metrics.clone(), indirect_objects_threshold, archive_readers.clone(), epoch_duration_ms).await { + if let Err(err) = Self::prune_checkpoints_for_eligible_epochs(&perpetual_db, &checkpoint_store, rpc_index.as_deref(), &objects_lock_table, config.clone(), metrics.clone(), indirect_objects_threshold, archive_readers.clone(), epoch_duration_ms).await { error!("Failed to prune checkpoints: {:?}", err); } }, @@ -704,7 +704,7 @@ impl AuthorityStorePruner { pub fn new( perpetual_db: Arc, checkpoint_store: Arc, - rest_index: Option>, + rpc_index: Option>, objects_lock_table: Arc>, mut pruning_config: AuthorityStorePruningConfig, is_validator: bool, @@ -729,7 +729,7 @@ impl AuthorityStorePruner { epoch_duration_ms, perpetual_db, checkpoint_store, - rest_index, + rpc_index, objects_lock_table, AuthorityStorePruningMetrics::new(registry), indirect_objects_threshold, diff --git a/crates/sui-core/src/authority/test_authority_builder.rs b/crates/sui-core/src/authority/test_authority_builder.rs index 6b66a2a85ebfd..1e9882161a933 100644 --- a/crates/sui-core/src/authority/test_authority_builder.rs +++ b/crates/sui-core/src/authority/test_authority_builder.rs @@ -13,7 +13,7 @@ use crate::execution_cache::build_execution_cache; use crate::jsonrpc_index::IndexStore; use crate::mock_consensus::{ConsensusMode, MockConsensusClient}; use crate::module_cache_metrics::ResolverMetrics; -use crate::rest_index::RestIndexStore; +use crate::rpc_index::RpcIndexStore; use crate::signature_verifier::SignatureVerifierMetrics; use fastcrypto::traits::KeyPair; use prometheus::Registry; @@ -277,11 +277,11 @@ impl<'a> TestAuthorityBuilder<'a> { &authority_store, ))) }; - let rest_index = if self.disable_indexer { + let rpc_index = if self.disable_indexer { None } else { - Some(Arc::new(RestIndexStore::new( - path.join("rest_index"), + Some(Arc::new(RpcIndexStore::new( + &path, &authority_store, &checkpoint_store, &epoch_store, @@ -315,7 +315,7 @@ impl<'a> TestAuthorityBuilder<'a> { epoch_store.clone(), committee_store, index_store, - rest_index, + rpc_index, checkpoint_store, ®istry, genesis.objects(), diff --git a/crates/sui-core/src/checkpoints/checkpoint_executor/mod.rs b/crates/sui-core/src/checkpoints/checkpoint_executor/mod.rs index 71c6dd44845dd..90bd7a10735fe 100644 --- a/crates/sui-core/src/checkpoints/checkpoint_executor/mod.rs +++ b/crates/sui-core/src/checkpoints/checkpoint_executor/mod.rs @@ -1309,7 +1309,7 @@ async fn finalize_checkpoint( let checkpoint_acc = accumulator.accumulate_checkpoint(effects, checkpoint.sequence_number, epoch_store)?; - if data_ingestion_dir.is_some() || state.rest_index.is_some() { + if data_ingestion_dir.is_some() || state.rpc_index.is_some() { let checkpoint_data = load_checkpoint_data( checkpoint, object_cache_reader, @@ -1320,12 +1320,12 @@ async fn finalize_checkpoint( // TODO(bmwill) discuss with team a better location for this indexing so that it isn't on // the critical path and the writes to the DB are done in checkpoint order - if let Some(rest_index) = &state.rest_index { + if let Some(rpc_index) = &state.rpc_index { let mut layout_resolver = epoch_store.executor().type_layout_resolver(Box::new( PackageStoreWithFallback::new(state.get_backing_package_store(), &checkpoint_data), )); - rest_index.index_checkpoint(&checkpoint_data, layout_resolver.as_mut())?; + rpc_index.index_checkpoint(&checkpoint_data, layout_resolver.as_mut())?; } if let Some(path) = data_ingestion_dir { diff --git a/crates/sui-core/src/db_checkpoint_handler.rs b/crates/sui-core/src/db_checkpoint_handler.rs index 3d84ea32014bf..fb4bc5cd87bc1 100644 --- a/crates/sui-core/src/db_checkpoint_handler.rs +++ b/crates/sui-core/src/db_checkpoint_handler.rs @@ -6,7 +6,7 @@ use crate::authority::authority_store_pruner::{ }; use crate::authority::authority_store_tables::AuthorityPerpetualTables; use crate::checkpoints::CheckpointStore; -use crate::rest_index::RestIndexStore; +use crate::rpc_index::RpcIndexStore; use anyhow::Result; use bytes::Bytes; use futures::future::try_join_all; @@ -263,7 +263,7 @@ impl DBCheckpointHandler { None, None, )); - let rest_index = RestIndexStore::new_without_init(db_path.join("rest_index")); + let rpc_index = RpcIndexStore::new_without_init(&db_path); let metrics = AuthorityStorePruningMetrics::new(&Registry::default()); let lock_table = Arc::new(RwLockTable::new(1)); info!( @@ -273,7 +273,7 @@ impl DBCheckpointHandler { AuthorityStorePruner::prune_objects_for_eligible_epochs( &perpetual_db, &checkpoint_store, - Some(&rest_index), + Some(&rpc_index), &lock_table, self.pruning_config.clone(), metrics, diff --git a/crates/sui-core/src/lib.rs b/crates/sui-core/src/lib.rs index 0d3920254b8e0..2852750d8b067 100644 --- a/crates/sui-core/src/lib.rs +++ b/crates/sui-core/src/lib.rs @@ -28,7 +28,7 @@ pub mod overload_monitor; mod par_index_live_object_set; pub(crate) mod post_consensus_tx_reorder; pub mod quorum_driver; -pub mod rest_index; +pub mod rpc_index; pub mod safe_client; mod scoring_decision; mod stake_aggregator; diff --git a/crates/sui-core/src/rest_index.rs b/crates/sui-core/src/rpc_index.rs similarity index 95% rename from crates/sui-core/src/rest_index.rs rename to crates/sui-core/src/rpc_index.rs index dd6fc86a97194..382c953f43a1a 100644 --- a/crates/sui-core/src/rest_index.rs +++ b/crates/sui-core/src/rpc_index.rs @@ -12,6 +12,7 @@ use rayon::iter::ParallelIterator; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; +use std::path::Path; use std::path::PathBuf; use std::sync::Arc; use std::sync::Mutex; @@ -101,7 +102,7 @@ impl CoinIndexInfo { } } -/// RocksDB tables for the RestIndexStore +/// RocksDB tables for the RpcIndexStore /// /// Anytime a new table is added, or and existing one has it's schema changed, make sure to also /// update the value of `CURRENT_DB_VERSION`. @@ -151,7 +152,7 @@ impl IndexStoreTables { fn open>(path: P) -> Self { IndexStoreTables::open_tables_read_write( path.into(), - MetricConf::new("rest-index"), + MetricConf::new("rpc-index"), None, None, ) @@ -180,7 +181,7 @@ impl IndexStoreTables { epoch_store: &AuthorityPerEpochStore, package_store: &Arc, ) -> Result<(), StorageError> { - info!("Initializing REST indexes"); + info!("Initializing RPC indexes"); // Iterate through available, executed checkpoints that have yet to be pruned // to initialize checkpoint and transaction based indexes. @@ -224,7 +225,7 @@ impl IndexStoreTables { let coin_index = Mutex::new(HashMap::new()); - let make_live_object_indexer = RestParLiveObjectSetIndexer { + let make_live_object_indexer = RpcParLiveObjectSetIndexer { tables: self, coin_index: &coin_index, epoch_store, @@ -245,7 +246,7 @@ impl IndexStoreTables { }, )?; - info!("Finished initializing REST indexes"); + info!("Finished initializing RPC indexes"); Ok(()) } @@ -454,18 +455,25 @@ impl IndexStoreTables { } } -pub struct RestIndexStore { +pub struct RpcIndexStore { tables: IndexStoreTables, } -impl RestIndexStore { +impl RpcIndexStore { + /// Given the provided directory, construct the path to the db + fn db_path(dir: &Path) -> PathBuf { + dir.join("rpc-index") + } + pub fn new( - path: PathBuf, + dir: &Path, authority_store: &AuthorityStore, checkpoint_store: &CheckpointStore, epoch_store: &AuthorityPerEpochStore, package_store: &Arc, ) -> Self { + let path = Self::db_path(dir); + let tables = { let tables = IndexStoreTables::open(&path); @@ -475,7 +483,7 @@ impl RestIndexStore { let mut tables = if tables.needs_to_delete_old_db() { drop(tables); typed_store::rocks::safe_drop_db(path.clone()) - .expect("unable to destroy old rest-index db"); + .expect("unable to destroy old rpc-index db"); IndexStoreTables::open(path) } else { tables @@ -488,7 +496,7 @@ impl RestIndexStore { epoch_store, package_store, ) - .expect("unable to initialize rest index from live object set"); + .expect("unable to initialize rpc index from live object set"); tables } else { tables @@ -498,7 +506,8 @@ impl RestIndexStore { Self { tables } } - pub fn new_without_init(path: PathBuf) -> Self { + pub fn new_without_init(dir: &Path) -> Self { + let path = Self::db_path(dir); let tables = IndexStoreTables::open(path); Self { tables } @@ -628,25 +637,25 @@ fn try_create_coin_index_info(object: &Object) -> Option<(CoinIndexKey, CoinInde }) } -struct RestParLiveObjectSetIndexer<'a> { +struct RpcParLiveObjectSetIndexer<'a> { tables: &'a IndexStoreTables, coin_index: &'a Mutex>, epoch_store: &'a AuthorityPerEpochStore, package_store: &'a Arc, } -struct RestLiveObjectIndexer<'a> { +struct RpcLiveObjectIndexer<'a> { tables: &'a IndexStoreTables, batch: typed_store::rocks::DBBatch, coin_index: &'a Mutex>, resolver: Box, } -impl<'a> ParMakeLiveObjectIndexer for RestParLiveObjectSetIndexer<'a> { - type ObjectIndexer = RestLiveObjectIndexer<'a>; +impl<'a> ParMakeLiveObjectIndexer for RpcParLiveObjectSetIndexer<'a> { + type ObjectIndexer = RpcLiveObjectIndexer<'a>; fn make_live_object_indexer(&self) -> Self::ObjectIndexer { - RestLiveObjectIndexer { + RpcLiveObjectIndexer { tables: self.tables, batch: self.tables.owner.batch(), coin_index: self.coin_index, @@ -658,7 +667,7 @@ impl<'a> ParMakeLiveObjectIndexer for RestParLiveObjectSetIndexer<'a> { } } -impl<'a> LiveObjectIndexer for RestLiveObjectIndexer<'a> { +impl<'a> LiveObjectIndexer for RpcLiveObjectIndexer<'a> { fn index_object(&mut self, object: Object) -> Result<(), StorageError> { match object.owner { // Owner Index diff --git a/crates/sui-core/src/storage.rs b/crates/sui-core/src/storage.rs index 4dc3e25107621..01b6a82b67b42 100644 --- a/crates/sui-core/src/storage.rs +++ b/crates/sui-core/src/storage.rs @@ -36,10 +36,10 @@ use crate::authority::AuthorityState; use crate::checkpoints::CheckpointStore; use crate::epoch::committee_store::CommitteeStore; use crate::execution_cache::ExecutionCacheTraitPointers; -use crate::rest_index::CoinIndexInfo; -use crate::rest_index::OwnerIndexInfo; -use crate::rest_index::OwnerIndexKey; -use crate::rest_index::RestIndexStore; +use crate::rpc_index::CoinIndexInfo; +use crate::rpc_index::OwnerIndexInfo; +use crate::rpc_index::OwnerIndexKey; +use crate::rpc_index::RpcIndexStore; #[derive(Clone)] pub struct RocksDbStore { @@ -341,9 +341,9 @@ impl RestReadStore { Self { state, rocks } } - fn index(&self) -> sui_types::storage::error::Result<&RestIndexStore> { + fn index(&self) -> sui_types::storage::error::Result<&RpcIndexStore> { self.state - .rest_index + .rpc_index .as_deref() .ok_or_else(|| sui_types::storage::error::Error::custom("rest index store is disabled")) } diff --git a/crates/sui-e2e-tests/tests/full_node_tests.rs b/crates/sui-e2e-tests/tests/full_node_tests.rs index 3db5442762edf..6c9648aadf533 100644 --- a/crates/sui-e2e-tests/tests/full_node_tests.rs +++ b/crates/sui-e2e-tests/tests/full_node_tests.rs @@ -1244,7 +1244,7 @@ async fn test_access_old_object_pruned() { .database_for_testing() .prune_objects_and_compact_for_testing( state.get_checkpoint_store(), - state.rest_index.as_deref(), + state.rpc_index.as_deref(), ) .await; // Make sure the old version of the object is already pruned. diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index ea1addf09cec2..fc5b3d11265cf 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -91,7 +91,7 @@ use sui_core::epoch::reconfiguration::ReconfigurationInitiator; use sui_core::jsonrpc_index::IndexStore; use sui_core::module_cache_metrics::ResolverMetrics; use sui_core::overload_monitor::overload_monitor; -use sui_core::rest_index::RestIndexStore; +use sui_core::rpc_index::RpcIndexStore; use sui_core::signature_verifier::SignatureVerifierMetrics; use sui_core::state_accumulator::StateAccumulator; use sui_core::storage::RocksDbStore; @@ -588,12 +588,12 @@ impl SuiNode { None }; - let rest_index = if is_full_node + let rpc_index = if is_full_node && config.enable_experimental_rest_api && config.enable_index_processing { - Some(Arc::new(RestIndexStore::new( - config.db_path().join("rest_index"), + Some(Arc::new(RpcIndexStore::new( + &config.db_path(), &store, &checkpoint_store, &epoch_store, @@ -696,7 +696,7 @@ impl SuiNode { epoch_store.clone(), committee_store.clone(), index_store.clone(), - rest_index, + rpc_index, checkpoint_store.clone(), &prometheus_registry, genesis.objects(), diff --git a/crates/sui-tool/src/db_tool/db_dump.rs b/crates/sui-tool/src/db_tool/db_dump.rs index 4149cd7be0e31..bbdda58c422b8 100644 --- a/crates/sui-tool/src/db_tool/db_dump.rs +++ b/crates/sui-tool/src/db_tool/db_dump.rs @@ -21,7 +21,7 @@ use sui_core::authority::authority_store_types::{StoreData, StoreObject}; use sui_core::checkpoints::CheckpointStore; use sui_core::epoch::committee_store::CommitteeStoreTables; use sui_core::jsonrpc_index::IndexStoreTables; -use sui_core::rest_index::RestIndexStore; +use sui_core::rpc_index::RpcIndexStore; use sui_storage::mutex_table::RwLockTable; use sui_types::base_types::{EpochId, ObjectID}; use tracing::info; @@ -204,7 +204,7 @@ pub async fn prune_objects(db_path: PathBuf) -> anyhow::Result<()> { None, None, )); - let rest_index = RestIndexStore::new_without_init(db_path.join("rest_index")); + let rpc_index = RpcIndexStore::new_without_init(&db_path); let highest_pruned_checkpoint = checkpoint_store.get_highest_pruned_checkpoint_seq_number()?; let latest_checkpoint = checkpoint_store.get_highest_executed_checkpoint()?; info!( @@ -223,7 +223,7 @@ pub async fn prune_objects(db_path: PathBuf) -> anyhow::Result<()> { AuthorityStorePruner::prune_objects_for_eligible_epochs( &perpetual_db, &checkpoint_store, - Some(&rest_index), + Some(&rpc_index), &lock_table, pruning_config, metrics, @@ -242,7 +242,7 @@ pub async fn prune_checkpoints(db_path: PathBuf) -> anyhow::Result<()> { None, None, )); - let rest_index = RestIndexStore::new_without_init(db_path.join("rest_index")); + let rpc_index = RpcIndexStore::new_without_init(&db_path); let metrics = AuthorityStorePruningMetrics::new(&Registry::default()); let lock_table = Arc::new(RwLockTable::new(1)); info!("Pruning setup for db at path: {:?}", db_path.display()); @@ -255,7 +255,7 @@ pub async fn prune_checkpoints(db_path: PathBuf) -> anyhow::Result<()> { AuthorityStorePruner::prune_checkpoints_for_eligible_epochs( &perpetual_db, &checkpoint_store, - Some(&rest_index), + Some(&rpc_index), &lock_table, pruning_config, metrics, From 7e313f27b5e4eafe74b255b8fafb36ab187e37a0 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 25 Nov 2024 15:51:45 -0600 Subject: [PATCH 05/28] rpc-indexes: separate out trait for accessing indexed data --- crates/simulacrum/src/lib.rs | 44 +------------------ crates/sui-core/src/storage.rs | 33 ++++++++------ crates/sui-rest-api/src/accounts.rs | 6 +-- crates/sui-rest-api/src/coins.rs | 5 ++- crates/sui-rest-api/src/error.rs | 7 +++ crates/sui-rest-api/src/objects.rs | 4 +- crates/sui-rest-api/src/reader.rs | 12 ++++- .../src/transactions/resolve/mod.rs | 2 + .../src/simulator_persisted_store.rs | 42 +----------------- crates/sui-types/src/storage/mod.rs | 1 + crates/sui-types/src/storage/read_store.rs | 15 ++++--- 11 files changed, 62 insertions(+), 109 deletions(-) diff --git a/crates/simulacrum/src/lib.rs b/crates/simulacrum/src/lib.rs index 954a710d4b494..826a0fc866157 100644 --- a/crates/simulacrum/src/lib.rs +++ b/crates/simulacrum/src/lib.rs @@ -16,7 +16,6 @@ use std::sync::Arc; use anyhow::{anyhow, Result}; use fastcrypto::traits::Signer; -use move_core_types::language_storage::StructTag; use rand::rngs::OsRng; use sui_config::verifier_signing_config::VerifierSigningConfig; use sui_config::{genesis, transaction_deny_config::TransactionDenyConfig}; @@ -550,15 +549,6 @@ impl ReadStore for Simulacrum { } impl RpcStateReader for Simulacrum { - fn get_transaction_checkpoint( - &self, - _digest: &sui_types::digests::TransactionDigest, - ) -> sui_types::storage::error::Result< - Option, - > { - todo!() - } - fn get_lowest_available_checkpoint_objects( &self, ) -> sui_types::storage::error::Result { @@ -577,38 +567,8 @@ impl RpcStateReader for .into()) } - fn account_owned_objects_info_iter( - &self, - _owner: SuiAddress, - _cursor: Option, - ) -> sui_types::storage::error::Result< - Box + '_>, - > { - todo!() - } - - fn dynamic_field_iter( - &self, - _parent: ObjectID, - _cursor: Option, - ) -> sui_types::storage::error::Result< - Box< - dyn Iterator< - Item = ( - sui_types::storage::DynamicFieldKey, - sui_types::storage::DynamicFieldIndexInfo, - ), - > + '_, - >, - > { - todo!() - } - - fn get_coin_info( - &self, - _coin_type: &StructTag, - ) -> sui_types::storage::error::Result> { - todo!() + fn indexes(&self) -> Option<&dyn sui_types::storage::RpcIndexes> { + None } } diff --git a/crates/sui-core/src/storage.rs b/crates/sui-core/src/storage.rs index 01b6a82b67b42..4bab83bfd1046 100644 --- a/crates/sui-core/src/storage.rs +++ b/crates/sui-core/src/storage.rs @@ -26,6 +26,7 @@ use sui_types::storage::CoinInfo; use sui_types::storage::DynamicFieldIndexInfo; use sui_types::storage::DynamicFieldKey; use sui_types::storage::ObjectStore; +use sui_types::storage::RpcIndexes; use sui_types::storage::RpcStateReader; use sui_types::storage::WriteStore; use sui_types::storage::{ObjectKey, ReadStore}; @@ -446,16 +447,6 @@ impl ReadStore for RestReadStore { } impl RpcStateReader for RestReadStore { - fn get_transaction_checkpoint( - &self, - digest: &TransactionDigest, - ) -> sui_types::storage::error::Result> { - self.index()? - .get_transaction_info(digest) - .map(|maybe_info| maybe_info.map(|info| info.checkpoint)) - .map_err(StorageError::custom) - } - fn get_lowest_available_checkpoint_objects( &self, ) -> sui_types::storage::error::Result { @@ -479,12 +470,27 @@ impl RpcStateReader for RestReadStore { .ok_or_else(|| StorageError::missing("unable to query chain identifier")) } + fn indexes(&self) -> Option<&dyn RpcIndexes> { + self.index().ok().map(|index| index as _) + } +} + +impl RpcIndexes for RpcIndexStore { + fn get_transaction_checkpoint( + &self, + digest: &TransactionDigest, + ) -> sui_types::storage::error::Result> { + self.get_transaction_info(digest) + .map(|maybe_info| maybe_info.map(|info| info.checkpoint)) + .map_err(StorageError::custom) + } + fn account_owned_objects_info_iter( &self, owner: SuiAddress, cursor: Option, ) -> Result + '_>> { - let iter = self.index()?.owner_iter(owner, cursor)?.map( + let iter = self.owner_iter(owner, cursor)?.map( |(OwnerIndexKey { owner, object_id }, OwnerIndexInfo { version, type_ })| { AccountOwnedObjectInfo { owner, @@ -505,7 +511,7 @@ impl RpcStateReader for RestReadStore { ) -> sui_types::storage::error::Result< Box + '_>, > { - let iter = self.index()?.dynamic_field_iter(parent, cursor)?; + let iter = self.dynamic_field_iter(parent, cursor)?; Ok(Box::new(iter) as _) } @@ -514,8 +520,7 @@ impl RpcStateReader for RestReadStore { &self, coin_type: &StructTag, ) -> sui_types::storage::error::Result> { - self.index()? - .get_coin_info(coin_type)? + self.get_coin_info(coin_type)? .map( |CoinIndexInfo { coin_metadata_object_id, diff --git a/crates/sui-rest-api/src/accounts.rs b/crates/sui-rest-api/src/accounts.rs index db06cc03bf940..a32583f225c29 100644 --- a/crates/sui-rest-api/src/accounts.rs +++ b/crates/sui-rest-api/src/accounts.rs @@ -4,7 +4,7 @@ use crate::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::reader::StateReader; use crate::{response::ResponseContent, Result}; -use crate::{Page, RestService}; +use crate::{Page, RestError, RestService}; use axum::extract::Query; use axum::extract::{Path, State}; use openapiv3::v3_1::Operation; @@ -49,11 +49,11 @@ async fn list_account_objects( Query(parameters): Query, State(state): State, ) -> Result> { + let indexes = state.inner().indexes().ok_or_else(RestError::not_found)?; let limit = parameters.limit(); let start = parameters.start(); - let mut object_info = state - .inner() + let mut object_info = indexes .account_owned_objects_info_iter(address.into(), start)? .take(limit + 1) .map(|info| { diff --git a/crates/sui-rest-api/src/coins.rs b/crates/sui-rest-api/src/coins.rs index ba1381e22b8f1..7cdb6eefcc53e 100644 --- a/crates/sui-rest-api/src/coins.rs +++ b/crates/sui-rest-api/src/coins.rs @@ -50,13 +50,14 @@ async fn get_coin_info( Path(coin_type): Path, State(state): State, ) -> Result> { + let indexes = state.inner().indexes().ok_or_else(RestError::not_found)?; + let core_coin_type = struct_tag_sdk_to_core(coin_type.clone())?; let sui_types::storage::CoinInfo { coin_metadata_object_id, treasury_object_id, - } = state - .inner() + } = indexes .get_coin_info(&core_coin_type)? .ok_or_else(|| CoinNotFoundError(coin_type.clone()))?; diff --git a/crates/sui-rest-api/src/error.rs b/crates/sui-rest-api/src/error.rs index f33cf4332d8af..1baf6c40a65f9 100644 --- a/crates/sui-rest-api/src/error.rs +++ b/crates/sui-rest-api/src/error.rs @@ -18,6 +18,13 @@ impl RestError { message: Some(message.into()), } } + + pub fn not_found() -> Self { + Self { + status: StatusCode::NOT_FOUND, + message: None, + } + } } // Tell axum how to convert `AppError` into a response. diff --git a/crates/sui-rest-api/src/objects.rs b/crates/sui-rest-api/src/objects.rs index 5bd04e0f8ad1a..21f7327cdef21 100644 --- a/crates/sui-rest-api/src/objects.rs +++ b/crates/sui-rest-api/src/objects.rs @@ -230,6 +230,7 @@ async fn list_dynamic_fields( accept: AcceptFormat, State(state): State, ) -> Result> { + let indexes = state.inner().indexes().ok_or_else(RestError::not_found)?; match accept { AcceptFormat::Json => {} _ => { @@ -243,8 +244,7 @@ async fn list_dynamic_fields( let limit = parameters.limit(); let start = parameters.start(); - let mut dynamic_fields = state - .inner() + let mut dynamic_fields = indexes .dynamic_field_iter(parent.into(), start)? .take(limit + 1) .map(DynamicFieldInfo::try_from) diff --git a/crates/sui-rest-api/src/reader.rs b/crates/sui-rest-api/src/reader.rs index a586614cd37f4..d7a7c884d5fa4 100644 --- a/crates/sui-rest-api/src/reader.rs +++ b/crates/sui-rest-api/src/reader.rs @@ -103,6 +103,16 @@ impl StateReader { )) } + pub fn get_transaction_checkpoint( + &self, + digest: &sui_types::digests::TransactionDigest, + ) -> Option { + self.inner() + .indexes()? + .get_transaction_checkpoint(digest) + .ok()? + } + pub fn get_transaction_response( &self, digest: sui_sdk_types::types::TransactionDigest, @@ -116,7 +126,7 @@ impl StateReader { events, ) = self.get_transaction(digest)?; - let checkpoint = self.inner().get_transaction_checkpoint(&(digest.into()))?; + let checkpoint = self.get_transaction_checkpoint(&(digest.into())); let timestamp_ms = if let Some(checkpoint) = checkpoint { self.inner() .get_checkpoint_by_sequence_number(checkpoint) diff --git a/crates/sui-rest-api/src/transactions/resolve/mod.rs b/crates/sui-rest-api/src/transactions/resolve/mod.rs index 3e359d46e0e95..573a62e1adafc 100644 --- a/crates/sui-rest-api/src/transactions/resolve/mod.rs +++ b/crates/sui-rest-api/src/transactions/resolve/mod.rs @@ -810,6 +810,8 @@ fn select_gas( //TODO implement index of gas coins sorted in order of decreasing value let gas_coins = reader .inner() + .indexes() + .ok_or_else(RestError::not_found)? .account_owned_objects_info_iter(owner, None)? .filter(|info| info.type_.is_gas_coin()) .filter(|info| !input_objects.contains(&info.object_id)) diff --git a/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs b/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs index c0b42e57a3d1d..72c021f859db0 100644 --- a/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs +++ b/crates/sui-transactional-test-runner/src/simulator_persisted_store.rs @@ -5,7 +5,6 @@ use std::{collections::BTreeMap, path::PathBuf, sync::Arc, time::Duration}; use move_binary_format::CompiledModule; use move_bytecode_utils::module_cache::GetModule; -use move_core_types::language_storage::StructTag; use move_core_types::{language_storage::ModuleId, resolver::ModuleResolver}; use simulacrum::Simulacrum; use std::num::NonZeroUsize; @@ -658,13 +657,6 @@ impl ReadStore for PersistedStoreInnerReadOnlyWrapper { } impl RpcStateReader for PersistedStoreInnerReadOnlyWrapper { - fn get_transaction_checkpoint( - &self, - _digest: &TransactionDigest, - ) -> sui_types::storage::error::Result> { - todo!() - } - fn get_lowest_available_checkpoint_objects( &self, ) -> sui_types::storage::error::Result { @@ -677,38 +669,8 @@ impl RpcStateReader for PersistedStoreInnerReadOnlyWrapper { Ok((*self.get_checkpoint_by_sequence_number(0).unwrap().digest()).into()) } - fn account_owned_objects_info_iter( - &self, - _owner: SuiAddress, - _cursor: Option, - ) -> sui_types::storage::error::Result< - Box + '_>, - > { - todo!() - } - - fn dynamic_field_iter( - &self, - _parent: ObjectID, - _cursor: Option, - ) -> sui_types::storage::error::Result< - Box< - dyn Iterator< - Item = ( - sui_types::storage::DynamicFieldKey, - sui_types::storage::DynamicFieldIndexInfo, - ), - > + '_, - >, - > { - todo!() - } - - fn get_coin_info( - &self, - _coin_type: &StructTag, - ) -> sui_types::storage::error::Result> { - todo!() + fn indexes(&self) -> Option<&dyn sui_types::storage::RpcIndexes> { + None } } diff --git a/crates/sui-types/src/storage/mod.rs b/crates/sui-types/src/storage/mod.rs index fa8ea24464687..671099a7cc0ae 100644 --- a/crates/sui-types/src/storage/mod.rs +++ b/crates/sui-types/src/storage/mod.rs @@ -27,6 +27,7 @@ pub use read_store::CoinInfo; pub use read_store::DynamicFieldIndexInfo; pub use read_store::DynamicFieldKey; pub use read_store::ReadStore; +pub use read_store::RpcIndexes; pub use read_store::RpcStateReader; use serde::{Deserialize, Serialize}; use serde_with::serde_as; diff --git a/crates/sui-types/src/storage/read_store.rs b/crates/sui-types/src/storage/read_store.rs index 893c76515fe02..7406d2e45bab1 100644 --- a/crates/sui-types/src/storage/read_store.rs +++ b/crates/sui-types/src/storage/read_store.rs @@ -599,11 +599,6 @@ impl ReadStore for Arc { /// It extends both ObjectStore and ReadStore by adding functionality that may require more /// detailed underlying databases or indexes to support. pub trait RpcStateReader: ObjectStore + ReadStore + Send + Sync { - fn get_transaction_checkpoint( - &self, - digest: &TransactionDigest, - ) -> Result>; - /// Lowest available checkpoint for which object data can be requested. /// /// Specifically this is the lowest checkpoint for which input/output object data will be @@ -612,6 +607,16 @@ pub trait RpcStateReader: ObjectStore + ReadStore + Send + Sync { fn get_chain_identifier(&self) -> Result; + // Get a handle to an instance of the RpcIndexes + fn indexes(&self) -> Option<&dyn RpcIndexes>; +} + +pub trait RpcIndexes: Send + Sync { + fn get_transaction_checkpoint( + &self, + digest: &TransactionDigest, + ) -> Result>; + fn account_owned_objects_info_iter( &self, owner: SuiAddress, From c64b514c096f612e5fa53b0661917ed58fe18efc Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 25 Nov 2024 16:21:54 -0600 Subject: [PATCH 06/28] rest: move openapi tests to its own file --- crates/sui-rest-api/src/lib.rs | 66 +--------------------------- crates/sui-rest-api/tests/openapi.rs | 62 ++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 64 deletions(-) create mode 100644 crates/sui-rest-api/tests/openapi.rs diff --git a/crates/sui-rest-api/src/lib.rs b/crates/sui-rest-api/src/lib.rs index 82fd98b0b4461..c7d2390c34a48 100644 --- a/crates/sui-rest-api/src/lib.rs +++ b/crates/sui-rest-api/src/lib.rs @@ -102,7 +102,7 @@ impl axum::response::IntoResponse for } } -const ENDPOINTS: &[&dyn ApiEndpoint] = &[ +pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ // stable APIs &info::GetNodeInfo, &health::HealthCheck, @@ -228,7 +228,7 @@ impl RestService { } } -fn info(version: &'static str) -> openapiv3::v3_1::Info { +pub fn info(version: &'static str) -> openapiv3::v3_1::Info { use openapiv3::v3_1::Contact; use openapiv3::v3_1::License; @@ -310,65 +310,3 @@ mod _schemars { } } } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn openapi_spec() { - const OPENAPI_SPEC_FILE: &str = - concat!(env!("CARGO_MANIFEST_DIR"), "/openapi/openapi.json"); - - let openapi = { - let mut api = openapi::Api::new(info("unknown")); - - api.register_endpoints(ENDPOINTS.iter().copied()); - api.openapi() - }; - - let mut actual = serde_json::to_string_pretty(&openapi).unwrap(); - actual.push('\n'); - - // Update the expected format - if std::env::var_os("UPDATE").is_some() { - std::fs::write(OPENAPI_SPEC_FILE, &actual).unwrap(); - } - - let expected = std::fs::read_to_string(OPENAPI_SPEC_FILE).unwrap(); - - let diff = diffy::create_patch(&expected, &actual); - - if !diff.hunks().is_empty() { - let formatter = if std::io::IsTerminal::is_terminal(&std::io::stderr()) { - diffy::PatchFormatter::new().with_color() - } else { - diffy::PatchFormatter::new() - }; - let header = "Generated and checked-in openapi spec does not match. \ - Re-run with `UPDATE=1` to update expected format"; - panic!("{header}\n\n{}", formatter.fmt_patch(&diff)); - } - } - - #[tokio::test] - async fn openapi_explorer() { - // Unless env var is set, just early return - if std::env::var_os("OPENAPI_EXPLORER").is_none() { - return; - } - - let openapi = { - let mut api = openapi::Api::new(info("unknown")); - api.register_endpoints(ENDPOINTS.to_owned()); - api.openapi() - }; - - let router = openapi::OpenApiDocument::new(openapi).into_router(); - - let listener = tokio::net::TcpListener::bind("127.0.0.1:8000") - .await - .unwrap(); - axum::serve(listener, router).await.unwrap(); - } -} diff --git a/crates/sui-rest-api/tests/openapi.rs b/crates/sui-rest-api/tests/openapi.rs new file mode 100644 index 0000000000000..700b17aef125d --- /dev/null +++ b/crates/sui-rest-api/tests/openapi.rs @@ -0,0 +1,62 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use sui_rest_api::openapi; +use sui_rest_api::ENDPOINTS; +use sui_rest_api::info; + +#[test] +fn openapi_spec() { + const OPENAPI_SPEC_FILE: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/openapi/openapi.json"); + + let openapi = { + let mut api = openapi::Api::new(info("unknown")); + + api.register_endpoints(ENDPOINTS.iter().copied()); + api.openapi() + }; + + let mut actual = serde_json::to_string_pretty(&openapi).unwrap(); + actual.push('\n'); + + // Update the expected format + if std::env::var_os("UPDATE").is_some() { + std::fs::write(OPENAPI_SPEC_FILE, &actual).unwrap(); + } + + let expected = std::fs::read_to_string(OPENAPI_SPEC_FILE).unwrap(); + + let diff = diffy::create_patch(&expected, &actual); + + if !diff.hunks().is_empty() { + let formatter = if std::io::IsTerminal::is_terminal(&std::io::stderr()) { + diffy::PatchFormatter::new().with_color() + } else { + diffy::PatchFormatter::new() + }; + let header = "Generated and checked-in openapi spec does not match. \ + Re-run with `UPDATE=1` to update expected format"; + panic!("{header}\n\n{}", formatter.fmt_patch(&diff)); + } +} + +#[tokio::test] +async fn openapi_explorer() { + // Unless env var is set, just early return + if std::env::var_os("OPENAPI_EXPLORER").is_none() { + return; + } + + let openapi = { + let mut api = openapi::Api::new(info("unknown")); + api.register_endpoints(ENDPOINTS.to_owned()); + api.openapi() + }; + + let router = openapi::OpenApiDocument::new(openapi).into_router(); + + let listener = tokio::net::TcpListener::bind("127.0.0.1:8000") + .await + .unwrap(); + axum::serve(listener, router).await.unwrap(); +} From bcfdd98990163b2c067e07c91c530b54886672f0 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 25 Nov 2024 16:29:19 -0600 Subject: [PATCH 07/28] rest: move config into its own module --- crates/sui-rest-api/src/config.rs | 28 ++++++++++++++++++++++++++++ crates/sui-rest-api/src/lib.rs | 27 ++------------------------- 2 files changed, 30 insertions(+), 25 deletions(-) create mode 100644 crates/sui-rest-api/src/config.rs diff --git a/crates/sui-rest-api/src/config.rs b/crates/sui-rest-api/src/config.rs new file mode 100644 index 0000000000000..b35ad6a670740 --- /dev/null +++ b/crates/sui-rest-api/src/config.rs @@ -0,0 +1,28 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct Config { + /// Enable serving of unstable APIs + /// + /// Defaults to `false`, with unstable APIs being disabled + #[serde(skip_serializing_if = "Option::is_none")] + pub enable_unstable_apis: Option, + + // Only include this till we have another field that isn't set with a non-default value for + // testing + #[doc(hidden)] + #[serde(skip)] + pub _hidden: (), +} + +impl Config { + pub fn enable_unstable_apis(&self) -> bool { + // TODO + // Until the rest service as a whole is "stabalized" with a sane set of default stable + // apis, have the default be to enable all apis + self.enable_unstable_apis.unwrap_or(true) + } +} + diff --git a/crates/sui-rest-api/src/lib.rs b/crates/sui-rest-api/src/lib.rs index c7d2390c34a48..8482f9d34fb61 100644 --- a/crates/sui-rest-api/src/lib.rs +++ b/crates/sui-rest-api/src/lib.rs @@ -20,6 +20,7 @@ mod checkpoints; pub mod client; mod coins; mod committee; +mod config; pub mod content_type; mod error; mod health; @@ -42,6 +43,7 @@ pub use metrics::RestMetrics; pub use objects::ObjectResponse; pub use sui_types::full_checkpoint_content::{CheckpointData, CheckpointTransaction}; pub use transactions::ExecuteTransactionQueryParameters; +pub use config::Config; pub const TEXT_PLAIN_UTF_8: &str = "text/plain; charset=utf-8"; pub const APPLICATION_BCS: &str = "application/bcs"; @@ -254,31 +256,6 @@ async fn redirect(axum::extract::Path(path): axum::extract::Path) -> Red Redirect::permanent(&format!("/v2/{path}")) } -#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct Config { - /// Enable serving of unstable APIs - /// - /// Defaults to `false`, with unstable APIs being disabled - #[serde(skip_serializing_if = "Option::is_none")] - pub enable_unstable_apis: Option, - - // Only include this till we have another field that isn't set with a non-default value for - // testing - #[doc(hidden)] - #[serde(skip)] - pub _hidden: (), -} - -impl Config { - pub fn enable_unstable_apis(&self) -> bool { - // TODO - // Until the rest service as a whole is "stabalized" with a sane set of default stable - // apis, have the default be to enable all apis - self.enable_unstable_apis.unwrap_or(true) - } -} - mod _schemars { use schemars::schema::InstanceType; use schemars::schema::Metadata; From b348cb8f253879fc56d077998ceeab0bca86942c Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Mon, 25 Nov 2024 17:01:05 -0600 Subject: [PATCH 08/28] rest: move rest infra into a module --- .../sui-e2e-tests/tests/rest/checkpoints.rs | 31 ++- crates/sui-e2e-tests/tests/rest/committee.rs | 12 +- crates/sui-e2e-tests/tests/rest/objects.rs | 12 +- crates/sui-e2e-tests/tests/rest/resolve.rs | 2 +- .../sui-e2e-tests/tests/rest/transactions.rs | 26 ++- crates/sui-rest-api/src/client/mod.rs | 4 +- crates/sui-rest-api/src/client/sdk.rs | 50 ++--- crates/sui-rest-api/src/config.rs | 1 - crates/sui-rest-api/src/lib.rs | 208 ++---------------- crates/sui-rest-api/src/proto/mod.rs | 70 +++--- crates/sui-rest-api/src/reader.rs | 8 +- crates/sui-rest-api/src/response.rs | 8 +- crates/sui-rest-api/src/{ => rest}/accept.rs | 0 .../sui-rest-api/src/{ => rest}/accounts.rs | 12 +- .../src/{ => rest}/checkpoints.rs | 12 +- crates/sui-rest-api/src/{ => rest}/coins.rs | 6 +- .../sui-rest-api/src/{ => rest}/committee.rs | 4 +- .../src/{ => rest}/content_type.rs | 0 crates/sui-rest-api/src/{ => rest}/health.rs | 4 +- crates/sui-rest-api/src/{ => rest}/info.rs | 14 +- crates/sui-rest-api/src/rest/mod.rs | 192 ++++++++++++++++ crates/sui-rest-api/src/{ => rest}/objects.rs | 17 +- crates/sui-rest-api/src/{ => rest}/openapi.rs | 10 +- crates/sui-rest-api/src/{ => rest}/system.rs | 97 ++++---- .../src/{ => rest}/transactions/execution.rs | 8 +- .../src/{ => rest}/transactions/mod.rs | 20 +- .../transactions/resolve/literal.rs | 0 .../{ => rest}/transactions/resolve/mod.rs | 14 +- crates/sui-rest-api/tests/openapi.rs | 6 +- 29 files changed, 461 insertions(+), 387 deletions(-) rename crates/sui-rest-api/src/{ => rest}/accept.rs (100%) rename crates/sui-rest-api/src/{ => rest}/accounts.rs (89%) rename crates/sui-rest-api/src/{ => rest}/checkpoints.rs (97%) rename crates/sui-rest-api/src/{ => rest}/coins.rs (95%) rename crates/sui-rest-api/src/{ => rest}/committee.rs (97%) rename crates/sui-rest-api/src/{ => rest}/content_type.rs (100%) rename crates/sui-rest-api/src/{ => rest}/health.rs (94%) rename crates/sui-rest-api/src/{ => rest}/info.rs (88%) create mode 100644 crates/sui-rest-api/src/rest/mod.rs rename crates/sui-rest-api/src/{ => rest}/objects.rs (94%) rename crates/sui-rest-api/src/{ => rest}/openapi.rs (98%) rename crates/sui-rest-api/src/{ => rest}/system.rs (92%) rename crates/sui-rest-api/src/{ => rest}/transactions/execution.rs (99%) rename crates/sui-rest-api/src/{ => rest}/transactions/mod.rs (95%) rename crates/sui-rest-api/src/{ => rest}/transactions/resolve/literal.rs (100%) rename crates/sui-rest-api/src/{ => rest}/transactions/resolve/mod.rs (98%) diff --git a/crates/sui-e2e-tests/tests/rest/checkpoints.rs b/crates/sui-e2e-tests/tests/rest/checkpoints.rs index d72ac52afdf61..bc6ec1a005876 100644 --- a/crates/sui-e2e-tests/tests/rest/checkpoints.rs +++ b/crates/sui-e2e-tests/tests/rest/checkpoints.rs @@ -37,7 +37,10 @@ async fn list_checkpoint() { // Make sure list works with json let _checkpoints = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_JSON) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_JSON, + ) .send() .await .unwrap() @@ -48,7 +51,10 @@ async fn list_checkpoint() { // Make sure list works with protobuf let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_PROTOBUF) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_PROTOBUF, + ) .send() .await .unwrap() @@ -62,7 +68,7 @@ async fn list_checkpoint() { // Make sure list works with BCS and the old format of only a SignedCheckpoint with no contents let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) .send() .await .unwrap() @@ -95,7 +101,10 @@ async fn get_checkpoint() { // Make sure list works with json let _checkpoints = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_JSON) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_JSON, + ) .send() .await .unwrap() @@ -106,7 +115,10 @@ async fn get_checkpoint() { // Make sure it works with protobuf let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_PROTOBUF) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_PROTOBUF, + ) .send() .await .unwrap() @@ -119,7 +131,7 @@ async fn get_checkpoint() { // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) .send() .await .unwrap() @@ -157,7 +169,10 @@ async fn get_full_checkpoint() { // Make sure it works with protobuf let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_PROTOBUF) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_PROTOBUF, + ) .send() .await .unwrap() @@ -170,7 +185,7 @@ async fn get_full_checkpoint() { // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-e2e-tests/tests/rest/committee.rs b/crates/sui-e2e-tests/tests/rest/committee.rs index 6e4b2227483fe..5edb4be13b80c 100644 --- a/crates/sui-e2e-tests/tests/rest/committee.rs +++ b/crates/sui-e2e-tests/tests/rest/committee.rs @@ -22,7 +22,10 @@ async fn get_committee() { // Make sure list works with json let _object = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_JSON) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_JSON, + ) .send() .await .unwrap() @@ -33,7 +36,10 @@ async fn get_committee() { // Make sure it works with protobuf let bytes = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_PROTOBUF) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_PROTOBUF, + ) .send() .await .unwrap() @@ -46,7 +52,7 @@ async fn get_committee() { // protobuf version let bytes = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-e2e-tests/tests/rest/objects.rs b/crates/sui-e2e-tests/tests/rest/objects.rs index afbcddd1f0fae..a87ab513009a0 100644 --- a/crates/sui-e2e-tests/tests/rest/objects.rs +++ b/crates/sui-e2e-tests/tests/rest/objects.rs @@ -37,7 +37,10 @@ async fn get_object() { // Make sure list works with json let _object = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_JSON) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_JSON, + ) .send() .await .unwrap() @@ -48,7 +51,10 @@ async fn get_object() { // Make sure it works with protobuf let bytes = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_PROTOBUF) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_PROTOBUF, + ) .send() .await .unwrap() @@ -61,7 +67,7 @@ async fn get_object() { // protobuf version let bytes = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-e2e-tests/tests/rest/resolve.rs b/crates/sui-e2e-tests/tests/rest/resolve.rs index 5ad8b6d7e7ec5..dd9d9858f8f54 100644 --- a/crates/sui-e2e-tests/tests/rest/resolve.rs +++ b/crates/sui-e2e-tests/tests/rest/resolve.rs @@ -5,7 +5,7 @@ use shared_crypto::intent::Intent; use sui_keys::keystore::AccountKeystore; use sui_macros::sim_test; use sui_rest_api::client::reqwest::StatusCode; -use sui_rest_api::transactions::ResolveTransactionQueryParameters; +use sui_rest_api::rest::transactions::ResolveTransactionQueryParameters; use sui_rest_api::Client; use sui_rest_api::ExecuteTransactionQueryParameters; use sui_sdk_types::types::unresolved; diff --git a/crates/sui-e2e-tests/tests/rest/transactions.rs b/crates/sui-e2e-tests/tests/rest/transactions.rs index 13b2d9925ff73..77a9ae649e233 100644 --- a/crates/sui-e2e-tests/tests/rest/transactions.rs +++ b/crates/sui-e2e-tests/tests/rest/transactions.rs @@ -4,7 +4,7 @@ use prost::Message; use sui_macros::sim_test; use sui_rest_api::client::sdk::Client; -use sui_rest_api::transactions::{ListTransactionsQueryParameters, TransactionResponse}; +use sui_rest_api::rest::transactions::{ListTransactionsQueryParameters, TransactionResponse}; use test_cluster::TestClusterBuilder; use crate::transfer_coin; @@ -28,7 +28,10 @@ async fn get_transaction() { // Make sure it works with json let _transaction = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_JSON) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_JSON, + ) .send() .await .unwrap() @@ -39,7 +42,10 @@ async fn get_transaction() { // Make sure it works with protobuf let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_PROTOBUF) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_PROTOBUF, + ) .send() .await .unwrap() @@ -52,7 +58,7 @@ async fn get_transaction() { // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) .send() .await .unwrap() @@ -83,7 +89,10 @@ async fn list_checkpoint() { // Make sure it works with json let _transactions = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_JSON) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_JSON, + ) .send() .await .unwrap() @@ -94,7 +103,10 @@ async fn list_checkpoint() { // Make sure it works with protobuf let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_PROTOBUF) + .header( + reqwest::header::ACCEPT, + sui_rest_api::rest::APPLICATION_PROTOBUF, + ) .send() .await .unwrap() @@ -107,7 +119,7 @@ async fn list_checkpoint() { // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-rest-api/src/client/mod.rs b/crates/sui-rest-api/src/client/mod.rs index d9cbe0f5ca7f0..35555e4a44162 100644 --- a/crates/sui-rest-api/src/client/mod.rs +++ b/crates/sui-rest-api/src/client/mod.rs @@ -6,7 +6,7 @@ use sdk::Result; pub use reqwest; -use crate::transactions::ExecuteTransactionQueryParameters; +use crate::rest::transactions::ExecuteTransactionQueryParameters; use sui_types::base_types::{ObjectID, SequenceNumber, SuiAddress}; use sui_types::crypto::AuthorityStrongQuorumSignInfo; use sui_types::effects::{TransactionEffects, TransactionEvents}; @@ -122,7 +122,7 @@ impl Client { .client() .post(url) .query(parameters) - .header(reqwest::header::CONTENT_TYPE, crate::APPLICATION_BCS) + .header(reqwest::header::CONTENT_TYPE, crate::rest::APPLICATION_BCS) .body(body); self.inner.bcs(request).await.map(Response::into_inner) diff --git a/crates/sui-rest-api/src/client/sdk.rs b/crates/sui-rest-api/src/client/sdk.rs index c249e4f34fa41..55338c27dede6 100644 --- a/crates/sui-rest-api/src/client/sdk.rs +++ b/crates/sui-rest-api/src/client/sdk.rs @@ -21,26 +21,26 @@ use sui_sdk_types::types::ValidatorCommittee; use sui_sdk_types::types::Version; use tap::Pipe; -use crate::accounts::AccountOwnedObjectInfo; -use crate::accounts::ListAccountOwnedObjectsQueryParameters; -use crate::checkpoints::CheckpointResponse; -use crate::checkpoints::ListCheckpointsQueryParameters; -use crate::coins::CoinInfo; -use crate::health::Threshold; -use crate::info::NodeInfo; -use crate::objects::DynamicFieldInfo; -use crate::objects::ListDynamicFieldsQueryParameters; -use crate::system::GasInfo; -use crate::system::ProtocolConfigResponse; -use crate::system::SystemStateSummary; -use crate::system::X_SUI_MAX_SUPPORTED_PROTOCOL_VERSION; -use crate::system::X_SUI_MIN_SUPPORTED_PROTOCOL_VERSION; -use crate::transactions::ListTransactionsQueryParameters; -use crate::transactions::ResolveTransactionQueryParameters; -use crate::transactions::ResolveTransactionResponse; -use crate::transactions::TransactionExecutionResponse; -use crate::transactions::TransactionResponse; -use crate::transactions::TransactionSimulationResponse; +use crate::rest::accounts::AccountOwnedObjectInfo; +use crate::rest::accounts::ListAccountOwnedObjectsQueryParameters; +use crate::rest::checkpoints::CheckpointResponse; +use crate::rest::checkpoints::ListCheckpointsQueryParameters; +use crate::rest::coins::CoinInfo; +use crate::rest::health::Threshold; +use crate::rest::info::NodeInfo; +use crate::rest::objects::DynamicFieldInfo; +use crate::rest::objects::ListDynamicFieldsQueryParameters; +use crate::rest::system::GasInfo; +use crate::rest::system::ProtocolConfigResponse; +use crate::rest::system::SystemStateSummary; +use crate::rest::system::X_SUI_MAX_SUPPORTED_PROTOCOL_VERSION; +use crate::rest::system::X_SUI_MIN_SUPPORTED_PROTOCOL_VERSION; +use crate::rest::transactions::ListTransactionsQueryParameters; +use crate::rest::transactions::ResolveTransactionQueryParameters; +use crate::rest::transactions::ResolveTransactionResponse; +use crate::rest::transactions::TransactionExecutionResponse; +use crate::rest::transactions::TransactionResponse; +use crate::rest::transactions::TransactionSimulationResponse; use crate::types::X_SUI_CHAIN; use crate::types::X_SUI_CHAIN_ID; use crate::types::X_SUI_CHECKPOINT_HEIGHT; @@ -324,7 +324,7 @@ impl Client { .inner .post(url) .query(parameters) - .header(reqwest::header::CONTENT_TYPE, crate::APPLICATION_BCS) + .header(reqwest::header::CONTENT_TYPE, crate::rest::APPLICATION_BCS) .body(body); self.bcs(request).await @@ -341,7 +341,7 @@ impl Client { let request = self .inner .post(url) - .header(reqwest::header::CONTENT_TYPE, crate::APPLICATION_BCS) + .header(reqwest::header::CONTENT_TYPE, crate::rest::APPLICATION_BCS) .body(body); self.bcs(request).await @@ -403,7 +403,7 @@ impl Client { request: reqwest::RequestBuilder, ) -> Result> { let response = request - .header(reqwest::header::ACCEPT, crate::APPLICATION_JSON) + .header(reqwest::header::ACCEPT, crate::rest::APPLICATION_JSON) .send() .await?; @@ -418,7 +418,7 @@ impl Client { request: reqwest::RequestBuilder, ) -> Result> { let response = request - .header(reqwest::header::ACCEPT, crate::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, crate::rest::APPLICATION_BCS) .send() .await?; @@ -437,7 +437,7 @@ impl Client { request: reqwest::RequestBuilder, ) -> Result> { let response = request - .header(reqwest::header::ACCEPT, crate::APPLICATION_PROTOBUF) + .header(reqwest::header::ACCEPT, crate::rest::APPLICATION_PROTOBUF) .send() .await?; diff --git a/crates/sui-rest-api/src/config.rs b/crates/sui-rest-api/src/config.rs index b35ad6a670740..9d1bfa0580cbb 100644 --- a/crates/sui-rest-api/src/config.rs +++ b/crates/sui-rest-api/src/config.rs @@ -25,4 +25,3 @@ impl Config { self.enable_unstable_apis.unwrap_or(true) } } - diff --git a/crates/sui-rest-api/src/lib.rs b/crates/sui-rest-api/src/lib.rs index 8482f9d34fb61..f6966349ce4aa 100644 --- a/crates/sui-rest-api/src/lib.rs +++ b/crates/sui-rest-api/src/lib.rs @@ -1,134 +1,33 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use axum::{ - response::{Redirect, ResponseParts}, - routing::get, - Router, -}; use mysten_network::callback::CallbackLayer; -use openapi::ApiEndpoint; use reader::StateReader; +use rest::build_rest_router; use std::sync::Arc; use sui_types::storage::RpcStateReader; use sui_types::transaction_executor::TransactionExecutor; use tap::Pipe; -pub mod accept; -mod accounts; -mod checkpoints; pub mod client; -mod coins; -mod committee; mod config; -pub mod content_type; mod error; -mod health; -mod info; mod metrics; -mod objects; -pub mod openapi; pub mod proto; mod reader; mod response; -mod system; -pub mod transactions; +pub mod rest; pub mod types; -pub use checkpoints::CheckpointResponse; -pub use checkpoints::ListCheckpointsQueryParameters; pub use client::Client; +pub use config::Config; pub use error::{RestError, Result}; pub use metrics::RestMetrics; -pub use objects::ObjectResponse; +pub use rest::checkpoints::CheckpointResponse; +pub use rest::checkpoints::ListCheckpointsQueryParameters; +pub use rest::objects::ObjectResponse; +pub use rest::transactions::ExecuteTransactionQueryParameters; pub use sui_types::full_checkpoint_content::{CheckpointData, CheckpointTransaction}; -pub use transactions::ExecuteTransactionQueryParameters; -pub use config::Config; - -pub const TEXT_PLAIN_UTF_8: &str = "text/plain; charset=utf-8"; -pub const APPLICATION_BCS: &str = "application/bcs"; -pub const APPLICATION_JSON: &str = "application/json"; -pub const APPLICATION_PROTOBUF: &str = "application/x-protobuf"; - -#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] -#[serde(rename_all = "lowercase")] -pub enum Direction { - Ascending, - Descending, -} - -impl Direction { - pub fn is_descending(self) -> bool { - matches!(self, Self::Descending) - } -} - -#[derive(Debug)] -pub struct Page { - pub entries: response::ResponseContent>, - pub cursor: Option, -} - -pub struct PageCursor(pub Option); - -impl axum::response::IntoResponseParts for PageCursor { - type Error = (axum::http::StatusCode, String); - - fn into_response_parts( - self, - res: ResponseParts, - ) -> std::result::Result { - self.0 - .map(|cursor| [(crate::types::X_SUI_CURSOR, cursor.to_string())]) - .into_response_parts(res) - .map_err(|e| (axum::http::StatusCode::INTERNAL_SERVER_ERROR, e.to_string())) - } -} - -impl axum::response::IntoResponse for PageCursor { - fn into_response(self) -> axum::response::Response { - (self, ()).into_response() - } -} - -pub const DEFAULT_PAGE_SIZE: usize = 50; -pub const MAX_PAGE_SIZE: usize = 100; - -impl axum::response::IntoResponse for Page { - fn into_response(self) -> axum::response::Response { - let cursor = self - .cursor - .map(|cursor| [(crate::types::X_SUI_CURSOR, cursor.to_string())]); - - (cursor, self.entries).into_response() - } -} - -pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ - // stable APIs - &info::GetNodeInfo, - &health::HealthCheck, - &checkpoints::ListCheckpoints, - &checkpoints::GetCheckpoint, - // unstable APIs - &accounts::ListAccountObjects, - &objects::GetObject, - &objects::GetObjectWithVersion, - &objects::ListDynamicFields, - &checkpoints::GetFullCheckpoint, - &transactions::GetTransaction, - &transactions::ListTransactions, - &committee::GetCommittee, - &committee::GetLatestCommittee, - &system::GetSystemStateSummary, - &system::GetCurrentProtocolConfig, - &system::GetProtocolConfig, - &system::GetGasInfo, - &transactions::ExecuteTransaction, - &transactions::SimulateTransaction, - &transactions::ResolveTransaction, - &coins::GetCoinInfo, -]; #[derive(Clone)] pub struct RestService { @@ -140,18 +39,6 @@ pub struct RestService { config: Config, } -impl axum::extract::FromRef for StateReader { - fn from_ref(input: &RestService) -> Self { - input.reader.clone() - } -} - -impl axum::extract::FromRef for Option> { - fn from_ref(input: &RestService) -> Self { - input.executor.clone() - } -} - impl RestService { pub fn new(reader: Arc, software_version: &'static str) -> Self { let chain_id = reader.get_chain_identifier().unwrap(); @@ -189,26 +76,12 @@ impl RestService { self.software_version } - pub fn into_router(self) -> Router { + pub fn into_router(self) -> axum::Router { let metrics = self.metrics.clone(); - let mut api = openapi::Api::new(info(self.software_version())); - - api.register_endpoints( - ENDPOINTS - .iter() - .copied() - .filter(|endpoint| endpoint.stable() || self.config.enable_unstable_apis()), - ); + let rest_router = build_rest_router(self.clone()); - Router::new() - .nest("/v2/", api.to_router().with_state(self.clone())) - .route("/v2", get(|| async { Redirect::permanent("/v2/") })) - // Previously the service used to be hosted at `/rest`. In an effort to migrate folks - // to the new versioned route, we'll issue redirects from `/rest` -> `/v2`. - .route("/rest/*path", axum::routing::method_routing::any(redirect)) - .route("/rest", get(|| async { Redirect::permanent("/v2/") })) - .route("/rest/", get(|| async { Redirect::permanent("/v2/") })) + rest_router .layer(axum::middleware::map_response_with_state( self, response::append_info_headers, @@ -230,60 +103,15 @@ impl RestService { } } -pub fn info(version: &'static str) -> openapiv3::v3_1::Info { - use openapiv3::v3_1::Contact; - use openapiv3::v3_1::License; - - openapiv3::v3_1::Info { - title: "Sui Node Api".to_owned(), - description: Some("REST Api for interacting with the Sui Blockchain".to_owned()), - contact: Some(Contact { - name: Some("Mysten Labs".to_owned()), - url: Some("https://github.com/MystenLabs/sui".to_owned()), - ..Default::default() - }), - license: Some(License { - name: "Apache 2.0".to_owned(), - url: Some("https://www.apache.org/licenses/LICENSE-2.0.html".to_owned()), - ..Default::default() - }), - version: version.to_owned(), - ..Default::default() - } -} - -async fn redirect(axum::extract::Path(path): axum::extract::Path) -> Redirect { - Redirect::permanent(&format!("/v2/{path}")) +#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum Direction { + Ascending, + Descending, } -mod _schemars { - use schemars::schema::InstanceType; - use schemars::schema::Metadata; - use schemars::schema::SchemaObject; - use schemars::JsonSchema; - - pub(crate) struct U64; - - impl JsonSchema for U64 { - fn schema_name() -> String { - "u64".to_owned() - } - - fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - SchemaObject { - metadata: Some(Box::new(Metadata { - description: Some("Radix-10 encoded 64-bit unsigned integer".to_owned()), - ..Default::default() - })), - instance_type: Some(InstanceType::String.into()), - format: Some("u64".to_owned()), - ..Default::default() - } - .into() - } - - fn is_referenceable() -> bool { - false - } +impl Direction { + pub fn is_descending(self) -> bool { + matches!(self, Self::Descending) } } diff --git a/crates/sui-rest-api/src/proto/mod.rs b/crates/sui-rest-api/src/proto/mod.rs index 3ed3a4dd28419..1720974e0a62a 100644 --- a/crates/sui-rest-api/src/proto/mod.rs +++ b/crates/sui-rest-api/src/proto/mod.rs @@ -341,10 +341,10 @@ impl TryFrom<&UserSignature> for sui_types::signature::GenericSignature { // GetObjectResponse // -impl TryFrom for GetObjectResponse { +impl TryFrom for GetObjectResponse { type Error = bcs::Error; - fn try_from(value: crate::objects::ObjectResponse) -> Result { + fn try_from(value: crate::rest::objects::ObjectResponse) -> Result { Ok(Self { digest: value.digest.as_bytes().to_vec().into(), object: Some(Object::try_from(&value.object)?), @@ -352,7 +352,7 @@ impl TryFrom for GetObjectResponse { } } -impl TryFrom for crate::objects::ObjectResponse { +impl TryFrom for crate::rest::objects::ObjectResponse { type Error = bcs::Error; fn try_from(value: GetObjectResponse) -> Result { @@ -371,10 +371,10 @@ impl TryFrom for crate::objects::ObjectResponse { // GetCheckpointResponse // -impl TryFrom for GetCheckpointResponse { +impl TryFrom for GetCheckpointResponse { type Error = bcs::Error; - fn try_from(c: crate::checkpoints::CheckpointResponse) -> Result { + fn try_from(c: crate::rest::checkpoints::CheckpointResponse) -> Result { Ok(Self { digest: c.digest.as_bytes().to_vec().into(), summary: Some(CheckpointSummary::try_from(&c.summary)?), @@ -388,7 +388,7 @@ impl TryFrom for GetCheckpointResponse { } } -impl TryFrom for crate::checkpoints::CheckpointResponse { +impl TryFrom for crate::rest::checkpoints::CheckpointResponse { type Error = bcs::Error; fn try_from(value: GetCheckpointResponse) -> Result { @@ -413,9 +413,11 @@ impl TryFrom for crate::checkpoints::CheckpointResponse { } } -impl TryFrom> for ListCheckpointResponse { +impl TryFrom> for ListCheckpointResponse { type Error = bcs::Error; - fn try_from(value: Vec) -> Result { + fn try_from( + value: Vec, + ) -> Result { let checkpoints = value .into_iter() .map(TryInto::try_into) @@ -429,10 +431,12 @@ impl TryFrom> for ListCheckpointResp // GetTransactionResponse // -impl TryFrom for GetTransactionResponse { +impl TryFrom for GetTransactionResponse { type Error = bcs::Error; - fn try_from(value: crate::transactions::TransactionResponse) -> Result { + fn try_from( + value: crate::rest::transactions::TransactionResponse, + ) -> Result { Ok(Self { digest: value.digest.as_bytes().to_vec().into(), transaction: Some(Transaction::try_from(&value.transaction)?), @@ -453,7 +457,7 @@ impl TryFrom for GetTransactionRespons } } -impl TryFrom for crate::transactions::TransactionResponse { +impl TryFrom for crate::rest::transactions::TransactionResponse { type Error = bcs::Error; fn try_from(value: GetTransactionResponse) -> Result { @@ -784,18 +788,18 @@ impl TryFrom<&BalanceChange> for crate::client::BalanceChange { // EffectsFinality // -impl TryFrom<&crate::transactions::EffectsFinality> for EffectsFinality { +impl TryFrom<&crate::rest::transactions::EffectsFinality> for EffectsFinality { type Error = bcs::Error; - fn try_from(value: &crate::transactions::EffectsFinality) -> Result { + fn try_from(value: &crate::rest::transactions::EffectsFinality) -> Result { let (signature, checkpoint, quorum_executed) = match value { - crate::transactions::EffectsFinality::Certified { signature } => { + crate::rest::transactions::EffectsFinality::Certified { signature } => { (Some(signature.try_into()?), None, None) } - crate::transactions::EffectsFinality::Checkpointed { checkpoint } => { + crate::rest::transactions::EffectsFinality::Checkpointed { checkpoint } => { (None, Some(*checkpoint), None) } - crate::transactions::EffectsFinality::QuorumExecuted => (None, None, Some(true)), + crate::rest::transactions::EffectsFinality::QuorumExecuted => (None, None, Some(true)), }; Ok(Self { @@ -806,7 +810,7 @@ impl TryFrom<&crate::transactions::EffectsFinality> for EffectsFinality { } } -impl TryFrom<&EffectsFinality> for crate::transactions::EffectsFinality { +impl TryFrom<&EffectsFinality> for crate::rest::transactions::EffectsFinality { type Error = bcs::Error; fn try_from(value: &EffectsFinality) -> Result { @@ -817,12 +821,12 @@ impl TryFrom<&EffectsFinality> for crate::transactions::EffectsFinality { .transpose()?; match (signature, value.checkpoint, value.quorum_executed) { (Some(signature), None, None) => { - crate::transactions::EffectsFinality::Certified { signature } + crate::rest::transactions::EffectsFinality::Certified { signature } } (None, Some(checkpoint), None) => { - crate::transactions::EffectsFinality::Checkpointed { checkpoint } + crate::rest::transactions::EffectsFinality::Checkpointed { checkpoint } } - (None, None, Some(true)) => crate::transactions::EffectsFinality::QuorumExecuted, + (None, None, Some(true)) => crate::rest::transactions::EffectsFinality::QuorumExecuted, _ => return Err(bcs::Error::Custom("invalid EffectsFinality message".into())), } .pipe(Ok) @@ -855,11 +859,13 @@ impl TryFrom<&EffectsFinality> for crate::client::EffectsFinality { // TransactionExecutionResponse // -impl TryFrom for TransactionExecutionResponse { +impl TryFrom + for TransactionExecutionResponse +{ type Error = bcs::Error; fn try_from( - value: crate::transactions::TransactionExecutionResponse, + value: crate::rest::transactions::TransactionExecutionResponse, ) -> Result { Ok(Self { effects: Some(TransactionEffects::try_from(&value.effects)?), @@ -891,7 +897,9 @@ impl TryFrom for TransactionE } } -impl TryFrom for crate::transactions::TransactionExecutionResponse { +impl TryFrom + for crate::rest::transactions::TransactionExecutionResponse +{ type Error = bcs::Error; fn try_from(value: TransactionExecutionResponse) -> Result { @@ -973,11 +981,13 @@ impl TryFrom for crate::client::TransactionExecuti // TransactionSimulationResponse // -impl TryFrom for TransactionSimulationResponse { +impl TryFrom + for TransactionSimulationResponse +{ type Error = bcs::Error; fn try_from( - value: crate::transactions::TransactionSimulationResponse, + value: crate::rest::transactions::TransactionSimulationResponse, ) -> Result { Ok(Self { effects: Some(TransactionEffects::try_from(&value.effects)?), @@ -1008,7 +1018,9 @@ impl TryFrom for Transaction } } -impl TryFrom for crate::transactions::TransactionSimulationResponse { +impl TryFrom + for crate::rest::transactions::TransactionSimulationResponse +{ type Error = bcs::Error; fn try_from(value: TransactionSimulationResponse) -> Result { @@ -1047,11 +1059,11 @@ impl TryFrom for crate::transactions::Transaction // ResolveTransactionResponse // -impl TryFrom for ResolveTransactionResponse { +impl TryFrom for ResolveTransactionResponse { type Error = bcs::Error; fn try_from( - value: crate::transactions::ResolveTransactionResponse, + value: crate::rest::transactions::ResolveTransactionResponse, ) -> Result { Ok(Self { transaction: Some(Transaction::try_from(&value.transaction)?), @@ -1063,7 +1075,7 @@ impl TryFrom for ResolveTransac } } -impl TryFrom for crate::transactions::ResolveTransactionResponse { +impl TryFrom for crate::rest::transactions::ResolveTransactionResponse { type Error = bcs::Error; fn try_from(value: ResolveTransactionResponse) -> Result { diff --git a/crates/sui-rest-api/src/reader.rs b/crates/sui-rest-api/src/reader.rs index d7a7c884d5fa4..46c602451f9be 100644 --- a/crates/sui-rest-api/src/reader.rs +++ b/crates/sui-rest-api/src/reader.rs @@ -54,7 +54,7 @@ impl StateReader { .map(|committee| (*committee).clone().into()) } - pub fn get_system_state_summary(&self) -> Result { + pub fn get_system_state_summary(&self) -> Result { use sui_types::sui_system_state::SuiSystemStateTrait; let system_state = sui_types::sui_system_state::get_sui_system_state(self.inner()) @@ -72,7 +72,7 @@ impl StateReader { sui_sdk_types::types::TransactionEffects, Option, )> { - use super::transactions::TransactionNotFoundError; + use super::rest::transactions::TransactionNotFoundError; use sui_types::effects::TransactionEffectsAPI; let transaction_digest = digest.into(); @@ -116,7 +116,7 @@ impl StateReader { pub fn get_transaction_response( &self, digest: sui_sdk_types::types::TransactionDigest, - ) -> crate::Result { + ) -> crate::Result { let ( SignedTransaction { transaction, @@ -135,7 +135,7 @@ impl StateReader { None }; - Ok(crate::transactions::TransactionResponse { + Ok(crate::rest::transactions::TransactionResponse { digest: transaction.digest(), transaction, signatures, diff --git a/crates/sui-rest-api/src/response.rs b/crates/sui-rest-api/src/response.rs index 0a6df29b0b00a..e2272f0611c89 100644 --- a/crates/sui-rest-api/src/response.rs +++ b/crates/sui-rest-api/src/response.rs @@ -9,14 +9,16 @@ use axum::{ use prost::bytes::BytesMut; use crate::{ - accept::APPLICATION_PROTOBUF, - content_type::ContentType, + rest::accept::APPLICATION_PROTOBUF, + rest::content_type::ContentType, + rest::APPLICATION_BCS, + rest::TEXT_PLAIN_UTF_8, types::{ X_SUI_CHAIN, X_SUI_CHAIN_ID, X_SUI_CHECKPOINT_HEIGHT, X_SUI_EPOCH, X_SUI_LOWEST_AVAILABLE_CHECKPOINT, X_SUI_LOWEST_AVAILABLE_CHECKPOINT_OBJECTS, X_SUI_TIMESTAMP_MS, }, - RestService, APPLICATION_BCS, TEXT_PLAIN_UTF_8, + RestService, }; pub struct Bcs(pub T); diff --git a/crates/sui-rest-api/src/accept.rs b/crates/sui-rest-api/src/rest/accept.rs similarity index 100% rename from crates/sui-rest-api/src/accept.rs rename to crates/sui-rest-api/src/rest/accept.rs diff --git a/crates/sui-rest-api/src/accounts.rs b/crates/sui-rest-api/src/rest/accounts.rs similarity index 89% rename from crates/sui-rest-api/src/accounts.rs rename to crates/sui-rest-api/src/rest/accounts.rs index a32583f225c29..04d5d5501c445 100644 --- a/crates/sui-rest-api/src/accounts.rs +++ b/crates/sui-rest-api/src/rest/accounts.rs @@ -1,10 +1,10 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::reader::StateReader; +use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::{response::ResponseContent, Result}; -use crate::{Page, RestError, RestService}; +use crate::{rest::Page, RestError, RestService}; use axum::extract::Query; use axum::extract::{Path, State}; use openapiv3::v3_1::Operation; @@ -39,7 +39,7 @@ impl ApiEndpoint for ListAccountObjects { .build() } - fn handler(&self) -> crate::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), list_account_objects) } } @@ -90,8 +90,8 @@ pub struct ListAccountOwnedObjectsQueryParameters { impl ListAccountOwnedObjectsQueryParameters { pub fn limit(&self) -> usize { self.limit - .map(|l| (l as usize).clamp(1, crate::MAX_PAGE_SIZE)) - .unwrap_or(crate::DEFAULT_PAGE_SIZE) + .map(|l| (l as usize).clamp(1, crate::rest::MAX_PAGE_SIZE)) + .unwrap_or(crate::rest::DEFAULT_PAGE_SIZE) } pub fn start(&self) -> Option { @@ -105,7 +105,7 @@ pub struct AccountOwnedObjectInfo { pub owner: Address, pub object_id: ObjectId, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "crate::rest::_schemars::U64")] pub version: Version, #[serde(rename = "type")] pub type_: StructTag, diff --git a/crates/sui-rest-api/src/checkpoints.rs b/crates/sui-rest-api/src/rest/checkpoints.rs similarity index 97% rename from crates/sui-rest-api/src/checkpoints.rs rename to crates/sui-rest-api/src/rest/checkpoints.rs index ffd0d020dd012..a0be15e84453b 100644 --- a/crates/sui-rest-api/src/checkpoints.rs +++ b/crates/sui-rest-api/src/rest/checkpoints.rs @@ -10,13 +10,13 @@ use sui_sdk_types::types::{ use sui_types::storage::ReadStore; use tap::Pipe; -use crate::accept::AcceptJsonProtobufBcs; -use crate::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::proto; use crate::proto::ListCheckpointResponse; use crate::reader::StateReader; use crate::response::{JsonProtobufBcs, ProtobufBcs}; -use crate::PageCursor; +use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; +use crate::rest::PageCursor; use crate::{Direction, RestService}; use crate::{RestError, Result}; use documented::Documented; @@ -141,7 +141,7 @@ pub enum CheckpointId { example = "CheckpointSequenceNumber::default" )] /// Sequence number or height of a Checkpoint - SequenceNumber(#[schemars(with = "crate::_schemars::U64")] CheckpointSequenceNumber), + SequenceNumber(#[schemars(with = "crate::rest::_schemars::U64")] CheckpointSequenceNumber), #[schemars(title = "Digest", example = "example_digest")] /// Base58 encoded 32-byte digest of a Checkpoint Digest(CheckpointDigest), @@ -369,8 +369,8 @@ pub struct ListCheckpointsQueryParameters { impl ListCheckpointsQueryParameters { pub fn limit(&self) -> usize { self.limit - .map(|l| (l as usize).clamp(1, crate::MAX_PAGE_SIZE)) - .unwrap_or(crate::DEFAULT_PAGE_SIZE) + .map(|l| (l as usize).clamp(1, crate::rest::MAX_PAGE_SIZE)) + .unwrap_or(crate::rest::DEFAULT_PAGE_SIZE) } pub fn start(&self, default: CheckpointSequenceNumber) -> CheckpointSequenceNumber { diff --git a/crates/sui-rest-api/src/coins.rs b/crates/sui-rest-api/src/rest/coins.rs similarity index 95% rename from crates/sui-rest-api/src/coins.rs rename to crates/sui-rest-api/src/rest/coins.rs index 7cdb6eefcc53e..59770656581fe 100644 --- a/crates/sui-rest-api/src/coins.rs +++ b/crates/sui-rest-api/src/rest/coins.rs @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; +use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::RestError; use crate::RestService; use crate::{reader::StateReader, Result}; @@ -41,7 +41,7 @@ impl ApiEndpoint for GetCoinInfo { .build() } - fn handler(&self) -> crate::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_coin_info) } } @@ -164,7 +164,7 @@ impl From for CoinMetadata { pub struct CoinTreasury { pub id: Option, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "crate::rest::_schemars::U64")] pub total_supply: u64, } diff --git a/crates/sui-rest-api/src/committee.rs b/crates/sui-rest-api/src/rest/committee.rs similarity index 97% rename from crates/sui-rest-api/src/committee.rs rename to crates/sui-rest-api/src/rest/committee.rs index 9b311ad7b0d8f..cebc688c10272 100644 --- a/crates/sui-rest-api/src/committee.rs +++ b/crates/sui-rest-api/src/rest/committee.rs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - accept::AcceptJsonProtobufBcs, - openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, proto, reader::StateReader, response::JsonProtobufBcs, + rest::accept::AcceptJsonProtobufBcs, + rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, RestService, Result, }; use axum::extract::{Path, State}; diff --git a/crates/sui-rest-api/src/content_type.rs b/crates/sui-rest-api/src/rest/content_type.rs similarity index 100% rename from crates/sui-rest-api/src/content_type.rs rename to crates/sui-rest-api/src/rest/content_type.rs diff --git a/crates/sui-rest-api/src/health.rs b/crates/sui-rest-api/src/rest/health.rs similarity index 94% rename from crates/sui-rest-api/src/health.rs rename to crates/sui-rest-api/src/rest/health.rs index cf45ae8a95382..6a9eb82e2851f 100644 --- a/crates/sui-rest-api/src/health.rs +++ b/crates/sui-rest-api/src/rest/health.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, reader::StateReader, + rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, RestService, Result, }; use axum::{ @@ -51,7 +51,7 @@ impl ApiEndpoint for HealthCheck { .build() } - fn handler(&self) -> crate::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), health) } } diff --git a/crates/sui-rest-api/src/info.rs b/crates/sui-rest-api/src/rest/info.rs similarity index 88% rename from crates/sui-rest-api/src/info.rs rename to crates/sui-rest-api/src/rest/info.rs index 29ba245ba5146..1104636984cc3 100644 --- a/crates/sui-rest-api/src/info.rs +++ b/crates/sui-rest-api/src/rest/info.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; -use crate::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; +use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::{RestService, Result}; use axum::extract::State; use axum::Json; @@ -46,7 +46,7 @@ impl ApiEndpoint for GetNodeInfo { .build() } - fn handler(&self) -> crate::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_node_info) } } @@ -90,28 +90,28 @@ pub struct NodeInfo { /// Current epoch of the Node based on its highest executed checkpoint #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "crate::rest::_schemars::U64")] pub epoch: u64, /// Checkpoint height of the most recently executed checkpoint #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "crate::rest::_schemars::U64")] pub checkpoint_height: u64, /// Unix timestamp of the most recently executed checkpoint #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "crate::rest::_schemars::U64")] pub timestamp_ms: u64, /// The lowest checkpoint for which checkpoints and transaction data is available #[serde_as(as = "Option>")] - #[schemars(with = "Option")] + #[schemars(with = "Option")] #[serde(skip_serializing_if = "Option::is_none")] pub lowest_available_checkpoint: Option, /// The lowest checkpoint for which object data is available #[serde_as(as = "Option>")] - #[schemars(with = "Option")] + #[schemars(with = "Option")] #[serde(skip_serializing_if = "Option::is_none")] pub lowest_available_checkpoint_objects: Option, pub software_version: Cow<'static, str>, diff --git a/crates/sui-rest-api/src/rest/mod.rs b/crates/sui-rest-api/src/rest/mod.rs new file mode 100644 index 0000000000000..26cec847168b9 --- /dev/null +++ b/crates/sui-rest-api/src/rest/mod.rs @@ -0,0 +1,192 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use std::sync::Arc; + +use axum::{ + response::{Redirect, ResponseParts}, + routing::get, + Router, +}; + +use crate::{reader::StateReader, response, RestService}; +use openapi::ApiEndpoint; + +pub mod accept; +pub mod accounts; +pub mod checkpoints; +pub mod coins; +mod committee; +pub mod content_type; +pub mod health; +pub mod info; +pub mod objects; +pub mod openapi; +pub mod system; +pub mod transactions; + +pub const TEXT_PLAIN_UTF_8: &str = "text/plain; charset=utf-8"; +pub const APPLICATION_BCS: &str = "application/bcs"; +pub const APPLICATION_JSON: &str = "application/json"; +pub const APPLICATION_PROTOBUF: &str = "application/x-protobuf"; + +pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ + // stable APIs + &info::GetNodeInfo, + &health::HealthCheck, + &checkpoints::ListCheckpoints, + &checkpoints::GetCheckpoint, + // unstable APIs + &accounts::ListAccountObjects, + &objects::GetObject, + &objects::GetObjectWithVersion, + &objects::ListDynamicFields, + &checkpoints::GetFullCheckpoint, + &transactions::GetTransaction, + &transactions::ListTransactions, + &committee::GetCommittee, + &committee::GetLatestCommittee, + &system::GetSystemStateSummary, + &system::GetCurrentProtocolConfig, + &system::GetProtocolConfig, + &system::GetGasInfo, + &transactions::ExecuteTransaction, + &transactions::SimulateTransaction, + &transactions::ResolveTransaction, + &coins::GetCoinInfo, +]; + +pub fn build_rest_router(service: RestService) -> axum::Router { + let mut api = openapi::Api::new(info(service.software_version())); + + api.register_endpoints( + ENDPOINTS + .iter() + .copied() + .filter(|endpoint| endpoint.stable() || service.config.enable_unstable_apis()), + ); + + Router::new() + .nest("/v2/", api.to_router().with_state(service)) + .route("/v2", get(|| async { Redirect::permanent("/v2/") })) + // Previously the service used to be hosted at `/rest`. In an effort to migrate folks + // to the new versioned route, we'll issue redirects from `/rest` -> `/v2`. + .route("/rest/*path", axum::routing::method_routing::any(redirect)) + .route("/rest", get(|| async { Redirect::permanent("/v2/") })) + .route("/rest/", get(|| async { Redirect::permanent("/v2/") })) +} + +#[derive(Debug)] +pub struct Page { + pub entries: response::ResponseContent>, + pub cursor: Option, +} + +pub struct PageCursor(pub Option); + +impl axum::response::IntoResponseParts for PageCursor { + type Error = (axum::http::StatusCode, String); + + fn into_response_parts( + self, + res: ResponseParts, + ) -> std::result::Result { + self.0 + .map(|cursor| [(crate::types::X_SUI_CURSOR, cursor.to_string())]) + .into_response_parts(res) + .map_err(|e| (axum::http::StatusCode::INTERNAL_SERVER_ERROR, e.to_string())) + } +} + +impl axum::response::IntoResponse for PageCursor { + fn into_response(self) -> axum::response::Response { + (self, ()).into_response() + } +} + +pub const DEFAULT_PAGE_SIZE: usize = 50; +pub const MAX_PAGE_SIZE: usize = 100; + +impl axum::response::IntoResponse for Page { + fn into_response(self) -> axum::response::Response { + let cursor = self + .cursor + .map(|cursor| [(crate::types::X_SUI_CURSOR, cursor.to_string())]); + + (cursor, self.entries).into_response() + } +} + +// Enable StateReader to be used as axum::extract::State +impl axum::extract::FromRef for StateReader { + fn from_ref(input: &RestService) -> Self { + input.reader.clone() + } +} + +// Enable TransactionExecutor to be used as axum::extract::State +impl axum::extract::FromRef + for Option> +{ + fn from_ref(input: &RestService) -> Self { + input.executor.clone() + } +} + +pub fn info(version: &'static str) -> openapiv3::v3_1::Info { + use openapiv3::v3_1::Contact; + use openapiv3::v3_1::License; + + openapiv3::v3_1::Info { + title: "Sui Node Api".to_owned(), + description: Some("REST Api for interacting with the Sui Blockchain".to_owned()), + contact: Some(Contact { + name: Some("Mysten Labs".to_owned()), + url: Some("https://github.com/MystenLabs/sui".to_owned()), + ..Default::default() + }), + license: Some(License { + name: "Apache 2.0".to_owned(), + url: Some("https://www.apache.org/licenses/LICENSE-2.0.html".to_owned()), + ..Default::default() + }), + version: version.to_owned(), + ..Default::default() + } +} + +async fn redirect(axum::extract::Path(path): axum::extract::Path) -> Redirect { + Redirect::permanent(&format!("/v2/{path}")) +} + +mod _schemars { + use schemars::schema::InstanceType; + use schemars::schema::Metadata; + use schemars::schema::SchemaObject; + use schemars::JsonSchema; + + pub(crate) struct U64; + + impl JsonSchema for U64 { + fn schema_name() -> String { + "u64".to_owned() + } + + fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + SchemaObject { + metadata: Some(Box::new(Metadata { + description: Some("Radix-10 encoded 64-bit unsigned integer".to_owned()), + ..Default::default() + })), + instance_type: Some(InstanceType::String.into()), + format: Some("u64".to_owned()), + ..Default::default() + } + .into() + } + + fn is_referenceable() -> bool { + false + } + } +} diff --git a/crates/sui-rest-api/src/objects.rs b/crates/sui-rest-api/src/rest/objects.rs similarity index 94% rename from crates/sui-rest-api/src/objects.rs rename to crates/sui-rest-api/src/rest/objects.rs index 21f7327cdef21..a8ec3234833b5 100644 --- a/crates/sui-rest-api/src/objects.rs +++ b/crates/sui-rest-api/src/rest/objects.rs @@ -2,12 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - accept::{AcceptFormat, AcceptJsonProtobufBcs}, - openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, proto::GetObjectResponse, reader::StateReader, response::{JsonProtobufBcs, ResponseContent}, - Page, RestError, RestService, Result, + rest::accept::{AcceptFormat, AcceptJsonProtobufBcs}, + rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, + rest::Page, + RestError, RestService, Result, }; use axum::extract::Query; use axum::extract::{Path, State}; @@ -57,7 +58,7 @@ impl ApiEndpoint for GetObject { .build() } - fn handler(&self) -> crate::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_object) } } @@ -118,7 +119,7 @@ impl ApiEndpoint for GetObjectWithVersion { .build() } - fn handler(&self) -> crate::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_object_with_version) } } @@ -219,7 +220,7 @@ impl ApiEndpoint for ListDynamicFields { .build() } - fn handler(&self) -> crate::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), list_dynamic_fields) } } @@ -277,8 +278,8 @@ pub struct ListDynamicFieldsQueryParameters { impl ListDynamicFieldsQueryParameters { pub fn limit(&self) -> usize { self.limit - .map(|l| (l as usize).clamp(1, crate::MAX_PAGE_SIZE)) - .unwrap_or(crate::DEFAULT_PAGE_SIZE) + .map(|l| (l as usize).clamp(1, crate::rest::MAX_PAGE_SIZE)) + .unwrap_or(crate::rest::DEFAULT_PAGE_SIZE) } pub fn start(&self) -> Option { diff --git a/crates/sui-rest-api/src/openapi.rs b/crates/sui-rest-api/src/rest/openapi.rs similarity index 98% rename from crates/sui-rest-api/src/openapi.rs rename to crates/sui-rest-api/src/rest/openapi.rs index cebcaf69a9e06..20bc6febe210d 100644 --- a/crates/sui-rest-api/src/openapi.rs +++ b/crates/sui-rest-api/src/rest/openapi.rs @@ -250,8 +250,8 @@ pub struct OpenApiDocument { impl OpenApiDocument { pub fn new(openapi: openapiv3::versioned::OpenApi) -> Self { - const OPENAPI_UI: &str = include_str!("../openapi/elements.html"); - // const OPENAPI_UI: &str = include_str!("../openapi/swagger.html"); + const OPENAPI_UI: &str = include_str!("../../openapi/elements.html"); + // const OPENAPI_UI: &str = include_str!("../../openapi/swagger.html"); Self { openapi, @@ -649,11 +649,11 @@ impl ResponseBuilder { } pub fn bcs_content(&mut self) -> &mut Self { - self.content(crate::APPLICATION_BCS, MediaType::default()) + self.content(crate::rest::APPLICATION_BCS, MediaType::default()) } pub fn protobuf_content(&mut self) -> &mut Self { - self.content(crate::APPLICATION_PROTOBUF, MediaType::default()) + self.content(crate::rest::APPLICATION_PROTOBUF, MediaType::default()) } pub fn text_content(&mut self) -> &mut Self { @@ -701,6 +701,6 @@ impl RequestBodyBuilder { } pub fn bcs_content(&mut self) -> &mut Self { - self.content(crate::APPLICATION_BCS, MediaType::default()) + self.content(crate::rest::APPLICATION_BCS, MediaType::default()) } } diff --git a/crates/sui-rest-api/src/system.rs b/crates/sui-rest-api/src/rest/system.rs similarity index 92% rename from crates/sui-rest-api/src/system.rs rename to crates/sui-rest-api/src/rest/system.rs index fc1d386dbce8c..b8dd6c2444893 100644 --- a/crates/sui-rest-api/src/system.rs +++ b/crates/sui-rest-api/src/rest/system.rs @@ -2,9 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - accept::AcceptFormat, - openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, reader::StateReader, + rest::_schemars::U64, + rest::accept::AcceptFormat, + rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, RestError, RestService, Result, }; use axum::{ @@ -73,28 +74,28 @@ async fn get_system_state_summary( pub struct SystemStateSummary { /// The current epoch ID, starting from 0. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub epoch: u64, /// The current protocol version, starting from 1. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub protocol_version: u64, /// The current version of the system state data structure type. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub system_state_version: u64, /// The storage rebates of all the objects on-chain stored in the storage fund. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub storage_fund_total_object_storage_rebates: u64, /// The non-refundable portion of the storage fund coming from storage reinvestment, non-refundable /// storage rebates and any leftover staking rewards. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub storage_fund_non_refundable_balance: u64, /// The reference gas price for the current epoch. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub reference_gas_price: u64, /// Whether the system is running in a downgraded safe mode due to a non-recoverable bug. /// This is set whenever we failed to execute advance_epoch, and ended up executing advance_epoch_safe_mode. @@ -102,84 +103,84 @@ pub struct SystemStateSummary { pub safe_mode: bool, /// Amount of storage rewards accumulated (and not yet distributed) during safe mode. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub safe_mode_storage_rewards: u64, /// Amount of computation rewards accumulated (and not yet distributed) during safe mode. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub safe_mode_computation_rewards: u64, /// Amount of storage rebates accumulated (and not yet burned) during safe mode. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub safe_mode_storage_rebates: u64, /// Amount of non-refundable storage fee accumulated during safe mode. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub safe_mode_non_refundable_storage_fee: u64, /// Unix timestamp of the current epoch start #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub epoch_start_timestamp_ms: u64, // System parameters /// The duration of an epoch, in milliseconds. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub epoch_duration_ms: u64, /// The starting epoch in which stake subsidies start being paid out #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub stake_subsidy_start_epoch: u64, /// Maximum number of active validators at any moment. /// We do not allow the number of validators in any epoch to go above this. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub max_validator_count: u64, /// Lower-bound on the amount of stake required to become a validator. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub min_validator_joining_stake: u64, /// Validators with stake amount below `validator_low_stake_threshold` are considered to /// have low stake and will be escorted out of the validator set after being below this /// threshold for more than `validator_low_stake_grace_period` number of epochs. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub validator_low_stake_threshold: u64, /// Validators with stake below `validator_very_low_stake_threshold` will be removed /// immediately at epoch change, no grace period. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub validator_very_low_stake_threshold: u64, /// A validator can have stake below `validator_low_stake_threshold` /// for this many epochs before being kicked out. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub validator_low_stake_grace_period: u64, // Stake subsidy information /// Balance of SUI set aside for stake subsidies that will be drawn down over time. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub stake_subsidy_balance: u64, /// This counter may be different from the current epoch number if /// in some epochs we decide to skip the subsidy. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub stake_subsidy_distribution_counter: u64, /// The amount of stake subsidy to be drawn down per epoch. /// This amount decays and decreases over time. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub stake_subsidy_current_distribution_amount: u64, /// Number of distributions to occur before the distribution amount decays. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub stake_subsidy_period_length: u64, /// The rate at which the distribution amount decays at the end of each /// period. Expressed in basis points. @@ -188,7 +189,7 @@ pub struct SystemStateSummary { // Validator set /// Total amount of stake from all active validators at the beginning of the epoch. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub total_stake: u64, /// The list of active validators in the current epoch. pub active_validators: Vec, @@ -196,34 +197,34 @@ pub struct SystemStateSummary { pub pending_active_validators_id: ObjectId, /// Number of new validators that will join at the end of the epoch. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub pending_active_validators_size: u64, /// Removal requests from the validators. Each element is an index /// pointing to `active_validators`. #[serde_as(as = "Vec>")] - #[schemars(with = "Vec")] + #[schemars(with = "Vec")] pub pending_removals: Vec, /// ID of the object that maps from staking pool's ID to the sui address of a validator. pub staking_pool_mappings_id: ObjectId, /// Number of staking pool mappings. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub staking_pool_mappings_size: u64, /// ID of the object that maps from a staking pool ID to the inactive validator that has that pool as its staking pool. pub inactive_pools_id: ObjectId, /// Number of inactive staking pools. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub inactive_pools_size: u64, /// ID of the object that stores preactive validators, mapping their addresses to their `Validator` structs. pub validator_candidates_id: ObjectId, /// Number of preactive validators. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub validator_candidates_size: u64, /// Map storing the number of epochs for which each validator has been below the low stake threshold. #[serde_as(as = "Vec<(_, sui_types::sui_serde::BigInt)>")] - #[schemars(with = "Vec<(Address, crate::_schemars::U64)>")] + #[schemars(with = "Vec<(Address, U64)>")] pub at_risk_validators: Vec<(Address, u64)>, /// A map storing the records of validator reporting each other. pub validator_report_records: Vec<(Address, Vec
)>, @@ -262,23 +263,23 @@ pub struct ValidatorSummary { pub next_epoch_worker_address: Option, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub voting_power: u64, pub operation_cap_id: ObjectId, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub gas_price: u64, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub commission_rate: u64, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub next_epoch_stake: u64, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub next_epoch_gas_price: u64, #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub next_epoch_commission_rate: u64, // Staking pool information @@ -286,41 +287,41 @@ pub struct ValidatorSummary { pub staking_pool_id: ObjectId, /// The epoch at which this pool became active. #[serde_as(as = "Option>")] - #[schemars(with = "Option")] + #[schemars(with = "Option")] pub staking_pool_activation_epoch: Option, /// The epoch at which this staking pool ceased to be active. `None` = {pre-active, active}, #[serde_as(as = "Option>")] - #[schemars(with = "Option")] + #[schemars(with = "Option")] pub staking_pool_deactivation_epoch: Option, /// The total number of SUI tokens in this pool. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub staking_pool_sui_balance: u64, /// The epoch stake rewards will be added here at the end of each epoch. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub rewards_pool: u64, /// Total number of pool tokens issued by the pool. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub pool_token_balance: u64, /// Pending stake amount for this epoch. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub pending_stake: u64, /// Pending stake withdrawn during the current epoch, emptied at epoch boundaries. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub pending_total_sui_withdraw: u64, /// Pending pool token withdrawn during the current epoch, emptied at epoch boundaries. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub pending_pool_token_withdraw: u64, /// ID of the exchange rate table object. pub exchange_rates_id: ObjectId, /// Number of exchange rates in the table. #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub exchange_rates_size: u64, } @@ -695,7 +696,7 @@ fn supported_protocol_headers() -> SupportedProtocolHeaders { #[serde(rename = "ProtocolConfig")] pub struct ProtocolConfigResponse { #[serde(with = "serde_with::As::")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub protocol_version: u64, pub feature_flags: BTreeMap, pub attributes: BTreeMap, @@ -782,6 +783,6 @@ async fn get_gas_info( #[derive(serde::Serialize, serde::Deserialize, JsonSchema)] pub struct GasInfo { #[serde(with = "serde_with::As::")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "U64")] pub reference_gas_price: u64, } diff --git a/crates/sui-rest-api/src/transactions/execution.rs b/crates/sui-rest-api/src/rest/transactions/execution.rs similarity index 99% rename from crates/sui-rest-api/src/transactions/execution.rs rename to crates/sui-rest-api/src/rest/transactions/execution.rs index ed22b5c466e2e..ec6d33e26d54c 100644 --- a/crates/sui-rest-api/src/transactions/execution.rs +++ b/crates/sui-rest-api/src/rest/transactions/execution.rs @@ -1,11 +1,11 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::accept::AcceptJsonProtobufBcs; -use crate::openapi::{ +use crate::response::{Bcs, JsonProtobufBcs}; +use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::rest::openapi::{ ApiEndpoint, OperationBuilder, RequestBodyBuilder, ResponseBuilder, RouteHandler, }; -use crate::response::{Bcs, JsonProtobufBcs}; use crate::{proto, RestError, RestService, Result}; use axum::extract::{Query, State}; use schemars::JsonSchema; @@ -303,7 +303,7 @@ enum ReadableEffectsFinality { }, Checkpointed { #[serde_as(as = "sui_types::sui_serde::Readable, _>")] - #[schemars(with = "crate::_schemars::U64")] + #[schemars(with = "crate::rest::_schemars::U64")] checkpoint: CheckpointSequenceNumber, }, QuorumExecuted, diff --git a/crates/sui-rest-api/src/transactions/mod.rs b/crates/sui-rest-api/src/rest/transactions/mod.rs similarity index 95% rename from crates/sui-rest-api/src/transactions/mod.rs rename to crates/sui-rest-api/src/rest/transactions/mod.rs index 261790855353e..f612c28312917 100644 --- a/crates/sui-rest-api/src/transactions/mod.rs +++ b/crates/sui-rest-api/src/rest/transactions/mod.rs @@ -24,17 +24,17 @@ use sui_sdk_types::types::{ }; use tap::Pipe; -use crate::accept::AcceptJsonProtobufBcs; -use crate::openapi::ApiEndpoint; -use crate::openapi::OperationBuilder; -use crate::openapi::ResponseBuilder; -use crate::openapi::RouteHandler; use crate::proto; use crate::proto::ListTransactionsResponse; use crate::reader::StateReader; use crate::response::JsonProtobufBcs; +use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::rest::openapi::ApiEndpoint; +use crate::rest::openapi::OperationBuilder; +use crate::rest::openapi::ResponseBuilder; +use crate::rest::openapi::RouteHandler; +use crate::rest::PageCursor; use crate::Direction; -use crate::PageCursor; use crate::RestError; use crate::RestService; use crate::Result; @@ -102,12 +102,12 @@ pub struct TransactionResponse { #[serde_as( as = "Option, _>>" )] - #[schemars(with = "Option")] + #[schemars(with = "Option")] pub checkpoint: Option, #[serde_as( as = "Option, _>>" )] - #[schemars(with = "Option")] + #[schemars(with = "Option")] pub timestamp_ms: Option, } @@ -308,8 +308,8 @@ pub struct ListTransactionsQueryParameters { impl ListTransactionsQueryParameters { pub fn limit(&self) -> usize { self.limit - .map(|l| (l as usize).clamp(1, crate::MAX_PAGE_SIZE)) - .unwrap_or(crate::DEFAULT_PAGE_SIZE) + .map(|l| (l as usize).clamp(1, crate::rest::MAX_PAGE_SIZE)) + .unwrap_or(crate::rest::DEFAULT_PAGE_SIZE) } pub fn start(&self, default: CheckpointSequenceNumber) -> TransactionCursor { diff --git a/crates/sui-rest-api/src/transactions/resolve/literal.rs b/crates/sui-rest-api/src/rest/transactions/resolve/literal.rs similarity index 100% rename from crates/sui-rest-api/src/transactions/resolve/literal.rs rename to crates/sui-rest-api/src/rest/transactions/resolve/literal.rs diff --git a/crates/sui-rest-api/src/transactions/resolve/mod.rs b/crates/sui-rest-api/src/rest/transactions/resolve/mod.rs similarity index 98% rename from crates/sui-rest-api/src/transactions/resolve/mod.rs rename to crates/sui-rest-api/src/rest/transactions/resolve/mod.rs index 573a62e1adafc..d779635a8ed42 100644 --- a/crates/sui-rest-api/src/transactions/resolve/mod.rs +++ b/crates/sui-rest-api/src/rest/transactions/resolve/mod.rs @@ -6,16 +6,16 @@ use std::collections::HashMap; use super::execution::SimulateTransactionQueryParameters; use super::TransactionSimulationResponse; -use crate::accept::AcceptJsonProtobufBcs; -use crate::objects::ObjectNotFoundError; -use crate::openapi::ApiEndpoint; -use crate::openapi::OperationBuilder; -use crate::openapi::RequestBodyBuilder; -use crate::openapi::ResponseBuilder; -use crate::openapi::RouteHandler; use crate::proto; use crate::reader::StateReader; use crate::response::JsonProtobufBcs; +use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::rest::objects::ObjectNotFoundError; +use crate::rest::openapi::ApiEndpoint; +use crate::rest::openapi::OperationBuilder; +use crate::rest::openapi::RequestBodyBuilder; +use crate::rest::openapi::ResponseBuilder; +use crate::rest::openapi::RouteHandler; use crate::RestError; use crate::RestService; use crate::Result; diff --git a/crates/sui-rest-api/tests/openapi.rs b/crates/sui-rest-api/tests/openapi.rs index 700b17aef125d..3f03a24a3fad0 100644 --- a/crates/sui-rest-api/tests/openapi.rs +++ b/crates/sui-rest-api/tests/openapi.rs @@ -1,9 +1,9 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use sui_rest_api::openapi; -use sui_rest_api::ENDPOINTS; -use sui_rest_api::info; +use sui_rest_api::rest::info; +use sui_rest_api::rest::openapi; +use sui_rest_api::rest::ENDPOINTS; #[test] fn openapi_spec() { From 6726bd876882da99a9a2212a92e160a308f2980f Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 08:46:03 -0600 Subject: [PATCH 09/28] metrics: rename RestMetrics to RpcMetrics --- crates/sui-node/src/lib.rs | 4 ++-- crates/sui-rest-api/src/lib.rs | 8 +++---- crates/sui-rest-api/src/metrics.rs | 38 +++++++++++++++--------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index fc5b3d11265cf..1c3f662e9c0bf 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -38,7 +38,7 @@ use sui_core::traffic_controller::metrics::TrafficControllerMetrics; use sui_json_rpc::bridge_api::BridgeReadApi; use sui_json_rpc_api::JsonRpcMetrics; use sui_network::randomness; -use sui_rest_api::RestMetrics; +use sui_rest_api::RpcMetrics; use sui_types::base_types::ConciseableName; use sui_types::crypto::RandomnessRound; use sui_types::digests::ChainIdentifier; @@ -2103,7 +2103,7 @@ pub async fn build_http_server( rest_service.with_config(config); } - rest_service.with_metrics(RestMetrics::new(prometheus_registry)); + rest_service.with_metrics(RpcMetrics::new(prometheus_registry)); if let Some(transaction_orchestrator) = transaction_orchestrator { rest_service.with_executor(transaction_orchestrator.clone()) diff --git a/crates/sui-rest-api/src/lib.rs b/crates/sui-rest-api/src/lib.rs index f6966349ce4aa..0a5dbff6e30b1 100644 --- a/crates/sui-rest-api/src/lib.rs +++ b/crates/sui-rest-api/src/lib.rs @@ -22,7 +22,7 @@ pub mod types; pub use client::Client; pub use config::Config; pub use error::{RestError, Result}; -pub use metrics::RestMetrics; +pub use metrics::RpcMetrics; pub use rest::checkpoints::CheckpointResponse; pub use rest::checkpoints::ListCheckpointsQueryParameters; pub use rest::objects::ObjectResponse; @@ -35,7 +35,7 @@ pub struct RestService { executor: Option>, chain_id: sui_types::digests::ChainIdentifier, software_version: &'static str, - metrics: Option>, + metrics: Option>, config: Config, } @@ -64,7 +64,7 @@ impl RestService { self.executor = Some(executor); } - pub fn with_metrics(&mut self, metrics: RestMetrics) { + pub fn with_metrics(&mut self, metrics: RpcMetrics) { self.metrics = Some(Arc::new(metrics)); } @@ -89,7 +89,7 @@ impl RestService { .pipe(|router| { if let Some(metrics) = metrics { router.layer(CallbackLayer::new( - metrics::RestMetricsMakeCallbackHandler::new(metrics), + metrics::RpcMetricsMakeCallbackHandler::new(metrics), )) } else { router diff --git a/crates/sui-rest-api/src/metrics.rs b/crates/sui-rest-api/src/metrics.rs index 4793ebe73aa16..51115ebbe1d37 100644 --- a/crates/sui-rest-api/src/metrics.rs +++ b/crates/sui-rest-api/src/metrics.rs @@ -11,7 +11,7 @@ use prometheus::{ }; #[derive(Clone)] -pub struct RestMetrics { +pub struct RpcMetrics { inflight_requests: IntGaugeVec, num_requests: IntCounterVec, request_latency: HistogramVec, @@ -21,26 +21,26 @@ const LATENCY_SEC_BUCKETS: &[f64] = &[ 0.001, 0.005, 0.01, 0.05, 0.1, 0.25, 0.5, 1., 2.5, 5., 10., 20., 30., 60., 90., ]; -impl RestMetrics { +impl RpcMetrics { pub fn new(registry: &Registry) -> Self { Self { inflight_requests: register_int_gauge_vec_with_registry!( - "rest_inflight_requests", - "Total in-flight REST requests per route", + "rpc_inflight_requests", + "Total in-flight RPC requests per route", &["path"], registry, ) .unwrap(), num_requests: register_int_counter_vec_with_registry!( - "rest_requests", - "Total REST requests per route and their http status", + "rpc_requests", + "Total RPC requests per route and their http status", &["path", "status"], registry, ) .unwrap(), request_latency: register_histogram_vec_with_registry!( - "rest_request_latency", - "Latency of REST requests per route", + "rpc_request_latency", + "Latency of RPC requests per route", &["path"], LATENCY_SEC_BUCKETS.to_vec(), registry, @@ -51,18 +51,18 @@ impl RestMetrics { } #[derive(Clone)] -pub struct RestMetricsMakeCallbackHandler { - metrics: Arc, +pub struct RpcMetricsMakeCallbackHandler { + metrics: Arc, } -impl RestMetricsMakeCallbackHandler { - pub fn new(metrics: Arc) -> Self { +impl RpcMetricsMakeCallbackHandler { + pub fn new(metrics: Arc) -> Self { Self { metrics } } } -impl MakeCallbackHandler for RestMetricsMakeCallbackHandler { - type Handler = RestMetricsCallbackHandler; +impl MakeCallbackHandler for RpcMetricsMakeCallbackHandler { + type Handler = RpcMetricsCallbackHandler; fn make_handler(&self, request: &http::request::Parts) -> Self::Handler { let start = Instant::now(); @@ -79,7 +79,7 @@ impl MakeCallbackHandler for RestMetricsMakeCallbackHandler { .with_label_values(&[path.as_ref()]) .inc(); - RestMetricsCallbackHandler { + RpcMetricsCallbackHandler { metrics, path, start, @@ -88,8 +88,8 @@ impl MakeCallbackHandler for RestMetricsMakeCallbackHandler { } } -pub struct RestMetricsCallbackHandler { - metrics: Arc, +pub struct RpcMetricsCallbackHandler { + metrics: Arc, path: Cow<'static, str>, start: Instant, // Indicates if we successfully counted the response. In some cases when a request is @@ -97,7 +97,7 @@ pub struct RestMetricsCallbackHandler { counted_response: bool, } -impl ResponseHandler for RestMetricsCallbackHandler { +impl ResponseHandler for RpcMetricsCallbackHandler { fn on_response(mut self, response: &http::response::Parts) { self.metrics .num_requests @@ -115,7 +115,7 @@ impl ResponseHandler for RestMetricsCallbackHandler { } } -impl Drop for RestMetricsCallbackHandler { +impl Drop for RpcMetricsCallbackHandler { fn drop(&mut self) { self.metrics .inflight_requests From 27a2daee52349c0e17c4d8f72b8869ecfea1ef23 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 08:51:26 -0600 Subject: [PATCH 10/28] rename RestService to RpcService --- .../sui-graphql-rpc/src/test_infra/cluster.rs | 2 +- crates/sui-indexer/src/test_utils.rs | 4 ++-- .../src/test_infra/cluster.rs | 2 +- crates/sui-mvr-indexer/src/test_utils.rs | 4 ++-- crates/sui-node/src/lib.rs | 2 +- crates/sui-rest-api/src/lib.rs | 4 ++-- crates/sui-rest-api/src/response.rs | 4 ++-- crates/sui-rest-api/src/rest/accounts.rs | 6 +++--- crates/sui-rest-api/src/rest/checkpoints.rs | 14 +++++++------- crates/sui-rest-api/src/rest/coins.rs | 6 +++--- crates/sui-rest-api/src/rest/committee.rs | 10 +++++----- crates/sui-rest-api/src/rest/health.rs | 6 +++--- crates/sui-rest-api/src/rest/info.rs | 8 ++++---- crates/sui-rest-api/src/rest/mod.rs | 14 +++++++------- crates/sui-rest-api/src/rest/objects.rs | 14 +++++++------- crates/sui-rest-api/src/rest/system.rs | 18 +++++++++--------- .../src/rest/transactions/execution.rs | 10 +++++----- .../sui-rest-api/src/rest/transactions/mod.rs | 10 +++++----- .../src/rest/transactions/resolve/mod.rs | 8 ++++---- 19 files changed, 73 insertions(+), 73 deletions(-) diff --git a/crates/sui-graphql-rpc/src/test_infra/cluster.rs b/crates/sui-graphql-rpc/src/test_infra/cluster.rs index de2b45c5cc7f6..e911eb44db9e9 100644 --- a/crates/sui-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/sui-graphql-rpc/src/test_infra/cluster.rs @@ -175,7 +175,7 @@ pub async fn serve_executor( .unwrap(); let executor_server_handle = tokio::spawn(async move { - sui_rest_api::RestService::new_without_version(executor) + sui_rest_api::RpcService::new_without_version(executor) .start_service(executor_server_url) .await; }); diff --git a/crates/sui-indexer/src/test_utils.rs b/crates/sui-indexer/src/test_utils.rs index ad2b465a40e5b..c5a93e6287989 100644 --- a/crates/sui-indexer/src/test_utils.rs +++ b/crates/sui-indexer/src/test_utils.rs @@ -291,7 +291,7 @@ pub async fn set_up_on_mvr_mode( .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RestService::new_without_version(sim) + sui_rest_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); @@ -326,7 +326,7 @@ pub async fn set_up_with_start_and_end_checkpoints( .parse() .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RestService::new_without_version(sim) + sui_rest_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); diff --git a/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs b/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs index f54de2dddfb26..13710b64e473f 100644 --- a/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs @@ -176,7 +176,7 @@ pub async fn serve_executor( .unwrap(); let executor_server_handle = tokio::spawn(async move { - sui_rest_api::RestService::new_without_version(executor) + sui_rest_api::RpcService::new_without_version(executor) .start_service(executor_server_url) .await; }); diff --git a/crates/sui-mvr-indexer/src/test_utils.rs b/crates/sui-mvr-indexer/src/test_utils.rs index cf2502e7136d6..a6e42e09ff238 100644 --- a/crates/sui-mvr-indexer/src/test_utils.rs +++ b/crates/sui-mvr-indexer/src/test_utils.rs @@ -245,7 +245,7 @@ pub async fn set_up( .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RestService::new_without_version(sim) + sui_rest_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); @@ -279,7 +279,7 @@ pub async fn set_up_with_start_and_end_checkpoints( .parse() .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RestService::new_without_version(sim) + sui_rest_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index 1c3f662e9c0bf..0ea16de2bd035 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -2094,7 +2094,7 @@ pub async fn build_http_server( router = router.merge(json_rpc_router); if config.enable_experimental_rest_api { - let mut rest_service = sui_rest_api::RestService::new( + let mut rest_service = sui_rest_api::RpcService::new( Arc::new(RestReadStore::new(state.clone(), store)), software_version, ); diff --git a/crates/sui-rest-api/src/lib.rs b/crates/sui-rest-api/src/lib.rs index 0a5dbff6e30b1..ee4dc3a489584 100644 --- a/crates/sui-rest-api/src/lib.rs +++ b/crates/sui-rest-api/src/lib.rs @@ -30,7 +30,7 @@ pub use rest::transactions::ExecuteTransactionQueryParameters; pub use sui_types::full_checkpoint_content::{CheckpointData, CheckpointTransaction}; #[derive(Clone)] -pub struct RestService { +pub struct RpcService { reader: StateReader, executor: Option>, chain_id: sui_types::digests::ChainIdentifier, @@ -39,7 +39,7 @@ pub struct RestService { config: Config, } -impl RestService { +impl RpcService { pub fn new(reader: Arc, software_version: &'static str) -> Self { let chain_id = reader.get_chain_identifier().unwrap(); Self { diff --git a/crates/sui-rest-api/src/response.rs b/crates/sui-rest-api/src/response.rs index e2272f0611c89..8abff279ddc17 100644 --- a/crates/sui-rest-api/src/response.rs +++ b/crates/sui-rest-api/src/response.rs @@ -18,7 +18,7 @@ use crate::{ X_SUI_LOWEST_AVAILABLE_CHECKPOINT, X_SUI_LOWEST_AVAILABLE_CHECKPOINT_OBJECTS, X_SUI_TIMESTAMP_MS, }, - RestService, + RpcService, }; pub struct Bcs(pub T); @@ -171,7 +171,7 @@ where } pub async fn append_info_headers( - State(state): State, + State(state): State, response: Response, ) -> impl IntoResponse { let mut headers = HeaderMap::new(); diff --git a/crates/sui-rest-api/src/rest/accounts.rs b/crates/sui-rest-api/src/rest/accounts.rs index 04d5d5501c445..6408a6af096f2 100644 --- a/crates/sui-rest-api/src/rest/accounts.rs +++ b/crates/sui-rest-api/src/rest/accounts.rs @@ -4,7 +4,7 @@ use crate::reader::StateReader; use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::{response::ResponseContent, Result}; -use crate::{rest::Page, RestError, RestService}; +use crate::{rest::Page, RestError, RpcService}; use axum::extract::Query; use axum::extract::{Path, State}; use openapiv3::v3_1::Operation; @@ -14,7 +14,7 @@ use tap::Pipe; pub struct ListAccountObjects; -impl ApiEndpoint for ListAccountObjects { +impl ApiEndpoint for ListAccountObjects { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -39,7 +39,7 @@ impl ApiEndpoint for ListAccountObjects { .build() } - fn handler(&self) -> crate::rest::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), list_account_objects) } } diff --git a/crates/sui-rest-api/src/rest/checkpoints.rs b/crates/sui-rest-api/src/rest/checkpoints.rs index a0be15e84453b..de3bace9e0c5c 100644 --- a/crates/sui-rest-api/src/rest/checkpoints.rs +++ b/crates/sui-rest-api/src/rest/checkpoints.rs @@ -17,7 +17,7 @@ use crate::response::{JsonProtobufBcs, ProtobufBcs}; use crate::rest::accept::AcceptJsonProtobufBcs; use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::rest::PageCursor; -use crate::{Direction, RestService}; +use crate::{Direction, RpcService}; use crate::{RestError, Result}; use documented::Documented; @@ -38,7 +38,7 @@ pub struct CheckpointResponse { #[derive(Documented)] pub struct GetCheckpoint; -impl ApiEndpoint for GetCheckpoint { +impl ApiEndpoint for GetCheckpoint { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -74,7 +74,7 @@ impl ApiEndpoint for GetCheckpoint { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_checkpoint) } } @@ -226,7 +226,7 @@ pub struct GetCheckpointQueryParameters { #[derive(Documented)] pub struct ListCheckpoints; -impl ApiEndpoint for ListCheckpoints { +impl ApiEndpoint for ListCheckpoints { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -262,7 +262,7 @@ impl ApiEndpoint for ListCheckpoints { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), list_checkpoints) } } @@ -395,7 +395,7 @@ impl ListCheckpointsQueryParameters { #[derive(Documented)] pub struct GetFullCheckpoint; -impl ApiEndpoint for GetFullCheckpoint { +impl ApiEndpoint for GetFullCheckpoint { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -427,7 +427,7 @@ impl ApiEndpoint for GetFullCheckpoint { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_full_checkpoint) } } diff --git a/crates/sui-rest-api/src/rest/coins.rs b/crates/sui-rest-api/src/rest/coins.rs index 59770656581fe..f1849499a5582 100644 --- a/crates/sui-rest-api/src/rest/coins.rs +++ b/crates/sui-rest-api/src/rest/coins.rs @@ -3,7 +3,7 @@ use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::RestError; -use crate::RestService; +use crate::RpcService; use crate::{reader::StateReader, Result}; use axum::extract::{Path, State}; use axum::Json; @@ -14,7 +14,7 @@ use sui_types::sui_sdk_types_conversions::struct_tag_sdk_to_core; pub struct GetCoinInfo; -impl ApiEndpoint for GetCoinInfo { +impl ApiEndpoint for GetCoinInfo { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -41,7 +41,7 @@ impl ApiEndpoint for GetCoinInfo { .build() } - fn handler(&self) -> crate::rest::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_coin_info) } } diff --git a/crates/sui-rest-api/src/rest/committee.rs b/crates/sui-rest-api/src/rest/committee.rs index cebc688c10272..7637c0ceaaf45 100644 --- a/crates/sui-rest-api/src/rest/committee.rs +++ b/crates/sui-rest-api/src/rest/committee.rs @@ -7,7 +7,7 @@ use crate::{ response::JsonProtobufBcs, rest::accept::AcceptJsonProtobufBcs, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, - RestService, Result, + Result, RpcService, }; use axum::extract::{Path, State}; use sui_sdk_types::types::{EpochId, ValidatorCommittee}; @@ -16,7 +16,7 @@ use tap::Pipe; pub struct GetLatestCommittee; -impl ApiEndpoint for GetLatestCommittee { +impl ApiEndpoint for GetLatestCommittee { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -43,7 +43,7 @@ impl ApiEndpoint for GetLatestCommittee { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_latest_committee) } } @@ -67,7 +67,7 @@ async fn get_latest_committee( pub struct GetCommittee; -impl ApiEndpoint for GetCommittee { +impl ApiEndpoint for GetCommittee { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -96,7 +96,7 @@ impl ApiEndpoint for GetCommittee { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_committee) } } diff --git a/crates/sui-rest-api/src/rest/health.rs b/crates/sui-rest-api/src/rest/health.rs index 6a9eb82e2851f..01b622182d899 100644 --- a/crates/sui-rest-api/src/rest/health.rs +++ b/crates/sui-rest-api/src/rest/health.rs @@ -4,7 +4,7 @@ use crate::{ reader::StateReader, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, - RestService, Result, + Result, RpcService, }; use axum::{ extract::{Query, State}, @@ -24,7 +24,7 @@ use tap::Pipe; #[derive(Documented)] pub struct HealthCheck; -impl ApiEndpoint for HealthCheck { +impl ApiEndpoint for HealthCheck { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -51,7 +51,7 @@ impl ApiEndpoint for HealthCheck { .build() } - fn handler(&self) -> crate::rest::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), health) } } diff --git a/crates/sui-rest-api/src/rest/info.rs b/crates/sui-rest-api/src/rest/info.rs index 1104636984cc3..afef51ccffae0 100644 --- a/crates/sui-rest-api/src/rest/info.rs +++ b/crates/sui-rest-api/src/rest/info.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; -use crate::{RestService, Result}; +use crate::{Result, RpcService}; use axum::extract::State; use axum::Json; use documented::Documented; @@ -15,7 +15,7 @@ use tap::Pipe; #[derive(Documented)] pub struct GetNodeInfo; -impl ApiEndpoint for GetNodeInfo { +impl ApiEndpoint for GetNodeInfo { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -46,12 +46,12 @@ impl ApiEndpoint for GetNodeInfo { .build() } - fn handler(&self) -> crate::rest::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_node_info) } } -async fn get_node_info(State(state): State) -> Result> { +async fn get_node_info(State(state): State) -> Result> { let latest_checkpoint = state.reader.inner().get_latest_checkpoint()?; let lowest_available_checkpoint = state .reader diff --git a/crates/sui-rest-api/src/rest/mod.rs b/crates/sui-rest-api/src/rest/mod.rs index 26cec847168b9..a43b634de38b5 100644 --- a/crates/sui-rest-api/src/rest/mod.rs +++ b/crates/sui-rest-api/src/rest/mod.rs @@ -9,7 +9,7 @@ use axum::{ Router, }; -use crate::{reader::StateReader, response, RestService}; +use crate::{reader::StateReader, response, RpcService}; use openapi::ApiEndpoint; pub mod accept; @@ -30,7 +30,7 @@ pub const APPLICATION_BCS: &str = "application/bcs"; pub const APPLICATION_JSON: &str = "application/json"; pub const APPLICATION_PROTOBUF: &str = "application/x-protobuf"; -pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ +pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ // stable APIs &info::GetNodeInfo, &health::HealthCheck, @@ -56,7 +56,7 @@ pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ &coins::GetCoinInfo, ]; -pub fn build_rest_router(service: RestService) -> axum::Router { +pub fn build_rest_router(service: RpcService) -> axum::Router { let mut api = openapi::Api::new(info(service.software_version())); api.register_endpoints( @@ -118,17 +118,17 @@ impl axum::response::IntoResponse for } // Enable StateReader to be used as axum::extract::State -impl axum::extract::FromRef for StateReader { - fn from_ref(input: &RestService) -> Self { +impl axum::extract::FromRef for StateReader { + fn from_ref(input: &RpcService) -> Self { input.reader.clone() } } // Enable TransactionExecutor to be used as axum::extract::State -impl axum::extract::FromRef +impl axum::extract::FromRef for Option> { - fn from_ref(input: &RestService) -> Self { + fn from_ref(input: &RpcService) -> Self { input.executor.clone() } } diff --git a/crates/sui-rest-api/src/rest/objects.rs b/crates/sui-rest-api/src/rest/objects.rs index a8ec3234833b5..c640c020dad27 100644 --- a/crates/sui-rest-api/src/rest/objects.rs +++ b/crates/sui-rest-api/src/rest/objects.rs @@ -8,7 +8,7 @@ use crate::{ rest::accept::{AcceptFormat, AcceptJsonProtobufBcs}, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, rest::Page, - RestError, RestService, Result, + RestError, Result, RpcService, }; use axum::extract::Query; use axum::extract::{Path, State}; @@ -29,7 +29,7 @@ pub struct ObjectResponse { pub struct GetObject; -impl ApiEndpoint for GetObject { +impl ApiEndpoint for GetObject { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -58,7 +58,7 @@ impl ApiEndpoint for GetObject { .build() } - fn handler(&self) -> crate::rest::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_object) } } @@ -89,7 +89,7 @@ pub async fn get_object( pub struct GetObjectWithVersion; -impl ApiEndpoint for GetObjectWithVersion { +impl ApiEndpoint for GetObjectWithVersion { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -119,7 +119,7 @@ impl ApiEndpoint for GetObjectWithVersion { .build() } - fn handler(&self) -> crate::rest::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), get_object_with_version) } } @@ -192,7 +192,7 @@ impl From for crate::RestError { pub struct ListDynamicFields; -impl ApiEndpoint for ListDynamicFields { +impl ApiEndpoint for ListDynamicFields { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -220,7 +220,7 @@ impl ApiEndpoint for ListDynamicFields { .build() } - fn handler(&self) -> crate::rest::openapi::RouteHandler { + fn handler(&self) -> crate::rest::openapi::RouteHandler { RouteHandler::new(self.method(), list_dynamic_fields) } } diff --git a/crates/sui-rest-api/src/rest/system.rs b/crates/sui-rest-api/src/rest/system.rs index b8dd6c2444893..463aa79a8b7c8 100644 --- a/crates/sui-rest-api/src/rest/system.rs +++ b/crates/sui-rest-api/src/rest/system.rs @@ -6,7 +6,7 @@ use crate::{ rest::_schemars::U64, rest::accept::AcceptFormat, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, - RestError, RestService, Result, + RestError, Result, RpcService, }; use axum::{ extract::{Path, State}, @@ -20,7 +20,7 @@ use sui_sdk_types::types::{Address, ObjectId}; pub struct GetSystemStateSummary; -impl ApiEndpoint for GetSystemStateSummary { +impl ApiEndpoint for GetSystemStateSummary { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -45,7 +45,7 @@ impl ApiEndpoint for GetSystemStateSummary { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_system_state_summary) } } @@ -530,7 +530,7 @@ impl From for GetCurrentProtocolConfig { +impl ApiEndpoint for GetCurrentProtocolConfig { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -557,7 +557,7 @@ impl ApiEndpoint for GetCurrentProtocolConfig { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_current_protocol_config) } } @@ -589,7 +589,7 @@ async fn get_current_protocol_config( pub struct GetProtocolConfig; -impl ApiEndpoint for GetProtocolConfig { +impl ApiEndpoint for GetProtocolConfig { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -618,7 +618,7 @@ impl ApiEndpoint for GetProtocolConfig { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_protocol_config) } } @@ -729,7 +729,7 @@ impl From for ProtocolConfigResponse { pub struct GetGasInfo; -impl ApiEndpoint for GetGasInfo { +impl ApiEndpoint for GetGasInfo { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -754,7 +754,7 @@ impl ApiEndpoint for GetGasInfo { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_gas_info) } } diff --git a/crates/sui-rest-api/src/rest/transactions/execution.rs b/crates/sui-rest-api/src/rest/transactions/execution.rs index ec6d33e26d54c..2c796bf983085 100644 --- a/crates/sui-rest-api/src/rest/transactions/execution.rs +++ b/crates/sui-rest-api/src/rest/transactions/execution.rs @@ -6,7 +6,7 @@ use crate::rest::accept::AcceptJsonProtobufBcs; use crate::rest::openapi::{ ApiEndpoint, OperationBuilder, RequestBodyBuilder, ResponseBuilder, RouteHandler, }; -use crate::{proto, RestError, RestService, Result}; +use crate::{proto, RestError, Result, RpcService}; use axum::extract::{Query, State}; use schemars::JsonSchema; use std::net::SocketAddr; @@ -21,7 +21,7 @@ use tap::Pipe; pub struct ExecuteTransaction; -impl ApiEndpoint for ExecuteTransaction { +impl ApiEndpoint for ExecuteTransaction { fn method(&self) -> axum::http::Method { axum::http::Method::POST } @@ -50,7 +50,7 @@ impl ApiEndpoint for ExecuteTransaction { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), execute_transaction) } } @@ -373,7 +373,7 @@ fn derive_balance_changes( pub struct SimulateTransaction; -impl ApiEndpoint for SimulateTransaction { +impl ApiEndpoint for SimulateTransaction { fn method(&self) -> axum::http::Method { axum::http::Method::POST } @@ -402,7 +402,7 @@ impl ApiEndpoint for SimulateTransaction { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), simulate_transaction) } } diff --git a/crates/sui-rest-api/src/rest/transactions/mod.rs b/crates/sui-rest-api/src/rest/transactions/mod.rs index f612c28312917..c2688f81bedba 100644 --- a/crates/sui-rest-api/src/rest/transactions/mod.rs +++ b/crates/sui-rest-api/src/rest/transactions/mod.rs @@ -36,12 +36,12 @@ use crate::rest::openapi::RouteHandler; use crate::rest::PageCursor; use crate::Direction; use crate::RestError; -use crate::RestService; use crate::Result; +use crate::RpcService; pub struct GetTransaction; -impl ApiEndpoint for GetTransaction { +impl ApiEndpoint for GetTransaction { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -70,7 +70,7 @@ impl ApiEndpoint for GetTransaction { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), get_transaction) } } @@ -130,7 +130,7 @@ impl From for crate::RestError { pub struct ListTransactions; -impl ApiEndpoint for ListTransactions { +impl ApiEndpoint for ListTransactions { fn method(&self) -> axum::http::Method { axum::http::Method::GET } @@ -160,7 +160,7 @@ impl ApiEndpoint for ListTransactions { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), list_transactions) } } diff --git a/crates/sui-rest-api/src/rest/transactions/resolve/mod.rs b/crates/sui-rest-api/src/rest/transactions/resolve/mod.rs index d779635a8ed42..b7f487128fc6a 100644 --- a/crates/sui-rest-api/src/rest/transactions/resolve/mod.rs +++ b/crates/sui-rest-api/src/rest/transactions/resolve/mod.rs @@ -17,8 +17,8 @@ use crate::rest::openapi::RequestBodyBuilder; use crate::rest::openapi::ResponseBuilder; use crate::rest::openapi::RouteHandler; use crate::RestError; -use crate::RestService; use crate::Result; +use crate::RpcService; use axum::extract::Query; use axum::extract::State; use axum::Json; @@ -50,7 +50,7 @@ mod literal; pub struct ResolveTransaction; -impl ApiEndpoint for ResolveTransaction { +impl ApiEndpoint for ResolveTransaction { fn method(&self) -> axum::http::Method { axum::http::Method::POST } @@ -83,13 +83,13 @@ impl ApiEndpoint for ResolveTransaction { .build() } - fn handler(&self) -> RouteHandler { + fn handler(&self) -> RouteHandler { RouteHandler::new(self.method(), resolve_transaction) } } async fn resolve_transaction( - State(state): State, + State(state): State, Query(parameters): Query, accept: AcceptJsonProtobufBcs, Json(unresolved_transaction): Json, From 9d8920e1365d6da9ce1540379e94f1c7ef904fc2 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 09:00:56 -0600 Subject: [PATCH 11/28] rename sui-rest-api crate to sui-rpc-api --- Cargo.lock | 98 +++++++++---------- Cargo.toml | 4 +- crates/sui-analytics-indexer/Cargo.toml | 2 +- .../src/analytics_processor.rs | 2 +- .../src/handlers/checkpoint_handler.rs | 2 +- .../src/handlers/df_handler.rs | 2 +- .../src/handlers/event_handler.rs | 2 +- .../src/handlers/move_call_handler.rs | 2 +- .../src/handlers/object_handler.rs | 2 +- .../src/handlers/package_handler.rs | 2 +- .../src/handlers/transaction_handler.rs | 2 +- .../handlers/transaction_objects_handler.rs | 2 +- .../src/handlers/wrapped_object_handler.rs | 2 +- crates/sui-analytics-indexer/src/lib.rs | 2 +- .../src/package_store.rs | 2 +- crates/sui-config/Cargo.toml | 2 +- crates/sui-config/src/node.rs | 2 +- crates/sui-data-ingestion-core/Cargo.toml | 2 +- crates/sui-data-ingestion-core/src/reader.rs | 10 +- crates/sui-e2e-tests/Cargo.toml | 2 +- .../tests/{rest => rpc}/checkpoints.rs | 34 +++---- .../tests/{rest => rpc}/committee.rs | 13 +-- .../tests/{rest => rpc}/execute.rs | 6 +- .../sui-e2e-tests/tests/{rest => rpc}/main.rs | 0 .../tests/{rest => rpc}/objects.rs | 17 ++-- .../tests/{rest => rpc}/resolve.rs | 8 +- .../tests/{rest => rpc}/transactions.rs | 26 ++--- crates/sui-graphql-rpc/Cargo.toml | 2 +- .../sui-graphql-rpc/src/test_infra/cluster.rs | 2 +- crates/sui-indexer/Cargo.toml | 2 +- .../src/handlers/checkpoint_handler.rs | 2 +- crates/sui-indexer/src/handlers/mod.rs | 2 +- .../src/handlers/objects_snapshot_handler.rs | 2 +- .../sui-indexer/src/handlers/tx_processor.rs | 2 +- crates/sui-indexer/src/test_utils.rs | 4 +- crates/sui-light-client/Cargo.toml | 2 +- crates/sui-light-client/src/construct.rs | 2 +- crates/sui-light-client/src/main.rs | 2 +- crates/sui-light-client/tests/check_proof.rs | 2 +- crates/sui-mvr-graphql-rpc/Cargo.toml | 2 +- .../src/test_infra/cluster.rs | 2 +- crates/sui-mvr-indexer/Cargo.toml | 2 +- .../src/handlers/checkpoint_handler.rs | 2 +- crates/sui-mvr-indexer/src/handlers/mod.rs | 2 +- .../src/handlers/objects_snapshot_handler.rs | 2 +- .../src/handlers/tx_processor.rs | 2 +- crates/sui-mvr-indexer/src/test_utils.rs | 4 +- crates/sui-node/Cargo.toml | 2 +- crates/sui-node/src/lib.rs | 6 +- crates/sui-package-resolver/Cargo.toml | 2 +- .../{sui-rest-api => sui-rpc-api}/Cargo.toml | 2 +- .../openapi/elements.html | 0 .../openapi/openapi.json | 0 .../openapi/swagger.html | 0 .../proto/rest.proto | 0 .../src/client/mod.rs | 0 .../src/client/sdk.rs | 0 .../src/config.rs | 0 .../src/error.rs | 0 .../{sui-rest-api => sui-rpc-api}/src/lib.rs | 0 .../src/metrics.rs | 0 .../src/proto/generated/sui.rest.rs | 0 .../src/proto/mod.rs | 0 .../src/reader.rs | 0 .../src/response.rs | 0 .../src/rest/accept.rs | 0 .../src/rest/accounts.rs | 0 .../src/rest/checkpoints.rs | 0 .../src/rest/coins.rs | 0 .../src/rest/committee.rs | 0 .../src/rest/content_type.rs | 0 .../src/rest/health.rs | 0 .../src/rest/info.rs | 0 .../src/rest/mod.rs | 0 .../src/rest/objects.rs | 0 .../src/rest/openapi.rs | 0 .../src/rest/system.rs | 0 .../src/rest/transactions/execution.rs | 0 .../src/rest/transactions/mod.rs | 0 .../src/rest/transactions/resolve/literal.rs | 0 .../src/rest/transactions/resolve/mod.rs | 0 .../src/types.rs | 0 .../tests/bootstrap.rs | 0 .../tests/openapi.rs | 6 +- crates/sui-swarm-config/Cargo.toml | 2 +- .../src/node_config_builder.rs | 4 +- .../sui-transactional-test-runner/Cargo.toml | 2 +- 87 files changed, 151 insertions(+), 169 deletions(-) rename crates/sui-e2e-tests/tests/{rest => rpc}/checkpoints.rs (82%) rename crates/sui-e2e-tests/tests/{rest => rpc}/committee.rs (81%) rename crates/sui-e2e-tests/tests/{rest => rpc}/execute.rs (93%) rename crates/sui-e2e-tests/tests/{rest => rpc}/main.rs (100%) rename crates/sui-e2e-tests/tests/{rest => rpc}/objects.rs (81%) rename crates/sui-e2e-tests/tests/{rest => rpc}/resolve.rs (98%) rename crates/sui-e2e-tests/tests/{rest => rpc}/transactions.rs (77%) rename crates/{sui-rest-api => sui-rpc-api}/Cargo.toml (97%) rename crates/{sui-rest-api => sui-rpc-api}/openapi/elements.html (100%) rename crates/{sui-rest-api => sui-rpc-api}/openapi/openapi.json (100%) rename crates/{sui-rest-api => sui-rpc-api}/openapi/swagger.html (100%) rename crates/{sui-rest-api => sui-rpc-api}/proto/rest.proto (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/client/mod.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/client/sdk.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/config.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/error.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/lib.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/metrics.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/proto/generated/sui.rest.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/proto/mod.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/reader.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/response.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/accept.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/accounts.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/checkpoints.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/coins.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/committee.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/content_type.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/health.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/info.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/mod.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/objects.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/openapi.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/system.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/transactions/execution.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/transactions/mod.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/transactions/resolve/literal.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/rest/transactions/resolve/mod.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/src/types.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/tests/bootstrap.rs (100%) rename crates/{sui-rest-api => sui-rpc-api}/tests/openapi.rs (94%) diff --git a/Cargo.lock b/Cargo.lock index d48e3310c8266..932538e97ddbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13086,7 +13086,7 @@ dependencies = [ "sui-indexer", "sui-json-rpc-types", "sui-package-resolver", - "sui-rest-api", + "sui-rpc-api", "sui-storage", "sui-types", "tap", @@ -13418,7 +13418,7 @@ dependencies = [ "serde_yaml 0.8.26", "sui-keys", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-types", "tempfile", "tracing", @@ -13599,7 +13599,7 @@ dependencies = [ "serde", "serde_json", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-storage", "sui-types", "tap", @@ -13699,7 +13699,7 @@ dependencies = [ "sui-network", "sui-node", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-sdk", "sui-sdk-types", "sui-simulator", @@ -14009,7 +14009,7 @@ dependencies = [ "sui-package-resolver", "sui-pg-temp-db", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-sdk", "sui-swarm-config", "sui-test-transaction-builder", @@ -14104,7 +14104,7 @@ dependencies = [ "sui-package-resolver", "sui-pg-temp-db", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-sdk", "sui-snapshot", "sui-storage", @@ -14432,7 +14432,7 @@ dependencies = [ "sui-config", "sui-json-rpc-types", "sui-package-resolver", - "sui-rest-api", + "sui-rpc-api", "sui-sdk", "sui-types", "tokio", @@ -14689,7 +14689,7 @@ dependencies = [ "sui-package-resolver", "sui-pg-temp-db", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-sdk", "sui-swarm-config", "sui-test-transaction-builder", @@ -14763,7 +14763,7 @@ dependencies = [ "sui-open-rpc", "sui-package-resolver", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-sdk", "sui-snapshot", "sui-storage", @@ -14861,7 +14861,7 @@ dependencies = [ "sui-macros", "sui-network", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-simulator", "sui-snapshot", "sui-storage", @@ -14992,7 +14992,7 @@ dependencies = [ "serde", "serde_json", "sui-move-build", - "sui-rest-api", + "sui-rpc-api", "sui-types", "thiserror", "tokio", @@ -15140,42 +15140,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "sui-rest-api" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "axum 0.7.5", - "bcs", - "diffy", - "documented", - "fastcrypto", - "itertools 0.13.0", - "mime", - "move-binary-format", - "move-core-types", - "mysten-network", - "openapiv3", - "prometheus", - "prost 0.13.3", - "prost-build", - "rand 0.8.5", - "reqwest 0.12.5", - "schemars", - "serde", - "serde_json", - "serde_with 3.9.0", - "serde_yaml 0.8.26", - "sui-protocol-config", - "sui-sdk-types", - "sui-types", - "tap", - "thiserror", - "tokio", - "url", -] - [[package]] name = "sui-rosetta" version = "1.40.0" @@ -15221,6 +15185,42 @@ dependencies = [ "typed-store", ] +[[package]] +name = "sui-rpc-api" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "axum 0.7.5", + "bcs", + "diffy", + "documented", + "fastcrypto", + "itertools 0.13.0", + "mime", + "move-binary-format", + "move-core-types", + "mysten-network", + "openapiv3", + "prometheus", + "prost 0.13.3", + "prost-build", + "rand 0.8.5", + "reqwest 0.12.5", + "schemars", + "serde", + "serde_json", + "serde_with 3.9.0", + "serde_yaml 0.8.26", + "sui-protocol-config", + "sui-sdk-types", + "sui-types", + "tap", + "thiserror", + "tokio", + "url", +] + [[package]] name = "sui-rpc-loadgen" version = "1.40.0" @@ -15618,7 +15618,7 @@ dependencies = [ "sui-genesis-builder", "sui-macros", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-simulator", "sui-types", "tempfile", @@ -15804,7 +15804,7 @@ dependencies = [ "sui-json-rpc-api", "sui-json-rpc-types", "sui-protocol-config", - "sui-rest-api", + "sui-rpc-api", "sui-storage", "sui-swarm-config", "sui-types", diff --git a/Cargo.toml b/Cargo.toml index 8c4c87ad986b0..7934c8ddc5276 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -148,8 +148,8 @@ members = [ "crates/sui-protocol-config-macros", "crates/sui-proxy", "crates/sui-replay", - "crates/sui-rest-api", "crates/sui-rosetta", + "crates/sui-rpc-api", "crates/sui-rpc-loadgen", "crates/sui-sdk", "crates/sui-security-watchdog", @@ -691,7 +691,7 @@ sui-telemetry = { path = "crates/sui-telemetry" } sui-test-transaction-builder = { path = "crates/sui-test-transaction-builder" } sui-test-validator = { path = "crates/sui-test-validator" } sui-tls = { path = "crates/sui-tls" } -sui-rest-api = { path = "crates/sui-rest-api" } +sui-rpc-api = { path = "crates/sui-rpc-api" } sui-tool = { path = "crates/sui-tool" } sui-transaction-builder = { path = "crates/sui-transaction-builder" } sui-transaction-checks = { path = "crates/sui-transaction-checks" } diff --git a/crates/sui-analytics-indexer/Cargo.toml b/crates/sui-analytics-indexer/Cargo.toml index 227d38b32315a..b8bf74a90816c 100644 --- a/crates/sui-analytics-indexer/Cargo.toml +++ b/crates/sui-analytics-indexer/Cargo.toml @@ -41,7 +41,7 @@ eyre.workspace = true tempfile.workspace = true sui-types.workspace = true telemetry-subscribers.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-storage.workspace = true sui-config.workspace = true typed-store.workspace = true diff --git a/crates/sui-analytics-indexer/src/analytics_processor.rs b/crates/sui-analytics-indexer/src/analytics_processor.rs index 1e55981dabafd..45c46c1a4a313 100644 --- a/crates/sui-analytics-indexer/src/analytics_processor.rs +++ b/crates/sui-analytics-indexer/src/analytics_processor.rs @@ -17,7 +17,7 @@ use tracing::{error, info}; use sui_config::object_storage_config::{ObjectStoreConfig, ObjectStoreType}; use sui_data_ingestion_core::Worker; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_storage::object_store::util::{copy_file, path_to_filesystem}; use sui_types::messages_checkpoint::CheckpointSequenceNumber; diff --git a/crates/sui-analytics-indexer/src/handlers/checkpoint_handler.rs b/crates/sui-analytics-indexer/src/handlers/checkpoint_handler.rs index b3dd2042637d9..8a88da92a1ac9 100644 --- a/crates/sui-analytics-indexer/src/handlers/checkpoint_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/checkpoint_handler.rs @@ -6,7 +6,7 @@ use fastcrypto::traits::EncodeDecodeBase64; use tokio::sync::Mutex; use sui_data_ingestion_core::Worker; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::effects::TransactionEffectsAPI; use sui_types::messages_checkpoint::{CertifiedCheckpointSummary, CheckpointSummary}; use sui_types::transaction::TransactionDataAPI; diff --git a/crates/sui-analytics-indexer/src/handlers/df_handler.rs b/crates/sui-analytics-indexer/src/handlers/df_handler.rs index f8dfdea85a039..cee9e689fe3af 100644 --- a/crates/sui-analytics-indexer/src/handlers/df_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/df_handler.rs @@ -16,7 +16,7 @@ use tracing::warn; use sui_indexer::types::owner_to_owner_info; use sui_json_rpc_types::SuiMoveValue; use sui_package_resolver::Resolver; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::base_types::ObjectID; use sui_types::dynamic_field::visitor as DFV; use sui_types::dynamic_field::{DynamicFieldName, DynamicFieldType}; diff --git a/crates/sui-analytics-indexer/src/handlers/event_handler.rs b/crates/sui-analytics-indexer/src/handlers/event_handler.rs index bd2cdf6776350..549f0f00eb79d 100644 --- a/crates/sui-analytics-indexer/src/handlers/event_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/event_handler.rs @@ -16,7 +16,7 @@ use crate::tables::EventEntry; use crate::FileType; use sui_json_rpc_types::type_and_fields_from_move_event_data; use sui_package_resolver::Resolver; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_types::digests::TransactionDigest; use sui_types::effects::TransactionEvents; use sui_types::event::Event; diff --git a/crates/sui-analytics-indexer/src/handlers/move_call_handler.rs b/crates/sui-analytics-indexer/src/handlers/move_call_handler.rs index 93c018164fcb3..39be7a02989cf 100644 --- a/crates/sui-analytics-indexer/src/handlers/move_call_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/move_call_handler.rs @@ -5,7 +5,7 @@ use anyhow::Result; use sui_data_ingestion_core::Worker; use tokio::sync::Mutex; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_types::base_types::ObjectID; use sui_types::transaction::TransactionDataAPI; diff --git a/crates/sui-analytics-indexer/src/handlers/object_handler.rs b/crates/sui-analytics-indexer/src/handlers/object_handler.rs index 0eafa11843bbd..f8263c8058441 100644 --- a/crates/sui-analytics-indexer/src/handlers/object_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/object_handler.rs @@ -10,7 +10,7 @@ use tokio::sync::Mutex; use sui_json_rpc_types::SuiMoveStruct; use sui_package_resolver::Resolver; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::base_types::ObjectID; use sui_types::effects::TransactionEffects; use sui_types::object::Object; diff --git a/crates/sui-analytics-indexer/src/handlers/package_handler.rs b/crates/sui-analytics-indexer/src/handlers/package_handler.rs index bfb6bcfdccd88..3cf1a503e085b 100644 --- a/crates/sui-analytics-indexer/src/handlers/package_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/package_handler.rs @@ -4,7 +4,7 @@ use anyhow::Result; use fastcrypto::encoding::{Base64, Encoding}; use sui_data_ingestion_core::Worker; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_types::full_checkpoint_content::CheckpointTransaction; use sui_types::object::Object; use tokio::sync::Mutex; diff --git a/crates/sui-analytics-indexer/src/handlers/transaction_handler.rs b/crates/sui-analytics-indexer/src/handlers/transaction_handler.rs index 8e4d4fab5dc7f..602297fa3c3c6 100644 --- a/crates/sui-analytics-indexer/src/handlers/transaction_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/transaction_handler.rs @@ -9,7 +9,7 @@ use sui_data_ingestion_core::Worker; use tokio::sync::Mutex; use tracing::error; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::effects::TransactionEffects; use sui_types::effects::TransactionEffectsAPI; use sui_types::transaction::{Command, TransactionDataAPI, TransactionKind}; diff --git a/crates/sui-analytics-indexer/src/handlers/transaction_objects_handler.rs b/crates/sui-analytics-indexer/src/handlers/transaction_objects_handler.rs index e9fbc38542fdb..6eb6b51bfb5e4 100644 --- a/crates/sui-analytics-indexer/src/handlers/transaction_objects_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/transaction_objects_handler.rs @@ -5,7 +5,7 @@ use anyhow::Result; use sui_data_ingestion_core::Worker; use tokio::sync::Mutex; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::base_types::ObjectID; use sui_types::effects::TransactionEffects; use sui_types::transaction::TransactionDataAPI; diff --git a/crates/sui-analytics-indexer/src/handlers/wrapped_object_handler.rs b/crates/sui-analytics-indexer/src/handlers/wrapped_object_handler.rs index 8887df15ffc0c..b7d6522f1c54c 100644 --- a/crates/sui-analytics-indexer/src/handlers/wrapped_object_handler.rs +++ b/crates/sui-analytics-indexer/src/handlers/wrapped_object_handler.rs @@ -9,7 +9,7 @@ use sui_types::SYSTEM_PACKAGE_ADDRESSES; use tokio::sync::Mutex; use sui_package_resolver::Resolver; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::object::Object; use crate::handlers::{get_move_struct, parse_struct, AnalyticsHandler}; diff --git a/crates/sui-analytics-indexer/src/lib.rs b/crates/sui-analytics-indexer/src/lib.rs index adc7a885a433e..4c79db2128831 100644 --- a/crates/sui-analytics-indexer/src/lib.rs +++ b/crates/sui-analytics-indexer/src/lib.rs @@ -19,7 +19,7 @@ use tracing::info; use sui_config::object_storage_config::ObjectStoreConfig; use sui_data_ingestion_core::Worker; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_storage::object_store::util::{ find_all_dirs_with_epoch_prefix, find_all_files_with_epoch_prefix, }; diff --git a/crates/sui-analytics-indexer/src/package_store.rs b/crates/sui-analytics-indexer/src/package_store.rs index ea6155ac2b4a1..7060ac8082806 100644 --- a/crates/sui-analytics-indexer/src/package_store.rs +++ b/crates/sui-analytics-indexer/src/package_store.rs @@ -9,7 +9,7 @@ use move_core_types::account_address::AccountAddress; use sui_package_resolver::{ error::Error as PackageResolverError, Package, PackageStore, PackageStoreWithLruCache, Result, }; -use sui_rest_api::Client; +use sui_rpc_api::Client; use sui_types::base_types::ObjectID; use sui_types::object::Object; use thiserror::Error; diff --git a/crates/sui-config/Cargo.toml b/crates/sui-config/Cargo.toml index 0bd4989c36556..4b2ae4e6e7082 100644 --- a/crates/sui-config/Cargo.toml +++ b/crates/sui-config/Cargo.toml @@ -33,7 +33,7 @@ sui-keys.workspace = true sui-protocol-config.workspace = true sui-types.workspace = true move-vm-config.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true mysten-common.workspace = true [dev-dependencies] diff --git a/crates/sui-config/src/node.rs b/crates/sui-config/src/node.rs index 12f307ac3729c..3317ca3f6e33f 100644 --- a/crates/sui-config/src/node.rs +++ b/crates/sui-config/src/node.rs @@ -67,7 +67,7 @@ pub struct NodeConfig { #[serde(default)] pub enable_experimental_rest_api: bool, #[serde(skip_serializing_if = "Option::is_none")] - pub rpc: Option, + pub rpc: Option, #[serde(default = "default_metrics_address")] pub metrics_address: SocketAddr, diff --git a/crates/sui-data-ingestion-core/Cargo.toml b/crates/sui-data-ingestion-core/Cargo.toml index 05245272cf332..01a2b20d0594a 100644 --- a/crates/sui-data-ingestion-core/Cargo.toml +++ b/crates/sui-data-ingestion-core/Cargo.toml @@ -28,7 +28,7 @@ url.workspace = true tempfile.workspace = true tap.workspace = true sui-protocol-config.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true [dev-dependencies] rand.workspace = true diff --git a/crates/sui-data-ingestion-core/src/reader.rs b/crates/sui-data-ingestion-core/src/reader.rs index 54f4c8540e0e3..f5771f372d548 100644 --- a/crates/sui-data-ingestion-core/src/reader.rs +++ b/crates/sui-data-ingestion-core/src/reader.rs @@ -16,7 +16,7 @@ use std::fs; use std::path::PathBuf; use std::time::Duration; use std::{collections::BTreeMap, sync::Arc}; -use sui_rest_api::Client; +use sui_rpc_api::Client; use sui_storage::blob::Blob; use sui_types::full_checkpoint_content::CheckpointData; use sui_types::messages_checkpoint::CheckpointSequenceNumber; @@ -71,8 +71,8 @@ impl Default for ReaderOptions { enum RemoteStore { ObjectStore(Box), - Rest(sui_rest_api::Client), - Hybrid(Box, sui_rest_api::Client), + Rest(sui_rpc_api::Client), + Hybrid(Box, sui_rpc_api::Client), } impl CheckpointReader { @@ -187,9 +187,9 @@ impl CheckpointReader { self.options.timeout_secs, ) .expect("failed to create remote store client"); - RemoteStore::Hybrid(object_store, sui_rest_api::Client::new(fn_url)) + RemoteStore::Hybrid(object_store, sui_rpc_api::Client::new(fn_url)) } else if url.ends_with("/rest") { - RemoteStore::Rest(sui_rest_api::Client::new(url)) + RemoteStore::Rest(sui_rpc_api::Client::new(url)) } else { let object_store = create_remote_store_client( url, diff --git a/crates/sui-e2e-tests/Cargo.toml b/crates/sui-e2e-tests/Cargo.toml index 7cfa4e5d1353b..b0e257f024c16 100644 --- a/crates/sui-e2e-tests/Cargo.toml +++ b/crates/sui-e2e-tests/Cargo.toml @@ -63,7 +63,7 @@ sui-json-rpc-types.workspace = true sui.workspace = true sui-sdk.workspace = true sui-keys.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true shared-crypto.workspace = true sui-sdk-types.workspace = true diff --git a/crates/sui-e2e-tests/tests/rest/checkpoints.rs b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs similarity index 82% rename from crates/sui-e2e-tests/tests/rest/checkpoints.rs rename to crates/sui-e2e-tests/tests/rpc/checkpoints.rs index bc6ec1a005876..ee10d01868f42 100644 --- a/crates/sui-e2e-tests/tests/rest/checkpoints.rs +++ b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs @@ -3,9 +3,9 @@ use prost::Message; use sui_macros::sim_test; -use sui_rest_api::client::sdk::Client; -use sui_rest_api::client::Client as CoreClient; -use sui_rest_api::{CheckpointResponse, ListCheckpointsQueryParameters}; +use sui_rpc_api::client::sdk::Client; +use sui_rpc_api::client::Client as CoreClient; +use sui_rpc_api::{CheckpointResponse, ListCheckpointsQueryParameters}; use sui_sdk_types::types::SignedCheckpointSummary; use test_cluster::TestClusterBuilder; @@ -37,10 +37,7 @@ async fn list_checkpoint() { // Make sure list works with json let _checkpoints = client .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_JSON, - ) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) .send() .await .unwrap() @@ -53,7 +50,7 @@ async fn list_checkpoint() { .get(&url) .header( reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_PROTOBUF, + sui_rpc_api::rest::APPLICATION_PROTOBUF, ) .send() .await @@ -61,14 +58,14 @@ async fn list_checkpoint() { .bytes() .await .unwrap(); - let _checkpoints = sui_rest_api::proto::ListCheckpointResponse::decode(bytes).unwrap(); + let _checkpoints = sui_rpc_api::proto::ListCheckpointResponse::decode(bytes).unwrap(); // TODO remove this once the BCS format is no longer accepted and clients have migrated to the // protobuf version // Make sure list works with BCS and the old format of only a SignedCheckpoint with no contents let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) .send() .await .unwrap() @@ -101,10 +98,7 @@ async fn get_checkpoint() { // Make sure list works with json let _checkpoints = client .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_JSON, - ) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) .send() .await .unwrap() @@ -117,7 +111,7 @@ async fn get_checkpoint() { .get(&url) .header( reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_PROTOBUF, + sui_rpc_api::rest::APPLICATION_PROTOBUF, ) .send() .await @@ -125,13 +119,13 @@ async fn get_checkpoint() { .bytes() .await .unwrap(); - let _checkpoints = sui_rest_api::proto::GetCheckpointResponse::decode(bytes).unwrap(); + let _checkpoints = sui_rpc_api::proto::GetCheckpointResponse::decode(bytes).unwrap(); // TODO remove this once the BCS format is no longer accepted and clients have migrated to the // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) .send() .await .unwrap() @@ -171,7 +165,7 @@ async fn get_full_checkpoint() { .get(&url) .header( reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_PROTOBUF, + sui_rpc_api::rest::APPLICATION_PROTOBUF, ) .send() .await @@ -179,13 +173,13 @@ async fn get_full_checkpoint() { .bytes() .await .unwrap(); - let _checkpoints = sui_rest_api::proto::FullCheckpoint::decode(bytes).unwrap(); + let _checkpoints = sui_rpc_api::proto::FullCheckpoint::decode(bytes).unwrap(); // TODO remove this once the BCS format is no longer accepted and clients have migrated to the // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-e2e-tests/tests/rest/committee.rs b/crates/sui-e2e-tests/tests/rpc/committee.rs similarity index 81% rename from crates/sui-e2e-tests/tests/rest/committee.rs rename to crates/sui-e2e-tests/tests/rpc/committee.rs index 5edb4be13b80c..e88f4aeaaa473 100644 --- a/crates/sui-e2e-tests/tests/rest/committee.rs +++ b/crates/sui-e2e-tests/tests/rpc/committee.rs @@ -3,7 +3,7 @@ use prost::Message; use sui_macros::sim_test; -use sui_rest_api::client::sdk::Client; +use sui_rpc_api::client::sdk::Client; use sui_sdk_types::types::ValidatorCommittee; use test_cluster::TestClusterBuilder; @@ -22,10 +22,7 @@ async fn get_committee() { // Make sure list works with json let _object = client .get(url) - .header( - reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_JSON, - ) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) .send() .await .unwrap() @@ -38,7 +35,7 @@ async fn get_committee() { .get(url) .header( reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_PROTOBUF, + sui_rpc_api::rest::APPLICATION_PROTOBUF, ) .send() .await @@ -46,13 +43,13 @@ async fn get_committee() { .bytes() .await .unwrap(); - let _object = sui_rest_api::proto::ValidatorCommittee::decode(bytes).unwrap(); + let _object = sui_rpc_api::proto::ValidatorCommittee::decode(bytes).unwrap(); // TODO remove this once the BCS format is no longer accepted and clients have migrated to the // protobuf version let bytes = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-e2e-tests/tests/rest/execute.rs b/crates/sui-e2e-tests/tests/rpc/execute.rs similarity index 93% rename from crates/sui-e2e-tests/tests/rest/execute.rs rename to crates/sui-e2e-tests/tests/rpc/execute.rs index ff408edee6549..431e4413253db 100644 --- a/crates/sui-e2e-tests/tests/rest/execute.rs +++ b/crates/sui-e2e-tests/tests/rpc/execute.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use sui_macros::sim_test; -use sui_rest_api::client::BalanceChange; -use sui_rest_api::Client; -use sui_rest_api::ExecuteTransactionQueryParameters; +use sui_rpc_api::client::BalanceChange; +use sui_rpc_api::Client; +use sui_rpc_api::ExecuteTransactionQueryParameters; use sui_test_transaction_builder::make_transfer_sui_transaction; use sui_types::base_types::SuiAddress; use sui_types::effects::TransactionEffectsAPI; diff --git a/crates/sui-e2e-tests/tests/rest/main.rs b/crates/sui-e2e-tests/tests/rpc/main.rs similarity index 100% rename from crates/sui-e2e-tests/tests/rest/main.rs rename to crates/sui-e2e-tests/tests/rpc/main.rs diff --git a/crates/sui-e2e-tests/tests/rest/objects.rs b/crates/sui-e2e-tests/tests/rpc/objects.rs similarity index 81% rename from crates/sui-e2e-tests/tests/rest/objects.rs rename to crates/sui-e2e-tests/tests/rpc/objects.rs index a87ab513009a0..8bbcaaa56d1ac 100644 --- a/crates/sui-e2e-tests/tests/rest/objects.rs +++ b/crates/sui-e2e-tests/tests/rpc/objects.rs @@ -3,9 +3,9 @@ use prost::Message; use sui_macros::sim_test; -use sui_rest_api::client::sdk::Client; -use sui_rest_api::client::Client as CoreClient; -use sui_rest_api::ObjectResponse; +use sui_rpc_api::client::sdk::Client; +use sui_rpc_api::client::Client as CoreClient; +use sui_rpc_api::ObjectResponse; use sui_sdk_types::types::Object; use test_cluster::TestClusterBuilder; @@ -37,10 +37,7 @@ async fn get_object() { // Make sure list works with json let _object = client .get(url) - .header( - reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_JSON, - ) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) .send() .await .unwrap() @@ -53,7 +50,7 @@ async fn get_object() { .get(url) .header( reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_PROTOBUF, + sui_rpc_api::rest::APPLICATION_PROTOBUF, ) .send() .await @@ -61,13 +58,13 @@ async fn get_object() { .bytes() .await .unwrap(); - let _object = sui_rest_api::proto::GetObjectResponse::decode(bytes).unwrap(); + let _object = sui_rpc_api::proto::GetObjectResponse::decode(bytes).unwrap(); // TODO remove this once the BCS format is no longer accepted and clients have migrated to the // protobuf version let bytes = client .get(url) - .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-e2e-tests/tests/rest/resolve.rs b/crates/sui-e2e-tests/tests/rpc/resolve.rs similarity index 98% rename from crates/sui-e2e-tests/tests/rest/resolve.rs rename to crates/sui-e2e-tests/tests/rpc/resolve.rs index dd9d9858f8f54..85f661276d5ce 100644 --- a/crates/sui-e2e-tests/tests/rest/resolve.rs +++ b/crates/sui-e2e-tests/tests/rpc/resolve.rs @@ -4,10 +4,10 @@ use shared_crypto::intent::Intent; use sui_keys::keystore::AccountKeystore; use sui_macros::sim_test; -use sui_rest_api::client::reqwest::StatusCode; -use sui_rest_api::rest::transactions::ResolveTransactionQueryParameters; -use sui_rest_api::Client; -use sui_rest_api::ExecuteTransactionQueryParameters; +use sui_rpc_api::client::reqwest::StatusCode; +use sui_rpc_api::rest::transactions::ResolveTransactionQueryParameters; +use sui_rpc_api::Client; +use sui_rpc_api::ExecuteTransactionQueryParameters; use sui_sdk_types::types::unresolved; use sui_sdk_types::types::Argument; use sui_sdk_types::types::Command; diff --git a/crates/sui-e2e-tests/tests/rest/transactions.rs b/crates/sui-e2e-tests/tests/rpc/transactions.rs similarity index 77% rename from crates/sui-e2e-tests/tests/rest/transactions.rs rename to crates/sui-e2e-tests/tests/rpc/transactions.rs index 77a9ae649e233..6c6786c62dd34 100644 --- a/crates/sui-e2e-tests/tests/rest/transactions.rs +++ b/crates/sui-e2e-tests/tests/rpc/transactions.rs @@ -3,8 +3,8 @@ use prost::Message; use sui_macros::sim_test; -use sui_rest_api::client::sdk::Client; -use sui_rest_api::rest::transactions::{ListTransactionsQueryParameters, TransactionResponse}; +use sui_rpc_api::client::sdk::Client; +use sui_rpc_api::rest::transactions::{ListTransactionsQueryParameters, TransactionResponse}; use test_cluster::TestClusterBuilder; use crate::transfer_coin; @@ -28,10 +28,7 @@ async fn get_transaction() { // Make sure it works with json let _transaction = client .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_JSON, - ) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) .send() .await .unwrap() @@ -44,7 +41,7 @@ async fn get_transaction() { .get(&url) .header( reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_PROTOBUF, + sui_rpc_api::rest::APPLICATION_PROTOBUF, ) .send() .await @@ -52,13 +49,13 @@ async fn get_transaction() { .bytes() .await .unwrap(); - let _transaction = sui_rest_api::proto::GetTransactionResponse::decode(bytes).unwrap(); + let _transaction = sui_rpc_api::proto::GetTransactionResponse::decode(bytes).unwrap(); // TODO remove this once the BCS format is no longer accepted and clients have migrated to the // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) .send() .await .unwrap() @@ -89,10 +86,7 @@ async fn list_checkpoint() { // Make sure it works with json let _transactions = client .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_JSON, - ) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) .send() .await .unwrap() @@ -105,7 +99,7 @@ async fn list_checkpoint() { .get(&url) .header( reqwest::header::ACCEPT, - sui_rest_api::rest::APPLICATION_PROTOBUF, + sui_rpc_api::rest::APPLICATION_PROTOBUF, ) .send() .await @@ -113,13 +107,13 @@ async fn list_checkpoint() { .bytes() .await .unwrap(); - let _transactions = sui_rest_api::proto::ListTransactionsResponse::decode(bytes).unwrap(); + let _transactions = sui_rpc_api::proto::ListTransactionsResponse::decode(bytes).unwrap(); // TODO remove this once the BCS format is no longer accepted and clients have migrated to the // protobuf version let bytes = client .get(&url) - .header(reqwest::header::ACCEPT, sui_rest_api::rest::APPLICATION_BCS) + .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) .send() .await .unwrap() diff --git a/crates/sui-graphql-rpc/Cargo.toml b/crates/sui-graphql-rpc/Cargo.toml index f58bd12123949..d8f797650fcdf 100644 --- a/crates/sui-graphql-rpc/Cargo.toml +++ b/crates/sui-graphql-rpc/Cargo.toml @@ -76,7 +76,7 @@ simulacrum.workspace = true # todo: cleanup test only deps sui-json-rpc.workspace = true sui-json-rpc-types.workspace = true sui-indexer.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-swarm-config.workspace = true test-cluster.workspace = true sui-protocol-config.workspace = true diff --git a/crates/sui-graphql-rpc/src/test_infra/cluster.rs b/crates/sui-graphql-rpc/src/test_infra/cluster.rs index e911eb44db9e9..0a05d0313e8ce 100644 --- a/crates/sui-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/sui-graphql-rpc/src/test_infra/cluster.rs @@ -175,7 +175,7 @@ pub async fn serve_executor( .unwrap(); let executor_server_handle = tokio::spawn(async move { - sui_rest_api::RpcService::new_without_version(executor) + sui_rpc_api::RpcService::new_without_version(executor) .start_service(executor_server_url) .await; }); diff --git a/crates/sui-indexer/Cargo.toml b/crates/sui-indexer/Cargo.toml index 4109f4fd17d9b..002ba14a9ded6 100644 --- a/crates/sui-indexer/Cargo.toml +++ b/crates/sui-indexer/Cargo.toml @@ -63,7 +63,7 @@ sui-types.workspace = true sui-package-resolver.workspace = true sui-protocol-config.workspace = true telemetry-subscribers.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-transaction-builder.workspace = true sui-synthetic-ingestion.workspace = true diff --git a/crates/sui-indexer/src/handlers/checkpoint_handler.rs b/crates/sui-indexer/src/handlers/checkpoint_handler.rs index 3a0f61558f525..e207a14fc9473 100644 --- a/crates/sui-indexer/src/handlers/checkpoint_handler.rs +++ b/crates/sui-indexer/src/handlers/checkpoint_handler.rs @@ -13,7 +13,7 @@ use tracing::{info, warn}; use move_core_types::language_storage::{StructTag, TypeTag}; use mysten_metrics::{get_metrics, spawn_monitored_task}; use sui_data_ingestion_core::Worker; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::dynamic_field::DynamicFieldType; use sui_types::effects::{ObjectChange, TransactionEffectsAPI}; use sui_types::event::SystemEpochInfoEvent; diff --git a/crates/sui-indexer/src/handlers/mod.rs b/crates/sui-indexer/src/handlers/mod.rs index 403ee8e22706c..5859b72616911 100644 --- a/crates/sui-indexer/src/handlers/mod.rs +++ b/crates/sui-indexer/src/handlers/mod.rs @@ -7,7 +7,7 @@ use async_trait::async_trait; use futures::{FutureExt, StreamExt}; use serde::{Deserialize, Serialize}; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use tokio_util::sync::CancellationToken; use crate::{ diff --git a/crates/sui-indexer/src/handlers/objects_snapshot_handler.rs b/crates/sui-indexer/src/handlers/objects_snapshot_handler.rs index d37d532827947..cdf4a2234e059 100644 --- a/crates/sui-indexer/src/handlers/objects_snapshot_handler.rs +++ b/crates/sui-indexer/src/handlers/objects_snapshot_handler.rs @@ -6,7 +6,7 @@ use mysten_metrics::get_metrics; use mysten_metrics::metered_channel::Sender; use mysten_metrics::spawn_monitored_task; use sui_data_ingestion_core::Worker; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use tokio_util::sync::CancellationToken; use tracing::info; diff --git a/crates/sui-indexer/src/handlers/tx_processor.rs b/crates/sui-indexer/src/handlers/tx_processor.rs index bae0448e34935..cbfd8fa0416b2 100644 --- a/crates/sui-indexer/src/handlers/tx_processor.rs +++ b/crates/sui-indexer/src/handlers/tx_processor.rs @@ -7,7 +7,7 @@ use async_trait::async_trait; use sui_json_rpc::get_balance_changes_from_effect; use sui_json_rpc::get_object_changes; use sui_json_rpc::ObjectProvider; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_types::base_types::ObjectID; use sui_types::base_types::SequenceNumber; use sui_types::digests::TransactionDigest; diff --git a/crates/sui-indexer/src/test_utils.rs b/crates/sui-indexer/src/test_utils.rs index c5a93e6287989..a9b50769042b1 100644 --- a/crates/sui-indexer/src/test_utils.rs +++ b/crates/sui-indexer/src/test_utils.rs @@ -291,7 +291,7 @@ pub async fn set_up_on_mvr_mode( .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RpcService::new_without_version(sim) + sui_rpc_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); @@ -326,7 +326,7 @@ pub async fn set_up_with_start_and_end_checkpoints( .parse() .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RpcService::new_without_version(sim) + sui_rpc_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); diff --git a/crates/sui-light-client/Cargo.toml b/crates/sui-light-client/Cargo.toml index 7992b77d71bb0..444fc48ee4a96 100644 --- a/crates/sui-light-client/Cargo.toml +++ b/crates/sui-light-client/Cargo.toml @@ -26,7 +26,7 @@ serde_yaml.workspace = true serde_json.workspace = true sui-types.workspace = true sui-config.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-sdk.workspace = true move-binary-format.workspace = true sui-json-rpc-types.workspace = true diff --git a/crates/sui-light-client/src/construct.rs b/crates/sui-light-client/src/construct.rs index 7658236768daa..f302b6b205664 100644 --- a/crates/sui-light-client/src/construct.rs +++ b/crates/sui-light-client/src/construct.rs @@ -4,7 +4,7 @@ use crate::proof::{Proof, ProofTarget, TransactionProof}; use anyhow::anyhow; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::effects::TransactionEffectsAPI; /// Construct a proof from the given checkpoint data and proof targets. diff --git a/crates/sui-light-client/src/main.rs b/crates/sui-light-client/src/main.rs index f335e5cde7e94..fa2ae818d0c63 100644 --- a/crates/sui-light-client/src/main.rs +++ b/crates/sui-light-client/src/main.rs @@ -6,7 +6,7 @@ use async_trait::async_trait; use move_core_types::account_address::AccountAddress; use sui_json_rpc_types::{SuiObjectDataOptions, SuiTransactionBlockResponseOptions}; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_types::{ base_types::ObjectID, committee::Committee, diff --git a/crates/sui-light-client/tests/check_proof.rs b/crates/sui-light-client/tests/check_proof.rs index b02cd3e627398..8de8761eec9a2 100644 --- a/crates/sui-light-client/tests/check_proof.rs +++ b/crates/sui-light-client/tests/check_proof.rs @@ -10,7 +10,7 @@ use sui_types::event::{Event, EventID}; use sui_types::{committee::Committee, effects::TransactionEffectsAPI, object::Object}; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use std::io::Read; use std::{fs, path::PathBuf}; diff --git a/crates/sui-mvr-graphql-rpc/Cargo.toml b/crates/sui-mvr-graphql-rpc/Cargo.toml index 39c88e978766f..0cae0d26c50e6 100644 --- a/crates/sui-mvr-graphql-rpc/Cargo.toml +++ b/crates/sui-mvr-graphql-rpc/Cargo.toml @@ -76,7 +76,7 @@ simulacrum.workspace = true # todo: cleanup test only deps sui-json-rpc.workspace = true sui-json-rpc-types.workspace = true sui-indexer.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-swarm-config.workspace = true test-cluster.workspace = true sui-protocol-config.workspace = true diff --git a/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs b/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs index 13710b64e473f..f86b5ca0d08d2 100644 --- a/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/sui-mvr-graphql-rpc/src/test_infra/cluster.rs @@ -176,7 +176,7 @@ pub async fn serve_executor( .unwrap(); let executor_server_handle = tokio::spawn(async move { - sui_rest_api::RpcService::new_without_version(executor) + sui_rpc_api::RpcService::new_without_version(executor) .start_service(executor_server_url) .await; }); diff --git a/crates/sui-mvr-indexer/Cargo.toml b/crates/sui-mvr-indexer/Cargo.toml index fd869ae522ddf..b592ede0bbd12 100644 --- a/crates/sui-mvr-indexer/Cargo.toml +++ b/crates/sui-mvr-indexer/Cargo.toml @@ -62,7 +62,7 @@ sui-types.workspace = true sui-package-resolver.workspace = true sui-protocol-config.workspace = true telemetry-subscribers.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-transaction-builder.workspace = true sui-synthetic-ingestion.workspace = true diff --git a/crates/sui-mvr-indexer/src/handlers/checkpoint_handler.rs b/crates/sui-mvr-indexer/src/handlers/checkpoint_handler.rs index 5e02535eb71e0..e7b0e55c7c4d1 100644 --- a/crates/sui-mvr-indexer/src/handlers/checkpoint_handler.rs +++ b/crates/sui-mvr-indexer/src/handlers/checkpoint_handler.rs @@ -13,7 +13,7 @@ use tracing::{info, warn}; use move_core_types::language_storage::{StructTag, TypeTag}; use mysten_metrics::{get_metrics, spawn_monitored_task}; use sui_data_ingestion_core::Worker; -use sui_rest_api::{CheckpointData, CheckpointTransaction}; +use sui_rpc_api::{CheckpointData, CheckpointTransaction}; use sui_types::dynamic_field::DynamicFieldType; use sui_types::effects::{ObjectChange, TransactionEffectsAPI}; use sui_types::event::SystemEpochInfoEvent; diff --git a/crates/sui-mvr-indexer/src/handlers/mod.rs b/crates/sui-mvr-indexer/src/handlers/mod.rs index 403ee8e22706c..5859b72616911 100644 --- a/crates/sui-mvr-indexer/src/handlers/mod.rs +++ b/crates/sui-mvr-indexer/src/handlers/mod.rs @@ -7,7 +7,7 @@ use async_trait::async_trait; use futures::{FutureExt, StreamExt}; use serde::{Deserialize, Serialize}; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use tokio_util::sync::CancellationToken; use crate::{ diff --git a/crates/sui-mvr-indexer/src/handlers/objects_snapshot_handler.rs b/crates/sui-mvr-indexer/src/handlers/objects_snapshot_handler.rs index d37d532827947..cdf4a2234e059 100644 --- a/crates/sui-mvr-indexer/src/handlers/objects_snapshot_handler.rs +++ b/crates/sui-mvr-indexer/src/handlers/objects_snapshot_handler.rs @@ -6,7 +6,7 @@ use mysten_metrics::get_metrics; use mysten_metrics::metered_channel::Sender; use mysten_metrics::spawn_monitored_task; use sui_data_ingestion_core::Worker; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use tokio_util::sync::CancellationToken; use tracing::info; diff --git a/crates/sui-mvr-indexer/src/handlers/tx_processor.rs b/crates/sui-mvr-indexer/src/handlers/tx_processor.rs index bae0448e34935..cbfd8fa0416b2 100644 --- a/crates/sui-mvr-indexer/src/handlers/tx_processor.rs +++ b/crates/sui-mvr-indexer/src/handlers/tx_processor.rs @@ -7,7 +7,7 @@ use async_trait::async_trait; use sui_json_rpc::get_balance_changes_from_effect; use sui_json_rpc::get_object_changes; use sui_json_rpc::ObjectProvider; -use sui_rest_api::CheckpointData; +use sui_rpc_api::CheckpointData; use sui_types::base_types::ObjectID; use sui_types::base_types::SequenceNumber; use sui_types::digests::TransactionDigest; diff --git a/crates/sui-mvr-indexer/src/test_utils.rs b/crates/sui-mvr-indexer/src/test_utils.rs index a6e42e09ff238..3faea10eeeec8 100644 --- a/crates/sui-mvr-indexer/src/test_utils.rs +++ b/crates/sui-mvr-indexer/src/test_utils.rs @@ -245,7 +245,7 @@ pub async fn set_up( .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RpcService::new_without_version(sim) + sui_rpc_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); @@ -279,7 +279,7 @@ pub async fn set_up_with_start_and_end_checkpoints( .parse() .unwrap(); let server_handle = tokio::spawn(async move { - sui_rest_api::RpcService::new_without_version(sim) + sui_rpc_api::RpcService::new_without_version(sim) .start_service(server_url) .await; }); diff --git a/crates/sui-node/Cargo.toml b/crates/sui-node/Cargo.toml index 636761b27341b..e45cb8abaef82 100644 --- a/crates/sui-node/Cargo.toml +++ b/crates/sui-node/Cargo.toml @@ -37,7 +37,7 @@ sui-tls.workspace = true sui-macros.workspace = true sui-config.workspace = true sui-core.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-storage.workspace = true sui-network.workspace = true sui-json-rpc.workspace = true diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index 0ea16de2bd035..6f49f8103714c 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -38,7 +38,7 @@ use sui_core::traffic_controller::metrics::TrafficControllerMetrics; use sui_json_rpc::bridge_api::BridgeReadApi; use sui_json_rpc_api::JsonRpcMetrics; use sui_network::randomness; -use sui_rest_api::RpcMetrics; +use sui_rpc_api::RpcMetrics; use sui_types::base_types::ConciseableName; use sui_types::crypto::RandomnessRound; use sui_types::digests::ChainIdentifier; @@ -2094,7 +2094,7 @@ pub async fn build_http_server( router = router.merge(json_rpc_router); if config.enable_experimental_rest_api { - let mut rest_service = sui_rest_api::RpcService::new( + let mut rest_service = sui_rpc_api::RpcService::new( Arc::new(RestReadStore::new(state.clone(), store)), software_version, ); @@ -2112,7 +2112,7 @@ pub async fn build_http_server( router = router.merge(rest_service.into_router()); } // TODO: Remove this health check when experimental REST API becomes default - // This is a copy of the health check in crates/sui-rest-api/src/health.rs + // This is a copy of the health check in crates/sui-rpc-api/src/health.rs router = router .route("/health", axum::routing::get(health_check_handler)) .route_layer(axum::Extension(state)); diff --git a/crates/sui-package-resolver/Cargo.toml b/crates/sui-package-resolver/Cargo.toml index 07a0e57d58d4d..9b52f2e00bfec 100644 --- a/crates/sui-package-resolver/Cargo.toml +++ b/crates/sui-package-resolver/Cargo.toml @@ -19,7 +19,7 @@ move-core-types.workspace = true move-command-line-common.workspace = true sui-types.workspace = true thiserror.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true tokio.workspace = true eyre.workspace = true serde.workspace = true diff --git a/crates/sui-rest-api/Cargo.toml b/crates/sui-rpc-api/Cargo.toml similarity index 97% rename from crates/sui-rest-api/Cargo.toml rename to crates/sui-rpc-api/Cargo.toml index 249c5569b7e6b..19a15bc05a5bc 100644 --- a/crates/sui-rest-api/Cargo.toml +++ b/crates/sui-rpc-api/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sui-rest-api" +name = "sui-rpc-api" version = "0.1.0" edition = "2021" license = "Apache-2.0" diff --git a/crates/sui-rest-api/openapi/elements.html b/crates/sui-rpc-api/openapi/elements.html similarity index 100% rename from crates/sui-rest-api/openapi/elements.html rename to crates/sui-rpc-api/openapi/elements.html diff --git a/crates/sui-rest-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json similarity index 100% rename from crates/sui-rest-api/openapi/openapi.json rename to crates/sui-rpc-api/openapi/openapi.json diff --git a/crates/sui-rest-api/openapi/swagger.html b/crates/sui-rpc-api/openapi/swagger.html similarity index 100% rename from crates/sui-rest-api/openapi/swagger.html rename to crates/sui-rpc-api/openapi/swagger.html diff --git a/crates/sui-rest-api/proto/rest.proto b/crates/sui-rpc-api/proto/rest.proto similarity index 100% rename from crates/sui-rest-api/proto/rest.proto rename to crates/sui-rpc-api/proto/rest.proto diff --git a/crates/sui-rest-api/src/client/mod.rs b/crates/sui-rpc-api/src/client/mod.rs similarity index 100% rename from crates/sui-rest-api/src/client/mod.rs rename to crates/sui-rpc-api/src/client/mod.rs diff --git a/crates/sui-rest-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs similarity index 100% rename from crates/sui-rest-api/src/client/sdk.rs rename to crates/sui-rpc-api/src/client/sdk.rs diff --git a/crates/sui-rest-api/src/config.rs b/crates/sui-rpc-api/src/config.rs similarity index 100% rename from crates/sui-rest-api/src/config.rs rename to crates/sui-rpc-api/src/config.rs diff --git a/crates/sui-rest-api/src/error.rs b/crates/sui-rpc-api/src/error.rs similarity index 100% rename from crates/sui-rest-api/src/error.rs rename to crates/sui-rpc-api/src/error.rs diff --git a/crates/sui-rest-api/src/lib.rs b/crates/sui-rpc-api/src/lib.rs similarity index 100% rename from crates/sui-rest-api/src/lib.rs rename to crates/sui-rpc-api/src/lib.rs diff --git a/crates/sui-rest-api/src/metrics.rs b/crates/sui-rpc-api/src/metrics.rs similarity index 100% rename from crates/sui-rest-api/src/metrics.rs rename to crates/sui-rpc-api/src/metrics.rs diff --git a/crates/sui-rest-api/src/proto/generated/sui.rest.rs b/crates/sui-rpc-api/src/proto/generated/sui.rest.rs similarity index 100% rename from crates/sui-rest-api/src/proto/generated/sui.rest.rs rename to crates/sui-rpc-api/src/proto/generated/sui.rest.rs diff --git a/crates/sui-rest-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs similarity index 100% rename from crates/sui-rest-api/src/proto/mod.rs rename to crates/sui-rpc-api/src/proto/mod.rs diff --git a/crates/sui-rest-api/src/reader.rs b/crates/sui-rpc-api/src/reader.rs similarity index 100% rename from crates/sui-rest-api/src/reader.rs rename to crates/sui-rpc-api/src/reader.rs diff --git a/crates/sui-rest-api/src/response.rs b/crates/sui-rpc-api/src/response.rs similarity index 100% rename from crates/sui-rest-api/src/response.rs rename to crates/sui-rpc-api/src/response.rs diff --git a/crates/sui-rest-api/src/rest/accept.rs b/crates/sui-rpc-api/src/rest/accept.rs similarity index 100% rename from crates/sui-rest-api/src/rest/accept.rs rename to crates/sui-rpc-api/src/rest/accept.rs diff --git a/crates/sui-rest-api/src/rest/accounts.rs b/crates/sui-rpc-api/src/rest/accounts.rs similarity index 100% rename from crates/sui-rest-api/src/rest/accounts.rs rename to crates/sui-rpc-api/src/rest/accounts.rs diff --git a/crates/sui-rest-api/src/rest/checkpoints.rs b/crates/sui-rpc-api/src/rest/checkpoints.rs similarity index 100% rename from crates/sui-rest-api/src/rest/checkpoints.rs rename to crates/sui-rpc-api/src/rest/checkpoints.rs diff --git a/crates/sui-rest-api/src/rest/coins.rs b/crates/sui-rpc-api/src/rest/coins.rs similarity index 100% rename from crates/sui-rest-api/src/rest/coins.rs rename to crates/sui-rpc-api/src/rest/coins.rs diff --git a/crates/sui-rest-api/src/rest/committee.rs b/crates/sui-rpc-api/src/rest/committee.rs similarity index 100% rename from crates/sui-rest-api/src/rest/committee.rs rename to crates/sui-rpc-api/src/rest/committee.rs diff --git a/crates/sui-rest-api/src/rest/content_type.rs b/crates/sui-rpc-api/src/rest/content_type.rs similarity index 100% rename from crates/sui-rest-api/src/rest/content_type.rs rename to crates/sui-rpc-api/src/rest/content_type.rs diff --git a/crates/sui-rest-api/src/rest/health.rs b/crates/sui-rpc-api/src/rest/health.rs similarity index 100% rename from crates/sui-rest-api/src/rest/health.rs rename to crates/sui-rpc-api/src/rest/health.rs diff --git a/crates/sui-rest-api/src/rest/info.rs b/crates/sui-rpc-api/src/rest/info.rs similarity index 100% rename from crates/sui-rest-api/src/rest/info.rs rename to crates/sui-rpc-api/src/rest/info.rs diff --git a/crates/sui-rest-api/src/rest/mod.rs b/crates/sui-rpc-api/src/rest/mod.rs similarity index 100% rename from crates/sui-rest-api/src/rest/mod.rs rename to crates/sui-rpc-api/src/rest/mod.rs diff --git a/crates/sui-rest-api/src/rest/objects.rs b/crates/sui-rpc-api/src/rest/objects.rs similarity index 100% rename from crates/sui-rest-api/src/rest/objects.rs rename to crates/sui-rpc-api/src/rest/objects.rs diff --git a/crates/sui-rest-api/src/rest/openapi.rs b/crates/sui-rpc-api/src/rest/openapi.rs similarity index 100% rename from crates/sui-rest-api/src/rest/openapi.rs rename to crates/sui-rpc-api/src/rest/openapi.rs diff --git a/crates/sui-rest-api/src/rest/system.rs b/crates/sui-rpc-api/src/rest/system.rs similarity index 100% rename from crates/sui-rest-api/src/rest/system.rs rename to crates/sui-rpc-api/src/rest/system.rs diff --git a/crates/sui-rest-api/src/rest/transactions/execution.rs b/crates/sui-rpc-api/src/rest/transactions/execution.rs similarity index 100% rename from crates/sui-rest-api/src/rest/transactions/execution.rs rename to crates/sui-rpc-api/src/rest/transactions/execution.rs diff --git a/crates/sui-rest-api/src/rest/transactions/mod.rs b/crates/sui-rpc-api/src/rest/transactions/mod.rs similarity index 100% rename from crates/sui-rest-api/src/rest/transactions/mod.rs rename to crates/sui-rpc-api/src/rest/transactions/mod.rs diff --git a/crates/sui-rest-api/src/rest/transactions/resolve/literal.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/literal.rs similarity index 100% rename from crates/sui-rest-api/src/rest/transactions/resolve/literal.rs rename to crates/sui-rpc-api/src/rest/transactions/resolve/literal.rs diff --git a/crates/sui-rest-api/src/rest/transactions/resolve/mod.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs similarity index 100% rename from crates/sui-rest-api/src/rest/transactions/resolve/mod.rs rename to crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs diff --git a/crates/sui-rest-api/src/types.rs b/crates/sui-rpc-api/src/types.rs similarity index 100% rename from crates/sui-rest-api/src/types.rs rename to crates/sui-rpc-api/src/types.rs diff --git a/crates/sui-rest-api/tests/bootstrap.rs b/crates/sui-rpc-api/tests/bootstrap.rs similarity index 100% rename from crates/sui-rest-api/tests/bootstrap.rs rename to crates/sui-rpc-api/tests/bootstrap.rs diff --git a/crates/sui-rest-api/tests/openapi.rs b/crates/sui-rpc-api/tests/openapi.rs similarity index 94% rename from crates/sui-rest-api/tests/openapi.rs rename to crates/sui-rpc-api/tests/openapi.rs index 3f03a24a3fad0..08172b7be894d 100644 --- a/crates/sui-rest-api/tests/openapi.rs +++ b/crates/sui-rpc-api/tests/openapi.rs @@ -1,9 +1,9 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use sui_rest_api::rest::info; -use sui_rest_api::rest::openapi; -use sui_rest_api::rest::ENDPOINTS; +use sui_rpc_api::rest::info; +use sui_rpc_api::rest::openapi; +use sui_rpc_api::rest::ENDPOINTS; #[test] fn openapi_spec() { diff --git a/crates/sui-swarm-config/Cargo.toml b/crates/sui-swarm-config/Cargo.toml index 3fa547a15b201..a32e0d9b9c230 100644 --- a/crates/sui-swarm-config/Cargo.toml +++ b/crates/sui-swarm-config/Cargo.toml @@ -30,7 +30,7 @@ sui-macros.workspace = true sui-protocol-config.workspace = true sui-types.workspace = true sui-genesis-builder.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true [target.'cfg(msim)'.dependencies] sui-simulator.workspace = true diff --git a/crates/sui-swarm-config/src/node_config_builder.rs b/crates/sui-swarm-config/src/node_config_builder.rs index 19ea5ce07dd78..49948514aff77 100644 --- a/crates/sui-swarm-config/src/node_config_builder.rs +++ b/crates/sui-swarm-config/src/node_config_builder.rs @@ -233,7 +233,7 @@ impl ValidatorConfigBuilder { transaction_kv_store_read_config: Default::default(), transaction_kv_store_write_config: None, enable_experimental_rest_api: true, - rpc: Some(sui_rest_api::Config { + rpc: Some(sui_rpc_api::Config { enable_unstable_apis: Some(true), ..Default::default() }), @@ -535,7 +535,7 @@ impl FullnodeConfigBuilder { transaction_kv_store_read_config: Default::default(), transaction_kv_store_write_config: Default::default(), enable_experimental_rest_api: true, - rpc: Some(sui_rest_api::Config { + rpc: Some(sui_rpc_api::Config { enable_unstable_apis: Some(true), ..Default::default() }), diff --git a/crates/sui-transactional-test-runner/Cargo.toml b/crates/sui-transactional-test-runner/Cargo.toml index 952096d312d6c..ec5a0ddf3ea2b 100644 --- a/crates/sui-transactional-test-runner/Cargo.toml +++ b/crates/sui-transactional-test-runner/Cargo.toml @@ -41,7 +41,7 @@ move-vm-runtime = { path = "../../external-crates/move/crates/move-vm-runtime" } simulacrum.workspace = true sui-graphql-rpc.workspace = true -sui-rest-api.workspace = true +sui-rpc-api.workspace = true sui-swarm-config.workspace = true sui-config.workspace = true sui-core.workspace = true From c0e93c879d94c4829753507a4902199cbb81dd9f Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 09:35:36 -0600 Subject: [PATCH 12/28] rpc: add config for enabling new indexes instad of reusing the jsonrpc config flag --- crates/sui-node/src/lib.rs | 2 +- crates/sui-rpc-api/src/config.rs | 16 ++++++++++++++++ .../sui-swarm-config/src/node_config_builder.rs | 2 ++ ...t_tests__network_config_snapshot_matches.snap | 7 +++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index 6f49f8103714c..7dd940c67e5d5 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -590,7 +590,7 @@ impl SuiNode { let rpc_index = if is_full_node && config.enable_experimental_rest_api - && config.enable_index_processing + && config.rpc.as_ref().is_some_and(|rpc| rpc.enable_indexing()) { Some(Arc::new(RpcIndexStore::new( &config.db_path(), diff --git a/crates/sui-rpc-api/src/config.rs b/crates/sui-rpc-api/src/config.rs index 9d1bfa0580cbb..a88df57dd0ff4 100644 --- a/crates/sui-rpc-api/src/config.rs +++ b/crates/sui-rpc-api/src/config.rs @@ -10,6 +10,18 @@ pub struct Config { #[serde(skip_serializing_if = "Option::is_none")] pub enable_unstable_apis: Option, + /// Enable indexing of transactions and objects + /// + /// This enables indexing of transactions and objects which allows for a slightly richer rpc + /// api. There are some APIs which will be disabled/enabled based on this config while others + /// (eg GetTransaction) will still be enabled regardless of this config but may return slight + /// less data (eg GetTransaction won't return the checkpoint that includes the requested + /// transaction). + /// + /// Defaults to `false`, with indexing and APIs which require indexes being disabled + #[serde(skip_serializing_if = "Option::is_none")] + pub enable_indexing: Option, + // Only include this till we have another field that isn't set with a non-default value for // testing #[doc(hidden)] @@ -24,4 +36,8 @@ impl Config { // apis, have the default be to enable all apis self.enable_unstable_apis.unwrap_or(true) } + + pub fn enable_indexing(&self) -> bool { + self.enable_indexing.unwrap_or(false) + } } diff --git a/crates/sui-swarm-config/src/node_config_builder.rs b/crates/sui-swarm-config/src/node_config_builder.rs index 49948514aff77..03cad22116465 100644 --- a/crates/sui-swarm-config/src/node_config_builder.rs +++ b/crates/sui-swarm-config/src/node_config_builder.rs @@ -235,6 +235,7 @@ impl ValidatorConfigBuilder { enable_experimental_rest_api: true, rpc: Some(sui_rpc_api::Config { enable_unstable_apis: Some(true), + enable_indexing: Some(true), ..Default::default() }), jwk_fetch_interval_seconds: self @@ -537,6 +538,7 @@ impl FullnodeConfigBuilder { enable_experimental_rest_api: true, rpc: Some(sui_rpc_api::Config { enable_unstable_apis: Some(true), + enable_indexing: Some(true), ..Default::default() }), // note: not used by fullnodes. diff --git a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap index 72acabc91c600..ffb015b09ddee 100644 --- a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap +++ b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__network_config_snapshot_matches.snap @@ -17,6 +17,7 @@ validator_configs: enable-experimental-rest-api: true rpc: enable-unstable-apis: true + enable-indexing: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 consensus-config: @@ -198,6 +199,7 @@ validator_configs: enable-experimental-rest-api: true rpc: enable-unstable-apis: true + enable-indexing: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 consensus-config: @@ -379,6 +381,7 @@ validator_configs: enable-experimental-rest-api: true rpc: enable-unstable-apis: true + enable-indexing: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 consensus-config: @@ -560,6 +563,7 @@ validator_configs: enable-experimental-rest-api: true rpc: enable-unstable-apis: true + enable-indexing: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 consensus-config: @@ -741,6 +745,7 @@ validator_configs: enable-experimental-rest-api: true rpc: enable-unstable-apis: true + enable-indexing: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 consensus-config: @@ -922,6 +927,7 @@ validator_configs: enable-experimental-rest-api: true rpc: enable-unstable-apis: true + enable-indexing: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 consensus-config: @@ -1103,6 +1109,7 @@ validator_configs: enable-experimental-rest-api: true rpc: enable-unstable-apis: true + enable-indexing: true metrics-address: "0.0.0.0:1" admin-interface-port: 8888 consensus-config: From acffae2607612ffe455217591d35d93ad15ec778 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 10:18:51 -0600 Subject: [PATCH 13/28] rpc: factor out logic for getting NodeInfo --- crates/sui-rpc-api/src/client/sdk.rs | 2 +- crates/sui-rpc-api/src/lib.rs | 1 + crates/sui-rpc-api/src/rest/info.rs | 70 +------------------------- crates/sui-rpc-api/src/rest/mod.rs | 2 +- crates/sui-rpc-api/src/service/info.rs | 35 +++++++++++++ crates/sui-rpc-api/src/service/mod.rs | 4 ++ crates/sui-rpc-api/src/types.rs | 40 +++++++++++++++ 7 files changed, 84 insertions(+), 70 deletions(-) create mode 100644 crates/sui-rpc-api/src/service/info.rs create mode 100644 crates/sui-rpc-api/src/service/mod.rs diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index 55338c27dede6..5562b6d14fbaa 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -27,7 +27,6 @@ use crate::rest::checkpoints::CheckpointResponse; use crate::rest::checkpoints::ListCheckpointsQueryParameters; use crate::rest::coins::CoinInfo; use crate::rest::health::Threshold; -use crate::rest::info::NodeInfo; use crate::rest::objects::DynamicFieldInfo; use crate::rest::objects::ListDynamicFieldsQueryParameters; use crate::rest::system::GasInfo; @@ -41,6 +40,7 @@ use crate::rest::transactions::ResolveTransactionResponse; use crate::rest::transactions::TransactionExecutionResponse; use crate::rest::transactions::TransactionResponse; use crate::rest::transactions::TransactionSimulationResponse; +use crate::types::NodeInfo; use crate::types::X_SUI_CHAIN; use crate::types::X_SUI_CHAIN_ID; use crate::types::X_SUI_CHECKPOINT_HEIGHT; diff --git a/crates/sui-rpc-api/src/lib.rs b/crates/sui-rpc-api/src/lib.rs index ee4dc3a489584..6d7d08d6981c1 100644 --- a/crates/sui-rpc-api/src/lib.rs +++ b/crates/sui-rpc-api/src/lib.rs @@ -17,6 +17,7 @@ pub mod proto; mod reader; mod response; pub mod rest; +mod service; pub mod types; pub use client::Client; diff --git a/crates/sui-rpc-api/src/rest/info.rs b/crates/sui-rpc-api/src/rest/info.rs index afef51ccffae0..435f91bb80d42 100644 --- a/crates/sui-rpc-api/src/rest/info.rs +++ b/crates/sui-rpc-api/src/rest/info.rs @@ -1,15 +1,12 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use std::borrow::Cow; - use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; +use crate::types::NodeInfo; use crate::{Result, RpcService}; use axum::extract::State; use axum::Json; use documented::Documented; -use sui_sdk_types::types::CheckpointDigest; -use tap::Pipe; /// Get basic information about the state of a Node #[derive(Documented)] @@ -52,68 +49,5 @@ impl ApiEndpoint for GetNodeInfo { } async fn get_node_info(State(state): State) -> Result> { - let latest_checkpoint = state.reader.inner().get_latest_checkpoint()?; - let lowest_available_checkpoint = state - .reader - .inner() - .get_lowest_available_checkpoint()? - .pipe(Some); - let lowest_available_checkpoint_objects = state - .reader - .inner() - .get_lowest_available_checkpoint_objects()? - .pipe(Some); - - NodeInfo { - checkpoint_height: latest_checkpoint.sequence_number, - lowest_available_checkpoint, - lowest_available_checkpoint_objects, - timestamp_ms: latest_checkpoint.timestamp_ms, - epoch: latest_checkpoint.epoch(), - chain_id: CheckpointDigest::new(state.chain_id().as_bytes().to_owned()), - chain: state.chain_id().chain().as_str().into(), - software_version: state.software_version().into(), - } - .pipe(Json) - .pipe(Ok) -} - -/// Basic information about the state of a Node -#[serde_with::serde_as] -#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] -pub struct NodeInfo { - /// The chain identifier of the chain that this Node is on - pub chain_id: CheckpointDigest, - - /// Human readable name of the chain that this Node is on - pub chain: Cow<'static, str>, - - /// Current epoch of the Node based on its highest executed checkpoint - #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::rest::_schemars::U64")] - pub epoch: u64, - - /// Checkpoint height of the most recently executed checkpoint - #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::rest::_schemars::U64")] - pub checkpoint_height: u64, - - /// Unix timestamp of the most recently executed checkpoint - #[serde_as(as = "sui_types::sui_serde::BigInt")] - #[schemars(with = "crate::rest::_schemars::U64")] - pub timestamp_ms: u64, - - /// The lowest checkpoint for which checkpoints and transaction data is available - #[serde_as(as = "Option>")] - #[schemars(with = "Option")] - #[serde(skip_serializing_if = "Option::is_none")] - pub lowest_available_checkpoint: Option, - - /// The lowest checkpoint for which object data is available - #[serde_as(as = "Option>")] - #[schemars(with = "Option")] - #[serde(skip_serializing_if = "Option::is_none")] - pub lowest_available_checkpoint_objects: Option, - pub software_version: Cow<'static, str>, - //TODO include current protocol version + state.get_node_info().map(Json) } diff --git a/crates/sui-rpc-api/src/rest/mod.rs b/crates/sui-rpc-api/src/rest/mod.rs index a43b634de38b5..4d52f305a3497 100644 --- a/crates/sui-rpc-api/src/rest/mod.rs +++ b/crates/sui-rpc-api/src/rest/mod.rs @@ -159,7 +159,7 @@ async fn redirect(axum::extract::Path(path): axum::extract::Path) -> Red Redirect::permanent(&format!("/v2/{path}")) } -mod _schemars { +pub(crate) mod _schemars { use schemars::schema::InstanceType; use schemars::schema::Metadata; use schemars::schema::SchemaObject; diff --git a/crates/sui-rpc-api/src/service/info.rs b/crates/sui-rpc-api/src/service/info.rs new file mode 100644 index 0000000000000..342c154457c9d --- /dev/null +++ b/crates/sui-rpc-api/src/service/info.rs @@ -0,0 +1,35 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::Result; +use crate::{types::NodeInfo, RpcService}; +use sui_sdk_types::types::CheckpointDigest; +use tap::Pipe; + +impl RpcService { + pub fn get_node_info(&self) -> Result { + let latest_checkpoint = self.reader.inner().get_latest_checkpoint()?; + let lowest_available_checkpoint = self + .reader + .inner() + .get_lowest_available_checkpoint()? + .pipe(Some); + let lowest_available_checkpoint_objects = self + .reader + .inner() + .get_lowest_available_checkpoint_objects()? + .pipe(Some); + + NodeInfo { + checkpoint_height: latest_checkpoint.sequence_number, + lowest_available_checkpoint, + lowest_available_checkpoint_objects, + timestamp_ms: latest_checkpoint.timestamp_ms, + epoch: latest_checkpoint.epoch(), + chain_id: CheckpointDigest::new(self.chain_id().as_bytes().to_owned()), + chain: self.chain_id().chain().as_str().into(), + software_version: self.software_version().into(), + } + .pipe(Ok) + } +} diff --git a/crates/sui-rpc-api/src/service/mod.rs b/crates/sui-rpc-api/src/service/mod.rs new file mode 100644 index 0000000000000..6c75479495b33 --- /dev/null +++ b/crates/sui-rpc-api/src/service/mod.rs @@ -0,0 +1,4 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +mod info; diff --git a/crates/sui-rpc-api/src/types.rs b/crates/sui-rpc-api/src/types.rs index d8204d41862a2..2de53d33be045 100644 --- a/crates/sui-rpc-api/src/types.rs +++ b/crates/sui-rpc-api/src/types.rs @@ -34,3 +34,43 @@ pub const X_SUI_CURSOR: &str = "x-sui-cursor"; /// Current timestamp of the chain - represented as number of milliseconds from the Unix epoch pub const X_SUI_TIMESTAMP_MS: &str = "x-sui-timestamp-ms"; + +/// Basic information about the state of a Node +#[serde_with::serde_as] +#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct NodeInfo { + /// The chain identifier of the chain that this Node is on + pub chain_id: sui_sdk_types::types::CheckpointDigest, + + /// Human readable name of the chain that this Node is on + pub chain: std::borrow::Cow<'static, str>, + + /// Current epoch of the Node based on its highest executed checkpoint + #[serde_as(as = "sui_types::sui_serde::BigInt")] + #[schemars(with = "crate::rest::_schemars::U64")] + pub epoch: u64, + + /// Checkpoint height of the most recently executed checkpoint + #[serde_as(as = "sui_types::sui_serde::BigInt")] + #[schemars(with = "crate::rest::_schemars::U64")] + pub checkpoint_height: u64, + + /// Unix timestamp of the most recently executed checkpoint + #[serde_as(as = "sui_types::sui_serde::BigInt")] + #[schemars(with = "crate::rest::_schemars::U64")] + pub timestamp_ms: u64, + + /// The lowest checkpoint for which checkpoints and transaction data is available + #[serde_as(as = "Option>")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lowest_available_checkpoint: Option, + + /// The lowest checkpoint for which object data is available + #[serde_as(as = "Option>")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lowest_available_checkpoint_objects: Option, + pub software_version: std::borrow::Cow<'static, str>, + //TODO include current protocol version +} From a8c579eec5842ddc57b5da53a2e95fdb20dc8a52 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 13:50:19 -0600 Subject: [PATCH 14/28] rpc: factor out health check logic --- crates/sui-rpc-api/src/rest/health.rs | 32 +++----------------- crates/sui-rpc-api/src/service/health.rs | 37 ++++++++++++++++++++++++ crates/sui-rpc-api/src/service/mod.rs | 1 + 3 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 crates/sui-rpc-api/src/service/health.rs diff --git a/crates/sui-rpc-api/src/rest/health.rs b/crates/sui-rpc-api/src/rest/health.rs index 01b622182d899..52f5386f029ad 100644 --- a/crates/sui-rpc-api/src/rest/health.rs +++ b/crates/sui-rpc-api/src/rest/health.rs @@ -2,19 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - reader::StateReader, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, Result, RpcService, }; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, -}; +use axum::extract::{Query, State}; use documented::Documented; -use std::time::{Duration, SystemTime}; -use sui_types::storage::ReadStore; -use tap::Pipe; /// Perform a service health check /// @@ -68,23 +60,7 @@ pub struct Threshold { async fn health( Query(Threshold { threshold_seconds }): Query, - State(state): State, -) -> Result { - let summary = state.inner().get_latest_checkpoint()?; - - // If we have a provided threshold, check that it's close to the current time - if let Some(threshold_seconds) = threshold_seconds { - let latest_chain_time = summary.timestamp(); - - let threshold = SystemTime::now() - Duration::from_secs(threshold_seconds as u64); - - if latest_chain_time < threshold { - return Err(anyhow::anyhow!( - "The latest checkpoint timestamp is less than the provided threshold" - ) - .into()); - } - } - - StatusCode::OK.pipe(Ok) + State(state): State, +) -> Result<()> { + state.health_check(threshold_seconds) } diff --git a/crates/sui-rpc-api/src/service/health.rs b/crates/sui-rpc-api/src/service/health.rs new file mode 100644 index 0000000000000..c4831c9ffd82e --- /dev/null +++ b/crates/sui-rpc-api/src/service/health.rs @@ -0,0 +1,37 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use std::time::Duration; +use std::time::SystemTime; + +use crate::Result; +use crate::RpcService; + +impl RpcService { + /// Perform a simple health check on the service. + /// + /// The threshold, or delta, between the server's system time and the timestamp in the most + /// recently executed checkpoint for which the server is considered to be healthy. + /// + /// If not provided, the server will be considered healthy if it can simply fetch the latest + /// checkpoint from its store. + pub fn health_check(&self, threshold_seconds: Option) -> Result<()> { + let summary = self.reader.inner().get_latest_checkpoint()?; + + // If we have a provided threshold, check that it's close to the current time + if let Some(threshold_seconds) = threshold_seconds { + let latest_chain_time = summary.timestamp(); + + let threshold = SystemTime::now() - Duration::from_secs(threshold_seconds as u64); + + if latest_chain_time < threshold { + return Err(anyhow::anyhow!( + "The latest checkpoint timestamp is less than the provided threshold" + ) + .into()); + } + } + + Ok(()) + } +} diff --git a/crates/sui-rpc-api/src/service/mod.rs b/crates/sui-rpc-api/src/service/mod.rs index 6c75479495b33..0b2b1eb7c076e 100644 --- a/crates/sui-rpc-api/src/service/mod.rs +++ b/crates/sui-rpc-api/src/service/mod.rs @@ -1,4 +1,5 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +mod health; mod info; From 6612e46ea26c865b55c978112f9cd26392f0ae94 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 20:13:04 -0600 Subject: [PATCH 15/28] rpc: factor out get_committee logic --- crates/sui-rpc-api/src/rest/committee.rs | 40 ++--------------- crates/sui-rpc-api/src/service/committee.rs | 48 +++++++++++++++++++++ crates/sui-rpc-api/src/service/mod.rs | 1 + 3 files changed, 53 insertions(+), 36 deletions(-) create mode 100644 crates/sui-rpc-api/src/service/committee.rs diff --git a/crates/sui-rpc-api/src/rest/committee.rs b/crates/sui-rpc-api/src/rest/committee.rs index 7637c0ceaaf45..5ea84e6ec2bdb 100644 --- a/crates/sui-rpc-api/src/rest/committee.rs +++ b/crates/sui-rpc-api/src/rest/committee.rs @@ -3,7 +3,6 @@ use crate::{ proto, - reader::StateReader, response::JsonProtobufBcs, rest::accept::AcceptJsonProtobufBcs, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, @@ -11,7 +10,6 @@ use crate::{ }; use axum::extract::{Path, State}; use sui_sdk_types::types::{EpochId, ValidatorCommittee}; -use sui_types::storage::ReadStore; use tap::Pipe; pub struct GetLatestCommittee; @@ -50,12 +48,9 @@ impl ApiEndpoint for GetLatestCommittee { async fn get_latest_committee( accept: AcceptJsonProtobufBcs, - State(state): State, + State(state): State, ) -> Result> { - let current_epoch = state.inner().get_latest_checkpoint()?.epoch(); - let committee = state - .get_committee(current_epoch) - .ok_or_else(|| CommitteeNotFoundError::new(current_epoch))?; + let committee = state.get_committee(None)?; match accept { AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(committee), @@ -104,11 +99,9 @@ impl ApiEndpoint for GetCommittee { async fn get_committee( Path(epoch): Path, accept: AcceptJsonProtobufBcs, - State(state): State, + State(state): State, ) -> Result> { - let committee = state - .get_committee(epoch) - .ok_or_else(|| CommitteeNotFoundError::new(epoch))?; + let committee = state.get_committee(Some(epoch))?; match accept { AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(committee), @@ -117,28 +110,3 @@ async fn get_committee( } .pipe(Ok) } - -#[derive(Debug)] -pub struct CommitteeNotFoundError { - epoch: EpochId, -} - -impl CommitteeNotFoundError { - pub fn new(epoch: EpochId) -> Self { - Self { epoch } - } -} - -impl std::fmt::Display for CommitteeNotFoundError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Committee for epoch {} not found", self.epoch) - } -} - -impl std::error::Error for CommitteeNotFoundError {} - -impl From for crate::RestError { - fn from(value: CommitteeNotFoundError) -> Self { - Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) - } -} diff --git a/crates/sui-rpc-api/src/service/committee.rs b/crates/sui-rpc-api/src/service/committee.rs new file mode 100644 index 0000000000000..84cda0be8b1f8 --- /dev/null +++ b/crates/sui-rpc-api/src/service/committee.rs @@ -0,0 +1,48 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::Result; +use crate::RpcService; +use sui_sdk_types::types::{EpochId, ValidatorCommittee}; + +impl RpcService { + pub fn get_committee(&self, epoch: Option) -> Result { + let epoch = if let Some(epoch) = epoch { + epoch + } else { + self.reader.inner().get_latest_checkpoint()?.epoch() + }; + + let committee = self + .reader + .get_committee(epoch) + .ok_or_else(|| CommitteeNotFoundError::new(epoch))?; + + Ok(committee) + } +} + +#[derive(Debug)] +pub struct CommitteeNotFoundError { + epoch: EpochId, +} + +impl CommitteeNotFoundError { + pub fn new(epoch: EpochId) -> Self { + Self { epoch } + } +} + +impl std::fmt::Display for CommitteeNotFoundError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Committee for epoch {} not found", self.epoch) + } +} + +impl std::error::Error for CommitteeNotFoundError {} + +impl From for crate::RestError { + fn from(value: CommitteeNotFoundError) -> Self { + Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) + } +} diff --git a/crates/sui-rpc-api/src/service/mod.rs b/crates/sui-rpc-api/src/service/mod.rs index 0b2b1eb7c076e..ba935d70b1d84 100644 --- a/crates/sui-rpc-api/src/service/mod.rs +++ b/crates/sui-rpc-api/src/service/mod.rs @@ -1,5 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +mod committee; mod health; mod info; From a4572d9f6646032e0ffe3d6ec2da262e475d87c8 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 20:57:35 -0600 Subject: [PATCH 16/28] rpc: remove support for protobuf from rest endpoints This patch removes support from the various rest endpoints where it was previously added. Instead, to support clients who want a binary format, a gRPC service will be added in a future patch. --- crates/sui-e2e-tests/tests/rpc/checkpoints.rs | 58 +------- crates/sui-e2e-tests/tests/rpc/committee.rs | 22 +-- crates/sui-e2e-tests/tests/rpc/objects.rs | 20 +-- .../sui-e2e-tests/tests/rpc/transactions.rs | 39 +----- crates/sui-rpc-api/openapi/openapi.json | 12 +- crates/sui-rpc-api/src/client/sdk.rs | 34 ----- crates/sui-rpc-api/src/response.rs | 130 ------------------ crates/sui-rpc-api/src/rest/accept.rs | 38 ----- crates/sui-rpc-api/src/rest/checkpoints.rs | 50 +++---- crates/sui-rpc-api/src/rest/committee.rs | 26 ++-- crates/sui-rpc-api/src/rest/mod.rs | 1 - crates/sui-rpc-api/src/rest/objects.rs | 29 ++-- crates/sui-rpc-api/src/rest/openapi.rs | 4 - .../src/rest/transactions/execution.rs | 38 ++--- .../sui-rpc-api/src/rest/transactions/mod.rs | 35 ++--- .../src/rest/transactions/resolve/mod.rs | 21 +-- 16 files changed, 82 insertions(+), 475 deletions(-) diff --git a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs index ee10d01868f42..08b41685f3b3f 100644 --- a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs +++ b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs @@ -1,7 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use prost::Message; use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; use sui_rpc_api::client::Client as CoreClient; @@ -45,23 +44,9 @@ async fn list_checkpoint() { .await .unwrap(); - // Make sure list works with protobuf - let bytes = client - .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rpc_api::rest::APPLICATION_PROTOBUF, - ) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _checkpoints = sui_rpc_api::proto::ListCheckpointResponse::decode(bytes).unwrap(); - - // TODO remove this once the BCS format is no longer accepted and clients have migrated to the - // protobuf version + // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients + // wanting binary have migrated to grpc + // // Make sure list works with BCS and the old format of only a SignedCheckpoint with no contents let bytes = client .get(&url) @@ -106,23 +91,8 @@ async fn get_checkpoint() { .await .unwrap(); - // Make sure it works with protobuf - let bytes = client - .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rpc_api::rest::APPLICATION_PROTOBUF, - ) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _checkpoints = sui_rpc_api::proto::GetCheckpointResponse::decode(bytes).unwrap(); - - // TODO remove this once the BCS format is no longer accepted and clients have migrated to the - // protobuf version + // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients + // wanting binary have migrated to grpc let bytes = client .get(&url) .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) @@ -160,23 +130,9 @@ async fn get_full_checkpoint() { test_cluster.rpc_url(), latest.checkpoint.sequence_number ); - // Make sure it works with protobuf - let bytes = client - .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rpc_api::rest::APPLICATION_PROTOBUF, - ) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _checkpoints = sui_rpc_api::proto::FullCheckpoint::decode(bytes).unwrap(); - // TODO remove this once the BCS format is no longer accepted and clients have migrated to the - // protobuf version + // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients + // wanting binary have migrated to grpc let bytes = client .get(&url) .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) diff --git a/crates/sui-e2e-tests/tests/rpc/committee.rs b/crates/sui-e2e-tests/tests/rpc/committee.rs index e88f4aeaaa473..9bf28bae9767d 100644 --- a/crates/sui-e2e-tests/tests/rpc/committee.rs +++ b/crates/sui-e2e-tests/tests/rpc/committee.rs @@ -1,7 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use prost::Message; use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; use sui_sdk_types::types::ValidatorCommittee; @@ -30,23 +29,8 @@ async fn get_committee() { .await .unwrap(); - // Make sure it works with protobuf - let bytes = client - .get(url) - .header( - reqwest::header::ACCEPT, - sui_rpc_api::rest::APPLICATION_PROTOBUF, - ) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _object = sui_rpc_api::proto::ValidatorCommittee::decode(bytes).unwrap(); - - // TODO remove this once the BCS format is no longer accepted and clients have migrated to the - // protobuf version + // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients + // wanting binary have migrated to grpc let bytes = client .get(url) .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) @@ -56,7 +40,7 @@ async fn get_committee() { .bytes() .await .unwrap(); - let _object = bcs::from_bytes::(&bytes).unwrap(); + let _committee = bcs::from_bytes::(&bytes).unwrap(); } let url = format!("{}/v2/system/committee", test_cluster.rpc_url(),); diff --git a/crates/sui-e2e-tests/tests/rpc/objects.rs b/crates/sui-e2e-tests/tests/rpc/objects.rs index 8bbcaaa56d1ac..d1a671f65ea20 100644 --- a/crates/sui-e2e-tests/tests/rpc/objects.rs +++ b/crates/sui-e2e-tests/tests/rpc/objects.rs @@ -1,7 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use prost::Message; use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; use sui_rpc_api::client::Client as CoreClient; @@ -45,23 +44,8 @@ async fn get_object() { .await .unwrap(); - // Make sure it works with protobuf - let bytes = client - .get(url) - .header( - reqwest::header::ACCEPT, - sui_rpc_api::rest::APPLICATION_PROTOBUF, - ) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _object = sui_rpc_api::proto::GetObjectResponse::decode(bytes).unwrap(); - - // TODO remove this once the BCS format is no longer accepted and clients have migrated to the - // protobuf version + // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients + // wanting binary have migrated to grpc let bytes = client .get(url) .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) diff --git a/crates/sui-e2e-tests/tests/rpc/transactions.rs b/crates/sui-e2e-tests/tests/rpc/transactions.rs index 6c6786c62dd34..a8c564f4699db 100644 --- a/crates/sui-e2e-tests/tests/rpc/transactions.rs +++ b/crates/sui-e2e-tests/tests/rpc/transactions.rs @@ -1,7 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use prost::Message; use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; use sui_rpc_api::rest::transactions::{ListTransactionsQueryParameters, TransactionResponse}; @@ -36,23 +35,8 @@ async fn get_transaction() { .await .unwrap(); - // Make sure it works with protobuf - let bytes = client - .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rpc_api::rest::APPLICATION_PROTOBUF, - ) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _transaction = sui_rpc_api::proto::GetTransactionResponse::decode(bytes).unwrap(); - - // TODO remove this once the BCS format is no longer accepted and clients have migrated to the - // protobuf version + // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients + // wanting binary have migrated to grpc let bytes = client .get(&url) .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) @@ -94,23 +78,8 @@ async fn list_checkpoint() { .await .unwrap(); - // Make sure it works with protobuf - let bytes = client - .get(&url) - .header( - reqwest::header::ACCEPT, - sui_rpc_api::rest::APPLICATION_PROTOBUF, - ) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _transactions = sui_rpc_api::proto::ListTransactionsResponse::decode(bytes).unwrap(); - - // TODO remove this once the BCS format is no longer accepted and clients have migrated to the - // protobuf version + // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients + // wanting binary have migrated to grpc let bytes = client .get(&url) .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) diff --git a/crates/sui-rpc-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json index 3aa3badcc70b6..9ef11418b1d84 100644 --- a/crates/sui-rpc-api/openapi/openapi.json +++ b/crates/sui-rpc-api/openapi/openapi.json @@ -155,8 +155,7 @@ } } }, - "application/bcs": {}, - "application/x-protobuf": {} + "application/bcs": {} } }, "410": { @@ -309,7 +308,6 @@ "$ref": "#/components/schemas/ObjectResponse" } }, - "application/x-protobuf": {}, "application/bcs": {} } }, @@ -357,7 +355,6 @@ "$ref": "#/components/schemas/ObjectResponse" } }, - "application/x-protobuf": {}, "application/bcs": {} } }, @@ -492,7 +489,6 @@ "$ref": "#/components/schemas/TransactionResponse" } }, - "application/x-protobuf": {}, "application/bcs": {} } }, @@ -557,7 +553,6 @@ } } }, - "application/x-protobuf": {}, "application/bcs": {} } }, @@ -632,7 +627,6 @@ "$ref": "#/components/schemas/TransactionExecutionResponse" } }, - "application/x-protobuf": {}, "application/bcs": {} } } @@ -668,7 +662,6 @@ "$ref": "#/components/schemas/ValidatorCommittee" } }, - "application/x-protobuf": {}, "application/bcs": {} } }, @@ -694,7 +687,6 @@ "$ref": "#/components/schemas/ValidatorCommittee" } }, - "application/x-protobuf": {}, "application/bcs": {} } } @@ -885,7 +877,6 @@ "$ref": "#/components/schemas/TransactionSimulationResponse" } }, - "application/x-protobuf": {}, "application/bcs": {} } } @@ -963,7 +954,6 @@ "$ref": "#/components/schemas/ResolveTransactionResponse" } }, - "application/x-protobuf": {}, "application/bcs": {} } } diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index 5562b6d14fbaa..e1f4fdf329e12 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -259,14 +259,6 @@ impl Client { let request = self.inner.get(url).query(parameters); self.bcs(request).await - // self.protobuf::(request) - // .await? - // .try_map(|page| { - // page.checkpoints - // .into_iter() - // .map(TryInto::try_into) - // .collect() - // }) } pub async fn get_full_checkpoint( @@ -280,13 +272,6 @@ impl Client { let request = self.inner.get(url); self.bcs(request).await - // self.protobuf::(request) - // .await? - // // TODO make this more efficient and convert directly into the sui-sdk-types version - // .try_map(|proto| { - // sui_types::full_checkpoint_content::CheckpointData::try_from(proto) - // .and_then(TryInto::try_into) - // }) } pub async fn get_transaction( @@ -430,25 +415,6 @@ impl Client { Err(e) => Err(Error::from_error(e).with_parts(parts)), } } - - #[allow(unused)] - pub(super) async fn protobuf( - &self, - request: reqwest::RequestBuilder, - ) -> Result> { - let response = request - .header(reqwest::header::ACCEPT, crate::rest::APPLICATION_PROTOBUF) - .send() - .await?; - - let (response, parts) = self.check_response(response).await?; - - let bytes = response.bytes().await?; - match T::decode(bytes) { - Ok(v) => Ok(Response::new(v, parts)), - Err(e) => Err(Error::from_error(e).with_parts(parts)), - } - } } #[derive(Debug)] diff --git a/crates/sui-rpc-api/src/response.rs b/crates/sui-rpc-api/src/response.rs index 8abff279ddc17..25f7f2c595f50 100644 --- a/crates/sui-rpc-api/src/response.rs +++ b/crates/sui-rpc-api/src/response.rs @@ -6,10 +6,8 @@ use axum::{ http::{HeaderMap, StatusCode}, response::{IntoResponse, Response}, }; -use prost::bytes::BytesMut; use crate::{ - rest::accept::APPLICATION_PROTOBUF, rest::content_type::ContentType, rest::APPLICATION_BCS, rest::TEXT_PLAIN_UTF_8, @@ -129,47 +127,6 @@ where } } -#[derive(Debug)] -pub enum JsonProtobufBcs { - Json(J), - Protobuf(P), - Bcs(T), -} - -impl axum::response::IntoResponse for JsonProtobufBcs -where - J: serde::Serialize, - P: prost::Message + std::default::Default, - T: serde::Serialize, -{ - fn into_response(self) -> axum::response::Response { - match self { - JsonProtobufBcs::Json(inner) => axum::Json(inner).into_response(), - JsonProtobufBcs::Protobuf(inner) => Protobuf(inner).into_response(), - JsonProtobufBcs::Bcs(inner) => Bcs(inner).into_response(), - } - } -} - -#[derive(Debug)] -pub enum ProtobufBcs { - Protobuf(P), - Bcs(T), -} - -impl axum::response::IntoResponse for ProtobufBcs -where - P: prost::Message + std::default::Default, - T: serde::Serialize, -{ - fn into_response(self) -> axum::response::Response { - match self { - Self::Protobuf(inner) => Protobuf(inner).into_response(), - Self::Bcs(inner) => Bcs(inner).into_response(), - } - } -} - pub async fn append_info_headers( State(state): State, response: Response, @@ -214,90 +171,3 @@ pub async fn append_info_headers( (headers, response) } - -pub struct Protobuf(pub T); - -impl axum::response::IntoResponse for Protobuf -where - T: prost::Message, -{ - fn into_response(self) -> axum::response::Response { - let mut buf = BytesMut::new(); - match self.0.encode(&mut buf) { - Ok(()) => ( - [( - axum::http::header::CONTENT_TYPE, - axum::http::HeaderValue::from_static(APPLICATION_PROTOBUF), - )], - buf, - ) - .into_response(), - Err(err) => ( - StatusCode::INTERNAL_SERVER_ERROR, - [( - axum::http::header::CONTENT_TYPE, - axum::http::HeaderValue::from_static(TEXT_PLAIN_UTF_8), - )], - err.to_string(), - ) - .into_response(), - } - } -} - -#[axum::async_trait] -impl axum::extract::FromRequest for Protobuf -where - T: prost::Message + std::default::Default, - S: Send + Sync, -{ - type Rejection = ProtobufRejection; - - async fn from_request( - req: axum::http::Request, - state: &S, - ) -> Result { - if protobuf_content_type(req.headers()) { - let bytes = axum::body::Bytes::from_request(req, state) - .await - .map_err(ProtobufRejection::BytesRejection)?; - T::decode(bytes) - .map(Self) - .map_err(ProtobufRejection::DeserializationError) - } else { - Err(ProtobufRejection::MissingProtobufContentType) - } - } -} - -fn protobuf_content_type(headers: &HeaderMap) -> bool { - let Some(ContentType(mime)) = ContentType::from_headers(headers) else { - return false; - }; - - mime.essence_str() == APPLICATION_PROTOBUF -} - -pub enum ProtobufRejection { - MissingProtobufContentType, - DeserializationError(prost::DecodeError), - BytesRejection(axum::extract::rejection::BytesRejection), -} - -impl axum::response::IntoResponse for ProtobufRejection { - fn into_response(self) -> axum::response::Response { - match self { - ProtobufRejection::MissingProtobufContentType => ( - StatusCode::UNSUPPORTED_MEDIA_TYPE, - "Expected request with `Content-Type: application/x-protobuf`", - ) - .into_response(), - ProtobufRejection::DeserializationError(e) => ( - StatusCode::UNPROCESSABLE_ENTITY, - format!("Failed to deserialize the protobuf body into the target type: {e}"), - ) - .into_response(), - ProtobufRejection::BytesRejection(bytes_rejection) => bytes_rejection.into_response(), - } - } -} diff --git a/crates/sui-rpc-api/src/rest/accept.rs b/crates/sui-rpc-api/src/rest/accept.rs index fbb93606c95c5..193158f1520c0 100644 --- a/crates/sui-rpc-api/src/rest/accept.rs +++ b/crates/sui-rpc-api/src/rest/accept.rs @@ -8,7 +8,6 @@ use mime::Mime; // include type information // "application/x.sui.+bcs" pub const APPLICATION_BCS: &str = "application/bcs"; -pub const APPLICATION_PROTOBUF: &str = "application/x-protobuf"; /// `Accept` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.2) #[derive(Debug, Clone)] @@ -52,7 +51,6 @@ where pub enum AcceptFormat { Json, Bcs, - // Protobuf, } #[axum::async_trait] @@ -82,42 +80,6 @@ where } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum AcceptJsonProtobufBcs { - Json, - Protobuf, - Bcs, -} - -#[axum::async_trait] -impl axum::extract::FromRequestParts for AcceptJsonProtobufBcs -where - S: Send + Sync, -{ - type Rejection = std::convert::Infallible; - - async fn from_request_parts( - parts: &mut http::request::Parts, - s: &S, - ) -> Result { - let accept = Accept::from_request_parts(parts, s).await?; - - for mime in accept.0 { - let essence = mime.essence_str(); - - if essence == mime::APPLICATION_JSON.essence_str() { - return Ok(Self::Json); - } else if essence == APPLICATION_PROTOBUF { - return Ok(Self::Protobuf); - } else if essence == APPLICATION_BCS { - return Ok(Self::Bcs); - } - } - - Ok(Self::Json) - } -} - #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/crates/sui-rpc-api/src/rest/checkpoints.rs b/crates/sui-rpc-api/src/rest/checkpoints.rs index de3bace9e0c5c..b135ed4fdcaa2 100644 --- a/crates/sui-rpc-api/src/rest/checkpoints.rs +++ b/crates/sui-rpc-api/src/rest/checkpoints.rs @@ -10,17 +10,16 @@ use sui_sdk_types::types::{ use sui_types::storage::ReadStore; use tap::Pipe; -use crate::proto; -use crate::proto::ListCheckpointResponse; use crate::reader::StateReader; -use crate::response::{JsonProtobufBcs, ProtobufBcs}; -use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::response::{Bcs, ResponseContent}; use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::rest::PageCursor; use crate::{Direction, RpcService}; use crate::{RestError, Result}; use documented::Documented; +use super::accept::AcceptFormat; + #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] pub struct CheckpointResponse { pub digest: CheckpointDigest, @@ -82,9 +81,9 @@ impl ApiEndpoint for GetCheckpoint { async fn get_checkpoint( Path(checkpoint_id): Path, Query(parameters): Query, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, -) -> Result> { +) -> Result> { let SignedCheckpointSummary { checkpoint, signature, @@ -126,9 +125,8 @@ async fn get_checkpoint( }; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(response), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(response.try_into()?), - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(response), + AcceptFormat::Json => ResponseContent::Json(response), + AcceptFormat::Bcs => ResponseContent::Bcs(response), } .pipe(Ok) } @@ -253,7 +251,6 @@ impl ApiEndpoint for ListCheckpoints { ResponseBuilder::new() .json_content::>(generator) .bcs_content() - .protobuf_content() .header::(crate::types::X_SUI_CURSOR, generator) .build(), ) @@ -269,11 +266,11 @@ impl ApiEndpoint for ListCheckpoints { async fn list_checkpoints( Query(parameters): Query, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, ) -> Result<( PageCursor, - JsonProtobufBcs, ListCheckpointResponse, Vec>, + ResponseContent, Vec>, )> { let latest_checkpoint = state.inner().get_latest_checkpoint()?.sequence_number; let oldest_checkpoint = state.inner().get_lowest_available_checkpoint()?; @@ -328,11 +325,10 @@ async fn list_checkpoints( }); match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(checkpoints), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(checkpoints.try_into()?), + AcceptFormat::Json => ResponseContent::Json(checkpoints), // In order to work around compatibility issues with existing clients, keep the BCS form as // the old format without contents - AcceptJsonProtobufBcs::Bcs => { + AcceptFormat::Bcs => { let checkpoints = checkpoints .into_iter() .map(|c| SignedCheckpointSummary { @@ -340,7 +336,7 @@ async fn list_checkpoints( signature: c.signature, }) .collect(); - JsonProtobufBcs::Bcs(checkpoints) + ResponseContent::Bcs(checkpoints) } } .pipe(|entries| (PageCursor(cursor), entries)) @@ -434,17 +430,15 @@ impl ApiEndpoint for GetFullCheckpoint { async fn get_full_checkpoint( Path(checkpoint_id): Path, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, -) -> Result> -{ +) -> Result> { match accept { - AcceptJsonProtobufBcs::Protobuf => {} - AcceptJsonProtobufBcs::Bcs => {} + AcceptFormat::Bcs => {} _ => { return Err(RestError::new( axum::http::StatusCode::BAD_REQUEST, - "invalid accept type; only 'application/x-protobuf' is supported", + "invalid accept type; only 'application/bcs' is supported", )) } } @@ -476,15 +470,5 @@ async fn get_full_checkpoint( .inner() .get_checkpoint_data(verified_summary, checkpoint_contents)?; - match accept { - AcceptJsonProtobufBcs::Protobuf => ProtobufBcs::Protobuf(checkpoint_data.try_into()?), - AcceptJsonProtobufBcs::Bcs => ProtobufBcs::Bcs(checkpoint_data), - _ => { - return Err(RestError::new( - axum::http::StatusCode::BAD_REQUEST, - "invalid accept type; only 'application/x-protobuf' is supported", - )) - } - } - .pipe(Ok) + Ok(Bcs(checkpoint_data)) } diff --git a/crates/sui-rpc-api/src/rest/committee.rs b/crates/sui-rpc-api/src/rest/committee.rs index 5ea84e6ec2bdb..aa5476d082c6d 100644 --- a/crates/sui-rpc-api/src/rest/committee.rs +++ b/crates/sui-rpc-api/src/rest/committee.rs @@ -2,9 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - proto, - response::JsonProtobufBcs, - rest::accept::AcceptJsonProtobufBcs, + response::ResponseContent, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, Result, RpcService, }; @@ -12,6 +10,8 @@ use axum::extract::{Path, State}; use sui_sdk_types::types::{EpochId, ValidatorCommittee}; use tap::Pipe; +use super::accept::AcceptFormat; + pub struct GetLatestCommittee; impl ApiEndpoint for GetLatestCommittee { @@ -34,7 +34,6 @@ impl ApiEndpoint for GetLatestCommittee { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -47,15 +46,14 @@ impl ApiEndpoint for GetLatestCommittee { } async fn get_latest_committee( - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, -) -> Result> { +) -> Result> { let committee = state.get_committee(None)?; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(committee), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(committee.into()), - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(committee), + AcceptFormat::Json => ResponseContent::Json(committee), + AcceptFormat::Bcs => ResponseContent::Bcs(committee), } .pipe(Ok) } @@ -83,7 +81,6 @@ impl ApiEndpoint for GetCommittee { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -98,15 +95,14 @@ impl ApiEndpoint for GetCommittee { async fn get_committee( Path(epoch): Path, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, -) -> Result> { +) -> Result> { let committee = state.get_committee(Some(epoch))?; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(committee), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(committee.into()), - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(committee), + AcceptFormat::Json => ResponseContent::Json(committee), + AcceptFormat::Bcs => ResponseContent::Bcs(committee), } .pipe(Ok) } diff --git a/crates/sui-rpc-api/src/rest/mod.rs b/crates/sui-rpc-api/src/rest/mod.rs index 4d52f305a3497..6d6fe1e97becd 100644 --- a/crates/sui-rpc-api/src/rest/mod.rs +++ b/crates/sui-rpc-api/src/rest/mod.rs @@ -28,7 +28,6 @@ pub mod transactions; pub const TEXT_PLAIN_UTF_8: &str = "text/plain; charset=utf-8"; pub const APPLICATION_BCS: &str = "application/bcs"; pub const APPLICATION_JSON: &str = "application/json"; -pub const APPLICATION_PROTOBUF: &str = "application/x-protobuf"; pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ // stable APIs diff --git a/crates/sui-rpc-api/src/rest/objects.rs b/crates/sui-rpc-api/src/rest/objects.rs index c640c020dad27..84a19ee523496 100644 --- a/crates/sui-rpc-api/src/rest/objects.rs +++ b/crates/sui-rpc-api/src/rest/objects.rs @@ -2,10 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - proto::GetObjectResponse, reader::StateReader, - response::{JsonProtobufBcs, ResponseContent}, - rest::accept::{AcceptFormat, AcceptJsonProtobufBcs}, + response::ResponseContent, + rest::accept::AcceptFormat, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, rest::Page, RestError, Result, RpcService, @@ -50,7 +49,6 @@ impl ApiEndpoint for GetObject { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -65,9 +63,9 @@ impl ApiEndpoint for GetObject { pub async fn get_object( Path(object_id): Path, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, -) -> Result> { +) -> Result> { let object = state .get_object(object_id)? .ok_or_else(|| ObjectNotFoundError::new(object_id))?; @@ -78,11 +76,8 @@ pub async fn get_object( }; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(object), - AcceptJsonProtobufBcs::Protobuf => { - JsonProtobufBcs::Protobuf(GetObjectResponse::try_from(object)?) - } - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(object.object), + AcceptFormat::Json => ResponseContent::Json(object), + AcceptFormat::Bcs => ResponseContent::Bcs(object.object), } .pipe(Ok) } @@ -111,7 +106,6 @@ impl ApiEndpoint for GetObjectWithVersion { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -126,9 +120,9 @@ impl ApiEndpoint for GetObjectWithVersion { pub async fn get_object_with_version( Path((object_id, version)): Path<(ObjectId, Version)>, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, -) -> Result> { +) -> Result> { let object = state .get_object_with_version(object_id, version)? .ok_or_else(|| ObjectNotFoundError::new_with_version(object_id, version))?; @@ -139,11 +133,8 @@ pub async fn get_object_with_version( }; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(object), - AcceptJsonProtobufBcs::Protobuf => { - JsonProtobufBcs::Protobuf(GetObjectResponse::try_from(object)?) - } - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(object.object), + AcceptFormat::Json => ResponseContent::Json(object), + AcceptFormat::Bcs => ResponseContent::Bcs(object.object), } .pipe(Ok) } diff --git a/crates/sui-rpc-api/src/rest/openapi.rs b/crates/sui-rpc-api/src/rest/openapi.rs index 20bc6febe210d..f0349704db859 100644 --- a/crates/sui-rpc-api/src/rest/openapi.rs +++ b/crates/sui-rpc-api/src/rest/openapi.rs @@ -652,10 +652,6 @@ impl ResponseBuilder { self.content(crate::rest::APPLICATION_BCS, MediaType::default()) } - pub fn protobuf_content(&mut self) -> &mut Self { - self.content(crate::rest::APPLICATION_PROTOBUF, MediaType::default()) - } - pub fn text_content(&mut self) -> &mut Self { self.content(mime::TEXT_PLAIN_UTF_8.as_ref(), MediaType::default()) } diff --git a/crates/sui-rpc-api/src/rest/transactions/execution.rs b/crates/sui-rpc-api/src/rest/transactions/execution.rs index 2c796bf983085..845134c3ca164 100644 --- a/crates/sui-rpc-api/src/rest/transactions/execution.rs +++ b/crates/sui-rpc-api/src/rest/transactions/execution.rs @@ -1,12 +1,12 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::response::{Bcs, JsonProtobufBcs}; -use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::response::{Bcs, ResponseContent}; +use crate::rest::accept::AcceptFormat; use crate::rest::openapi::{ ApiEndpoint, OperationBuilder, RequestBodyBuilder, ResponseBuilder, RouteHandler, }; -use crate::{proto, RestError, Result, RpcService}; +use crate::{RestError, Result, RpcService}; use axum::extract::{Query, State}; use schemars::JsonSchema; use std::net::SocketAddr; @@ -43,7 +43,6 @@ impl ApiEndpoint for ExecuteTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -66,15 +65,9 @@ async fn execute_transaction( State(state): State>>, Query(parameters): Query, client_address: Option>, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, Bcs(transaction): Bcs, -) -> Result< - JsonProtobufBcs< - TransactionExecutionResponse, - proto::TransactionExecutionResponse, - TransactionExecutionResponse, - >, -> { +) -> Result> { let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; let request = sui_types::quorum_driver_types::ExecuteTransactionRequestV3 { transaction: transaction.try_into()?, @@ -171,9 +164,8 @@ async fn execute_transaction( }; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(response), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(response.try_into()?), - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(response), + AcceptFormat::Json => ResponseContent::Json(response), + AcceptFormat::Bcs => ResponseContent::Bcs(response), } .pipe(Ok) } @@ -395,7 +387,6 @@ impl ApiEndpoint for SimulateTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -410,24 +401,17 @@ impl ApiEndpoint for SimulateTransaction { async fn simulate_transaction( State(state): State>>, Query(parameters): Query, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, //TODO allow accepting JSON as well as BCS Bcs(transaction): Bcs, -) -> Result< - JsonProtobufBcs< - TransactionSimulationResponse, - proto::TransactionSimulationResponse, - TransactionSimulationResponse, - >, -> { +) -> Result> { let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; let response = simulate_transaction_impl(&executor, ¶meters, transaction)?; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(response), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(response.try_into()?), - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(response), + AcceptFormat::Json => ResponseContent::Json(response), + AcceptFormat::Bcs => ResponseContent::Bcs(response), } .pipe(Ok) } diff --git a/crates/sui-rpc-api/src/rest/transactions/mod.rs b/crates/sui-rpc-api/src/rest/transactions/mod.rs index c2688f81bedba..755ec9295b45f 100644 --- a/crates/sui-rpc-api/src/rest/transactions/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/mod.rs @@ -24,11 +24,9 @@ use sui_sdk_types::types::{ }; use tap::Pipe; -use crate::proto; -use crate::proto::ListTransactionsResponse; use crate::reader::StateReader; -use crate::response::JsonProtobufBcs; -use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::response::ResponseContent; +use crate::rest::accept::AcceptFormat; use crate::rest::openapi::ApiEndpoint; use crate::rest::openapi::OperationBuilder; use crate::rest::openapi::ResponseBuilder; @@ -62,7 +60,6 @@ impl ApiEndpoint for GetTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -77,16 +74,14 @@ impl ApiEndpoint for GetTransaction { async fn get_transaction( Path(transaction_digest): Path, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, -) -> Result> -{ +) -> Result> { let response = state.get_transaction_response(transaction_digest)?; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(response), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(response.try_into()?), - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(response), + AcceptFormat::Json => ResponseContent::Json(response), + AcceptFormat::Bcs => ResponseContent::Bcs(response), } .pipe(Ok) } @@ -151,7 +146,6 @@ impl ApiEndpoint for ListTransactions { 200, ResponseBuilder::new() .json_content::>(generator) - .protobuf_content() .bcs_content() .header::(crate::types::X_SUI_CURSOR, generator) .build(), @@ -167,11 +161,11 @@ impl ApiEndpoint for ListTransactions { async fn list_transactions( Query(parameters): Query, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, State(state): State, ) -> Result<( PageCursor, - JsonProtobufBcs, ListTransactionsResponse, Vec>, + ResponseContent>, )> { let latest_checkpoint = state.inner().get_latest_checkpoint()?.sequence_number; let oldest_checkpoint = state.inner().get_lowest_available_checkpoint()?; @@ -216,17 +210,8 @@ async fn list_transactions( }); match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(transactions), - AcceptJsonProtobufBcs::Protobuf => { - let proto = ListTransactionsResponse { - transactions: transactions - .into_iter() - .map(TryInto::try_into) - .collect::>()?, - }; - JsonProtobufBcs::Protobuf(proto) - } - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(transactions), + AcceptFormat::Json => ResponseContent::Json(transactions), + AcceptFormat::Bcs => ResponseContent::Bcs(transactions), } .pipe(|entries| (PageCursor(cursor), entries)) .pipe(Ok) diff --git a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs index b7f487128fc6a..2a9134333cc09 100644 --- a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs @@ -6,10 +6,9 @@ use std::collections::HashMap; use super::execution::SimulateTransactionQueryParameters; use super::TransactionSimulationResponse; -use crate::proto; use crate::reader::StateReader; -use crate::response::JsonProtobufBcs; -use crate::rest::accept::AcceptJsonProtobufBcs; +use crate::response::ResponseContent; +use crate::rest::accept::AcceptFormat; use crate::rest::objects::ObjectNotFoundError; use crate::rest::openapi::ApiEndpoint; use crate::rest::openapi::OperationBuilder; @@ -76,7 +75,6 @@ impl ApiEndpoint for ResolveTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .protobuf_content() .bcs_content() .build(), ) @@ -91,15 +89,9 @@ impl ApiEndpoint for ResolveTransaction { async fn resolve_transaction( State(state): State, Query(parameters): Query, - accept: AcceptJsonProtobufBcs, + accept: AcceptFormat, Json(unresolved_transaction): Json, -) -> Result< - JsonProtobufBcs< - ResolveTransactionResponse, - proto::ResolveTransactionResponse, - ResolveTransactionResponse, - >, -> { +) -> Result> { let executor = state .executor .as_ref() @@ -193,9 +185,8 @@ async fn resolve_transaction( }; match accept { - AcceptJsonProtobufBcs::Json => JsonProtobufBcs::Json(response), - AcceptJsonProtobufBcs::Protobuf => JsonProtobufBcs::Protobuf(response.try_into()?), - AcceptJsonProtobufBcs::Bcs => JsonProtobufBcs::Bcs(response), + AcceptFormat::Json => ResponseContent::Json(response), + AcceptFormat::Bcs => ResponseContent::Bcs(response), } .pipe(Ok) } From 13549fe5a221c09aa3fa764b36929b9b5fe86f71 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 26 Nov 2024 21:53:46 -0600 Subject: [PATCH 17/28] rest: remove support for bcs response types from various endpoints Remove support for bcs response types from various endpoints, a few are kept due to existing clients, as support for a binary response type will be supported via a gRPC service that will be added in a future patch. --- crates/sui-e2e-tests/tests/rpc/checkpoints.rs | 30 ---------- crates/sui-e2e-tests/tests/rpc/committee.rs | 36 ------------ .../sui-e2e-tests/tests/rpc/transactions.rs | 58 +------------------ crates/sui-rpc-api/openapi/openapi.json | 24 +++----- crates/sui-rpc-api/src/client/mod.rs | 47 +++++++-------- crates/sui-rpc-api/src/client/sdk.rs | 38 +++++++----- crates/sui-rpc-api/src/rest/checkpoints.rs | 13 ++--- crates/sui-rpc-api/src/rest/committee.rs | 35 +++-------- .../src/rest/transactions/execution.rs | 30 +++------- .../sui-rpc-api/src/rest/transactions/mod.rs | 42 +++++--------- .../src/rest/transactions/resolve/mod.rs | 14 +---- 11 files changed, 90 insertions(+), 277 deletions(-) diff --git a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs index 08b41685f3b3f..6d68cd0c3caac 100644 --- a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs +++ b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs @@ -73,36 +73,6 @@ async fn get_checkpoint() { .get_checkpoint(latest.checkpoint.sequence_number) .await .unwrap(); - - let client = reqwest::Client::new(); - let url = format!( - "{}/v2/checkpoints/{}", - test_cluster.rpc_url(), - latest.checkpoint.sequence_number - ); - // Make sure list works with json - let _checkpoints = client - .get(&url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - - // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients - // wanting binary have migrated to grpc - let bytes = client - .get(&url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _checkpoints = bcs::from_bytes::(&bytes).unwrap(); } #[sim_test] diff --git a/crates/sui-e2e-tests/tests/rpc/committee.rs b/crates/sui-e2e-tests/tests/rpc/committee.rs index 9bf28bae9767d..c62e5155c18dc 100644 --- a/crates/sui-e2e-tests/tests/rpc/committee.rs +++ b/crates/sui-e2e-tests/tests/rpc/committee.rs @@ -3,7 +3,6 @@ use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; -use sui_sdk_types::types::ValidatorCommittee; use test_cluster::TestClusterBuilder; #[sim_test] @@ -14,39 +13,4 @@ async fn get_committee() { let _committee = client.get_committee(0).await.unwrap(); let _committee = client.get_current_committee().await.unwrap(); - - async fn raw_request(url: &str) { - let client = reqwest::Client::new(); - - // Make sure list works with json - let _object = client - .get(url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - - // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients - // wanting binary have migrated to grpc - let bytes = client - .get(url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _committee = bcs::from_bytes::(&bytes).unwrap(); - } - - let url = format!("{}/v2/system/committee", test_cluster.rpc_url(),); - - raw_request(&url).await; - - let url = format!("{}/v2/system/committee/0", test_cluster.rpc_url()); - raw_request(&url).await; } diff --git a/crates/sui-e2e-tests/tests/rpc/transactions.rs b/crates/sui-e2e-tests/tests/rpc/transactions.rs index a8c564f4699db..12014d7c3c94a 100644 --- a/crates/sui-e2e-tests/tests/rpc/transactions.rs +++ b/crates/sui-e2e-tests/tests/rpc/transactions.rs @@ -3,7 +3,7 @@ use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; -use sui_rpc_api::rest::transactions::{ListTransactionsQueryParameters, TransactionResponse}; +use sui_rpc_api::rest::transactions::ListTransactionsQueryParameters; use test_cluster::TestClusterBuilder; use crate::transfer_coin; @@ -17,36 +17,6 @@ async fn get_transaction() { let client = Client::new(test_cluster.rpc_url()).unwrap(); let _transaction = client.get_transaction(&transaction_digest).await.unwrap(); - - let client = reqwest::Client::new(); - let url = format!( - "{}/v2/transactions/{}", - test_cluster.rpc_url(), - transaction_digest, - ); - // Make sure it works with json - let _transaction = client - .get(&url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - - // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients - // wanting binary have migrated to grpc - let bytes = client - .get(&url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _transaction = bcs::from_bytes::(&bytes).unwrap(); } #[sim_test] @@ -64,30 +34,4 @@ async fn list_checkpoint() { .into_inner(); assert!(!transactions.is_empty()); - - let client = reqwest::Client::new(); - let url = format!("{}/v2/transactions", test_cluster.rpc_url()); - // Make sure it works with json - let _transactions = client - .get(&url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_JSON) - .send() - .await - .unwrap() - .json::>() - .await - .unwrap(); - - // TODO remove this once the BCS format is no longer supported by the rest endpoint and clients - // wanting binary have migrated to grpc - let bytes = client - .get(&url) - .header(reqwest::header::ACCEPT, sui_rpc_api::rest::APPLICATION_BCS) - .send() - .await - .unwrap() - .bytes() - .await - .unwrap(); - let _transactions = bcs::from_bytes::>(&bytes).unwrap(); } diff --git a/crates/sui-rpc-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json index 9ef11418b1d84..9d7a30836f7ee 100644 --- a/crates/sui-rpc-api/openapi/openapi.json +++ b/crates/sui-rpc-api/openapi/openapi.json @@ -204,8 +204,7 @@ "schema": { "$ref": "#/components/schemas/CheckpointResponse" } - }, - "application/bcs": {} + } } }, "404": { @@ -488,8 +487,7 @@ "schema": { "$ref": "#/components/schemas/TransactionResponse" } - }, - "application/bcs": {} + } } }, "404": { @@ -552,8 +550,7 @@ "$ref": "#/components/schemas/TransactionResponse" } } - }, - "application/bcs": {} + } } }, "410": { @@ -626,8 +623,7 @@ "schema": { "$ref": "#/components/schemas/TransactionExecutionResponse" } - }, - "application/bcs": {} + } } } } @@ -661,8 +657,7 @@ "schema": { "$ref": "#/components/schemas/ValidatorCommittee" } - }, - "application/bcs": {} + } } }, "404": { @@ -686,8 +681,7 @@ "schema": { "$ref": "#/components/schemas/ValidatorCommittee" } - }, - "application/bcs": {} + } } } } @@ -876,8 +870,7 @@ "schema": { "$ref": "#/components/schemas/TransactionSimulationResponse" } - }, - "application/bcs": {} + } } } } @@ -953,8 +946,7 @@ "schema": { "$ref": "#/components/schemas/ResolveTransactionResponse" } - }, - "application/bcs": {} + } } } } diff --git a/crates/sui-rpc-api/src/client/mod.rs b/crates/sui-rpc-api/src/client/mod.rs index 35555e4a44162..d76379445ce2b 100644 --- a/crates/sui-rpc-api/src/client/mod.rs +++ b/crates/sui-rpc-api/src/client/mod.rs @@ -54,12 +54,6 @@ impl Client { let request = self.inner.client().get(url); self.inner.bcs(request).await.map(Response::into_inner) - // let proto = self - // .inner - // .protobuf::(request) - // .await? - // .into_inner(); - // proto.try_into().map_err(Into::into) } pub async fn get_checkpoint_summary( @@ -105,27 +99,28 @@ impl Client { parameters: &ExecuteTransactionQueryParameters, transaction: &Transaction, ) -> Result { - #[derive(serde::Serialize)] - struct SignedTransaction<'a> { - transaction: &'a sui_types::transaction::TransactionData, - signatures: &'a [sui_types::signature::GenericSignature], - } - - let url = self.inner.url().join("transactions")?; - let body = bcs::to_bytes(&SignedTransaction { - transaction: &transaction.inner().intent_message.value, - signatures: &transaction.inner().tx_signatures, - })?; - - let request = self + let signed_transaction = sui_sdk_types::types::SignedTransaction { + transaction: transaction + .inner() + .intent_message + .value + .clone() + .try_into()?, + signatures: transaction + .inner() + .tx_signatures + .clone() + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + }; + + let response = self .inner - .client() - .post(url) - .query(parameters) - .header(reqwest::header::CONTENT_TYPE, crate::rest::APPLICATION_BCS) - .body(body); - - self.inner.bcs(request).await.map(Response::into_inner) + .execute_transaction(parameters, &signed_transaction) + .await? + .into_inner(); + bcs::from_bytes(&bcs::to_bytes(&response)?).map_err(Into::into) } } diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index e1f4fdf329e12..e025c015c75fe 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -133,7 +133,9 @@ impl Client { let request = self.inner.get(url); - self.bcs(request).await + self.json::(request) + .await + .map(|response| response.map(|response| response.object)) } pub async fn get_object_with_version( @@ -147,7 +149,9 @@ impl Client { let request = self.inner.get(url); - self.bcs(request).await + self.json::(request) + .await + .map(|response| response.map(|response| response.object)) } pub async fn list_dynamic_fields( @@ -209,7 +213,7 @@ impl Client { let request = self.inner.get(url); - self.bcs(request).await + self.json(request).await } pub async fn get_committee(&self, epoch: EpochId) -> Result> { @@ -217,7 +221,7 @@ impl Client { let request = self.inner.get(url); - self.bcs(request).await + self.json(request).await } pub async fn get_checkpoint( @@ -230,7 +234,7 @@ impl Client { let request = self.inner.get(url); - self.bcs(request).await + self.json(request).await } pub async fn get_latest_checkpoint(&self) -> Result> { @@ -247,18 +251,24 @@ impl Client { .pop() .ok_or_else(|| Error::new_message("server returned empty checkpoint list"))?; - Ok(Response::new(checkpoint, parts)) + Ok(Response::new( + SignedCheckpointSummary { + checkpoint: checkpoint.summary, + signature: checkpoint.signature, + }, + parts, + )) } pub async fn list_checkpoints( &self, parameters: &ListCheckpointsQueryParameters, - ) -> Result>> { + ) -> Result>> { let url = self.url().join("checkpoints")?; let request = self.inner.get(url).query(parameters); - self.bcs(request).await + self.json(request).await } pub async fn get_full_checkpoint( @@ -282,7 +292,7 @@ impl Client { let request = self.inner.get(url); - self.bcs(request).await + self.json(request).await } pub async fn list_transactions( @@ -293,7 +303,7 @@ impl Client { let request = self.inner.get(url).query(parameters); - self.bcs(request).await + self.json(request).await } pub async fn execute_transaction( @@ -312,7 +322,7 @@ impl Client { .header(reqwest::header::CONTENT_TYPE, crate::rest::APPLICATION_BCS) .body(body); - self.bcs(request).await + self.json(request).await } pub async fn simulate_transaction( @@ -329,7 +339,7 @@ impl Client { .header(reqwest::header::CONTENT_TYPE, crate::rest::APPLICATION_BCS) .body(body); - self.bcs(request).await + self.json(request).await } pub async fn resolve_transaction( @@ -340,7 +350,7 @@ impl Client { let request = self.inner.post(url).json(unresolved_transaction); - self.bcs(request).await + self.json(request).await } pub async fn resolve_transaction_with_parameters( @@ -356,7 +366,7 @@ impl Client { .query(¶meters) .json(unresolved_transaction); - self.bcs(request).await + self.json(request).await } async fn check_response( diff --git a/crates/sui-rpc-api/src/rest/checkpoints.rs b/crates/sui-rpc-api/src/rest/checkpoints.rs index b135ed4fdcaa2..003b510a22445 100644 --- a/crates/sui-rpc-api/src/rest/checkpoints.rs +++ b/crates/sui-rpc-api/src/rest/checkpoints.rs @@ -3,6 +3,7 @@ use axum::extract::Query; use axum::extract::{Path, State}; +use axum::Json; use sui_sdk_types::types::{ CheckpointContents, CheckpointDigest, CheckpointSequenceNumber, CheckpointSummary, SignedCheckpointSummary, ValidatorAggregatedSignature, @@ -64,7 +65,6 @@ impl ApiEndpoint for GetCheckpoint { 200, ResponseBuilder::new() .json_content::(generator) - .bcs_content() .build(), ) .response(404, ResponseBuilder::new().build()) @@ -81,9 +81,8 @@ impl ApiEndpoint for GetCheckpoint { async fn get_checkpoint( Path(checkpoint_id): Path, Query(parameters): Query, - accept: AcceptFormat, State(state): State, -) -> Result> { +) -> Result> { let SignedCheckpointSummary { checkpoint, signature, @@ -117,17 +116,13 @@ async fn get_checkpoint( None }; - let response = CheckpointResponse { + CheckpointResponse { digest: checkpoint.digest(), summary: checkpoint, signature, contents, - }; - - match accept { - AcceptFormat::Json => ResponseContent::Json(response), - AcceptFormat::Bcs => ResponseContent::Bcs(response), } + .pipe(Json) .pipe(Ok) } diff --git a/crates/sui-rpc-api/src/rest/committee.rs b/crates/sui-rpc-api/src/rest/committee.rs index aa5476d082c6d..6e2a98df41ac3 100644 --- a/crates/sui-rpc-api/src/rest/committee.rs +++ b/crates/sui-rpc-api/src/rest/committee.rs @@ -2,15 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - response::ResponseContent, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, Result, RpcService, }; -use axum::extract::{Path, State}; +use axum::{ + extract::{Path, State}, + Json, +}; use sui_sdk_types::types::{EpochId, ValidatorCommittee}; -use tap::Pipe; - -use super::accept::AcceptFormat; pub struct GetLatestCommittee; @@ -34,7 +33,6 @@ impl ApiEndpoint for GetLatestCommittee { 200, ResponseBuilder::new() .json_content::(generator) - .bcs_content() .build(), ) .build() @@ -45,17 +43,8 @@ impl ApiEndpoint for GetLatestCommittee { } } -async fn get_latest_committee( - accept: AcceptFormat, - State(state): State, -) -> Result> { - let committee = state.get_committee(None)?; - - match accept { - AcceptFormat::Json => ResponseContent::Json(committee), - AcceptFormat::Bcs => ResponseContent::Bcs(committee), - } - .pipe(Ok) +async fn get_latest_committee(State(state): State) -> Result> { + state.get_committee(None).map(Json) } pub struct GetCommittee; @@ -81,7 +70,6 @@ impl ApiEndpoint for GetCommittee { 200, ResponseBuilder::new() .json_content::(generator) - .bcs_content() .build(), ) .response(404, ResponseBuilder::new().build()) @@ -95,14 +83,7 @@ impl ApiEndpoint for GetCommittee { async fn get_committee( Path(epoch): Path, - accept: AcceptFormat, State(state): State, -) -> Result> { - let committee = state.get_committee(Some(epoch))?; - - match accept { - AcceptFormat::Json => ResponseContent::Json(committee), - AcceptFormat::Bcs => ResponseContent::Bcs(committee), - } - .pipe(Ok) +) -> Result> { + state.get_committee(Some(epoch)).map(Json) } diff --git a/crates/sui-rpc-api/src/rest/transactions/execution.rs b/crates/sui-rpc-api/src/rest/transactions/execution.rs index 845134c3ca164..fd96a63caef81 100644 --- a/crates/sui-rpc-api/src/rest/transactions/execution.rs +++ b/crates/sui-rpc-api/src/rest/transactions/execution.rs @@ -1,13 +1,13 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::response::{Bcs, ResponseContent}; -use crate::rest::accept::AcceptFormat; +use crate::response::Bcs; use crate::rest::openapi::{ ApiEndpoint, OperationBuilder, RequestBodyBuilder, ResponseBuilder, RouteHandler, }; use crate::{RestError, Result, RpcService}; use axum::extract::{Query, State}; +use axum::Json; use schemars::JsonSchema; use std::net::SocketAddr; use std::sync::Arc; @@ -43,7 +43,6 @@ impl ApiEndpoint for ExecuteTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .bcs_content() .build(), ) .build() @@ -59,15 +58,12 @@ impl ApiEndpoint for ExecuteTransaction { /// Handles client transaction submission request by passing off the provided signed transaction to /// an internal QuorumDriver which drives execution of the transaction with the current validator /// set. -/// -/// A client can signal, using the `Accept` header, the response format as either JSON or BCS. async fn execute_transaction( State(state): State>>, Query(parameters): Query, client_address: Option>, - accept: AcceptFormat, Bcs(transaction): Bcs, -) -> Result> { +) -> Result> { let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; let request = sui_types::quorum_driver_types::ExecuteTransactionRequestV3 { transaction: transaction.try_into()?, @@ -154,19 +150,15 @@ async fn execute_transaction( None }; - let response = TransactionExecutionResponse { + TransactionExecutionResponse { effects, finality, events, balance_changes, input_objects, output_objects, - }; - - match accept { - AcceptFormat::Json => ResponseContent::Json(response), - AcceptFormat::Bcs => ResponseContent::Bcs(response), } + .pipe(Json) .pipe(Ok) } @@ -387,7 +379,6 @@ impl ApiEndpoint for SimulateTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .bcs_content() .build(), ) .build() @@ -401,19 +392,12 @@ impl ApiEndpoint for SimulateTransaction { async fn simulate_transaction( State(state): State>>, Query(parameters): Query, - accept: AcceptFormat, //TODO allow accepting JSON as well as BCS Bcs(transaction): Bcs, -) -> Result> { +) -> Result> { let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; - let response = simulate_transaction_impl(&executor, ¶meters, transaction)?; - - match accept { - AcceptFormat::Json => ResponseContent::Json(response), - AcceptFormat::Bcs => ResponseContent::Bcs(response), - } - .pipe(Ok) + simulate_transaction_impl(&executor, ¶meters, transaction).map(Json) } pub(super) fn simulate_transaction_impl( diff --git a/crates/sui-rpc-api/src/rest/transactions/mod.rs b/crates/sui-rpc-api/src/rest/transactions/mod.rs index 755ec9295b45f..f8c9fff7909f2 100644 --- a/crates/sui-rpc-api/src/rest/transactions/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/mod.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 mod execution; +use axum::Json; pub use execution::EffectsFinality; pub use execution::ExecuteTransaction; pub use execution::ExecuteTransactionQueryParameters; @@ -25,8 +26,6 @@ use sui_sdk_types::types::{ use tap::Pipe; use crate::reader::StateReader; -use crate::response::ResponseContent; -use crate::rest::accept::AcceptFormat; use crate::rest::openapi::ApiEndpoint; use crate::rest::openapi::OperationBuilder; use crate::rest::openapi::ResponseBuilder; @@ -60,7 +59,6 @@ impl ApiEndpoint for GetTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .bcs_content() .build(), ) .response(404, ResponseBuilder::new().build()) @@ -74,16 +72,9 @@ impl ApiEndpoint for GetTransaction { async fn get_transaction( Path(transaction_digest): Path, - accept: AcceptFormat, State(state): State, -) -> Result> { - let response = state.get_transaction_response(transaction_digest)?; - - match accept { - AcceptFormat::Json => ResponseContent::Json(response), - AcceptFormat::Bcs => ResponseContent::Bcs(response), - } - .pipe(Ok) +) -> Result> { + state.get_transaction_response(transaction_digest).map(Json) } #[serde_with::serde_as] @@ -146,7 +137,6 @@ impl ApiEndpoint for ListTransactions { 200, ResponseBuilder::new() .json_content::>(generator) - .bcs_content() .header::(crate::types::X_SUI_CURSOR, generator) .build(), ) @@ -161,11 +151,10 @@ impl ApiEndpoint for ListTransactions { async fn list_transactions( Query(parameters): Query, - accept: AcceptFormat, State(state): State, ) -> Result<( PageCursor, - ResponseContent>, + Json>, )> { let latest_checkpoint = state.inner().get_latest_checkpoint()?.sequence_number; let oldest_checkpoint = state.inner().get_lowest_available_checkpoint()?; @@ -201,20 +190,17 @@ async fn list_transactions( }) .collect::, _>>()?; - let cursor = next_cursor.and_then(|(checkpoint, index)| { - if checkpoint < oldest_checkpoint { - None - } else { - Some(TransactionCursor { checkpoint, index }) - } - }); + let cursor = next_cursor + .and_then(|(checkpoint, index)| { + if checkpoint < oldest_checkpoint { + None + } else { + Some(TransactionCursor { checkpoint, index }) + } + }) + .pipe(PageCursor); - match accept { - AcceptFormat::Json => ResponseContent::Json(transactions), - AcceptFormat::Bcs => ResponseContent::Bcs(transactions), - } - .pipe(|entries| (PageCursor(cursor), entries)) - .pipe(Ok) + Ok((cursor, Json(transactions))) } /// A Cursor that points at a specific transaction in history. diff --git a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs index 2a9134333cc09..2fe8ca6b8903a 100644 --- a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs @@ -7,8 +7,6 @@ use std::collections::HashMap; use super::execution::SimulateTransactionQueryParameters; use super::TransactionSimulationResponse; use crate::reader::StateReader; -use crate::response::ResponseContent; -use crate::rest::accept::AcceptFormat; use crate::rest::objects::ObjectNotFoundError; use crate::rest::openapi::ApiEndpoint; use crate::rest::openapi::OperationBuilder; @@ -75,7 +73,6 @@ impl ApiEndpoint for ResolveTransaction { 200, ResponseBuilder::new() .json_content::(generator) - .bcs_content() .build(), ) .build() @@ -89,9 +86,8 @@ impl ApiEndpoint for ResolveTransaction { async fn resolve_transaction( State(state): State, Query(parameters): Query, - accept: AcceptFormat, Json(unresolved_transaction): Json, -) -> Result> { +) -> Result> { let executor = state .executor .as_ref() @@ -179,15 +175,11 @@ async fn resolve_transaction( None }; - let response = ResolveTransactionResponse { + ResolveTransactionResponse { transaction: resolved_transaction.try_into()?, simulation, - }; - - match accept { - AcceptFormat::Json => ResponseContent::Json(response), - AcceptFormat::Bcs => ResponseContent::Bcs(response), } + .pipe(Json) .pipe(Ok) } From 49f9d2bd37aa6255448c3de69ee2f86379d435e6 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Wed, 27 Nov 2024 10:01:17 -0600 Subject: [PATCH 18/28] rpc: rename RestError to RpcServiceError --- crates/sui-rpc-api/src/error.rs | 40 +++++++++++-------- crates/sui-rpc-api/src/lib.rs | 2 +- crates/sui-rpc-api/src/rest/accounts.rs | 7 +++- crates/sui-rpc-api/src/rest/checkpoints.rs | 12 +++--- crates/sui-rpc-api/src/rest/coins.rs | 13 +++--- crates/sui-rpc-api/src/rest/objects.rs | 11 +++-- crates/sui-rpc-api/src/rest/system.rs | 12 +++--- .../src/rest/transactions/execution.rs | 6 +-- .../sui-rpc-api/src/rest/transactions/mod.rs | 6 +-- .../src/rest/transactions/resolve/literal.rs | 32 +++++++-------- .../src/rest/transactions/resolve/mod.rs | 34 ++++++++-------- crates/sui-rpc-api/src/service/committee.rs | 2 +- 12 files changed, 96 insertions(+), 81 deletions(-) diff --git a/crates/sui-rpc-api/src/error.rs b/crates/sui-rpc-api/src/error.rs index 1baf6c40a65f9..bc751118198e0 100644 --- a/crates/sui-rpc-api/src/error.rs +++ b/crates/sui-rpc-api/src/error.rs @@ -3,15 +3,21 @@ use axum::http::StatusCode; -pub type Result = std::result::Result; - +pub type Result = std::result::Result; + +/// An internal RPC service error +/// +/// General error type used by top-level RPC service methods. The main purpose of this error type +/// is to provide a convenient type for converting between internal errors and a response that +/// needs to be sent to a calling client. This is done by converting this type into either an +/// `axum::Response` or a `tonic::Status`. #[derive(Debug)] -pub struct RestError { +pub struct RpcServiceError { status: StatusCode, message: Option, } -impl RestError { +impl RpcServiceError { pub fn new>(status: StatusCode, message: T) -> Self { Self { status, @@ -28,7 +34,7 @@ impl RestError { } // Tell axum how to convert `AppError` into a response. -impl axum::response::IntoResponse for RestError { +impl axum::response::IntoResponse for RpcServiceError { fn into_response(self) -> axum::response::Response { match self.message { Some(message) => (self.status, message).into_response(), @@ -37,7 +43,7 @@ impl axum::response::IntoResponse for RestError { } } -impl From for RestError { +impl From for RpcServiceError { fn from(value: sui_types::storage::error::Error) -> Self { Self { status: StatusCode::INTERNAL_SERVER_ERROR, @@ -46,7 +52,7 @@ impl From for RestError { } } -impl From for RestError { +impl From for RpcServiceError { fn from(value: anyhow::Error) -> Self { Self { status: StatusCode::INTERNAL_SERVER_ERROR, @@ -55,7 +61,7 @@ impl From for RestError { } } -impl From for RestError { +impl From for RpcServiceError { fn from(value: sui_types::sui_sdk_types_conversions::SdkTypeConversionError) -> Self { Self { status: StatusCode::INTERNAL_SERVER_ERROR, @@ -64,7 +70,7 @@ impl From for Rest } } -impl From for RestError { +impl From for RpcServiceError { fn from(value: bcs::Error) -> Self { Self { status: StatusCode::INTERNAL_SERVER_ERROR, @@ -73,7 +79,7 @@ impl From for RestError { } } -impl From for RestError { +impl From for RpcServiceError { fn from(error: sui_types::quorum_driver_types::QuorumDriverError) -> Self { use itertools::Itertools; use sui_types::error::SuiError; @@ -89,10 +95,10 @@ impl From for RestError { format!("Invalid user signature: {err}") }; - RestError::new(StatusCode::BAD_REQUEST, message) + RpcServiceError::new(StatusCode::BAD_REQUEST, message) } QuorumDriverInternalError(err) => { - RestError::new(StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) + RpcServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) } ObjectsDoubleUsed { conflicting_txes, @@ -115,11 +121,11 @@ impl From for RestError { new_map, ); - RestError::new(StatusCode::CONFLICT, message) + RpcServiceError::new(StatusCode::CONFLICT, message) } TimeoutBeforeFinality | FailedWithTransientErrorAfterMaximumAttempts { .. } => { // TODO add a Retry-After header - RestError::new( + RpcServiceError::new( StatusCode::SERVICE_UNAVAILABLE, "timed-out before finality could be reached", ) @@ -161,15 +167,15 @@ impl From for RestError { let error_list = new_errors.join(", "); let error_msg = format!("Transaction execution failed due to issues with transaction inputs, please review the errors and try again: {}.", error_list); - RestError::new(StatusCode::BAD_REQUEST, error_msg) + RpcServiceError::new(StatusCode::BAD_REQUEST, error_msg) } - TxAlreadyFinalizedWithDifferentUserSignatures => RestError::new( + TxAlreadyFinalizedWithDifferentUserSignatures => RpcServiceError::new( StatusCode::CONFLICT, "The transaction is already finalized but with different user signatures", ), SystemOverload { .. } | SystemOverloadRetryAfter { .. } => { // TODO add a Retry-After header - RestError::new(StatusCode::SERVICE_UNAVAILABLE, "system is overloaded") + RpcServiceError::new(StatusCode::SERVICE_UNAVAILABLE, "system is overloaded") } } } diff --git a/crates/sui-rpc-api/src/lib.rs b/crates/sui-rpc-api/src/lib.rs index 6d7d08d6981c1..ec2fc1080e284 100644 --- a/crates/sui-rpc-api/src/lib.rs +++ b/crates/sui-rpc-api/src/lib.rs @@ -22,7 +22,7 @@ pub mod types; pub use client::Client; pub use config::Config; -pub use error::{RestError, Result}; +pub use error::{Result, RpcServiceError}; pub use metrics::RpcMetrics; pub use rest::checkpoints::CheckpointResponse; pub use rest::checkpoints::ListCheckpointsQueryParameters; diff --git a/crates/sui-rpc-api/src/rest/accounts.rs b/crates/sui-rpc-api/src/rest/accounts.rs index 6408a6af096f2..8943e9005a9e9 100644 --- a/crates/sui-rpc-api/src/rest/accounts.rs +++ b/crates/sui-rpc-api/src/rest/accounts.rs @@ -4,7 +4,7 @@ use crate::reader::StateReader; use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::{response::ResponseContent, Result}; -use crate::{rest::Page, RestError, RpcService}; +use crate::{rest::Page, RpcService, RpcServiceError}; use axum::extract::Query; use axum::extract::{Path, State}; use openapiv3::v3_1::Operation; @@ -49,7 +49,10 @@ async fn list_account_objects( Query(parameters): Query, State(state): State, ) -> Result> { - let indexes = state.inner().indexes().ok_or_else(RestError::not_found)?; + let indexes = state + .inner() + .indexes() + .ok_or_else(RpcServiceError::not_found)?; let limit = parameters.limit(); let start = parameters.start(); diff --git a/crates/sui-rpc-api/src/rest/checkpoints.rs b/crates/sui-rpc-api/src/rest/checkpoints.rs index 003b510a22445..26ead748bf3ee 100644 --- a/crates/sui-rpc-api/src/rest/checkpoints.rs +++ b/crates/sui-rpc-api/src/rest/checkpoints.rs @@ -16,7 +16,7 @@ use crate::response::{Bcs, ResponseContent}; use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::rest::PageCursor; use crate::{Direction, RpcService}; -use crate::{RestError, Result}; +use crate::{Result, RpcServiceError}; use documented::Documented; use super::accept::AcceptFormat; @@ -90,7 +90,7 @@ async fn get_checkpoint( CheckpointId::SequenceNumber(s) => { let oldest_checkpoint = state.inner().get_lowest_available_checkpoint()?; if s < oldest_checkpoint { - return Err(crate::RestError::new( + return Err(crate::RpcServiceError::new( axum::http::StatusCode::GONE, "Old checkpoints have been pruned", )); @@ -195,7 +195,7 @@ impl std::fmt::Display for CheckpointNotFoundError { impl std::error::Error for CheckpointNotFoundError {} -impl From for crate::RestError { +impl From for crate::RpcServiceError { fn from(value: CheckpointNotFoundError) -> Self { Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) } @@ -274,7 +274,7 @@ async fn list_checkpoints( let direction = parameters.direction(); if start < oldest_checkpoint { - return Err(crate::RestError::new( + return Err(crate::RpcServiceError::new( axum::http::StatusCode::GONE, "Old checkpoints have been pruned", )); @@ -431,7 +431,7 @@ async fn get_full_checkpoint( match accept { AcceptFormat::Bcs => {} _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid accept type; only 'application/bcs' is supported", )) @@ -444,7 +444,7 @@ async fn get_full_checkpoint( // with objects that hasn't been pruned let oldest_checkpoint = state.inner().get_lowest_available_checkpoint_objects()?; if s < oldest_checkpoint { - return Err(crate::RestError::new( + return Err(crate::RpcServiceError::new( axum::http::StatusCode::GONE, "Old checkpoints have been pruned", )); diff --git a/crates/sui-rpc-api/src/rest/coins.rs b/crates/sui-rpc-api/src/rest/coins.rs index f1849499a5582..4bd1bd2c6dbe5 100644 --- a/crates/sui-rpc-api/src/rest/coins.rs +++ b/crates/sui-rpc-api/src/rest/coins.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; -use crate::RestError; use crate::RpcService; +use crate::RpcServiceError; use crate::{reader::StateReader, Result}; use axum::extract::{Path, State}; use axum::Json; @@ -50,7 +50,10 @@ async fn get_coin_info( Path(coin_type): Path, State(state): State, ) -> Result> { - let indexes = state.inner().indexes().ok_or_else(RestError::not_found)?; + let indexes = state + .inner() + .indexes() + .ok_or_else(RpcServiceError::not_found)?; let core_coin_type = struct_tag_sdk_to_core(coin_type.clone())?; @@ -68,7 +71,7 @@ async fn get_coin_info( .map(sui_types::coin::CoinMetadata::try_from) .transpose() .map_err(|_| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::INTERNAL_SERVER_ERROR, format!("Unable to read object {coin_metadata_object_id} for coin type {core_coin_type} as CoinMetadata"), ) @@ -85,7 +88,7 @@ async fn get_coin_info( .map(sui_types::coin::TreasuryCap::try_from) .transpose() .map_err(|_| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::INTERNAL_SERVER_ERROR, format!("Unable to read object {treasury_object_id} for coin type {core_coin_type} as TreasuryCap"), ) @@ -118,7 +121,7 @@ impl std::fmt::Display for CoinNotFoundError { impl std::error::Error for CoinNotFoundError {} -impl From for crate::RestError { +impl From for crate::RpcServiceError { fn from(value: CoinNotFoundError) -> Self { Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) } diff --git a/crates/sui-rpc-api/src/rest/objects.rs b/crates/sui-rpc-api/src/rest/objects.rs index 84a19ee523496..38588d937e33f 100644 --- a/crates/sui-rpc-api/src/rest/objects.rs +++ b/crates/sui-rpc-api/src/rest/objects.rs @@ -7,7 +7,7 @@ use crate::{ rest::accept::AcceptFormat, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, rest::Page, - RestError, Result, RpcService, + Result, RpcService, RpcServiceError, }; use axum::extract::Query; use axum::extract::{Path, State}; @@ -175,7 +175,7 @@ impl std::fmt::Display for ObjectNotFoundError { impl std::error::Error for ObjectNotFoundError {} -impl From for crate::RestError { +impl From for crate::RpcServiceError { fn from(value: ObjectNotFoundError) -> Self { Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) } @@ -222,11 +222,14 @@ async fn list_dynamic_fields( accept: AcceptFormat, State(state): State, ) -> Result> { - let indexes = state.inner().indexes().ok_or_else(RestError::not_found)?; + let indexes = state + .inner() + .indexes() + .ok_or_else(RpcServiceError::not_found)?; match accept { AcceptFormat::Json => {} _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid accept type", )) diff --git a/crates/sui-rpc-api/src/rest/system.rs b/crates/sui-rpc-api/src/rest/system.rs index 463aa79a8b7c8..fb07fb323d4ec 100644 --- a/crates/sui-rpc-api/src/rest/system.rs +++ b/crates/sui-rpc-api/src/rest/system.rs @@ -6,7 +6,7 @@ use crate::{ rest::_schemars::U64, rest::accept::AcceptFormat, rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}, - RestError, Result, RpcService, + Result, RpcService, RpcServiceError, }; use axum::{ extract::{Path, State}, @@ -57,7 +57,7 @@ async fn get_system_state_summary( match accept { AcceptFormat::Json => {} _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid accept type", )) @@ -569,7 +569,7 @@ async fn get_current_protocol_config( match accept { AcceptFormat::Json => {} _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid accept type", )) @@ -631,7 +631,7 @@ async fn get_protocol_config( match accept { AcceptFormat::Json => {} _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid accept type", )) @@ -666,7 +666,7 @@ impl std::fmt::Display for ProtocolNotFoundError { impl std::error::Error for ProtocolNotFoundError {} -impl From for crate::RestError { +impl From for crate::RpcServiceError { fn from(value: ProtocolNotFoundError) -> Self { Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) } @@ -766,7 +766,7 @@ async fn get_gas_info( match accept { AcceptFormat::Json => {} _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid accept type", )) diff --git a/crates/sui-rpc-api/src/rest/transactions/execution.rs b/crates/sui-rpc-api/src/rest/transactions/execution.rs index fd96a63caef81..18a994c59913d 100644 --- a/crates/sui-rpc-api/src/rest/transactions/execution.rs +++ b/crates/sui-rpc-api/src/rest/transactions/execution.rs @@ -5,7 +5,7 @@ use crate::response::Bcs; use crate::rest::openapi::{ ApiEndpoint, OperationBuilder, RequestBodyBuilder, ResponseBuilder, RouteHandler, }; -use crate::{RestError, Result, RpcService}; +use crate::{Result, RpcService, RpcServiceError}; use axum::extract::{Query, State}; use axum::Json; use schemars::JsonSchema; @@ -406,7 +406,7 @@ pub(super) fn simulate_transaction_impl( transaction: Transaction, ) -> Result { if transaction.gas_payment.objects.is_empty() { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "no gas payment provided", )); @@ -423,7 +423,7 @@ pub(super) fn simulate_transaction_impl( .map_err(anyhow::Error::from)?; if mock_gas_id.is_some() { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::INTERNAL_SERVER_ERROR, "simulate unexpectedly used a mock gas payment", )); diff --git a/crates/sui-rpc-api/src/rest/transactions/mod.rs b/crates/sui-rpc-api/src/rest/transactions/mod.rs index f8c9fff7909f2..820fa9923df24 100644 --- a/crates/sui-rpc-api/src/rest/transactions/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/mod.rs @@ -32,9 +32,9 @@ use crate::rest::openapi::ResponseBuilder; use crate::rest::openapi::RouteHandler; use crate::rest::PageCursor; use crate::Direction; -use crate::RestError; use crate::Result; use crate::RpcService; +use crate::RpcServiceError; pub struct GetTransaction; @@ -108,7 +108,7 @@ impl std::fmt::Display for TransactionNotFoundError { impl std::error::Error for TransactionNotFoundError {} -impl From for crate::RestError { +impl From for crate::RpcServiceError { fn from(value: TransactionNotFoundError) -> Self { Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) } @@ -163,7 +163,7 @@ async fn list_transactions( let direction = parameters.direction(); if start.checkpoint < oldest_checkpoint { - return Err(RestError::new( + return Err(RpcServiceError::new( StatusCode::GONE, "Old transactions have been pruned", )); diff --git a/crates/sui-rpc-api/src/rest/transactions/resolve/literal.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/literal.rs index 156dac7c16817..e64dffc00a4e4 100644 --- a/crates/sui-rpc-api/src/rest/transactions/resolve/literal.rs +++ b/crates/sui-rpc-api/src/rest/transactions/resolve/literal.rs @@ -4,8 +4,8 @@ use std::collections::HashMap; use super::NormalizedPackage; -use crate::RestError; use crate::Result; +use crate::RpcServiceError; use move_binary_format::normalized::Type; use sui_sdk_types::types::unresolved::Value; use sui_sdk_types::types::Command; @@ -43,7 +43,7 @@ fn determine_literal_type( match maybe_type { Some(literal_type) if literal_type == &ty => {} Some(_) => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "unable to resolve literal as it is used as multiple different types across commands", )) @@ -76,7 +76,7 @@ fn determine_literal_type( sui_types::sui_sdk_types_conversions::type_tag_sdk_to_core(ty.clone())?; set_type(&mut literal_type, ty.into())?; } else { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "unable to resolve literal as an unknown type", )); @@ -90,7 +90,7 @@ fn determine_literal_type( | (Command::Upgrade(_), _) | (Command::MergeCoins(_), _) | (Command::SplitCoins(_), None) => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid use of literal", )); @@ -100,7 +100,7 @@ fn determine_literal_type( (Command::MakeMoveVector(_), None) | (Command::Publish(_), _) | (Command::MoveCall(_), None) => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::INTERNAL_SERVER_ERROR, "error determining type of literal", )); @@ -109,7 +109,7 @@ fn determine_literal_type( } literal_type.ok_or_else(|| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "unable to determine type of literal", ) @@ -170,7 +170,7 @@ fn resolve_literal_to_type(buf: &mut Vec, type_: &Type, value: &Value) -> Re | Type::Struct { .. } | Type::TypeParameter(_) | Type::Reference(_) - | Type::MutableReference(_) => Err(RestError::new( + | Type::MutableReference(_) => Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("literal cannot be resolved into type {type_}"), )), @@ -181,13 +181,13 @@ fn resolve_as_bool(buf: &mut Vec, value: &Value) -> Result<()> { let b: bool = match value { Value::Bool(b) => *b, Value::String(s) => s.parse().map_err(|e| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("literal cannot be resolved as bool: {e}"), ) })?, Value::Null | Value::Number(_) | Value::Array(_) => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "literal cannot be resolved into type bool", )) @@ -207,7 +207,7 @@ where { let n: T = match value { Value::Number(n) => T::try_from(*n).map_err(|e| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!( "literal cannot be resolved as {}: {e}", @@ -217,7 +217,7 @@ where })?, Value::String(s) => s.parse().map_err(|e| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!( "literal cannot be resolved as {}: {e}", @@ -227,7 +227,7 @@ where })?, Value::Null | Value::Bool(_) | Value::Array(_) => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!( "literal cannot be resolved into type {}", @@ -246,13 +246,13 @@ fn resolve_as_address(buf: &mut Vec, value: &Value) -> Result<()> { let address = match value { // parse as ObjectID to handle the case where 0x is present or missing Value::String(s) => s.parse::().map_err(|e| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("literal cannot be resolved as bool: {e}"), ) })?, Value::Null | Value::Bool(_) | Value::Number(_) | Value::Array(_) => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "literal cannot be resolved into type address", )) @@ -270,7 +270,7 @@ fn resolve_as_string(buf: &mut Vec, value: &Value) -> Result<()> { bcs::serialize_into(buf, s)?; } Value::Bool(_) | Value::Null | Value::Number(_) | Value::Array(_) => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "literal cannot be resolved into string", )) @@ -314,7 +314,7 @@ fn resolve_as_vector(buf: &mut Vec, type_: &Type, value: &Value) -> Result<( } } Value::Bool(_) | Value::Number(_) | Value::String(_) | Value::Null => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("literal cannot be resolved into type Vector<{type_}>"), )); diff --git a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs index 2fe8ca6b8903a..10299699e0751 100644 --- a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs @@ -13,9 +13,9 @@ use crate::rest::openapi::OperationBuilder; use crate::rest::openapi::RequestBodyBuilder; use crate::rest::openapi::ResponseBuilder; use crate::rest::openapi::RouteHandler; -use crate::RestError; use crate::Result; use crate::RpcService; +use crate::RpcServiceError; use axum::extract::Query; use axum::extract::State; use axum::Json; @@ -102,7 +102,7 @@ async fn resolve_transaction( state.reader.inner().get_chain_identifier()?.chain(), ) .ok_or_else(|| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::INTERNAL_SERVER_ERROR, "unable to get current protocol config", ) @@ -227,7 +227,7 @@ fn called_packages( .data .try_as_package() .ok_or_else(|| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("object {} is not a package", move_call.package), ) @@ -241,7 +241,7 @@ fn called_packages( // Despite the above this is safe given we are only using the signature information (and in // particular the reference kind) from the normalized package. let normalized_modules = package.normalize(&binary_config).map_err(|e| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::INTERNAL_SERVER_ERROR, format!("unable to normalize package {}: {e}", move_call.package), ) @@ -333,7 +333,7 @@ fn resolve_object_reference_with_object( match object.owner() { sui_types::object::Owner::AddressOwner(_) | sui_types::object::Owner::Immutable => {} _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("object {object_id} is not Immutable or AddressOwned"), )) @@ -346,21 +346,21 @@ fn resolve_object_reference_with_object( // This really should be an assert if object_id.inner() != &id.into_bytes() { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::INTERNAL_SERVER_ERROR, "provided object and object_id should match", )); } if version.is_some_and(|version| version != v.value()) { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("provided version doesn't match, provided: {version:?} actual: {v}"), )); } if digest.is_some_and(|digest| digest.inner() != d.inner()) { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("provided digest doesn't match, provided: {digest:?} actual: {d}"), )); @@ -424,7 +424,7 @@ fn resolve_arg( // pre serialized BCS input encoded as a base64 string (Some(Pure), Some(unresolved::Value::String(v)), None, None, None, None) => { let value = Base64::decode(&v).map_err(|e| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("argument is an invalid pure arguement: {e}"), ) @@ -434,7 +434,7 @@ fn resolve_arg( // pre serialized BCS input encoded as a a JSON array of u8s (Some(Pure), Some(array @ unresolved::Value::Array(_)), None, None, None, None) => { let value = serde_json::from_value(serde_json::Value::from(array)).map_err(|e| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("argument is an invalid pure arguement: {e}"), ) @@ -493,7 +493,7 @@ fn resolve_arg( )?), _ => { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid unresolved input argument", )) @@ -549,7 +549,7 @@ fn resolve_object( sui_types::object::Owner::Shared { .. } | sui_types::object::Owner::ConsensusV2 { .. } => { resolve_shared_input_with_object(called_packages, commands, arg_idx, object) } - sui_types::object::Owner::ObjectOwner(_) => Err(RestError::new( + sui_types::object::Owner::ObjectOwner(_) => Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("object {object_id} is object owned and cannot be used as an input"), )), @@ -625,7 +625,7 @@ fn arg_type_of_move_call_input<'a>( // Find the function .and_then(|module| module.functions.get(move_call.function.as_str())) .ok_or_else(|| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!( "unable to find function {package}::{module}::{function}", @@ -636,7 +636,7 @@ fn arg_type_of_move_call_input<'a>( ) })?; function.parameters.get(idx).ok_or_else(|| { - RestError::new( + RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, "invalid input parameter", ) @@ -660,7 +660,7 @@ fn resolve_shared_input_with_object( { *initial_shared_version } else { - return Err(RestError::new( + return Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!("object {object_id} is not a shared or consensus object"), )); @@ -794,7 +794,7 @@ fn select_gas( let gas_coins = reader .inner() .indexes() - .ok_or_else(RestError::not_found)? + .ok_or_else(RpcServiceError::not_found)? .account_owned_objects_info_iter(owner, None)? .filter(|info| info.type_.is_gas_coin()) .filter(|info| !input_objects.contains(&info.object_id)) @@ -817,7 +817,7 @@ fn select_gas( if selected_gas_value >= budget { Ok(selected_gas) } else { - Err(RestError::new( + Err(RpcServiceError::new( axum::http::StatusCode::BAD_REQUEST, format!( "unable to select sufficient gas coins from account {owner} \ diff --git a/crates/sui-rpc-api/src/service/committee.rs b/crates/sui-rpc-api/src/service/committee.rs index 84cda0be8b1f8..323c52b9f4e35 100644 --- a/crates/sui-rpc-api/src/service/committee.rs +++ b/crates/sui-rpc-api/src/service/committee.rs @@ -41,7 +41,7 @@ impl std::fmt::Display for CommitteeNotFoundError { impl std::error::Error for CommitteeNotFoundError {} -impl From for crate::RestError { +impl From for crate::RpcServiceError { fn from(value: CommitteeNotFoundError) -> Self { Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) } From fe93e817b0297c28051ebddbd564759b90897008 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Wed, 27 Nov 2024 10:02:44 -0600 Subject: [PATCH 19/28] rest: mark ListCheckpoints unstable till bcs return type is removed --- crates/sui-rpc-api/openapi/openapi.json | 180 ++++++++++----------- crates/sui-rpc-api/src/rest/checkpoints.rs | 2 +- crates/sui-rpc-api/src/rest/mod.rs | 2 +- 3 files changed, 92 insertions(+), 92 deletions(-) diff --git a/crates/sui-rpc-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json index 9d7a30836f7ee..10f37fd98d68a 100644 --- a/crates/sui-rpc-api/openapi/openapi.json +++ b/crates/sui-rpc-api/openapi/openapi.json @@ -77,96 +77,6 @@ } } }, - "/checkpoints": { - "get": { - "tags": [ - "Checkpoint" - ], - "description": "[![stable](https://img.shields.io/badge/api-stable-53b576?style=for-the-badge)](#)\n\nList Checkpoints\n\nRequest a page of checkpoints, and optionally their contents, ordered by\n`CheckpointSequenceNumber`.\n\nIf the requested page is below the Node's `lowest_available_checkpoint`, a 410 will be\nreturned.", - "operationId": "List Checkpoints", - "parameters": [ - { - "in": "query", - "name": "contents", - "description": "Request `CheckpointContents` be included in the response", - "schema": { - "description": "Request `CheckpointContents` be included in the response", - "default": false, - "type": "boolean" - }, - "style": "form" - }, - { - "in": "query", - "name": "direction", - "description": "The direction to paginate in.\n\nDefaults to `descending` if not provided.", - "schema": { - "description": "The direction to paginate in.\n\nDefaults to `descending` if not provided.", - "allOf": [ - { - "$ref": "#/components/schemas/Direction" - } - ] - }, - "style": "form" - }, - { - "in": "query", - "name": "limit", - "description": "Page size limit for the response.\n\nDefaults to `50` if not provided with a maximum page size of `100`.", - "schema": { - "description": "Page size limit for the response.\n\nDefaults to `50` if not provided with a maximum page size of `100`.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "style": "form" - }, - { - "in": "query", - "name": "start", - "description": "The checkpoint to start listing from.\n\nDefaults to the latest checkpoint if not provided.", - "schema": { - "description": "The checkpoint to start listing from.\n\nDefaults to the latest checkpoint if not provided.", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "style": "form" - } - ], - "responses": { - "200": { - "description": "", - "headers": { - "x-sui-cursor": { - "style": "simple", - "schema": { - "type": "string" - } - } - }, - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CheckpointResponse" - } - } - }, - "application/bcs": {} - } - }, - "410": { - "description": "" - }, - "500": { - "description": "" - } - } - } - }, "/checkpoints/{checkpoint}": { "get": { "tags": [ @@ -424,6 +334,96 @@ } } }, + "/checkpoints": { + "get": { + "tags": [ + "Checkpoint" + ], + "description": "[![unstable](https://img.shields.io/badge/api-unstable-red?style=for-the-badge)](#) _Api subject to change; use at your own risk_\n\nList Checkpoints\n\nRequest a page of checkpoints, and optionally their contents, ordered by\n`CheckpointSequenceNumber`.\n\nIf the requested page is below the Node's `lowest_available_checkpoint`, a 410 will be\nreturned.", + "operationId": "List Checkpoints", + "parameters": [ + { + "in": "query", + "name": "contents", + "description": "Request `CheckpointContents` be included in the response", + "schema": { + "description": "Request `CheckpointContents` be included in the response", + "default": false, + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "direction", + "description": "The direction to paginate in.\n\nDefaults to `descending` if not provided.", + "schema": { + "description": "The direction to paginate in.\n\nDefaults to `descending` if not provided.", + "allOf": [ + { + "$ref": "#/components/schemas/Direction" + } + ] + }, + "style": "form" + }, + { + "in": "query", + "name": "limit", + "description": "Page size limit for the response.\n\nDefaults to `50` if not provided with a maximum page size of `100`.", + "schema": { + "description": "Page size limit for the response.\n\nDefaults to `50` if not provided with a maximum page size of `100`.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "style": "form" + }, + { + "in": "query", + "name": "start", + "description": "The checkpoint to start listing from.\n\nDefaults to the latest checkpoint if not provided.", + "schema": { + "description": "The checkpoint to start listing from.\n\nDefaults to the latest checkpoint if not provided.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "style": "form" + } + ], + "responses": { + "200": { + "description": "", + "headers": { + "x-sui-cursor": { + "style": "simple", + "schema": { + "type": "string" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CheckpointResponse" + } + } + }, + "application/bcs": {} + } + }, + "410": { + "description": "" + }, + "500": { + "description": "" + } + } + } + }, "/checkpoints/{checkpoint}/full": { "get": { "tags": [ diff --git a/crates/sui-rpc-api/src/rest/checkpoints.rs b/crates/sui-rpc-api/src/rest/checkpoints.rs index 26ead748bf3ee..41a3707cccec3 100644 --- a/crates/sui-rpc-api/src/rest/checkpoints.rs +++ b/crates/sui-rpc-api/src/rest/checkpoints.rs @@ -229,7 +229,7 @@ impl ApiEndpoint for ListCheckpoints { } fn stable(&self) -> bool { - true + false } fn operation( diff --git a/crates/sui-rpc-api/src/rest/mod.rs b/crates/sui-rpc-api/src/rest/mod.rs index 6d6fe1e97becd..cdcff45d13a78 100644 --- a/crates/sui-rpc-api/src/rest/mod.rs +++ b/crates/sui-rpc-api/src/rest/mod.rs @@ -33,13 +33,13 @@ pub const ENDPOINTS: &[&dyn ApiEndpoint] = &[ // stable APIs &info::GetNodeInfo, &health::HealthCheck, - &checkpoints::ListCheckpoints, &checkpoints::GetCheckpoint, // unstable APIs &accounts::ListAccountObjects, &objects::GetObject, &objects::GetObjectWithVersion, &objects::ListDynamicFields, + &checkpoints::ListCheckpoints, &checkpoints::GetFullCheckpoint, &transactions::GetTransaction, &transactions::ListTransactions, From e35372c01b5624cc2ade2f31d520b19c3e3f55df Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Wed, 27 Nov 2024 11:28:09 -0600 Subject: [PATCH 20/28] rpc: factor out get_object logic --- crates/sui-rpc-api/openapi/openapi.json | 54 +++++++++++- crates/sui-rpc-api/src/client/sdk.rs | 8 +- crates/sui-rpc-api/src/lib.rs | 2 +- crates/sui-rpc-api/src/proto/mod.rs | 30 ------- crates/sui-rpc-api/src/rest/objects.rs | 81 +++--------------- .../src/rest/transactions/resolve/mod.rs | 2 +- crates/sui-rpc-api/src/service/mod.rs | 1 + crates/sui-rpc-api/src/service/objects.rs | 85 +++++++++++++++++++ crates/sui-rpc-api/src/types.rs | 44 +++++++++- 9 files changed, 200 insertions(+), 107 deletions(-) create mode 100644 crates/sui-rpc-api/src/service/objects.rs diff --git a/crates/sui-rpc-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json index 10f37fd98d68a..f842a1a212048 100644 --- a/crates/sui-rpc-api/openapi/openapi.json +++ b/crates/sui-rpc-api/openapi/openapi.json @@ -206,6 +206,26 @@ "$ref": "#/components/schemas/ObjectId" }, "style": "simple" + }, + { + "in": "query", + "name": "object", + "description": "Request that `Object` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request that `Object` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "object_bcs", + "description": "Request that `Object` formated as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request that `Object` formated as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" } ], "responses": { @@ -253,6 +273,26 @@ "minimum": 0.0 }, "style": "simple" + }, + { + "in": "query", + "name": "object", + "description": "Request that `Object` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request that `Object` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "object_bcs", + "description": "Request that `Object` formated as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request that `Object` formated as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" } ], "responses": { @@ -3873,7 +3913,8 @@ "type": "object", "required": [ "digest", - "object" + "object_id", + "version" ], "properties": { "digest": { @@ -3881,6 +3922,17 @@ }, "object": { "$ref": "#/components/schemas/Object" + }, + "object_bcs": { + "type": "string" + }, + "object_id": { + "$ref": "#/components/schemas/ObjectId" + }, + "version": { + "description": "Radix-10 encoded 64-bit unsigned integer", + "type": "string", + "format": "u64" } } }, diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index e025c015c75fe..c69e0f0c56074 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -134,8 +134,8 @@ impl Client { let request = self.inner.get(url); self.json::(request) - .await - .map(|response| response.map(|response| response.object)) + .await? + .try_map(|response| response.object.ok_or("object missing from response")) } pub async fn get_object_with_version( @@ -150,8 +150,8 @@ impl Client { let request = self.inner.get(url); self.json::(request) - .await - .map(|response| response.map(|response| response.object)) + .await? + .try_map(|response| response.object.ok_or("object missing from response")) } pub async fn list_dynamic_fields( diff --git a/crates/sui-rpc-api/src/lib.rs b/crates/sui-rpc-api/src/lib.rs index ec2fc1080e284..ca5d4d671a0e0 100644 --- a/crates/sui-rpc-api/src/lib.rs +++ b/crates/sui-rpc-api/src/lib.rs @@ -26,9 +26,9 @@ pub use error::{Result, RpcServiceError}; pub use metrics::RpcMetrics; pub use rest::checkpoints::CheckpointResponse; pub use rest::checkpoints::ListCheckpointsQueryParameters; -pub use rest::objects::ObjectResponse; pub use rest::transactions::ExecuteTransactionQueryParameters; pub use sui_types::full_checkpoint_content::{CheckpointData, CheckpointTransaction}; +pub use types::ObjectResponse; #[derive(Clone)] pub struct RpcService { diff --git a/crates/sui-rpc-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs index 1720974e0a62a..8050c33717552 100644 --- a/crates/sui-rpc-api/src/proto/mod.rs +++ b/crates/sui-rpc-api/src/proto/mod.rs @@ -337,36 +337,6 @@ impl TryFrom<&UserSignature> for sui_types::signature::GenericSignature { } } -// -// GetObjectResponse -// - -impl TryFrom for GetObjectResponse { - type Error = bcs::Error; - - fn try_from(value: crate::rest::objects::ObjectResponse) -> Result { - Ok(Self { - digest: value.digest.as_bytes().to_vec().into(), - object: Some(Object::try_from(&value.object)?), - }) - } -} - -impl TryFrom for crate::rest::objects::ObjectResponse { - type Error = bcs::Error; - - fn try_from(value: GetObjectResponse) -> Result { - Ok(Self { - digest: sui_sdk_types::types::ObjectDigest::from_bytes(&value.digest) - .map_err(|e| bcs::Error::Custom(e.to_string()))?, - object: value - .object - .ok_or_else(|| bcs::Error::Custom("missing object".into()))? - .pipe_ref(TryInto::try_into)?, - }) - } -} - // // GetCheckpointResponse // diff --git a/crates/sui-rpc-api/src/rest/objects.rs b/crates/sui-rpc-api/src/rest/objects.rs index 38588d937e33f..9a37e9bc2c60c 100644 --- a/crates/sui-rpc-api/src/rest/objects.rs +++ b/crates/sui-rpc-api/src/rest/objects.rs @@ -1,6 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +use crate::types::{GetObjectOptions, ObjectResponse}; use crate::{ reader::StateReader, response::ResponseContent, @@ -12,7 +13,7 @@ use crate::{ use axum::extract::Query; use axum::extract::{Path, State}; use serde::{Deserialize, Serialize}; -use sui_sdk_types::types::{Object, ObjectDigest, ObjectId, TypeTag, Version}; +use sui_sdk_types::types::{Object, ObjectId, TypeTag, Version}; use sui_types::sui_sdk_types_conversions::type_tag_core_to_sdk; use sui_types::{ storage::{DynamicFieldIndexInfo, DynamicFieldKey}, @@ -20,12 +21,6 @@ use sui_types::{ }; use tap::Pipe; -#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] -pub struct ObjectResponse { - pub digest: ObjectDigest, - pub object: Object, -} - pub struct GetObject; impl ApiEndpoint for GetObject { @@ -45,6 +40,7 @@ impl ApiEndpoint for GetObject { .tag("Objects") .operation_id("GetObject") .path_parameter::("object_id", generator) + .query_parameters::(generator) .response( 200, ResponseBuilder::new() @@ -63,21 +59,15 @@ impl ApiEndpoint for GetObject { pub async fn get_object( Path(object_id): Path, + Query(options): Query, accept: AcceptFormat, - State(state): State, + State(state): State, ) -> Result> { - let object = state - .get_object(object_id)? - .ok_or_else(|| ObjectNotFoundError::new(object_id))?; - - let object = ObjectResponse { - digest: object.digest(), - object, - }; + let object = state.get_object(object_id, None, options)?; match accept { AcceptFormat::Json => ResponseContent::Json(object), - AcceptFormat::Bcs => ResponseContent::Bcs(object.object), + AcceptFormat::Bcs => ResponseContent::Bcs(object.object.unwrap()), } .pipe(Ok) } @@ -102,6 +92,7 @@ impl ApiEndpoint for GetObjectWithVersion { .operation_id("GetObjectWithVersion") .path_parameter::("object_id", generator) .path_parameter::("version", generator) + .query_parameters::(generator) .response( 200, ResponseBuilder::new() @@ -120,67 +111,19 @@ impl ApiEndpoint for GetObjectWithVersion { pub async fn get_object_with_version( Path((object_id, version)): Path<(ObjectId, Version)>, + Query(options): Query, accept: AcceptFormat, - State(state): State, + State(state): State, ) -> Result> { - let object = state - .get_object_with_version(object_id, version)? - .ok_or_else(|| ObjectNotFoundError::new_with_version(object_id, version))?; - - let object = ObjectResponse { - digest: object.digest(), - object, - }; + let object = state.get_object(object_id, Some(version), options)?; match accept { AcceptFormat::Json => ResponseContent::Json(object), - AcceptFormat::Bcs => ResponseContent::Bcs(object.object), + AcceptFormat::Bcs => ResponseContent::Bcs(object.object.unwrap()), } .pipe(Ok) } -#[derive(Debug)] -pub struct ObjectNotFoundError { - object_id: ObjectId, - version: Option, -} - -impl ObjectNotFoundError { - pub fn new(object_id: ObjectId) -> Self { - Self { - object_id, - version: None, - } - } - - pub fn new_with_version(object_id: ObjectId, version: Version) -> Self { - Self { - object_id, - version: Some(version), - } - } -} - -impl std::fmt::Display for ObjectNotFoundError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Object {}", self.object_id)?; - - if let Some(version) = self.version { - write!(f, " with version {version}")?; - } - - write!(f, " not found") - } -} - -impl std::error::Error for ObjectNotFoundError {} - -impl From for crate::RpcServiceError { - fn from(value: ObjectNotFoundError) -> Self { - Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) - } -} - pub struct ListDynamicFields; impl ApiEndpoint for ListDynamicFields { diff --git a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs index 10299699e0751..26eba002356dd 100644 --- a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs @@ -7,12 +7,12 @@ use std::collections::HashMap; use super::execution::SimulateTransactionQueryParameters; use super::TransactionSimulationResponse; use crate::reader::StateReader; -use crate::rest::objects::ObjectNotFoundError; use crate::rest::openapi::ApiEndpoint; use crate::rest::openapi::OperationBuilder; use crate::rest::openapi::RequestBodyBuilder; use crate::rest::openapi::ResponseBuilder; use crate::rest::openapi::RouteHandler; +use crate::service::objects::ObjectNotFoundError; use crate::Result; use crate::RpcService; use crate::RpcServiceError; diff --git a/crates/sui-rpc-api/src/service/mod.rs b/crates/sui-rpc-api/src/service/mod.rs index ba935d70b1d84..18146a694927c 100644 --- a/crates/sui-rpc-api/src/service/mod.rs +++ b/crates/sui-rpc-api/src/service/mod.rs @@ -4,3 +4,4 @@ mod committee; mod health; mod info; +pub(crate) mod objects; diff --git a/crates/sui-rpc-api/src/service/objects.rs b/crates/sui-rpc-api/src/service/objects.rs new file mode 100644 index 0000000000000..950d65ed002fc --- /dev/null +++ b/crates/sui-rpc-api/src/service/objects.rs @@ -0,0 +1,85 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::types::GetObjectOptions; +use crate::types::ObjectResponse; +use crate::Result; +use crate::RpcService; +use sui_sdk_types::types::ObjectId; +use sui_sdk_types::types::Version; +use tap::Pipe; + +impl RpcService { + pub fn get_object( + &self, + object_id: ObjectId, + version: Option, + options: GetObjectOptions, + ) -> Result { + let object = if let Some(version) = version { + self.reader + .get_object_with_version(object_id, version)? + .ok_or_else(|| ObjectNotFoundError::new_with_version(object_id, version))? + } else { + self.reader + .get_object(object_id)? + .ok_or_else(|| ObjectNotFoundError::new(object_id))? + }; + + let object_bcs = options + .include_object_bcs() + .then(|| bcs::to_bytes(&object)) + .transpose()?; + + ObjectResponse { + object_id: object.object_id(), + version: object.version(), + digest: object.digest(), + object: options.include_object().then_some(object), + object_bcs, + } + .pipe(Ok) + } +} + +#[derive(Debug)] +pub struct ObjectNotFoundError { + object_id: ObjectId, + version: Option, +} + +impl ObjectNotFoundError { + pub fn new(object_id: ObjectId) -> Self { + Self { + object_id, + version: None, + } + } + + pub fn new_with_version(object_id: ObjectId, version: Version) -> Self { + Self { + object_id, + version: Some(version), + } + } +} + +impl std::fmt::Display for ObjectNotFoundError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Object {}", self.object_id)?; + + if let Some(version) = self.version { + write!(f, " with version {version}")?; + } + + write!(f, " not found") + } +} + +impl std::error::Error for ObjectNotFoundError {} + +impl From for crate::RpcServiceError { + fn from(value: ObjectNotFoundError) -> Self { + Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) + } +} diff --git a/crates/sui-rpc-api/src/types.rs b/crates/sui-rpc-api/src/types.rs index 2de53d33be045..34e6bdf331c63 100644 --- a/crates/sui-rpc-api/src/types.rs +++ b/crates/sui-rpc-api/src/types.rs @@ -72,5 +72,47 @@ pub struct NodeInfo { #[serde(skip_serializing_if = "Option::is_none")] pub lowest_available_checkpoint_objects: Option, pub software_version: std::borrow::Cow<'static, str>, - //TODO include current protocol version +} + +#[serde_with::serde_as] +#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct ObjectResponse { + pub object_id: sui_sdk_types::types::ObjectId, + #[serde_as(as = "sui_types::sui_serde::BigInt")] + #[schemars(with = "crate::rest::_schemars::U64")] + pub version: sui_sdk_types::types::Version, + pub digest: sui_sdk_types::types::ObjectDigest, + + #[serde(skip_serializing_if = "Option::is_none")] + pub object: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub object_bcs: Option>, +} + +#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct GetObjectOptions { + /// Request that `Object` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub object: Option, + /// Request that `Object` formated as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub object_bcs: Option, +} + +impl GetObjectOptions { + pub fn include_object(&self) -> bool { + self.object.unwrap_or(true) + } + + pub fn include_object_bcs(&self) -> bool { + self.object_bcs.unwrap_or(false) + } + } From 149f585985e74eea362ecbc18983c083749620da Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Wed, 27 Nov 2024 21:07:05 -0600 Subject: [PATCH 21/28] rpc: factor out get_checkpoint logic --- crates/sui-e2e-tests/tests/rpc/checkpoints.rs | 4 +- crates/sui-rpc-api/openapi/openapi.json | 120 +++++++++++-- crates/sui-rpc-api/src/client/mod.rs | 4 +- crates/sui-rpc-api/src/client/sdk.rs | 13 +- crates/sui-rpc-api/src/lib.rs | 3 +- crates/sui-rpc-api/src/proto/mod.rs | 60 ------- crates/sui-rpc-api/src/rest/checkpoints.rs | 170 +++--------------- crates/sui-rpc-api/src/service/checkpoints.rs | 160 +++++++++++++++++ crates/sui-rpc-api/src/service/mod.rs | 1 + crates/sui-rpc-api/src/types.rs | 83 +++++++++ 10 files changed, 384 insertions(+), 234 deletions(-) create mode 100644 crates/sui-rpc-api/src/service/checkpoints.rs diff --git a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs index 6d68cd0c3caac..1c89aa06856ca 100644 --- a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs +++ b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs @@ -4,7 +4,7 @@ use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; use sui_rpc_api::client::Client as CoreClient; -use sui_rpc_api::{CheckpointResponse, ListCheckpointsQueryParameters}; +use sui_rpc_api::CheckpointResponse; use sui_sdk_types::types::SignedCheckpointSummary; use test_cluster::TestClusterBuilder; @@ -20,7 +20,7 @@ async fn list_checkpoint() { let core_client = CoreClient::new(test_cluster.rpc_url()); let checkpoints = client - .list_checkpoints(&ListCheckpointsQueryParameters::default()) + .list_checkpoints(&Default::default()) .await .unwrap() .into_inner(); diff --git a/crates/sui-rpc-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json index f842a1a212048..efaca94c0d21a 100644 --- a/crates/sui-rpc-api/openapi/openapi.json +++ b/crates/sui-rpc-api/openapi/openapi.json @@ -97,10 +97,49 @@ { "in": "query", "name": "contents", - "description": "Request `CheckpointContents` be included in the response", + "description": "Request `CheckpointContents` be included in the response\n\nDefaults to `false` if not provided.", "schema": { - "description": "Request `CheckpointContents` be included in the response", - "default": false, + "description": "Request `CheckpointContents` be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "contents_bcs", + "description": "Request `CheckpointContents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `CheckpointContents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "signature", + "description": "Request `ValidatorAggregatedSignature` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `ValidatorAggregatedSignature` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "summary", + "description": "Request `CheckpointSummary` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `CheckpointSummary` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "summary_bcs", + "description": "Request `CheckpointSummary` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `CheckpointSummary` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", "type": "boolean" }, "style": "form" @@ -382,17 +421,6 @@ "description": "[![unstable](https://img.shields.io/badge/api-unstable-red?style=for-the-badge)](#) _Api subject to change; use at your own risk_\n\nList Checkpoints\n\nRequest a page of checkpoints, and optionally their contents, ordered by\n`CheckpointSequenceNumber`.\n\nIf the requested page is below the Node's `lowest_available_checkpoint`, a 410 will be\nreturned.", "operationId": "List Checkpoints", "parameters": [ - { - "in": "query", - "name": "contents", - "description": "Request `CheckpointContents` be included in the response", - "schema": { - "description": "Request `CheckpointContents` be included in the response", - "default": false, - "type": "boolean" - }, - "style": "form" - }, { "in": "query", "name": "direction", @@ -430,6 +458,56 @@ "minimum": 0.0 }, "style": "form" + }, + { + "in": "query", + "name": "contents", + "description": "Request `CheckpointContents` be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `CheckpointContents` be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "contents_bcs", + "description": "Request `CheckpointContents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `CheckpointContents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "signature", + "description": "Request `ValidatorAggregatedSignature` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `ValidatorAggregatedSignature` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "summary", + "description": "Request `CheckpointSummary` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `CheckpointSummary` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "summary_bcs", + "description": "Request `CheckpointSummary` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `CheckpointSummary` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" } ], "responses": { @@ -1368,21 +1446,31 @@ "type": "object", "required": [ "digest", - "signature", - "summary" + "sequence_number" ], "properties": { "contents": { "$ref": "#/components/schemas/CheckpointContents" }, + "contents_bcs": { + "type": "string" + }, "digest": { "$ref": "#/components/schemas/CheckpointDigest" }, + "sequence_number": { + "description": "Radix-10 encoded 64-bit unsigned integer", + "type": "string", + "format": "u64" + }, "signature": { "$ref": "#/components/schemas/ValidatorAggregatedSignature" }, "summary": { "$ref": "#/components/schemas/CheckpointSummary" + }, + "summary_bcs": { + "type": "string" } } }, diff --git a/crates/sui-rpc-api/src/client/mod.rs b/crates/sui-rpc-api/src/client/mod.rs index d76379445ce2b..c6b31d753bc32 100644 --- a/crates/sui-rpc-api/src/client/mod.rs +++ b/crates/sui-rpc-api/src/client/mod.rs @@ -66,8 +66,8 @@ impl Client { .map(Response::into_inner) .and_then(|checkpoint| { sui_sdk_types::types::SignedCheckpointSummary { - checkpoint: checkpoint.summary, - signature: checkpoint.signature, + checkpoint: checkpoint.summary.unwrap(), + signature: checkpoint.signature.unwrap(), } .try_into() .map_err(Into::into) diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index c69e0f0c56074..8d402ee76637a 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -23,8 +23,7 @@ use tap::Pipe; use crate::rest::accounts::AccountOwnedObjectInfo; use crate::rest::accounts::ListAccountOwnedObjectsQueryParameters; -use crate::rest::checkpoints::CheckpointResponse; -use crate::rest::checkpoints::ListCheckpointsQueryParameters; +use crate::rest::checkpoints::ListCheckpointsPaginationParameters; use crate::rest::coins::CoinInfo; use crate::rest::health::Threshold; use crate::rest::objects::DynamicFieldInfo; @@ -40,6 +39,7 @@ use crate::rest::transactions::ResolveTransactionResponse; use crate::rest::transactions::TransactionExecutionResponse; use crate::rest::transactions::TransactionResponse; use crate::rest::transactions::TransactionSimulationResponse; +use crate::types::CheckpointResponse; use crate::types::NodeInfo; use crate::types::X_SUI_CHAIN; use crate::types::X_SUI_CHAIN_ID; @@ -238,11 +238,10 @@ impl Client { } pub async fn get_latest_checkpoint(&self) -> Result> { - let parameters = ListCheckpointsQueryParameters { + let parameters = ListCheckpointsPaginationParameters { limit: Some(1), start: None, direction: None, - contents: false, }; let (mut page, parts) = self.list_checkpoints(¶meters).await?.into_parts(); @@ -253,8 +252,8 @@ impl Client { Ok(Response::new( SignedCheckpointSummary { - checkpoint: checkpoint.summary, - signature: checkpoint.signature, + checkpoint: checkpoint.summary.unwrap(), + signature: checkpoint.signature.unwrap(), }, parts, )) @@ -262,7 +261,7 @@ impl Client { pub async fn list_checkpoints( &self, - parameters: &ListCheckpointsQueryParameters, + parameters: &ListCheckpointsPaginationParameters, ) -> Result>> { let url = self.url().join("checkpoints")?; diff --git a/crates/sui-rpc-api/src/lib.rs b/crates/sui-rpc-api/src/lib.rs index ca5d4d671a0e0..350712d24fb86 100644 --- a/crates/sui-rpc-api/src/lib.rs +++ b/crates/sui-rpc-api/src/lib.rs @@ -24,10 +24,9 @@ pub use client::Client; pub use config::Config; pub use error::{Result, RpcServiceError}; pub use metrics::RpcMetrics; -pub use rest::checkpoints::CheckpointResponse; -pub use rest::checkpoints::ListCheckpointsQueryParameters; pub use rest::transactions::ExecuteTransactionQueryParameters; pub use sui_types::full_checkpoint_content::{CheckpointData, CheckpointTransaction}; +pub use types::CheckpointResponse; pub use types::ObjectResponse; #[derive(Clone)] diff --git a/crates/sui-rpc-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs index 8050c33717552..d5285566d1e51 100644 --- a/crates/sui-rpc-api/src/proto/mod.rs +++ b/crates/sui-rpc-api/src/proto/mod.rs @@ -337,66 +337,6 @@ impl TryFrom<&UserSignature> for sui_types::signature::GenericSignature { } } -// -// GetCheckpointResponse -// - -impl TryFrom for GetCheckpointResponse { - type Error = bcs::Error; - - fn try_from(c: crate::rest::checkpoints::CheckpointResponse) -> Result { - Ok(Self { - digest: c.digest.as_bytes().to_vec().into(), - summary: Some(CheckpointSummary::try_from(&c.summary)?), - signature: Some(ValidatorAggregatedSignature::try_from(&c.signature)?), - contents: c - .contents - .as_ref() - .map(CheckpointContents::try_from) - .transpose()?, - }) - } -} - -impl TryFrom for crate::rest::checkpoints::CheckpointResponse { - type Error = bcs::Error; - - fn try_from(value: GetCheckpointResponse) -> Result { - let summary = value - .summary - .ok_or_else(|| bcs::Error::Custom("missing summary".into()))? - .pipe_ref(TryInto::try_into)?; - let signature = value - .signature - .ok_or_else(|| bcs::Error::Custom("missing signature".into()))? - .pipe_ref(TryInto::try_into)?; - - let contents = value.contents.as_ref().map(TryInto::try_into).transpose()?; - - Ok(Self { - digest: sui_sdk_types::types::CheckpointDigest::from_bytes(&value.digest) - .map_err(|e| bcs::Error::Custom(e.to_string()))?, - summary, - signature, - contents, - }) - } -} - -impl TryFrom> for ListCheckpointResponse { - type Error = bcs::Error; - fn try_from( - value: Vec, - ) -> Result { - let checkpoints = value - .into_iter() - .map(TryInto::try_into) - .collect::>()?; - - Ok(Self { checkpoints }) - } -} - // // GetTransactionResponse // diff --git a/crates/sui-rpc-api/src/rest/checkpoints.rs b/crates/sui-rpc-api/src/rest/checkpoints.rs index 41a3707cccec3..74eed2c1ad5e2 100644 --- a/crates/sui-rpc-api/src/rest/checkpoints.rs +++ b/crates/sui-rpc-api/src/rest/checkpoints.rs @@ -4,10 +4,7 @@ use axum::extract::Query; use axum::extract::{Path, State}; use axum::Json; -use sui_sdk_types::types::{ - CheckpointContents, CheckpointDigest, CheckpointSequenceNumber, CheckpointSummary, - SignedCheckpointSummary, ValidatorAggregatedSignature, -}; +use sui_sdk_types::types::{CheckpointSequenceNumber, SignedCheckpointSummary}; use sui_types::storage::ReadStore; use tap::Pipe; @@ -15,20 +12,14 @@ use crate::reader::StateReader; use crate::response::{Bcs, ResponseContent}; use crate::rest::openapi::{ApiEndpoint, OperationBuilder, ResponseBuilder, RouteHandler}; use crate::rest::PageCursor; +use crate::service::checkpoints::{CheckpointId, CheckpointNotFoundError}; +use crate::types::{CheckpointResponse, GetCheckpointOptions}; use crate::{Direction, RpcService}; use crate::{Result, RpcServiceError}; use documented::Documented; use super::accept::AcceptFormat; -#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] -pub struct CheckpointResponse { - pub digest: CheckpointDigest, - pub summary: CheckpointSummary, - pub signature: ValidatorAggregatedSignature, - pub contents: Option, -} - /// Fetch a Checkpoint /// /// Fetch a checkpoint either by `CheckpointSequenceNumber` (checkpoint height) or by @@ -60,7 +51,7 @@ impl ApiEndpoint for GetCheckpoint { .operation_id("Get Checkpoint") .description(Self::DOCS) .path_parameter::("checkpoint", generator) - .query_parameters::(generator) + .query_parameters::(generator) .response( 200, ResponseBuilder::new() @@ -80,125 +71,10 @@ impl ApiEndpoint for GetCheckpoint { async fn get_checkpoint( Path(checkpoint_id): Path, - Query(parameters): Query, - State(state): State, + Query(options): Query, + State(state): State, ) -> Result> { - let SignedCheckpointSummary { - checkpoint, - signature, - } = match checkpoint_id { - CheckpointId::SequenceNumber(s) => { - let oldest_checkpoint = state.inner().get_lowest_available_checkpoint()?; - if s < oldest_checkpoint { - return Err(crate::RpcServiceError::new( - axum::http::StatusCode::GONE, - "Old checkpoints have been pruned", - )); - } - - state.inner().get_checkpoint_by_sequence_number(s) - } - CheckpointId::Digest(d) => state.inner().get_checkpoint_by_digest(&d.into()), - } - .ok_or(CheckpointNotFoundError(checkpoint_id))? - .into_inner() - .try_into()?; - - let contents = if parameters.contents { - Some( - state - .inner() - .get_checkpoint_contents_by_sequence_number(checkpoint.sequence_number) - .ok_or(CheckpointNotFoundError(checkpoint_id))? - .try_into()?, - ) - } else { - None - }; - - CheckpointResponse { - digest: checkpoint.digest(), - summary: checkpoint, - signature, - contents, - } - .pipe(Json) - .pipe(Ok) -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, schemars::JsonSchema)] -#[schemars(untagged)] -pub enum CheckpointId { - #[schemars( - title = "SequenceNumber", - example = "CheckpointSequenceNumber::default" - )] - /// Sequence number or height of a Checkpoint - SequenceNumber(#[schemars(with = "crate::rest::_schemars::U64")] CheckpointSequenceNumber), - #[schemars(title = "Digest", example = "example_digest")] - /// Base58 encoded 32-byte digest of a Checkpoint - Digest(CheckpointDigest), -} - -fn example_digest() -> CheckpointDigest { - "4btiuiMPvEENsttpZC7CZ53DruC3MAgfznDbASZ7DR6S" - .parse() - .unwrap() -} - -impl<'de> serde::Deserialize<'de> for CheckpointId { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - let raw = String::deserialize(deserializer)?; - - if let Ok(s) = raw.parse::() { - Ok(Self::SequenceNumber(s)) - } else if let Ok(d) = raw.parse::() { - Ok(Self::Digest(d)) - } else { - Err(serde::de::Error::custom(format!( - "unrecognized checkpoint-id {raw}" - ))) - } - } -} - -impl serde::Serialize for CheckpointId { - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - match self { - CheckpointId::SequenceNumber(s) => serializer.serialize_str(&s.to_string()), - CheckpointId::Digest(d) => serializer.serialize_str(&d.to_string()), - } - } -} - -#[derive(Debug)] -pub struct CheckpointNotFoundError(CheckpointId); - -impl std::fmt::Display for CheckpointNotFoundError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Checkpoint ")?; - - match self.0 { - CheckpointId::SequenceNumber(n) => write!(f, "{n}")?, - CheckpointId::Digest(d) => write!(f, "{d}")?, - } - - write!(f, " not found") - } -} - -impl std::error::Error for CheckpointNotFoundError {} - -impl From for crate::RpcServiceError { - fn from(value: CheckpointNotFoundError) -> Self { - Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) - } + state.get_checkpoint(Some(checkpoint_id), options).map(Json) } /// Query parameters for the GetCheckpoint endpoint @@ -229,6 +105,8 @@ impl ApiEndpoint for ListCheckpoints { } fn stable(&self) -> bool { + // Before making this api stable we'll need to properly handle the options that can be + // provided as inputs. false } @@ -240,7 +118,8 @@ impl ApiEndpoint for ListCheckpoints { .tag("Checkpoint") .operation_id("List Checkpoints") .description(Self::DOCS) - .query_parameters::(generator) + .query_parameters::(generator) + .query_parameters::(generator) .response( 200, ResponseBuilder::new() @@ -260,7 +139,8 @@ impl ApiEndpoint for ListCheckpoints { } async fn list_checkpoints( - Query(parameters): Query, + Query(parameters): Query, + Query(options): Query, accept: AcceptFormat, State(state): State, ) -> Result<( @@ -291,25 +171,28 @@ async fn list_checkpoints( checkpoint, signature, } = checkpoint.try_into()?; - let contents = if parameters.contents { + let contents = if options.include_contents() { Some(contents.try_into()?) } else { None }; Ok(CheckpointResponse { + sequence_number: checkpoint.sequence_number, digest: checkpoint.digest(), - summary: checkpoint, - signature, + summary: Some(checkpoint), + signature: Some(signature), contents, + summary_bcs: None, + contents_bcs: None, }) }) }) .collect::>>()?; let cursor = checkpoints.last().and_then(|checkpoint| match direction { - Direction::Ascending => checkpoint.summary.sequence_number.checked_add(1), + Direction::Ascending => checkpoint.sequence_number.checked_add(1), Direction::Descending => { - let cursor = checkpoint.summary.sequence_number.checked_sub(1); + let cursor = checkpoint.sequence_number.checked_sub(1); // If we've exhausted our available checkpoint range then there are no more pages left if cursor < Some(oldest_checkpoint) { None @@ -327,8 +210,8 @@ async fn list_checkpoints( let checkpoints = checkpoints .into_iter() .map(|c| SignedCheckpointSummary { - checkpoint: c.summary, - signature: c.signature, + checkpoint: c.summary.unwrap(), + signature: c.signature.unwrap(), }) .collect(); ResponseContent::Bcs(checkpoints) @@ -339,7 +222,7 @@ async fn list_checkpoints( } #[derive(Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] -pub struct ListCheckpointsQueryParameters { +pub struct ListCheckpointsPaginationParameters { /// Page size limit for the response. /// /// Defaults to `50` if not provided with a maximum page size of `100`. @@ -352,12 +235,9 @@ pub struct ListCheckpointsQueryParameters { /// /// Defaults to `descending` if not provided. pub direction: Option, - /// Request `CheckpointContents` be included in the response - #[serde(default)] - pub contents: bool, } -impl ListCheckpointsQueryParameters { +impl ListCheckpointsPaginationParameters { pub fn limit(&self) -> usize { self.limit .map(|l| (l as usize).clamp(1, crate::rest::MAX_PAGE_SIZE)) diff --git a/crates/sui-rpc-api/src/service/checkpoints.rs b/crates/sui-rpc-api/src/service/checkpoints.rs new file mode 100644 index 0000000000000..17f88d29c0ff2 --- /dev/null +++ b/crates/sui-rpc-api/src/service/checkpoints.rs @@ -0,0 +1,160 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::types::CheckpointResponse; +use crate::types::GetCheckpointOptions; +use crate::Result; +use crate::RpcService; +use sui_sdk_types::types::CheckpointContents; +use sui_sdk_types::types::CheckpointDigest; +use sui_sdk_types::types::CheckpointSequenceNumber; +use sui_sdk_types::types::SignedCheckpointSummary; +use tap::Pipe; + +impl RpcService { + pub fn get_checkpoint( + &self, + checkpoint: Option, + options: GetCheckpointOptions, + ) -> Result { + let SignedCheckpointSummary { + checkpoint, + signature, + } = match checkpoint { + Some(checkpoint_id @ CheckpointId::SequenceNumber(s)) => { + let oldest_checkpoint = self.reader.inner().get_lowest_available_checkpoint()?; + if s < oldest_checkpoint { + return Err(crate::RpcServiceError::new( + axum::http::StatusCode::GONE, + "Old checkpoints have been pruned", + )); + } + + self.reader + .inner() + .get_checkpoint_by_sequence_number(s) + .ok_or(CheckpointNotFoundError(checkpoint_id))? + } + Some(checkpoint_id @ CheckpointId::Digest(d)) => self + .reader + .inner() + .get_checkpoint_by_digest(&d.into()) + .ok_or(CheckpointNotFoundError(checkpoint_id))?, + None => self.reader.inner().get_latest_checkpoint()?, + } + .into_inner() + .try_into()?; + + let (contents, contents_bcs) = + if options.include_contents() || options.include_contents_bcs() { + let contents: CheckpointContents = self + .reader + .inner() + .get_checkpoint_contents_by_sequence_number(checkpoint.sequence_number) + .ok_or(CheckpointNotFoundError(CheckpointId::SequenceNumber( + checkpoint.sequence_number, + )))? + .try_into()?; + + let contents_bcs = options + .include_contents_bcs() + .then(|| bcs::to_bytes(&contents)) + .transpose()?; + + (options.include_contents().then_some(contents), contents_bcs) + } else { + (None, None) + }; + + let summary_bcs = options + .include_summary_bcs() + .then(|| bcs::to_bytes(&checkpoint)) + .transpose()?; + + CheckpointResponse { + sequence_number: checkpoint.sequence_number, + digest: checkpoint.digest(), + summary: options.include_summary().then_some(checkpoint), + summary_bcs, + signature: options.include_signature().then_some(signature), + contents, + contents_bcs, + } + .pipe(Ok) + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, schemars::JsonSchema)] +#[schemars(untagged)] +pub enum CheckpointId { + #[schemars( + title = "SequenceNumber", + example = "CheckpointSequenceNumber::default" + )] + /// Sequence number or height of a Checkpoint + SequenceNumber(#[schemars(with = "crate::rest::_schemars::U64")] CheckpointSequenceNumber), + #[schemars(title = "Digest", example = "example_digest")] + /// Base58 encoded 32-byte digest of a Checkpoint + Digest(CheckpointDigest), +} + +fn example_digest() -> CheckpointDigest { + "4btiuiMPvEENsttpZC7CZ53DruC3MAgfznDbASZ7DR6S" + .parse() + .unwrap() +} + +impl<'de> serde::Deserialize<'de> for CheckpointId { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + let raw = String::deserialize(deserializer)?; + + if let Ok(s) = raw.parse::() { + Ok(Self::SequenceNumber(s)) + } else if let Ok(d) = raw.parse::() { + Ok(Self::Digest(d)) + } else { + Err(serde::de::Error::custom(format!( + "unrecognized checkpoint-id {raw}" + ))) + } + } +} + +impl serde::Serialize for CheckpointId { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + match self { + CheckpointId::SequenceNumber(s) => serializer.serialize_str(&s.to_string()), + CheckpointId::Digest(d) => serializer.serialize_str(&d.to_string()), + } + } +} + +#[derive(Debug)] +pub struct CheckpointNotFoundError(pub CheckpointId); + +impl std::fmt::Display for CheckpointNotFoundError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Checkpoint ")?; + + match self.0 { + CheckpointId::SequenceNumber(n) => write!(f, "{n}")?, + CheckpointId::Digest(d) => write!(f, "{d}")?, + } + + write!(f, " not found") + } +} + +impl std::error::Error for CheckpointNotFoundError {} + +impl From for crate::RpcServiceError { + fn from(value: CheckpointNotFoundError) -> Self { + Self::new(axum::http::StatusCode::NOT_FOUND, value.to_string()) + } +} diff --git a/crates/sui-rpc-api/src/service/mod.rs b/crates/sui-rpc-api/src/service/mod.rs index 18146a694927c..34f1f8e4cb622 100644 --- a/crates/sui-rpc-api/src/service/mod.rs +++ b/crates/sui-rpc-api/src/service/mod.rs @@ -1,6 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +pub(crate) mod checkpoints; mod committee; mod health; mod info; diff --git a/crates/sui-rpc-api/src/types.rs b/crates/sui-rpc-api/src/types.rs index 34e6bdf331c63..e822854eb8d7c 100644 --- a/crates/sui-rpc-api/src/types.rs +++ b/crates/sui-rpc-api/src/types.rs @@ -114,5 +114,88 @@ impl GetObjectOptions { pub fn include_object_bcs(&self) -> bool { self.object_bcs.unwrap_or(false) } +} + +#[serde_with::serde_as] +#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct CheckpointResponse { + #[serde_as(as = "sui_types::sui_serde::BigInt")] + #[schemars(with = "crate::rest::_schemars::U64")] + pub sequence_number: sui_sdk_types::types::CheckpointSequenceNumber, + + pub digest: sui_sdk_types::types::CheckpointDigest, + + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub summary_bcs: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub signature: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub contents: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub contents_bcs: Option>, +} + +#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct GetCheckpointOptions { + /// Request `CheckpointSummary` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, + /// Request `CheckpointSummary` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub summary_bcs: Option, + + /// Request `ValidatorAggregatedSignature` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub signature: Option, + + /// Request `CheckpointContents` be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub contents: Option, + + /// Request `CheckpointContents` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub contents_bcs: Option, +} + +impl GetCheckpointOptions { + pub fn include_summary(&self) -> bool { + self.summary.unwrap_or(true) + } + + pub fn include_summary_bcs(&self) -> bool { + self.summary_bcs.unwrap_or(false) + } + + pub fn include_signature(&self) -> bool { + self.signature.unwrap_or(true) + } + + pub fn include_contents(&self) -> bool { + self.contents.unwrap_or(false) + } + + pub fn include_contents_bcs(&self) -> bool { + self.contents_bcs.unwrap_or(false) + } } From d53ec7ceb83d06db7717075223b3b938707b6b9a Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Sat, 30 Nov 2024 15:51:22 -0600 Subject: [PATCH 22/28] rpc: factor out get_transaction logic --- .../sui-e2e-tests/tests/rpc/transactions.rs | 4 +- crates/sui-rpc-api/openapi/openapi.json | 156 +++++++++++++++++- crates/sui-rpc-api/src/client/sdk.rs | 6 +- crates/sui-rpc-api/src/proto/mod.rs | 57 ------- crates/sui-rpc-api/src/reader.rs | 17 +- .../sui-rpc-api/src/rest/transactions/mod.rs | 77 ++++----- crates/sui-rpc-api/src/service/mod.rs | 1 + .../src/service/transactions/mod.rs | 57 +++++++ crates/sui-rpc-api/src/types.rs | 122 ++++++++++++++ 9 files changed, 380 insertions(+), 117 deletions(-) create mode 100644 crates/sui-rpc-api/src/service/transactions/mod.rs diff --git a/crates/sui-e2e-tests/tests/rpc/transactions.rs b/crates/sui-e2e-tests/tests/rpc/transactions.rs index 12014d7c3c94a..213aae1a49d03 100644 --- a/crates/sui-e2e-tests/tests/rpc/transactions.rs +++ b/crates/sui-e2e-tests/tests/rpc/transactions.rs @@ -3,7 +3,7 @@ use sui_macros::sim_test; use sui_rpc_api::client::sdk::Client; -use sui_rpc_api::rest::transactions::ListTransactionsQueryParameters; +use sui_rpc_api::rest::transactions::ListTransactionsCursorParameters; use test_cluster::TestClusterBuilder; use crate::transfer_coin; @@ -28,7 +28,7 @@ async fn list_checkpoint() { let client = Client::new(test_cluster.rpc_url()).unwrap(); let transactions = client - .list_transactions(&ListTransactionsQueryParameters::default()) + .list_transactions(&ListTransactionsCursorParameters::default()) .await .unwrap() .into_inner(); diff --git a/crates/sui-rpc-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json index efaca94c0d21a..8e0a5322efb81 100644 --- a/crates/sui-rpc-api/openapi/openapi.json +++ b/crates/sui-rpc-api/openapi/openapi.json @@ -595,6 +595,76 @@ "$ref": "#/components/schemas/TransactionDigest" }, "style": "simple" + }, + { + "in": "query", + "name": "effects", + "description": "Request `TransactionEffects` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `TransactionEffects` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "effects_bcs", + "description": "Request `TransactionEffects` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `TransactionEffects` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "events", + "description": "Request `TransactionEvents` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `TransactionEvents` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "events_bcs", + "description": "Request `TransactionEvents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `TransactionEvents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "signatures", + "description": "Request `Vec` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `Vec` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "transaction", + "description": "Request `Transaction` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `Transaction` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "transaction_bcs", + "description": "Request `Transaction` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `Transaction` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" } ], "responses": { @@ -647,6 +717,76 @@ "type": "string" }, "style": "form" + }, + { + "in": "query", + "name": "effects", + "description": "Request `TransactionEffects` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `TransactionEffects` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "effects_bcs", + "description": "Request `TransactionEffects` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `TransactionEffects` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "events", + "description": "Request `TransactionEvents` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `TransactionEvents` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "events_bcs", + "description": "Request `TransactionEvents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `TransactionEvents` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "signatures", + "description": "Request `Vec` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `Vec` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "transaction", + "description": "Request `Transaction` be included in the response\n\nDefaults to `true` if not provided.", + "schema": { + "description": "Request `Transaction` be included in the response\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "transaction_bcs", + "description": "Request `Transaction` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `Transaction` encoded as BCS be included in the response\n\nDefaults to `false` if not provided.", + "type": "boolean" + }, + "style": "form" } ], "responses": { @@ -5362,15 +5502,11 @@ "TransactionResponse": { "type": "object", "required": [ - "digest", - "effects", - "signatures", - "transaction" + "digest" ], "properties": { "checkpoint": { "description": "Radix-10 encoded 64-bit unsigned integer", - "default": null, "type": "string", "format": "u64" }, @@ -5380,9 +5516,15 @@ "effects": { "$ref": "#/components/schemas/TransactionEffects" }, + "effects_bcs": { + "type": "string" + }, "events": { "$ref": "#/components/schemas/TransactionEvents" }, + "events_bcs": { + "type": "string" + }, "signatures": { "type": "array", "items": { @@ -5391,12 +5533,14 @@ }, "timestamp_ms": { "description": "Radix-10 encoded 64-bit unsigned integer", - "default": null, "type": "string", "format": "u64" }, "transaction": { "$ref": "#/components/schemas/Transaction" + }, + "transaction_bcs": { + "type": "string" } } }, diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index 8d402ee76637a..2a7f042d06738 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -33,14 +33,14 @@ use crate::rest::system::ProtocolConfigResponse; use crate::rest::system::SystemStateSummary; use crate::rest::system::X_SUI_MAX_SUPPORTED_PROTOCOL_VERSION; use crate::rest::system::X_SUI_MIN_SUPPORTED_PROTOCOL_VERSION; -use crate::rest::transactions::ListTransactionsQueryParameters; +use crate::rest::transactions::ListTransactionsCursorParameters; use crate::rest::transactions::ResolveTransactionQueryParameters; use crate::rest::transactions::ResolveTransactionResponse; use crate::rest::transactions::TransactionExecutionResponse; -use crate::rest::transactions::TransactionResponse; use crate::rest::transactions::TransactionSimulationResponse; use crate::types::CheckpointResponse; use crate::types::NodeInfo; +use crate::types::TransactionResponse; use crate::types::X_SUI_CHAIN; use crate::types::X_SUI_CHAIN_ID; use crate::types::X_SUI_CHECKPOINT_HEIGHT; @@ -296,7 +296,7 @@ impl Client { pub async fn list_transactions( &self, - parameters: &ListTransactionsQueryParameters, + parameters: &ListTransactionsCursorParameters, ) -> Result>> { let url = self.url().join("transactions")?; diff --git a/crates/sui-rpc-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs index d5285566d1e51..fdb9b81f8d00f 100644 --- a/crates/sui-rpc-api/src/proto/mod.rs +++ b/crates/sui-rpc-api/src/proto/mod.rs @@ -337,63 +337,6 @@ impl TryFrom<&UserSignature> for sui_types::signature::GenericSignature { } } -// -// GetTransactionResponse -// - -impl TryFrom for GetTransactionResponse { - type Error = bcs::Error; - - fn try_from( - value: crate::rest::transactions::TransactionResponse, - ) -> Result { - Ok(Self { - digest: value.digest.as_bytes().to_vec().into(), - transaction: Some(Transaction::try_from(&value.transaction)?), - signatures: value - .signatures - .iter() - .map(UserSignature::try_from) - .collect::>()?, - effects: Some(TransactionEffects::try_from(&value.effects)?), - events: value - .events - .as_ref() - .map(TransactionEvents::try_from) - .transpose()?, - checkpoint: value.checkpoint, - timestamp_ms: value.timestamp_ms, - }) - } -} - -impl TryFrom for crate::rest::transactions::TransactionResponse { - type Error = bcs::Error; - - fn try_from(value: GetTransactionResponse) -> Result { - Ok(Self { - digest: sui_sdk_types::types::TransactionDigest::from_bytes(&value.digest) - .map_err(|e| bcs::Error::Custom(e.to_string()))?, - transaction: value - .transaction - .ok_or_else(|| bcs::Error::Custom("missing transaction".into()))? - .pipe_ref(TryInto::try_into)?, - signatures: value - .signatures - .iter() - .map(TryInto::try_into) - .collect::>()?, - effects: value - .effects - .ok_or_else(|| bcs::Error::Custom("missing effects".into()))? - .pipe_ref(TryInto::try_into)?, - events: value.events.as_ref().map(TryInto::try_into).transpose()?, - checkpoint: value.checkpoint, - timestamp_ms: value.timestamp_ms, - }) - } -} - // // CheckpointTransaction // diff --git a/crates/sui-rpc-api/src/reader.rs b/crates/sui-rpc-api/src/reader.rs index 46c602451f9be..6384d143c3cd5 100644 --- a/crates/sui-rpc-api/src/reader.rs +++ b/crates/sui-rpc-api/src/reader.rs @@ -113,10 +113,10 @@ impl StateReader { .ok()? } - pub fn get_transaction_response( + pub fn get_transaction_read( &self, digest: sui_sdk_types::types::TransactionDigest, - ) -> crate::Result { + ) -> crate::Result { let ( SignedTransaction { transaction, @@ -135,7 +135,7 @@ impl StateReader { None }; - Ok(crate::rest::transactions::TransactionResponse { + Ok(TransactionRead { digest: transaction.digest(), transaction, signatures, @@ -163,6 +163,17 @@ impl StateReader { } } +#[derive(Debug)] +pub struct TransactionRead { + pub digest: sui_sdk_types::types::TransactionDigest, + pub transaction: sui_sdk_types::types::Transaction, + pub signatures: Vec, + pub effects: sui_sdk_types::types::TransactionEffects, + pub events: Option, + pub checkpoint: Option, + pub timestamp_ms: Option, +} + pub struct CheckpointTransactionsIter { reader: StateReader, direction: Direction, diff --git a/crates/sui-rpc-api/src/rest/transactions/mod.rs b/crates/sui-rpc-api/src/rest/transactions/mod.rs index 820fa9923df24..5073970acee43 100644 --- a/crates/sui-rpc-api/src/rest/transactions/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/mod.rs @@ -19,18 +19,16 @@ pub use resolve::ResolveTransactionResponse; use axum::extract::{Path, Query, State}; use axum::http::StatusCode; use sui_sdk_types::types::CheckpointSequenceNumber; -use sui_sdk_types::types::Transaction; -use sui_sdk_types::types::{ - TransactionDigest, TransactionEffects, TransactionEvents, UserSignature, -}; +use sui_sdk_types::types::TransactionDigest; use tap::Pipe; -use crate::reader::StateReader; use crate::rest::openapi::ApiEndpoint; use crate::rest::openapi::OperationBuilder; use crate::rest::openapi::ResponseBuilder; use crate::rest::openapi::RouteHandler; use crate::rest::PageCursor; +use crate::types::GetTransactionOptions; +use crate::types::TransactionResponse; use crate::Direction; use crate::Result; use crate::RpcService; @@ -55,6 +53,7 @@ impl ApiEndpoint for GetTransaction { .tag("Transactions") .operation_id("GetTransaction") .path_parameter::("transaction", generator) + .query_parameters::(generator) .response( 200, ResponseBuilder::new() @@ -72,29 +71,12 @@ impl ApiEndpoint for GetTransaction { async fn get_transaction( Path(transaction_digest): Path, - State(state): State, + Query(options): Query, + State(state): State, ) -> Result> { - state.get_transaction_response(transaction_digest).map(Json) -} - -#[serde_with::serde_as] -#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] -pub struct TransactionResponse { - pub digest: TransactionDigest, - pub transaction: Transaction, - pub signatures: Vec, - pub effects: TransactionEffects, - pub events: Option, - #[serde_as( - as = "Option, _>>" - )] - #[schemars(with = "Option")] - pub checkpoint: Option, - #[serde_as( - as = "Option, _>>" - )] - #[schemars(with = "Option")] - pub timestamp_ms: Option, + state + .get_transaction(transaction_digest, &options) + .map(Json) } #[derive(Debug)] @@ -132,7 +114,8 @@ impl ApiEndpoint for ListTransactions { OperationBuilder::new() .tag("Transactions") .operation_id("ListTransactions") - .query_parameters::(generator) + .query_parameters::(generator) + .query_parameters::(generator) .response( 200, ResponseBuilder::new() @@ -150,17 +133,22 @@ impl ApiEndpoint for ListTransactions { } async fn list_transactions( - Query(parameters): Query, - State(state): State, + Query(cursor): Query, + Query(options): Query, + State(state): State, ) -> Result<( PageCursor, Json>, )> { - let latest_checkpoint = state.inner().get_latest_checkpoint()?.sequence_number; - let oldest_checkpoint = state.inner().get_lowest_available_checkpoint()?; - let limit = parameters.limit(); - let start = parameters.start(latest_checkpoint); - let direction = parameters.direction(); + let latest_checkpoint = state + .reader + .inner() + .get_latest_checkpoint()? + .sequence_number; + let oldest_checkpoint = state.reader.inner().get_lowest_available_checkpoint()?; + let limit = cursor.limit(); + let start = cursor.start(latest_checkpoint); + let direction = cursor.direction(); if start.checkpoint < oldest_checkpoint { return Err(RpcServiceError::new( @@ -171,21 +159,18 @@ async fn list_transactions( let mut next_cursor = None; let transactions = state + .reader .transaction_iter(direction, (start.checkpoint, start.index)) .take(limit) .map(|entry| { let (cursor_info, digest) = entry?; next_cursor = cursor_info.next_cursor; state - .get_transaction(digest.into()) - .map(|(transaction, effects, events)| TransactionResponse { - digest: transaction.transaction.digest(), - transaction: transaction.transaction, - signatures: transaction.signatures, - effects, - events, - checkpoint: Some(cursor_info.checkpoint), - timestamp_ms: Some(cursor_info.timestamp_ms), + .get_transaction(digest.into(), &options) + .map(|mut response| { + response.checkpoint = Some(cursor_info.checkpoint); + response.timestamp_ms = Some(cursor_info.timestamp_ms); + response }) }) .collect::, _>>()?; @@ -269,14 +254,14 @@ impl serde::Serialize for TransactionCursor { } #[derive(Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] -pub struct ListTransactionsQueryParameters { +pub struct ListTransactionsCursorParameters { pub limit: Option, #[schemars(with = "Option")] pub start: Option, pub direction: Option, } -impl ListTransactionsQueryParameters { +impl ListTransactionsCursorParameters { pub fn limit(&self) -> usize { self.limit .map(|l| (l as usize).clamp(1, crate::rest::MAX_PAGE_SIZE)) diff --git a/crates/sui-rpc-api/src/service/mod.rs b/crates/sui-rpc-api/src/service/mod.rs index 34f1f8e4cb622..29a80321c8889 100644 --- a/crates/sui-rpc-api/src/service/mod.rs +++ b/crates/sui-rpc-api/src/service/mod.rs @@ -6,3 +6,4 @@ mod committee; mod health; mod info; pub(crate) mod objects; +pub(crate) mod transactions; diff --git a/crates/sui-rpc-api/src/service/transactions/mod.rs b/crates/sui-rpc-api/src/service/transactions/mod.rs new file mode 100644 index 0000000000000..f3ba1f06128cc --- /dev/null +++ b/crates/sui-rpc-api/src/service/transactions/mod.rs @@ -0,0 +1,57 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::types::GetTransactionOptions; +use crate::types::TransactionResponse; +use crate::Result; +use crate::RpcService; +use sui_sdk_types::types::TransactionDigest; +use tap::Pipe; + +impl RpcService { + pub fn get_transaction( + &self, + transaction_digest: TransactionDigest, + options: &GetTransactionOptions, + ) -> Result { + let crate::reader::TransactionRead { + digest, + transaction, + signatures, + effects, + events, + checkpoint, + timestamp_ms, + } = self.reader.get_transaction_read(transaction_digest)?; + + let transaction_bcs = options + .include_transaction_bcs() + .then(|| bcs::to_bytes(&transaction)) + .transpose()?; + + let effects_bcs = options + .include_effects_bcs() + .then(|| bcs::to_bytes(&effects)) + .transpose()?; + + let events_bcs = options + .include_events_bcs() + .then(|| events.as_ref().map(bcs::to_bytes)) + .flatten() + .transpose()?; + + TransactionResponse { + digest, + transaction: options.include_transaction().then_some(transaction), + transaction_bcs, + signatures: options.include_signatures().then_some(signatures), + effects: options.include_effects().then_some(effects), + effects_bcs, + events: options.include_events().then_some(events).flatten(), + events_bcs, + checkpoint, + timestamp_ms, + } + .pipe(Ok) + } +} diff --git a/crates/sui-rpc-api/src/types.rs b/crates/sui-rpc-api/src/types.rs index e822854eb8d7c..87f69da3ba43f 100644 --- a/crates/sui-rpc-api/src/types.rs +++ b/crates/sui-rpc-api/src/types.rs @@ -199,3 +199,125 @@ impl GetCheckpointOptions { self.contents_bcs.unwrap_or(false) } } + +#[serde_with::serde_as] +#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct TransactionResponse { + pub digest: sui_sdk_types::types::TransactionDigest, + + #[serde(skip_serializing_if = "Option::is_none")] + pub transaction: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub transaction_bcs: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub signatures: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub effects: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub effects_bcs: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub events: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub events_bcs: Option>, + + #[serde_as( + as = "Option, _>>" + )] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub checkpoint: Option, + + #[serde_as( + as = "Option, _>>" + )] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub timestamp_ms: Option, +} + +#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct GetTransactionOptions { + /// Request `Transaction` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub transaction: Option, + + /// Request `Transaction` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub transaction_bcs: Option, + + /// Request `Vec` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub signatures: Option, + + /// Request `TransactionEffects` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub effects: Option, + + /// Request `TransactionEffects` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub effects_bcs: Option, + + /// Request `TransactionEvents` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub events: Option, + + /// Request `TransactionEvents` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub events_bcs: Option, +} + +impl GetTransactionOptions { + pub fn include_transaction(&self) -> bool { + self.transaction.unwrap_or(true) + } + + pub fn include_transaction_bcs(&self) -> bool { + self.transaction_bcs.unwrap_or(false) + } + + pub fn include_signatures(&self) -> bool { + self.signatures.unwrap_or(true) + } + + pub fn include_effects(&self) -> bool { + self.effects.unwrap_or(true) + } + + pub fn include_effects_bcs(&self) -> bool { + self.effects_bcs.unwrap_or(false) + } + + pub fn include_events(&self) -> bool { + self.events.unwrap_or(true) + } + + pub fn include_events_bcs(&self) -> bool { + self.events_bcs.unwrap_or(false) + } +} From e488af92ebfda150e1cadf3d86b2fba9f639c141 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Sat, 30 Nov 2024 20:25:04 -0600 Subject: [PATCH 23/28] rpc: factor out {execute, simulate}_transaction logic --- crates/sui-e2e-tests/tests/rpc/execute.rs | 26 +- crates/sui-e2e-tests/tests/rpc/resolve.rs | 26 +- crates/sui-rpc-api/openapi/openapi.json | 136 +++--- crates/sui-rpc-api/src/client/mod.rs | 70 +-- crates/sui-rpc-api/src/client/sdk.rs | 10 +- crates/sui-rpc-api/src/lib.rs | 1 - crates/sui-rpc-api/src/proto/mod.rs | 444 ------------------ .../src/rest/transactions/execution.rs | 374 +-------------- .../sui-rpc-api/src/rest/transactions/mod.rs | 3 - .../src/rest/transactions/resolve/mod.rs | 12 +- .../src/service/transactions/execution.rs | 237 ++++++++++ .../src/service/transactions/mod.rs | 2 + crates/sui-rpc-api/src/types.rs | 121 +++++ 13 files changed, 522 insertions(+), 940 deletions(-) create mode 100644 crates/sui-rpc-api/src/service/transactions/execution.rs diff --git a/crates/sui-e2e-tests/tests/rpc/execute.rs b/crates/sui-e2e-tests/tests/rpc/execute.rs index 431e4413253db..7f33a7cf09cc8 100644 --- a/crates/sui-e2e-tests/tests/rpc/execute.rs +++ b/crates/sui-e2e-tests/tests/rpc/execute.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use sui_macros::sim_test; -use sui_rpc_api::client::BalanceChange; +use sui_rpc_api::types::ExecuteTransactionOptions; use sui_rpc_api::Client; -use sui_rpc_api::ExecuteTransactionQueryParameters; +use sui_sdk_types::types::BalanceChange; use sui_test_transaction_builder::make_transfer_sui_transaction; use sui_types::base_types::SuiAddress; use sui_types::effects::TransactionEffectsAPI; @@ -23,26 +23,28 @@ async fn execute_transaction_transfer() { make_transfer_sui_transaction(&test_cluster.wallet, Some(address), Some(amount)).await; let sender = txn.transaction_data().sender(); - let request = ExecuteTransactionQueryParameters { - events: false, - balance_changes: true, - input_objects: true, - output_objects: true, + let options = ExecuteTransactionOptions { + balance_changes: Some(true), + ..Default::default() }; - let response = client.execute_transaction(&request, &txn).await.unwrap(); + let response = client.execute_transaction(&options, &txn).await.unwrap(); let gas = response.effects.gas_cost_summary().net_gas_usage(); + let coin_type = sui_types::sui_sdk_types_conversions::type_tag_core_to_sdk( + sui_types::gas_coin::GAS::type_tag(), + ) + .unwrap(); let mut expected = vec![ BalanceChange { - address: sender, - coin_type: sui_types::gas_coin::GAS::type_tag(), + address: sender.into(), + coin_type: coin_type.clone(), amount: -(amount as i128 + gas as i128), }, BalanceChange { - address, - coin_type: sui_types::gas_coin::GAS::type_tag(), + address: address.into(), + coin_type, amount: amount as i128, }, ]; diff --git a/crates/sui-e2e-tests/tests/rpc/resolve.rs b/crates/sui-e2e-tests/tests/rpc/resolve.rs index 85f661276d5ce..15b3fb66aef4b 100644 --- a/crates/sui-e2e-tests/tests/rpc/resolve.rs +++ b/crates/sui-e2e-tests/tests/rpc/resolve.rs @@ -7,7 +7,6 @@ use sui_macros::sim_test; use sui_rpc_api::client::reqwest::StatusCode; use sui_rpc_api::rest::transactions::ResolveTransactionQueryParameters; use sui_rpc_api::Client; -use sui_rpc_api::ExecuteTransactionQueryParameters; use sui_sdk_types::types::unresolved; use sui_sdk_types::types::Argument; use sui_sdk_types::types::Command; @@ -68,10 +67,7 @@ async fn resolve_transaction_simple_transfer() { .wallet .sign_transaction(&resolved.transaction.try_into().unwrap()); let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) + .execute_transaction(&Default::default(), &signed_transaction) .await .unwrap() .effects; @@ -155,10 +151,7 @@ async fn resolve_transaction_transfer_with_sponsor() { vec![sender_sig, sponsor_sig], ); let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) + .execute_transaction(&Default::default(), &signed_transaction) .await .unwrap() .effects; @@ -214,10 +207,7 @@ async fn resolve_transaction_borrowed_shared_object() { .wallet .sign_transaction(&resolved.transaction.try_into().unwrap()); let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) + .execute_transaction(&Default::default(), &signed_transaction) .await .unwrap() .effects; @@ -291,10 +281,7 @@ async fn resolve_transaction_mutable_shared_object() { .wallet .sign_transaction(&resolved.transaction.try_into().unwrap()); let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) + .execute_transaction(&Default::default(), &signed_transaction) .await .unwrap() .effects; @@ -417,10 +404,7 @@ async fn resolve_transaction_with_raw_json() { .wallet .sign_transaction(&resolved.transaction.try_into().unwrap()); let effects = client - .execute_transaction( - &ExecuteTransactionQueryParameters::default(), - &signed_transaction, - ) + .execute_transaction(&Default::default(), &signed_transaction) .await .unwrap() .effects; diff --git a/crates/sui-rpc-api/openapi/openapi.json b/crates/sui-rpc-api/openapi/openapi.json index 8e0a5322efb81..1b0056f50dad9 100644 --- a/crates/sui-rpc-api/openapi/openapi.json +++ b/crates/sui-rpc-api/openapi/openapi.json @@ -826,43 +826,49 @@ { "in": "query", "name": "balance_changes", - "description": "Request `BalanceChanges` be included in the Response.", + "description": "Request `BalanceChanges` be included in the Response.\n\nDefaults to `false` if not provided.", "schema": { - "description": "Request `BalanceChanges` be included in the Response.", - "default": false, + "description": "Request `BalanceChanges` be included in the Response.\n\nDefaults to `false` if not provided.", "type": "boolean" }, "style": "form" }, { "in": "query", - "name": "events", - "description": "Request `TransactionEvents` be included in the Response.", + "name": "effects", + "description": "Request `TransactionEffects` be included in the Response.\n\nDefaults to `true` if not provided.", "schema": { - "description": "Request `TransactionEvents` be included in the Response.", - "default": false, + "description": "Request `TransactionEffects` be included in the Response.\n\nDefaults to `true` if not provided.", "type": "boolean" }, "style": "form" }, { "in": "query", - "name": "input_objects", - "description": "Request input `Object`s be included in the Response.", + "name": "effects_bcs", + "description": "Request `TransactionEffects` encoded as BCS be included in the Response.\n\nDefaults to `false` if not provided.", "schema": { - "description": "Request input `Object`s be included in the Response.", - "default": false, + "description": "Request `TransactionEffects` encoded as BCS be included in the Response.\n\nDefaults to `false` if not provided.", "type": "boolean" }, "style": "form" }, { "in": "query", - "name": "output_objects", - "description": "Request output `Object`s be included in the Response.", + "name": "events", + "description": "Request `TransactionEvents` be included in the Response.\n\nDefaults to `true` if not provided.", "schema": { - "description": "Request output `Object`s be included in the Response.", - "default": false, + "description": "Request `TransactionEvents` be included in the Response.\n\nDefaults to `true` if not provided.", + "type": "boolean" + }, + "style": "form" + }, + { + "in": "query", + "name": "events_bcs", + "description": "Request `TransactionEvents` encoded as BCS be included in the Response.\n\nDefaults to `false` if not provided.", + "schema": { + "description": "Request `TransactionEvents` encoded as BCS be included in the Response.\n\nDefaults to `false` if not provided.", "type": "boolean" }, "style": "form" @@ -879,7 +885,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TransactionExecutionResponse" + "$ref": "#/components/schemas/ExecuteTransactionResponse" } } } @@ -2361,13 +2367,20 @@ "$ref": "#/components/schemas/Digest" }, "EffectsFinality": { - "anyOf": [ + "oneOf": [ { "type": "object", "required": [ + "finality", "signature" ], "properties": { + "finality": { + "type": "string", + "enum": [ + "certified" + ] + }, "signature": { "description": "Validator aggregated signature", "allOf": [ @@ -2381,18 +2394,36 @@ { "type": "object", "required": [ - "checkpoint" + "checkpoint", + "finality" ], "properties": { "checkpoint": { "description": "Radix-10 encoded 64-bit unsigned integer", "type": "string", "format": "u64" + }, + "finality": { + "type": "string", + "enum": [ + "checkpointed" + ] } } }, { - "type": "null" + "type": "object", + "required": [ + "finality" + ], + "properties": { + "finality": { + "type": "string", + "enum": [ + "quorum_executed" + ] + } + } } ] }, @@ -2630,6 +2661,36 @@ } } }, + "ExecuteTransactionResponse": { + "description": "Response type for the execute transaction endpoint", + "type": "object", + "required": [ + "finality" + ], + "properties": { + "balance_changes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BalanceChange" + } + }, + "effects": { + "$ref": "#/components/schemas/TransactionEffects" + }, + "effects_bcs": { + "type": "string" + }, + "events": { + "$ref": "#/components/schemas/TransactionEvents" + }, + "events_bcs": { + "type": "string" + }, + "finality": { + "$ref": "#/components/schemas/EffectsFinality" + } + } + }, "ExecutionError": { "oneOf": [ { @@ -5092,43 +5153,6 @@ "TransactionEventsDigest": { "$ref": "#/components/schemas/Digest" }, - "TransactionExecutionResponse": { - "description": "Response type for the execute transaction endpoint", - "type": "object", - "required": [ - "effects", - "finality" - ], - "properties": { - "balance_changes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BalanceChange" - } - }, - "effects": { - "$ref": "#/components/schemas/TransactionEffects" - }, - "events": { - "$ref": "#/components/schemas/TransactionEvents" - }, - "finality": { - "$ref": "#/components/schemas/EffectsFinality" - }, - "input_objects": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Object" - } - }, - "output_objects": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Object" - } - } - } - }, "TransactionExpiration": { "oneOf": [ { diff --git a/crates/sui-rpc-api/src/client/mod.rs b/crates/sui-rpc-api/src/client/mod.rs index c6b31d753bc32..3d9ac332708df 100644 --- a/crates/sui-rpc-api/src/client/mod.rs +++ b/crates/sui-rpc-api/src/client/mod.rs @@ -5,16 +5,15 @@ pub mod sdk; use sdk::Result; pub use reqwest; +use tap::Pipe; -use crate::rest::transactions::ExecuteTransactionQueryParameters; -use sui_types::base_types::{ObjectID, SequenceNumber, SuiAddress}; -use sui_types::crypto::AuthorityStrongQuorumSignInfo; +use crate::types::ExecuteTransactionOptions; +use sui_types::base_types::{ObjectID, SequenceNumber}; use sui_types::effects::{TransactionEffects, TransactionEvents}; use sui_types::full_checkpoint_content::CheckpointData; use sui_types::messages_checkpoint::{CertifiedCheckpointSummary, CheckpointSequenceNumber}; use sui_types::object::Object; use sui_types::transaction::Transaction; -use sui_types::TypeTag; use self::sdk::Response; @@ -96,7 +95,7 @@ impl Client { pub async fn execute_transaction( &self, - parameters: &ExecuteTransactionQueryParameters, + parameters: &ExecuteTransactionOptions, transaction: &Transaction, ) -> Result { let signed_transaction = sui_sdk_types::types::SignedTransaction { @@ -115,43 +114,44 @@ impl Client { .collect::>()?, }; - let response = self + let options = ExecuteTransactionOptions { + effects_bcs: Some(true), + events_bcs: Some(true), + ..(parameters.to_owned()) + }; + + let crate::types::ExecuteTransactionResponse { + finality, + effects: _, + effects_bcs, + events: _, + events_bcs, + balance_changes, + } = self .inner - .execute_transaction(parameters, &signed_transaction) + .execute_transaction(&options, &signed_transaction) .await? .into_inner(); - bcs::from_bytes(&bcs::to_bytes(&response)?).map_err(Into::into) + + TransactionExecutionResponse { + finality, + effects: bcs::from_bytes( + effects_bcs + .as_deref() + .ok_or_else(|| sdk::Error::from_error("missing effects"))?, + )?, + events: events_bcs.as_deref().map(bcs::from_bytes).transpose()?, + balance_changes, + } + .pipe(Ok) } } -#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[derive(Debug)] pub struct TransactionExecutionResponse { - pub effects: TransactionEffects, + pub finality: crate::types::EffectsFinality, - pub finality: EffectsFinality, + pub effects: TransactionEffects, pub events: Option, - pub balance_changes: Option>, - pub input_objects: Option>, - pub output_objects: Option>, -} - -#[derive(Debug, serde::Serialize, serde::Deserialize)] -pub enum EffectsFinality { - Certified { - signature: AuthorityStrongQuorumSignInfo, - }, - Checkpointed { - checkpoint: CheckpointSequenceNumber, - }, -} - -#[derive(PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)] -pub struct BalanceChange { - /// Owner of the balance change - pub address: SuiAddress, - /// Type of the Coin - pub coin_type: TypeTag, - /// The amount indicate the balance value changes, - /// negative amount means spending coin value and positive means receiving coin value. - pub amount: i128, + pub balance_changes: Option>, } diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index 2a7f042d06738..e231df5040698 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -36,9 +36,10 @@ use crate::rest::system::X_SUI_MIN_SUPPORTED_PROTOCOL_VERSION; use crate::rest::transactions::ListTransactionsCursorParameters; use crate::rest::transactions::ResolveTransactionQueryParameters; use crate::rest::transactions::ResolveTransactionResponse; -use crate::rest::transactions::TransactionExecutionResponse; use crate::rest::transactions::TransactionSimulationResponse; use crate::types::CheckpointResponse; +use crate::types::ExecuteTransactionOptions; +use crate::types::ExecuteTransactionResponse; use crate::types::NodeInfo; use crate::types::TransactionResponse; use crate::types::X_SUI_CHAIN; @@ -49,7 +50,6 @@ use crate::types::X_SUI_EPOCH; use crate::types::X_SUI_LOWEST_AVAILABLE_CHECKPOINT; use crate::types::X_SUI_LOWEST_AVAILABLE_CHECKPOINT_OBJECTS; use crate::types::X_SUI_TIMESTAMP_MS; -use crate::ExecuteTransactionQueryParameters; static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); @@ -307,9 +307,9 @@ impl Client { pub async fn execute_transaction( &self, - parameters: &ExecuteTransactionQueryParameters, + parameters: &ExecuteTransactionOptions, transaction: &SignedTransaction, - ) -> Result> { + ) -> Result> { let url = self.url().join("transactions")?; let body = bcs::to_bytes(transaction)?; @@ -578,7 +578,7 @@ impl Error { } } - fn from_error>(error: E) -> Self { + pub(super) fn from_error>(error: E) -> Self { Self::empty().with_error(error.into()) } diff --git a/crates/sui-rpc-api/src/lib.rs b/crates/sui-rpc-api/src/lib.rs index 350712d24fb86..281ad243dde7b 100644 --- a/crates/sui-rpc-api/src/lib.rs +++ b/crates/sui-rpc-api/src/lib.rs @@ -24,7 +24,6 @@ pub use client::Client; pub use config::Config; pub use error::{Result, RpcServiceError}; pub use metrics::RpcMetrics; -pub use rest::transactions::ExecuteTransactionQueryParameters; pub use sui_types::full_checkpoint_content::{CheckpointData, CheckpointTransaction}; pub use types::CheckpointResponse; pub use types::ObjectResponse; diff --git a/crates/sui-rpc-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs index fdb9b81f8d00f..539c2c6dab0ab 100644 --- a/crates/sui-rpc-api/src/proto/mod.rs +++ b/crates/sui-rpc-api/src/proto/mod.rs @@ -560,450 +560,6 @@ impl TryFrom<&I128> for i128 { } } -// -// BalanceChange -// - -impl From<&sui_sdk_types::types::BalanceChange> for BalanceChange { - fn from(value: &sui_sdk_types::types::BalanceChange) -> Self { - Self { - address: Some(Address::from(&value.address)), - coin_type: Some(TypeTag::from(&value.coin_type)), - amount: Some(I128::from(value.amount)), - } - } -} - -impl TryFrom<&BalanceChange> for sui_sdk_types::types::BalanceChange { - type Error = bcs::Error; - - fn try_from(value: &BalanceChange) -> Result { - let address = value - .address - .as_ref() - .ok_or_else(|| bcs::Error::Custom("missing address".into()))? - .try_into()?; - - let coin_type = value - .coin_type - .as_ref() - .ok_or_else(|| bcs::Error::Custom("missing coin_type".into()))? - .pipe(sui_sdk_types::types::TypeTag::try_from) - .map_err(|e| bcs::Error::Custom(e.to_string()))?; - - let amount = value - .amount - .as_ref() - .ok_or_else(|| bcs::Error::Custom("missing amount".into()))? - .pipe(i128::try_from) - .map_err(|e| bcs::Error::Custom(e.to_string()))?; - - Ok(Self { - address, - coin_type, - amount, - }) - } -} - -impl TryFrom<&BalanceChange> for crate::client::BalanceChange { - type Error = bcs::Error; - - fn try_from(value: &BalanceChange) -> Result { - let address = value - .address - .as_ref() - .ok_or_else(|| bcs::Error::Custom("missing address".into()))? - .try_into()?; - - let coin_type = value - .coin_type - .as_ref() - .ok_or_else(|| bcs::Error::Custom("missing coin_type".into()))? - .pipe(sui_types::TypeTag::try_from) - .map_err(|e| bcs::Error::Custom(e.to_string()))?; - - let amount = value - .amount - .as_ref() - .ok_or_else(|| bcs::Error::Custom("missing amount".into()))? - .pipe(i128::try_from) - .map_err(|e| bcs::Error::Custom(e.to_string()))?; - - Ok(Self { - address, - coin_type, - amount, - }) - } -} -// -// EffectsFinality -// - -impl TryFrom<&crate::rest::transactions::EffectsFinality> for EffectsFinality { - type Error = bcs::Error; - - fn try_from(value: &crate::rest::transactions::EffectsFinality) -> Result { - let (signature, checkpoint, quorum_executed) = match value { - crate::rest::transactions::EffectsFinality::Certified { signature } => { - (Some(signature.try_into()?), None, None) - } - crate::rest::transactions::EffectsFinality::Checkpointed { checkpoint } => { - (None, Some(*checkpoint), None) - } - crate::rest::transactions::EffectsFinality::QuorumExecuted => (None, None, Some(true)), - }; - - Ok(Self { - signature, - checkpoint, - quorum_executed, - }) - } -} - -impl TryFrom<&EffectsFinality> for crate::rest::transactions::EffectsFinality { - type Error = bcs::Error; - - fn try_from(value: &EffectsFinality) -> Result { - let signature = value - .signature - .as_ref() - .map(sui_sdk_types::types::ValidatorAggregatedSignature::try_from) - .transpose()?; - match (signature, value.checkpoint, value.quorum_executed) { - (Some(signature), None, None) => { - crate::rest::transactions::EffectsFinality::Certified { signature } - } - (None, Some(checkpoint), None) => { - crate::rest::transactions::EffectsFinality::Checkpointed { checkpoint } - } - (None, None, Some(true)) => crate::rest::transactions::EffectsFinality::QuorumExecuted, - _ => return Err(bcs::Error::Custom("invalid EffectsFinality message".into())), - } - .pipe(Ok) - } -} - -impl TryFrom<&EffectsFinality> for crate::client::EffectsFinality { - type Error = bcs::Error; - - fn try_from(value: &EffectsFinality) -> Result { - let signature = value - .signature - .as_ref() - .map(sui_types::crypto::AuthorityStrongQuorumSignInfo::try_from) - .transpose()?; - match (signature, value.checkpoint) { - (Some(signature), _) => crate::client::EffectsFinality::Certified { signature }, - (None, Some(checkpoint)) => crate::client::EffectsFinality::Checkpointed { checkpoint }, - (None, None) => { - return Err(bcs::Error::Custom( - "missing signature or checkpoint field".into(), - )) - } - } - .pipe(Ok) - } -} - -// -// TransactionExecutionResponse -// - -impl TryFrom - for TransactionExecutionResponse -{ - type Error = bcs::Error; - - fn try_from( - value: crate::rest::transactions::TransactionExecutionResponse, - ) -> Result { - Ok(Self { - effects: Some(TransactionEffects::try_from(&value.effects)?), - finality: Some(EffectsFinality::try_from(&value.finality)?), - events: value - .events - .as_ref() - .map(TransactionEvents::try_from) - .transpose()?, - balance_changes: value - .balance_changes - .iter() - .flat_map(|balance_changes| balance_changes.iter()) - .map(BalanceChange::from) - .collect(), - input_objects: value - .input_objects - .iter() - .flat_map(|objects| objects.iter()) - .map(Object::try_from) - .collect::>()?, - output_objects: value - .output_objects - .iter() - .flat_map(|objects| objects.iter()) - .map(Object::try_from) - .collect::>()?, - }) - } -} - -impl TryFrom - for crate::rest::transactions::TransactionExecutionResponse -{ - type Error = bcs::Error; - - fn try_from(value: TransactionExecutionResponse) -> Result { - Ok(Self { - effects: value - .effects - .ok_or_else(|| bcs::Error::Custom("missing Effects".into()))? - .pipe_ref(TryInto::try_into)?, - events: value.events.as_ref().map(TryInto::try_into).transpose()?, - input_objects: Some( - value - .input_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - output_objects: Some( - value - .output_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - finality: value - .finality - .ok_or_else(|| bcs::Error::Custom("missing finality".into()))? - .pipe_ref(TryInto::try_into)?, - balance_changes: Some( - value - .balance_changes - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - }) - } -} - -impl TryFrom for crate::client::TransactionExecutionResponse { - type Error = bcs::Error; - - fn try_from(value: TransactionExecutionResponse) -> Result { - Ok(Self { - effects: value - .effects - .ok_or_else(|| bcs::Error::Custom("missing Effects".into()))? - .pipe_ref(TryInto::try_into)?, - events: value.events.as_ref().map(TryInto::try_into).transpose()?, - input_objects: Some( - value - .input_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - output_objects: Some( - value - .output_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - finality: value - .finality - .ok_or_else(|| bcs::Error::Custom("missing finality".into()))? - .pipe_ref(TryInto::try_into)?, - balance_changes: Some( - value - .balance_changes - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - }) - } -} - -// -// TransactionSimulationResponse -// - -impl TryFrom - for TransactionSimulationResponse -{ - type Error = bcs::Error; - - fn try_from( - value: crate::rest::transactions::TransactionSimulationResponse, - ) -> Result { - Ok(Self { - effects: Some(TransactionEffects::try_from(&value.effects)?), - events: value - .events - .as_ref() - .map(TransactionEvents::try_from) - .transpose()?, - balance_changes: value - .balance_changes - .iter() - .flat_map(|balance_changes| balance_changes.iter()) - .map(BalanceChange::from) - .collect(), - input_objects: value - .input_objects - .iter() - .flat_map(|objects| objects.iter()) - .map(Object::try_from) - .collect::>()?, - output_objects: value - .output_objects - .iter() - .flat_map(|objects| objects.iter()) - .map(Object::try_from) - .collect::>()?, - }) - } -} - -impl TryFrom - for crate::rest::transactions::TransactionSimulationResponse -{ - type Error = bcs::Error; - - fn try_from(value: TransactionSimulationResponse) -> Result { - Ok(Self { - effects: value - .effects - .ok_or_else(|| bcs::Error::Custom("missing Effects".into()))? - .pipe_ref(TryInto::try_into)?, - events: value.events.as_ref().map(TryInto::try_into).transpose()?, - input_objects: Some( - value - .input_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - output_objects: Some( - value - .output_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - balance_changes: Some( - value - .balance_changes - .iter() - .map(TryInto::try_into) - .collect::>()?, - ), - }) - } -} - -// -// ResolveTransactionResponse -// - -impl TryFrom for ResolveTransactionResponse { - type Error = bcs::Error; - - fn try_from( - value: crate::rest::transactions::ResolveTransactionResponse, - ) -> Result { - Ok(Self { - transaction: Some(Transaction::try_from(&value.transaction)?), - simulation: value - .simulation - .map(TransactionSimulationResponse::try_from) - .transpose()?, - }) - } -} - -impl TryFrom for crate::rest::transactions::ResolveTransactionResponse { - type Error = bcs::Error; - - fn try_from(value: ResolveTransactionResponse) -> Result { - Ok(Self { - transaction: value - .transaction - .ok_or_else(|| bcs::Error::Custom("missing transaction".into()))? - .pipe_ref(TryInto::try_into)?, - simulation: value.simulation.map(TryInto::try_into).transpose()?, - }) - } -} - -// -// ExecuteTransactionRequest -// - -impl TryFrom for ExecuteTransactionRequest { - type Error = bcs::Error; - - fn try_from(value: sui_sdk_types::types::SignedTransaction) -> Result { - Ok(Self { - transaction: Some(Transaction::try_from(&value.transaction)?), - signatures: value - .signatures - .iter() - .map(UserSignature::try_from) - .collect::>()?, - }) - } -} - -impl TryFrom for sui_sdk_types::types::SignedTransaction { - type Error = bcs::Error; - - fn try_from(value: ExecuteTransactionRequest) -> Result { - Ok(Self { - transaction: value - .transaction - .ok_or_else(|| bcs::Error::Custom("missing transaction".into()))? - .pipe_ref(TryInto::try_into)?, - signatures: value - .signatures - .iter() - .map(TryInto::try_into) - .collect::>()?, - }) - } -} - -// -// SimulateTransactionRequest -// - -impl TryFrom for SimulateTransactionRequest { - type Error = bcs::Error; - - fn try_from(value: sui_sdk_types::types::Transaction) -> Result { - Ok(Self { - transaction: Some(Transaction::try_from(&value)?), - }) - } -} - -impl TryFrom for sui_sdk_types::types::Transaction { - type Error = bcs::Error; - - fn try_from(value: SimulateTransactionRequest) -> Result { - value - .transaction - .ok_or_else(|| bcs::Error::Custom("missing transaction".into()))? - .pipe_ref(TryInto::try_into) - } -} - // // ValidatorCommitteeMember // diff --git a/crates/sui-rpc-api/src/rest/transactions/execution.rs b/crates/sui-rpc-api/src/rest/transactions/execution.rs index 18a994c59913d..141126ee71e42 100644 --- a/crates/sui-rpc-api/src/rest/transactions/execution.rs +++ b/crates/sui-rpc-api/src/rest/transactions/execution.rs @@ -5,19 +5,16 @@ use crate::response::Bcs; use crate::rest::openapi::{ ApiEndpoint, OperationBuilder, RequestBodyBuilder, ResponseBuilder, RouteHandler, }; -use crate::{Result, RpcService, RpcServiceError}; +use crate::types::ExecuteTransactionOptions; +use crate::types::ExecuteTransactionResponse; +use crate::{Result, RpcService}; use axum::extract::{Query, State}; use axum::Json; use schemars::JsonSchema; use std::net::SocketAddr; -use std::sync::Arc; -use sui_sdk_types::types::framework::Coin; use sui_sdk_types::types::{ - Address, BalanceChange, CheckpointSequenceNumber, Object, Owner, SignedTransaction, - Transaction, TransactionEffects, TransactionEvents, ValidatorAggregatedSignature, + BalanceChange, Object, SignedTransaction, Transaction, TransactionEffects, TransactionEvents, }; -use sui_types::transaction_executor::{SimulateTransactionResult, TransactionExecutor}; -use tap::Pipe; pub struct ExecuteTransaction; @@ -37,12 +34,12 @@ impl ApiEndpoint for ExecuteTransaction { OperationBuilder::new() .tag("Transactions") .operation_id("ExecuteTransaction") - .query_parameters::(generator) + .query_parameters::(generator) .request_body(RequestBodyBuilder::new().bcs_content().build()) .response( 200, ResponseBuilder::new() - .json_content::(generator) + .json_content::(generator) .build(), ) .build() @@ -59,300 +56,15 @@ impl ApiEndpoint for ExecuteTransaction { /// an internal QuorumDriver which drives execution of the transaction with the current validator /// set. async fn execute_transaction( - State(state): State>>, - Query(parameters): Query, + State(state): State, + Query(options): Query, client_address: Option>, Bcs(transaction): Bcs, -) -> Result> { - let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; - let request = sui_types::quorum_driver_types::ExecuteTransactionRequestV3 { - transaction: transaction.try_into()?, - include_events: parameters.events, - include_input_objects: parameters.input_objects || parameters.balance_changes, - include_output_objects: parameters.output_objects || parameters.balance_changes, - include_auxiliary_data: false, - }; - - let sui_types::quorum_driver_types::ExecuteTransactionResponseV3 { - effects, - events, - input_objects, - output_objects, - auxiliary_data: _, - } = executor - .execute_transaction(request, client_address.map(|a| a.0)) - .await?; - - let (effects, finality) = { - let sui_types::quorum_driver_types::FinalizedEffects { - effects, - finality_info, - } = effects; - let finality = match finality_info { - sui_types::quorum_driver_types::EffectsFinalityInfo::Certified(sig) => { - EffectsFinality::Certified { - signature: sig.into(), - } - } - sui_types::quorum_driver_types::EffectsFinalityInfo::Checkpointed( - _epoch, - checkpoint, - ) => EffectsFinality::Checkpointed { checkpoint }, - sui_types::quorum_driver_types::EffectsFinalityInfo::QuorumExecuted(_) => { - EffectsFinality::QuorumExecuted - } - }; - - (effects.try_into()?, finality) - }; - - let events = if parameters.events { - events.map(TryInto::try_into).transpose()? - } else { - None - }; - - let input_objects = input_objects - .map(|objects| { - objects - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - }) - .transpose()?; - let output_objects = output_objects - .map(|objects| { - objects - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - }) - .transpose()?; - - let balance_changes = match (parameters.balance_changes, &input_objects, &output_objects) { - (true, Some(input_objects), Some(output_objects)) => Some(derive_balance_changes( - &effects, - input_objects, - output_objects, - )), - _ => None, - }; - - let input_objects = if parameters.input_objects { - input_objects - } else { - None - }; - - let output_objects = if parameters.output_objects { - output_objects - } else { - None - }; - - TransactionExecutionResponse { - effects, - finality, - events, - balance_changes, - input_objects, - output_objects, - } - .pipe(Json) - .pipe(Ok) -} - -/// Query parameters for the execute transaction endpoint -#[derive(Debug, Default, serde::Serialize, serde::Deserialize, JsonSchema)] -pub struct ExecuteTransactionQueryParameters { - // TODO once transaction finality support is more fully implemented up and down the stack, add - // back in this parameter, which will be mutally-exclusive with the other parameters. When - // `true` will submit the txn and return a `202 Accepted` response with no payload. - // effects: Option, - /// Request `TransactionEvents` be included in the Response. - #[serde(default)] - pub events: bool, - /// Request `BalanceChanges` be included in the Response. - #[serde(default)] - pub balance_changes: bool, - /// Request input `Object`s be included in the Response. - #[serde(default)] - pub input_objects: bool, - /// Request output `Object`s be included in the Response. - #[serde(default)] - pub output_objects: bool, -} - -/// Response type for the execute transaction endpoint -#[derive(Debug, serde::Serialize, serde::Deserialize, JsonSchema)] -pub struct TransactionExecutionResponse { - pub effects: TransactionEffects, - - pub finality: EffectsFinality, - pub events: Option, - pub balance_changes: Option>, - pub input_objects: Option>, - pub output_objects: Option>, -} - -#[derive(Clone, Debug)] -pub enum EffectsFinality { - Certified { - /// Validator aggregated signature - signature: ValidatorAggregatedSignature, - }, - Checkpointed { - checkpoint: CheckpointSequenceNumber, - }, - QuorumExecuted, -} - -impl serde::Serialize for EffectsFinality { - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - if serializer.is_human_readable() { - let readable = match self.clone() { - EffectsFinality::Certified { signature } => { - ReadableEffectsFinality::Certified { signature } - } - EffectsFinality::Checkpointed { checkpoint } => { - ReadableEffectsFinality::Checkpointed { checkpoint } - } - EffectsFinality::QuorumExecuted => ReadableEffectsFinality::QuorumExecuted, - }; - readable.serialize(serializer) - } else { - let binary = match self.clone() { - EffectsFinality::Certified { signature } => { - BinaryEffectsFinality::Certified { signature } - } - EffectsFinality::Checkpointed { checkpoint } => { - BinaryEffectsFinality::Checkpointed { checkpoint } - } - EffectsFinality::QuorumExecuted => BinaryEffectsFinality::QuorumExecuted, - }; - binary.serialize(serializer) - } - } -} - -impl<'de> serde::Deserialize<'de> for EffectsFinality { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - if deserializer.is_human_readable() { - ReadableEffectsFinality::deserialize(deserializer).map(|readable| match readable { - ReadableEffectsFinality::Certified { signature } => { - EffectsFinality::Certified { signature } - } - ReadableEffectsFinality::Checkpointed { checkpoint } => { - EffectsFinality::Checkpointed { checkpoint } - } - ReadableEffectsFinality::QuorumExecuted => EffectsFinality::QuorumExecuted, - }) - } else { - BinaryEffectsFinality::deserialize(deserializer).map(|binary| match binary { - BinaryEffectsFinality::Certified { signature } => { - EffectsFinality::Certified { signature } - } - BinaryEffectsFinality::Checkpointed { checkpoint } => { - EffectsFinality::Checkpointed { checkpoint } - } - BinaryEffectsFinality::QuorumExecuted => EffectsFinality::QuorumExecuted, - }) - } - } -} - -impl JsonSchema for EffectsFinality { - fn schema_name() -> String { - ReadableEffectsFinality::schema_name() - } - - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - ReadableEffectsFinality::json_schema(gen) - } -} - -#[serde_with::serde_as] -#[derive(serde::Serialize, serde::Deserialize, JsonSchema)] -#[serde(rename = "EffectsFinality", untagged)] -enum ReadableEffectsFinality { - Certified { - /// Validator aggregated signature - signature: ValidatorAggregatedSignature, - }, - Checkpointed { - #[serde_as(as = "sui_types::sui_serde::Readable, _>")] - #[schemars(with = "crate::rest::_schemars::U64")] - checkpoint: CheckpointSequenceNumber, - }, - QuorumExecuted, -} - -#[derive(serde::Serialize, serde::Deserialize)] -enum BinaryEffectsFinality { - Certified { - /// Validator aggregated signature - signature: ValidatorAggregatedSignature, - }, - Checkpointed { - checkpoint: CheckpointSequenceNumber, - }, - QuorumExecuted, -} - -fn coins(objects: &[Object]) -> impl Iterator)> + '_ { - objects.iter().filter_map(|object| { - let address = match object.owner() { - Owner::Address(address) => address, - Owner::Object(object_id) => object_id.as_address(), - Owner::Shared { .. } | Owner::Immutable => return None, - }; - let coin = Coin::try_from_object(object)?; - Some((address, coin)) - }) -} - -fn derive_balance_changes( - _effects: &TransactionEffects, - input_objects: &[Object], - output_objects: &[Object], -) -> Vec { - // 1. subtract all input coins - let balances = coins(input_objects).fold( - std::collections::BTreeMap::<_, i128>::new(), - |mut acc, (address, coin)| { - *acc.entry((address, coin.coin_type().to_owned())) - .or_default() -= coin.balance() as i128; - acc - }, - ); - - // 2. add all mutated coins - let balances = coins(output_objects).fold(balances, |mut acc, (address, coin)| { - *acc.entry((address, coin.coin_type().to_owned())) - .or_default() += coin.balance() as i128; - acc - }); - - balances - .into_iter() - .filter_map(|((address, coin_type), amount)| { - if amount == 0 { - return None; - } - - Some(BalanceChange { - address: *address, - coin_type, - amount, - }) - }) - .collect() +) -> Result> { + state + .execute_transaction(transaction, client_address.map(|a| a.0), &options) + .await + .map(Json) } pub struct SimulateTransaction; @@ -390,66 +102,14 @@ impl ApiEndpoint for SimulateTransaction { } async fn simulate_transaction( - State(state): State>>, + State(state): State, Query(parameters): Query, //TODO allow accepting JSON as well as BCS Bcs(transaction): Bcs, ) -> Result> { - let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; - - simulate_transaction_impl(&executor, ¶meters, transaction).map(Json) -} - -pub(super) fn simulate_transaction_impl( - executor: &Arc, - parameters: &SimulateTransactionQueryParameters, - transaction: Transaction, -) -> Result { - if transaction.gas_payment.objects.is_empty() { - return Err(RpcServiceError::new( - axum::http::StatusCode::BAD_REQUEST, - "no gas payment provided", - )); - } - - let SimulateTransactionResult { - input_objects, - output_objects, - events, - effects, - mock_gas_id, - } = executor - .simulate_transaction(transaction.try_into()?) - .map_err(anyhow::Error::from)?; - - if mock_gas_id.is_some() { - return Err(RpcServiceError::new( - axum::http::StatusCode::INTERNAL_SERVER_ERROR, - "simulate unexpectedly used a mock gas payment", - )); - } - - let events = events.map(TryInto::try_into).transpose()?; - let effects = effects.try_into()?; - - let input_objects = input_objects - .into_values() - .map(TryInto::try_into) - .collect::, _>>()?; - let output_objects = output_objects - .into_values() - .map(TryInto::try_into) - .collect::, _>>()?; - let balance_changes = derive_balance_changes(&effects, &input_objects, &output_objects); - - TransactionSimulationResponse { - events, - effects, - balance_changes: parameters.balance_changes.then_some(balance_changes), - input_objects: parameters.input_objects.then_some(input_objects), - output_objects: parameters.output_objects.then_some(output_objects), - } - .pipe(Ok) + state + .simulate_transaction(¶meters, transaction) + .map(Json) } /// Response type for the transaction simulation endpoint diff --git a/crates/sui-rpc-api/src/rest/transactions/mod.rs b/crates/sui-rpc-api/src/rest/transactions/mod.rs index 5073970acee43..1ae447ac4d08a 100644 --- a/crates/sui-rpc-api/src/rest/transactions/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/mod.rs @@ -3,12 +3,9 @@ mod execution; use axum::Json; -pub use execution::EffectsFinality; pub use execution::ExecuteTransaction; -pub use execution::ExecuteTransactionQueryParameters; pub use execution::SimulateTransaction; pub use execution::SimulateTransactionQueryParameters; -pub use execution::TransactionExecutionResponse; pub use execution::TransactionSimulationResponse; mod resolve; diff --git a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs index 26eba002356dd..631fb8196ef3a 100644 --- a/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs +++ b/crates/sui-rpc-api/src/rest/transactions/resolve/mod.rs @@ -165,12 +165,12 @@ async fn resolve_transaction( } let simulation = if parameters.simulate { - super::execution::simulate_transaction_impl( - executor, - ¶meters.simulate_transaction_parameters, - resolved_transaction.clone().try_into()?, - )? - .pipe(Some) + state + .simulate_transaction( + ¶meters.simulate_transaction_parameters, + resolved_transaction.clone().try_into()?, + )? + .pipe(Some) } else { None }; diff --git a/crates/sui-rpc-api/src/service/transactions/execution.rs b/crates/sui-rpc-api/src/service/transactions/execution.rs new file mode 100644 index 0000000000000..b0bc83c045de3 --- /dev/null +++ b/crates/sui-rpc-api/src/service/transactions/execution.rs @@ -0,0 +1,237 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::rest::transactions::SimulateTransactionQueryParameters; +use crate::rest::transactions::TransactionSimulationResponse; +use crate::types::EffectsFinality; +use crate::types::ExecuteTransactionOptions; +use crate::types::ExecuteTransactionResponse; +use crate::Result; +use crate::RpcService; +use crate::RpcServiceError; +use sui_sdk_types::types::framework::Coin; +use sui_sdk_types::types::Address; +use sui_sdk_types::types::BalanceChange; +use sui_sdk_types::types::Object; +use sui_sdk_types::types::Owner; +use sui_sdk_types::types::SignedTransaction; +use sui_sdk_types::types::Transaction; +use sui_sdk_types::types::TransactionEffects; +use sui_types::transaction_executor::SimulateTransactionResult; +use tap::Pipe; + +impl RpcService { + pub async fn execute_transaction( + &self, + signed_transaction: SignedTransaction, + client_address: Option, + options: &ExecuteTransactionOptions, + ) -> Result { + let executor = self + .executor + .as_ref() + .ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; + + let request = sui_types::quorum_driver_types::ExecuteTransactionRequestV3 { + transaction: signed_transaction.try_into()?, + include_events: options.include_events(), + include_input_objects: options.include_input_objects() + || options.include_balance_changes(), + include_output_objects: options.include_output_objects() + || options.include_balance_changes(), + include_auxiliary_data: false, + }; + + let sui_types::quorum_driver_types::ExecuteTransactionResponseV3 { + effects, + events, + input_objects, + output_objects, + auxiliary_data: _, + } = executor + .execute_transaction(request, client_address) + .await?; + + let (effects, finality) = { + let sui_types::quorum_driver_types::FinalizedEffects { + effects, + finality_info, + } = effects; + let finality = match finality_info { + sui_types::quorum_driver_types::EffectsFinalityInfo::Certified(sig) => { + EffectsFinality::Certified { + signature: sig.into(), + } + } + sui_types::quorum_driver_types::EffectsFinalityInfo::Checkpointed( + _epoch, + checkpoint, + ) => EffectsFinality::Checkpointed { checkpoint }, + sui_types::quorum_driver_types::EffectsFinalityInfo::QuorumExecuted(_) => { + EffectsFinality::QuorumExecuted + } + }; + + (effects.try_into()?, finality) + }; + + let effects_bcs = options + .include_effects_bcs() + .then(|| bcs::to_bytes(&effects)) + .transpose()?; + + let events = events.map(TryInto::try_into).transpose()?; + let events_bcs = options + .include_events_bcs() + .then(|| events.as_ref().map(bcs::to_bytes)) + .flatten() + .transpose()?; + + let input_objects = input_objects + .map(|objects| { + objects + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + }) + .transpose()?; + let output_objects = output_objects + .map(|objects| { + objects + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + }) + .transpose()?; + + let balance_changes = match ( + options.include_balance_changes(), + &input_objects, + &output_objects, + ) { + (true, Some(input_objects), Some(output_objects)) => Some(derive_balance_changes( + &effects, + input_objects, + output_objects, + )), + _ => None, + }; + + ExecuteTransactionResponse { + finality, + effects: options.include_effects().then_some(effects), + effects_bcs, + events: options.include_events().then_some(events).flatten(), + events_bcs, + balance_changes, + } + .pipe(Ok) + } + + pub fn simulate_transaction( + self, + parameters: &SimulateTransactionQueryParameters, + transaction: Transaction, + ) -> Result { + let executor = self + .executor + .as_ref() + .ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; + + if transaction.gas_payment.objects.is_empty() { + return Err(RpcServiceError::new( + axum::http::StatusCode::BAD_REQUEST, + "no gas payment provided", + )); + } + + let SimulateTransactionResult { + input_objects, + output_objects, + events, + effects, + mock_gas_id, + } = executor + .simulate_transaction(transaction.try_into()?) + .map_err(anyhow::Error::from)?; + + if mock_gas_id.is_some() { + return Err(RpcServiceError::new( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + "simulate unexpectedly used a mock gas payment", + )); + } + + let events = events.map(TryInto::try_into).transpose()?; + let effects = effects.try_into()?; + + let input_objects = input_objects + .into_values() + .map(TryInto::try_into) + .collect::, _>>()?; + let output_objects = output_objects + .into_values() + .map(TryInto::try_into) + .collect::, _>>()?; + let balance_changes = derive_balance_changes(&effects, &input_objects, &output_objects); + + TransactionSimulationResponse { + events, + effects, + balance_changes: parameters.balance_changes.then_some(balance_changes), + input_objects: parameters.input_objects.then_some(input_objects), + output_objects: parameters.output_objects.then_some(output_objects), + } + .pipe(Ok) + } +} + +fn coins(objects: &[Object]) -> impl Iterator)> + '_ { + objects.iter().filter_map(|object| { + let address = match object.owner() { + Owner::Address(address) => address, + Owner::Object(object_id) => object_id.as_address(), + Owner::Shared { .. } | Owner::Immutable => return None, + }; + let coin = Coin::try_from_object(object)?; + Some((address, coin)) + }) +} + +fn derive_balance_changes( + _effects: &TransactionEffects, + input_objects: &[Object], + output_objects: &[Object], +) -> Vec { + // 1. subtract all input coins + let balances = coins(input_objects).fold( + std::collections::BTreeMap::<_, i128>::new(), + |mut acc, (address, coin)| { + *acc.entry((address, coin.coin_type().to_owned())) + .or_default() -= coin.balance() as i128; + acc + }, + ); + + // 2. add all mutated coins + let balances = coins(output_objects).fold(balances, |mut acc, (address, coin)| { + *acc.entry((address, coin.coin_type().to_owned())) + .or_default() += coin.balance() as i128; + acc + }); + + balances + .into_iter() + .filter_map(|((address, coin_type), amount)| { + if amount == 0 { + return None; + } + + Some(BalanceChange { + address: *address, + coin_type, + amount, + }) + }) + .collect() +} diff --git a/crates/sui-rpc-api/src/service/transactions/mod.rs b/crates/sui-rpc-api/src/service/transactions/mod.rs index f3ba1f06128cc..130874b074720 100644 --- a/crates/sui-rpc-api/src/service/transactions/mod.rs +++ b/crates/sui-rpc-api/src/service/transactions/mod.rs @@ -8,6 +8,8 @@ use crate::RpcService; use sui_sdk_types::types::TransactionDigest; use tap::Pipe; +mod execution; + impl RpcService { pub fn get_transaction( &self, diff --git a/crates/sui-rpc-api/src/types.rs b/crates/sui-rpc-api/src/types.rs index 87f69da3ba43f..cfaa8604b5c3b 100644 --- a/crates/sui-rpc-api/src/types.rs +++ b/crates/sui-rpc-api/src/types.rs @@ -321,3 +321,124 @@ impl GetTransactionOptions { self.events_bcs.unwrap_or(false) } } + +/// Options for the execute transaction endpoint +#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct ExecuteTransactionOptions { + /// Request `TransactionEffects` be included in the Response. + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub effects: Option, + + /// Request `TransactionEffects` encoded as BCS be included in the Response. + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub effects_bcs: Option, + + /// Request `TransactionEvents` be included in the Response. + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub events: Option, + + /// Request `TransactionEvents` encoded as BCS be included in the Response. + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub events_bcs: Option, + + /// Request `BalanceChanges` be included in the Response. + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub balance_changes: Option, + // TODO determine if we want to provide the same level of options for Objects here as we do in + // the get_object apis + // /// Request input `Object`s be included in the Response. + // /// + // /// Defaults to `false` if not provided. + // #[serde(skip_serializing_if = "Option::is_none")] + // pub input_objects: Option, + + // /// Request output `Object`s be included in the Response. + // /// + // /// Defaults to `false` if not provided. + // #[serde(skip_serializing_if = "Option::is_none")] + // pub output_objects: Option, +} + +impl ExecuteTransactionOptions { + pub fn include_effects(&self) -> bool { + self.effects.unwrap_or(true) + } + + pub fn include_effects_bcs(&self) -> bool { + self.effects_bcs.unwrap_or(false) + } + + pub fn include_events(&self) -> bool { + self.events.unwrap_or(true) + } + + pub fn include_events_bcs(&self) -> bool { + self.events_bcs.unwrap_or(false) + } + + pub fn include_balance_changes(&self) -> bool { + self.balance_changes.unwrap_or(false) + } + + pub fn include_input_objects(&self) -> bool { + false + } + + pub fn include_output_objects(&self) -> bool { + false + } +} + +/// Response type for the execute transaction endpoint +#[serde_with::serde_as] +#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct ExecuteTransactionResponse { + pub finality: EffectsFinality, + + #[serde(skip_serializing_if = "Option::is_none")] + pub effects: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub effects_bcs: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub events: Option, + + #[serde_as(as = "Option")] + #[schemars(with = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub events_bcs: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub balance_changes: Option>, + // pub input_objects: Option>, + // pub output_objects: Option>, +} + +#[serde_with::serde_as] +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +#[serde(tag = "finality", rename_all = "snake_case")] +pub enum EffectsFinality { + Certified { + /// Validator aggregated signature + signature: sui_sdk_types::types::ValidatorAggregatedSignature, + }, + Checkpointed { + #[serde_as(as = "sui_types::sui_serde::Readable, _>")] + #[schemars(with = "crate::rest::_schemars::U64")] + checkpoint: sui_sdk_types::types::CheckpointSequenceNumber, + }, + QuorumExecuted, +} From 583629e03b61a11d2b60e58d650c86fbbb3a8b3a Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Sun, 1 Dec 2024 15:25:37 -0600 Subject: [PATCH 24/28] rpc: introduce a get_full_checkpoint method on RpcService --- crates/sui-rpc-api/src/service/checkpoints.rs | 185 ++++++++++++++++ crates/sui-rpc-api/src/types.rs | 207 ++++++++++++++++++ 2 files changed, 392 insertions(+) diff --git a/crates/sui-rpc-api/src/service/checkpoints.rs b/crates/sui-rpc-api/src/service/checkpoints.rs index 17f88d29c0ff2..219a9c7133323 100644 --- a/crates/sui-rpc-api/src/service/checkpoints.rs +++ b/crates/sui-rpc-api/src/service/checkpoints.rs @@ -2,7 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::types::CheckpointResponse; +use crate::types::FullCheckpointObject; +use crate::types::FullCheckpointResponse; +use crate::types::FullCheckpointTransaction; use crate::types::GetCheckpointOptions; +use crate::types::GetFullCheckpointOptions; use crate::Result; use crate::RpcService; use sui_sdk_types::types::CheckpointContents; @@ -82,6 +86,187 @@ impl RpcService { } .pipe(Ok) } + + pub fn get_full_checkpoint( + &self, + checkpoint: CheckpointId, + options: &GetFullCheckpointOptions, + ) -> Result { + let verified_summary = match checkpoint { + CheckpointId::SequenceNumber(s) => { + let oldest_checkpoint = self + .reader + .inner() + .get_lowest_available_checkpoint_objects()?; + if s < oldest_checkpoint { + return Err(crate::RpcServiceError::new( + axum::http::StatusCode::GONE, + "Old checkpoints have been pruned", + )); + } + + self.reader + .inner() + .get_checkpoint_by_sequence_number(s) + .ok_or(CheckpointNotFoundError(checkpoint))? + } + CheckpointId::Digest(d) => self + .reader + .inner() + .get_checkpoint_by_digest(&d.into()) + .ok_or(CheckpointNotFoundError(checkpoint))?, + }; + + let checkpoint_contents = self + .reader + .inner() + .get_checkpoint_contents_by_digest(&verified_summary.content_digest) + .ok_or(CheckpointNotFoundError(checkpoint))?; + + let sui_types::full_checkpoint_content::CheckpointData { + checkpoint_summary, + checkpoint_contents, + transactions, + } = self + .reader + .inner() + .get_checkpoint_data(verified_summary, checkpoint_contents)?; + + let sequence_number = checkpoint_summary.sequence_number; + let digest = checkpoint_summary.digest().to_owned().into(); + let (summary, signature) = checkpoint_summary.into_data_and_sig(); + + let summary_bcs = options + .include_summary_bcs() + .then(|| bcs::to_bytes(&summary)) + .transpose()?; + let contents_bcs = options + .include_contents_bcs() + .then(|| bcs::to_bytes(&checkpoint_contents)) + .transpose()?; + + let transactions = transactions + .into_iter() + .map(|transaction| transaction_to_checkpoint_transaction(transaction, options)) + .collect::>()?; + + FullCheckpointResponse { + sequence_number, + digest, + summary: options + .include_summary() + .then(|| summary.try_into()) + .transpose()?, + summary_bcs, + signature: options.include_signature().then(|| signature.into()), + contents: options + .include_contents() + .then(|| checkpoint_contents.try_into()) + .transpose()?, + contents_bcs, + transactions, + } + .pipe(Ok) + } +} + +fn transaction_to_checkpoint_transaction( + sui_types::full_checkpoint_content::CheckpointTransaction { + transaction, + effects, + events, + input_objects, + output_objects, + }: sui_types::full_checkpoint_content::CheckpointTransaction, + options: &GetFullCheckpointOptions, +) -> Result { + let digest = transaction.digest().to_owned().into(); + let transaction = transaction.into_data().into_inner().intent_message.value; + let transaction_bcs = options + .include_transaction_bcs() + .then(|| bcs::to_bytes(&transaction)) + .transpose()?; + let transaction = options + .include_transaction() + .then(|| transaction.try_into()) + .transpose()?; + let effects_bcs = options + .include_effects_bcs() + .then(|| bcs::to_bytes(&effects)) + .transpose()?; + let effects = options + .include_effects() + .then(|| effects.try_into()) + .transpose()?; + let events_bcs = options + .include_events_bcs() + .then(|| events.as_ref().map(bcs::to_bytes)) + .flatten() + .transpose()?; + let events = options + .include_events() + .then(|| events.map(TryInto::try_into)) + .flatten() + .transpose()?; + + let input_objects = options + .include_input_objects() + .then(|| { + input_objects + .into_iter() + .map(|object| object_to_object_response(object, options)) + .collect::>() + }) + .transpose()?; + let output_objects = options + .include_output_objects() + .then(|| { + output_objects + .into_iter() + .map(|object| object_to_object_response(object, options)) + .collect::>() + }) + .transpose()?; + + FullCheckpointTransaction { + digest, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + } + .pipe(Ok) +} + +fn object_to_object_response( + object: sui_types::object::Object, + options: &GetFullCheckpointOptions, +) -> Result { + let object_id = object.id().into(); + let version = object.version().value(); + let digest = object.digest().into(); + + let object_bcs = options + .include_object_bcs() + .then(|| bcs::to_bytes(&object)) + .transpose()?; + let object = options + .include_object() + .then(|| object.try_into()) + .transpose()?; + + FullCheckpointObject { + object_id, + version, + digest, + object, + object_bcs, + } + .pipe(Ok) } #[derive(Debug, Copy, Clone, Eq, PartialEq, schemars::JsonSchema)] diff --git a/crates/sui-rpc-api/src/types.rs b/crates/sui-rpc-api/src/types.rs index cfaa8604b5c3b..f7c1345750d5b 100644 --- a/crates/sui-rpc-api/src/types.rs +++ b/crates/sui-rpc-api/src/types.rs @@ -442,3 +442,210 @@ pub enum EffectsFinality { }, QuorumExecuted, } + +#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct GetFullCheckpointOptions { + /// Request `CheckpointSummary` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, + + /// Request `CheckpointSummary` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub summary_bcs: Option, + + /// Request `ValidatorAggregatedSignature` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub signature: Option, + + /// Request `CheckpointContents` be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub contents: Option, + + /// Request `CheckpointContents` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub contents_bcs: Option, + + /// Request `Transaction` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub transaction: Option, + + /// Request `Transaction` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub transaction_bcs: Option, + + /// Request `TransactionEffects` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub effects: Option, + + /// Request `TransactionEffects` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub effects_bcs: Option, + + /// Request `TransactionEvents` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub events: Option, + + /// Request `TransactionEvents` encoded as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub events_bcs: Option, + + /// Request that input objects be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub input_objects: Option, + + /// Request that output objects be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub output_objects: Option, + + /// Request that `Object` be included in the response + /// + /// Defaults to `true` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub object: Option, + + /// Request that `Object` formated as BCS be included in the response + /// + /// Defaults to `false` if not provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub object_bcs: Option, +} + +impl GetFullCheckpointOptions { + pub fn include_summary(&self) -> bool { + self.summary.unwrap_or(true) + } + + pub fn include_summary_bcs(&self) -> bool { + self.summary_bcs.unwrap_or(false) + } + + pub fn include_signature(&self) -> bool { + self.signature.unwrap_or(true) + } + + pub fn include_contents(&self) -> bool { + self.contents.unwrap_or(false) + } + + pub fn include_contents_bcs(&self) -> bool { + self.contents_bcs.unwrap_or(false) + } + + pub fn include_transaction(&self) -> bool { + self.transaction.unwrap_or(true) + } + + pub fn include_transaction_bcs(&self) -> bool { + self.transaction_bcs.unwrap_or(false) + } + + pub fn include_effects(&self) -> bool { + self.effects.unwrap_or(true) + } + + pub fn include_effects_bcs(&self) -> bool { + self.effects_bcs.unwrap_or(false) + } + + pub fn include_events(&self) -> bool { + self.events.unwrap_or(true) + } + + pub fn include_events_bcs(&self) -> bool { + self.events_bcs.unwrap_or(false) + } + + pub fn include_input_objects(&self) -> bool { + self.input_objects.unwrap_or(true) + } + + pub fn include_output_objects(&self) -> bool { + self.output_objects.unwrap_or(true) + } + + pub fn include_object(&self) -> bool { + self.object.unwrap_or(true) + } + + pub fn include_object_bcs(&self) -> bool { + self.object_bcs.unwrap_or(false) + } + + pub fn include_any_transaction_info(&self) -> bool { + self.include_transaction() + || self.include_transaction_bcs() + || self.include_effects() + || self.include_effects_bcs() + || self.include_events() + || self.include_events_bcs() + || self.include_input_objects() + || self.include_output_objects() + } +} + +#[derive(Clone, Debug, PartialEq)] +pub struct FullCheckpointResponse { + pub sequence_number: sui_sdk_types::types::CheckpointSequenceNumber, + pub digest: sui_sdk_types::types::CheckpointDigest, + + pub summary: Option, + pub summary_bcs: Option>, + pub signature: Option, + pub contents: Option, + pub contents_bcs: Option>, + + pub transactions: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct FullCheckpointTransaction { + pub digest: sui_sdk_types::types::TransactionDigest, + + pub transaction: Option, + pub transaction_bcs: Option>, + + pub effects: Option, + pub effects_bcs: Option>, + + pub events: Option, + pub events_bcs: Option>, + + pub input_objects: Option>, + pub output_objects: Option>, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct FullCheckpointObject { + pub object_id: sui_sdk_types::types::ObjectId, + pub version: sui_sdk_types::types::Version, + pub digest: sui_sdk_types::types::ObjectDigest, + + pub object: Option, + pub object_bcs: Option>, +} From 52405543aa7f874b80c32f1b4a517486b679b623 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Sun, 1 Dec 2024 21:05:29 -0600 Subject: [PATCH 25/28] rpc: introduce new protobuf definitions Introduces a new set of more fleshed out protobuf definitions for both core types (and conversions to/from sui-sdk-types and the protobuf types) as well as rpc request and response types. --- Cargo.lock | 10 +- crates/sui-rpc-api/Cargo.toml | 9 +- .../proto/google/protobuf/empty.proto | 51 + .../proto/google/protobuf/timestamp.proto | 133 ++ crates/sui-rpc-api/proto/rest.proto | 157 -- crates/sui-rpc-api/proto/sui.node.v2.proto | 352 ++++ crates/sui-rpc-api/proto/sui.types.proto | 1038 +++++++++++ .../src/proto/generated/sui.node.v2.rs | 1178 +++++++++++++ .../src/proto/generated/sui.types.rs | 1553 +++++++++++++++++ crates/sui-rpc-api/src/proto/mod.rs | 622 +------ crates/sui-rpc-api/src/proto/node.rs | 966 ++++++++++ .../sui-rpc-api/src/proto/types/checkpoint.rs | 320 ++++ crates/sui-rpc-api/src/proto/types/effects.rs | 634 +++++++ crates/sui-rpc-api/src/proto/types/events.rs | 87 + .../src/proto/types/execution_status.rs | 520 ++++++ crates/sui-rpc-api/src/proto/types/mod.rs | 241 +++ .../sui-rpc-api/src/proto/types/move_types.rs | 132 ++ crates/sui-rpc-api/src/proto/types/object.rs | 422 +++++ .../sui-rpc-api/src/proto/types/signatures.rs | 883 ++++++++++ .../src/proto/types/transaction_convert.rs | 1388 +++++++++++++++ crates/sui-rpc-api/tests/bootstrap.rs | 11 +- 21 files changed, 9956 insertions(+), 751 deletions(-) create mode 100644 crates/sui-rpc-api/proto/google/protobuf/empty.proto create mode 100644 crates/sui-rpc-api/proto/google/protobuf/timestamp.proto delete mode 100644 crates/sui-rpc-api/proto/rest.proto create mode 100644 crates/sui-rpc-api/proto/sui.node.v2.proto create mode 100644 crates/sui-rpc-api/proto/sui.types.proto create mode 100644 crates/sui-rpc-api/src/proto/generated/sui.node.v2.rs create mode 100644 crates/sui-rpc-api/src/proto/generated/sui.types.rs create mode 100644 crates/sui-rpc-api/src/proto/node.rs create mode 100644 crates/sui-rpc-api/src/proto/types/checkpoint.rs create mode 100644 crates/sui-rpc-api/src/proto/types/effects.rs create mode 100644 crates/sui-rpc-api/src/proto/types/events.rs create mode 100644 crates/sui-rpc-api/src/proto/types/execution_status.rs create mode 100644 crates/sui-rpc-api/src/proto/types/mod.rs create mode 100644 crates/sui-rpc-api/src/proto/types/move_types.rs create mode 100644 crates/sui-rpc-api/src/proto/types/object.rs create mode 100644 crates/sui-rpc-api/src/proto/types/signatures.rs create mode 100644 crates/sui-rpc-api/src/proto/types/transaction_convert.rs diff --git a/Cargo.lock b/Cargo.lock index 932538e97ddbe..3b22e064b3e6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15193,6 +15193,7 @@ dependencies = [ "async-trait", "axum 0.7.5", "bcs", + "bytes", "diffy", "documented", "fastcrypto", @@ -15205,8 +15206,10 @@ dependencies = [ "prometheus", "prost 0.13.3", "prost-build", + "prost-types 0.13.3", "rand 0.8.5", "reqwest 0.12.5", + "roaring", "schemars", "serde", "serde_json", @@ -15218,6 +15221,8 @@ dependencies = [ "tap", "thiserror", "tokio", + "tonic 0.12.3", + "tonic-build", "url", ] @@ -16967,13 +16972,14 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568392c5a2bd0020723e3f387891176aabafe36fd9fcd074ad309dfa0c8eb964" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ "prettyplease", "proc-macro2 1.0.87", "prost-build", + "prost-types 0.13.3", "quote 1.0.35", "syn 2.0.79", ] diff --git a/crates/sui-rpc-api/Cargo.toml b/crates/sui-rpc-api/Cargo.toml index 19a15bc05a5bc..24863b48ec454 100644 --- a/crates/sui-rpc-api/Cargo.toml +++ b/crates/sui-rpc-api/Cargo.toml @@ -27,7 +27,6 @@ prometheus.workspace = true openapiv3 = { git = "https://github.com/bmwill/openapiv3.git", rev = "ca4b4845b7c159a39f5c68ad8f7f76cb6f4d6963" } schemars.workspace = true documented = "0.6.0" -prost.workspace = true fastcrypto.workspace = true sui-types.workspace = true @@ -36,6 +35,14 @@ sui-protocol-config.workspace = true move-binary-format.workspace = true move-core-types.workspace = true +# dependencies for the protobuf definitions +roaring.workspace = true +tonic.workspace = true +prost.workspace = true +prost-types = "0.13.3" +bytes.workspace = true + [dev-dependencies] diffy = "0.3" prost-build = "0.13.3" +tonic-build = "0.12.3" diff --git a/crates/sui-rpc-api/proto/google/protobuf/empty.proto b/crates/sui-rpc-api/proto/google/protobuf/empty.proto new file mode 100644 index 0000000000000..b87c89dcfce9e --- /dev/null +++ b/crates/sui-rpc-api/proto/google/protobuf/empty.proto @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/known/emptypb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "EmptyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +message Empty {} diff --git a/crates/sui-rpc-api/proto/google/protobuf/timestamp.proto b/crates/sui-rpc-api/proto/google/protobuf/timestamp.proto new file mode 100644 index 0000000000000..06750ab1f127d --- /dev/null +++ b/crates/sui-rpc-api/proto/google/protobuf/timestamp.proto @@ -0,0 +1,133 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TimestampProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required, though only UTC (as indicated by "Z") is presently supported. +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) +// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one +// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--) +// to obtain a formatter capable of generating timestamps in this format. +// +// +message Timestamp { + + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} diff --git a/crates/sui-rpc-api/proto/rest.proto b/crates/sui-rpc-api/proto/rest.proto deleted file mode 100644 index b94e5b73d2637..0000000000000 --- a/crates/sui-rpc-api/proto/rest.proto +++ /dev/null @@ -1,157 +0,0 @@ -syntax = "proto3"; - -package sui.rest; - -// Sui `TransactionData` type serialized as Bcs -message Transaction { - bytes transaction = 1; -} - -// Sui `TransactionEffects` type serialized as Bcs -message TransactionEffects { - bytes effects = 1; -} - -// Sui `TransactionEvents` type serialized as Bcs -message TransactionEvents { - bytes events = 1; -} - -// Sui `Object` type serialized as Bcs -message Object { - bytes object = 1; -} - -// Sui `CheckpointSummary` type serialized as Bcs -message CheckpointSummary { - bytes summary = 1; -} - -// Sui `CheckpointContents` type serialized as Bcs -message CheckpointContents { - bytes contents = 1; -} - -// Sui `UserSignature` type serialized as bytes -message UserSignature { - bytes signature = 1; -} - -// Sui `ValidatorAggregatedSignature` type serialized as Bcs -message ValidatorAggregatedSignature { - bytes signature = 1; -} - -message GetTransactionResponse { - // The digest of this transaction - bytes digest = 1; - optional Transaction transaction = 2; - repeated UserSignature signatures = 3; - optional TransactionEffects effects = 4; - optional TransactionEvents events = 5; - optional uint64 checkpoint = 6; - optional uint64 timestamp_ms = 7; -} - -message GetObjectResponse { - // The digest of this object - bytes digest = 1; - optional Object object = 2; -} - -message GetCheckpointResponse { - // The digest of this CheckpointSummary - bytes digest = 1; - optional CheckpointSummary summary = 2; - optional ValidatorAggregatedSignature signature = 3; - optional CheckpointContents contents = 4; -} - -message FullCheckpoint { - optional CheckpointSummary summary = 1; - optional ValidatorAggregatedSignature signature = 2; - optional CheckpointContents contents = 3; - repeated CheckpointTransaction transactions = 4; -} - -message CheckpointTransaction { - optional Transaction transaction = 1; - repeated UserSignature signatures = 2; - optional TransactionEffects effects = 3; - optional TransactionEvents events = 4; - repeated Object input_objects = 5; - repeated Object output_objects = 6; -} - -message ListCheckpointResponse { - repeated GetCheckpointResponse checkpoints = 1; -} - -message ListTransactionsResponse { - repeated GetTransactionResponse transactions = 1; -} - -message Address { - bytes address = 1; -} - -message TypeTag { - string type_tag = 1; -} - -message I128 { - bytes little_endian_bytes = 1; -} - -message BalanceChange { - Address address = 1; - TypeTag coin_type = 2; - I128 amount = 3; -} - -message EffectsFinality { - optional ValidatorAggregatedSignature signature = 1; - optional uint64 checkpoint = 2; - optional bool quorum_executed = 3; -} - -message TransactionExecutionResponse { - optional TransactionEffects effects = 1; - optional EffectsFinality finality = 2; - optional TransactionEvents events = 3; - repeated BalanceChange balance_changes = 4; - repeated Object input_objects = 5; - repeated Object output_objects = 6; -} - -message TransactionSimulationResponse { - optional TransactionEffects effects = 1; - optional TransactionEvents events = 2; - repeated BalanceChange balance_changes = 3; - repeated Object input_objects = 4; - repeated Object output_objects = 5; -} - -message ResolveTransactionResponse { - optional Transaction transaction = 1; - optional TransactionSimulationResponse simulation = 2; -} - -message ExecuteTransactionRequest { - optional Transaction transaction = 1; - repeated UserSignature signatures = 2; -} - -message SimulateTransactionRequest { - optional Transaction transaction = 1; -} - -message ValidatorCommittee { - uint64 epoch = 1; - repeated ValidatorCommitteeMember members = 2; -} - -message ValidatorCommitteeMember { - bytes public_key = 1; - uint64 stake = 2; -} diff --git a/crates/sui-rpc-api/proto/sui.node.v2.proto b/crates/sui-rpc-api/proto/sui.node.v2.proto new file mode 100644 index 0000000000000..8cf251479a2e9 --- /dev/null +++ b/crates/sui-rpc-api/proto/sui.node.v2.proto @@ -0,0 +1,352 @@ +syntax = "proto3"; + +package sui.node.v2; + +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +import "sui.types.proto"; + +// +// Rpc Node interface +// + +service Node { + rpc GetNodeInfo(google.protobuf.Empty) returns (GetNodeInfoResponse); + rpc GetCommittee(GetCommitteeRequest) returns (GetCommitteeResponse); + + rpc GetObject(GetObjectRequest) returns (GetObjectResponse); + rpc GetTransaction(GetTransactionRequest) returns (GetTransactionResponse); + rpc GetCheckpoint(GetCheckpointRequest) returns (GetCheckpointResponse); + rpc GetFullCheckpoint(GetFullCheckpointRequest) returns (GetFullCheckpointResponse); + + rpc ExecuteTransaction(ExecuteTransactionRequest) returns (ExecuteTransactionResponse); +} + +message GetNodeInfoResponse { + // The chain identifier of the chain that this Node is on + optional sui.types.Digest chain_id = 1; + + // Human readable name of the chain that this Node is on + optional string chain = 2; + + // Current epoch of the Node based on its highest executed checkpoint + optional uint64 epoch = 3; + + // Checkpoint height of the most recently executed checkpoint + optional uint64 checkpoint_height = 4; + + // Unix timestamp of the most recently executed checkpoint + optional google.protobuf.Timestamp timestamp = 5; + + // The lowest checkpoint for which checkpoints and transaction data is available + optional uint64 lowest_available_checkpoint = 6; + + // The lowest checkpoint for which object data is available + optional uint64 lowest_available_checkpoint_objects = 7; + + optional string software_version = 8; +} + +message GetCommitteeRequest { + optional uint64 epoch = 1; +} + +message GetCommitteeResponse { + optional sui.types.ValidatorCommittee committee = 1; +} + +message GetTransactionRequest { + optional sui.types.Digest digest = 1; + + optional GetTransactionOptions options = 3; +} + +message GetTransactionOptions { + // Include the sui.types.Transaction message in the response. + // + // Defaults to true if not included + optional bool transaction = 1; + // Include the Transaction formatted as BCS in the response. + // + // Defaults to false if not included + optional bool transaction_bcs = 2; + // Include the set of sui.types.UserSignature's in the response. + // + // Defaults to true if not included + optional bool signatures = 3; + // Include the sui.types.TransactionEffects message in the response. + // + // Defaults to true if not included + optional bool effects = 4; + // Include the TransactionEffects formatted as BCS in the response. + // + // Defaults to false if not included + optional bool effects_bcs = 5; + // Include the sui.types.TransactionEvents message in the response. + // + // Defaults to true if not included + optional bool events = 6; + // Include the TransactionEvents formatted as BCS in the response. + // + // Defaults to false if not included + optional bool events_bcs = 7; +} + +message GetTransactionResponse { + // The digest of this transaction + optional sui.types.Digest digest = 1; + optional sui.types.Transaction transaction = 2; + optional sui.types.Bcs transaction_bcs = 3; + optional UserSignatures signatures = 4; + optional sui.types.TransactionEffects effects = 5; + optional sui.types.Bcs effects_bcs = 6; + optional sui.types.TransactionEvents events = 7; + optional sui.types.Bcs events_bcs = 8; + optional uint64 checkpoint = 9; + optional google.protobuf.Timestamp timestamp = 10; +} + +message UserSignatures { + repeated sui.types.UserSignature signatures = 1; +} + +message GetObjectRequest { + optional sui.types.ObjectId object_id = 1; + optional uint64 version = 2; + + optional GetObjectOptions options = 3; +} + +message GetObjectOptions { + // Include the sui.types.Object message in the response. + // + // Defaults to true if not included + optional bool object = 1; + // Include the Object formatted as BCS in the response. + // + // Defaults to false if not included + optional bool object_bcs = 2; +} + +message GetObjectResponse { + optional sui.types.ObjectId object_id = 1; + optional uint64 version = 2; + // The digest of this object + optional sui.types.Digest digest = 3; + + optional sui.types.Object object = 4; + optional sui.types.Bcs object_bcs = 5; +} + +message GetCheckpointRequest { + optional uint64 sequence_number = 1; + optional sui.types.Digest digest = 2; + + optional GetCheckpointOptions options = 3; +} + +message GetCheckpointOptions { + // Include the sui.types.CheckpointSummary in the response. + // + // Defaults to true if not included + optional bool summary = 3; + // Include the CheckpointSummary formatted as BCS in the response. + // + // Defaults to false if not included + optional bool summary_bcs = 4; + // Include the sui.types.ValidatorAggregatedSignature in the response. + // + // Defaults to true if not included + optional bool signature = 5; + // Include the sui.types.CheckpointContents message in the response. + // + // Defaults to false if not included + optional bool contents = 6; + // Include the CheckpointContents formatted as BCS in the response. + // + // Defaults to false if not included + optional bool contents_bcs = 7; +} + +message GetCheckpointResponse { + // The sequence number of this Checkpoint + optional uint64 sequence_number = 1; + // The digest of this Checkpoint's CheckpointSummary + optional sui.types.Digest digest = 2; + + optional sui.types.CheckpointSummary summary = 3; + optional sui.types.Bcs summary_bcs = 4; + optional sui.types.ValidatorAggregatedSignature signature = 5; + optional sui.types.CheckpointContents contents = 6; + optional sui.types.Bcs contents_bcs = 7; +} + +message GetFullCheckpointRequest { + optional uint64 sequence_number = 1; + optional sui.types.Digest digest = 2; + + optional GetFullCheckpointOptions options = 3; +} + +message GetFullCheckpointOptions { + // Include the sui.types.CheckpointSummary in the response. + // + // Defaults to true if not included + optional bool summary = 3; + // Include the CheckpointSummary formatted as BCS in the response. + // + // Defaults to false if not included + optional bool summary_bcs = 4; + // Include the sui.types.ValidatorAggregatedSignature in the response. + // + // Defaults to true if not included + optional bool signature = 5; + // Include the sui.types.CheckpointContents message in the response. + // + // Defaults to false if not included + optional bool contents = 6; + // Include the CheckpointContents formatted as BCS in the response. + // + // Defaults to false if not included + optional bool contents_bcs = 7; + + // Include the sui.types.Transaction message in the response. + // + // Defaults to true if not included + optional bool transaction = 8; + // Include the Transaction formatted as BCS in the response. + // + // Defaults to false if not included + optional bool transaction_bcs = 9; + // Include the sui.types.TransactionEffects message in the response. + // + // Defaults to true if not included + optional bool effects = 10; + // Include the TransactionEffects formatted as BCS in the response. + // + // Defaults to false if not included + optional bool effects_bcs = 11; + // Include the sui.types.TransactionEvents message in the response. + // + // Defaults to true if not included + optional bool events = 12; + // Include the TransactionEvents formatted as BCS in the response. + // + // Defaults to false if not included + optional bool events_bcs = 13; + + optional bool input_objects = 14; + optional bool output_objects = 15; + + // Include the sui.types.Object message in the response. + // + // Defaults to true if not included + optional bool object = 16; + // Include the Object formatted as BCS in the response. + // + // Defaults to false if not included + optional bool object_bcs = 17; +} + +message GetFullCheckpointResponse { + // The sequence number of this Checkpoint + optional uint64 sequence_number = 1; + // The digest of this Checkpoint's CheckpointSummary + optional sui.types.Digest digest = 2; + + optional sui.types.CheckpointSummary summary = 3; + optional sui.types.Bcs summary_bcs = 4; + optional sui.types.ValidatorAggregatedSignature signature = 5; + optional sui.types.CheckpointContents contents = 6; + optional sui.types.Bcs contents_bcs = 7; + + repeated FullCheckpointTransaction transactions = 8; +} + +message FullCheckpointTransaction { + // The digest of this transaction + optional sui.types.Digest digest = 1; + optional sui.types.Transaction transaction = 2; + optional sui.types.Bcs transaction_bcs = 3; + + optional sui.types.TransactionEffects effects = 5; + optional sui.types.Bcs effects_bcs = 6; + optional sui.types.TransactionEvents events = 7; + optional sui.types.Bcs events_bcs = 8; + + optional FullCheckpointObjects input_objects = 11; + optional FullCheckpointObjects output_objects = 12; +} + +message FullCheckpointObjects { + repeated FullCheckpointObject objects = 1; +} + +message FullCheckpointObject { + optional sui.types.ObjectId object_id = 1; + optional uint64 version = 2; + // The digest of this object + optional sui.types.Digest digest = 3; + + optional sui.types.Object object = 4; + optional sui.types.Bcs object_bcs = 5; +} + +message BalanceChange { + optional sui.types.Address address = 1; + optional sui.types.TypeTag coin_type = 2; + optional sui.types.I128 amount = 3; +} + +message BalanceChanges { + repeated BalanceChange balance_changes = 4; +} + +message EffectsFinality { + oneof finality { + sui.types.ValidatorAggregatedSignature certified = 1; + uint64 checkpointed = 2; + google.protobuf.Empty quorum_executed = 3; + } +} + +message ExecuteTransactionResponse { + optional EffectsFinality finality = 1; + optional sui.types.TransactionEffects effects = 2; + optional sui.types.Bcs effects_bcs = 3; + optional sui.types.TransactionEvents events = 4; + optional sui.types.Bcs events_bcs = 5; + optional BalanceChanges balance_changes = 6; +} + +message ExecuteTransactionRequest { + optional sui.types.Transaction transaction = 1; + optional sui.types.Bcs transaction_bcs = 2; + repeated sui.types.UserSignature signatures = 3; + + optional ExecuteTransactionOptions options = 4; +} + +message ExecuteTransactionOptions { + // Include the sui.types.TransactionEffects message in the response. + // + // Defaults to true if not included + optional bool effects = 4; + // Include the TransactionEffects formatted as BCS in the response. + // + // Defaults to false if not included + optional bool effects_bcs = 5; + // Include the sui.types.TransactionEvents message in the response. + // + // Defaults to true if not included + optional bool events = 6; + // Include the TransactionEvents formatted as BCS in the response. + // + // Defaults to false if not included + optional bool events_bcs = 7; + + // Include the BalanceChanges in the response. + // + // Defaults to false if not included + optional bool balance_changes = 8; +} diff --git a/crates/sui-rpc-api/proto/sui.types.proto b/crates/sui-rpc-api/proto/sui.types.proto new file mode 100644 index 0000000000000..2404383a89b72 --- /dev/null +++ b/crates/sui-rpc-api/proto/sui.types.proto @@ -0,0 +1,1038 @@ +// Protobuf definitions of public Sui core types +// +// This file contains a complete set of protobuf definitions for all of the +// public sui core types. All sui types are intended to have a 1:1 mapping to a +// protobuf message defined in this file and be able to roundtrip to/from their +// rust and protobuf definitions assuming a sufficiently up-to-date version of +// both these definitions. + +syntax = "proto3"; + +package sui.types; + +import "google/protobuf/empty.proto"; + +message Address { + optional bytes address = 1; +} + +message ObjectId { + optional bytes object_id = 1; +} + +message Digest { + optional bytes digest = 1; +} + +message Bcs { + optional bytes bcs = 1; +} + +// Primitives {{{ + +// Little-endian encoded u128 +message U128 { + optional bytes bytes = 1; +} + +// Little-endian encoded i128 +message I128 { + optional bytes bytes = 1; +} + +// Little-endian encoded u256 +message U256 { + optional bytes bytes = 1; +} + +// End Primitives }}} + +// Checkpoint {{{ + +message CheckpointSummary { + optional uint64 epoch = 1; + optional uint64 sequence_number = 2; + optional uint64 total_network_transactions = 3; + optional Digest content_digest = 4; + optional Digest previous_digest = 5; + + optional GasCostSummary epoch_rolling_gas_cost_summary = 6; + + optional uint64 timestamp_ms = 7; + + repeated CheckpointCommitment commitments = 8; + optional EndOfEpochData end_of_epoch_data = 9; + optional bytes version_specific_data = 10; +} + +message CheckpointCommitment { + oneof commitment { + Digest ecmh_live_object_set = 1; + } +} + +message EndOfEpochData { + repeated ValidatorCommitteeMember next_epoch_committee = 1; + optional uint64 next_epoch_protocol_version = 2; + repeated CheckpointCommitment epoch_commitments = 3; +} + +message CheckpointedTransactionInfo { + // TransactionDigest + optional Digest transaction = 1; + // EffectsDigest + optional Digest effects = 2; + repeated UserSignature signatures = 3; +} + +message CheckpointContents { + message V1 { + repeated CheckpointedTransactionInfo transactions = 1; + } + + oneof contents { + V1 v1 = 1; + } +} + +// End Checkpoint }}} + +// TransactionEvents {{{ + +message TransactionEvents { + repeated Event events = 1; +} + +message Event { + optional ObjectId package_id = 1; + optional Identifier module = 2; + optional Address sender = 3; + optional StructTag event_type = 4; + optional bytes contents = 5; +} + +// End TransactionEvents }}} + +// Object {{{ + +message ObjectReference { + optional ObjectId object_id = 1; + optional uint64 version = 2; + optional Digest digest = 3; +} + +message MovePackage { + optional ObjectId id = 1; + optional uint64 version = 2; + repeated MoveModule modules = 3; + repeated TypeOrigin type_origin_table = 4; + repeated UpgradeInfo linkage_table = 5; +} + +message MoveModule { + optional Identifier name = 1; + optional bytes contents = 2; +} + +message TypeOrigin { + optional Identifier module_name = 1; + optional Identifier struct_name = 2; + optional ObjectId package_id = 3; +} + +message UpgradeInfo { + optional ObjectId original_id = 1; + optional ObjectId upgraded_id = 2; + optional uint64 upgraded_version = 3; +} + +message Owner { + oneof kind { + Address address = 1; + ObjectId object = 2; + uint64 shared = 3; + google.protobuf.Empty immutable = 4; + } +} + +message MoveStruct { + optional ObjectId object_id = 1; + optional StructTag object_type = 2; + optional bool has_public_transfer = 3; + optional uint64 version = 4; + optional bytes contents = 5; +} + +message Object { + optional ObjectId object_id = 1; + optional uint64 version = 2; + optional Owner owner = 3; + + optional ObjectData object = 4; + + optional Digest previous_transaction = 5; + optional uint64 storage_rebate = 6; +} + +message ObjectData { + oneof kind { + MoveStruct struct = 1; + MovePackage package = 2; + } +} + +message GenesisObject { + optional ObjectId object_id = 1; + optional uint64 version = 2; + optional Owner owner = 3; + optional ObjectData object = 4; +} + +// End Object }}} + +// GasCostSummary {{{ + +message GasCostSummary { + optional uint64 computation_cost = 1; + optional uint64 storage_cost = 2; + optional uint64 storage_rebate = 3; + optional uint64 non_refundable_storage_fee = 4; +} + +// End GasCostSummary }}} + +// Move {{{ + +message Identifier { + optional bytes identifier = 1; +} + +message StructTag { + optional Address address = 1; + optional Identifier module = 2; + optional Identifier name = 3; + repeated TypeTag type_parameters = 4; +} + +message TypeTag { + oneof tag { + google.protobuf.Empty U8 = 1; + google.protobuf.Empty U16 = 2; + google.protobuf.Empty U32 = 3; + google.protobuf.Empty U64 = 4; + google.protobuf.Empty U128 = 5; + google.protobuf.Empty U256 = 6; + google.protobuf.Empty Bool = 7; + google.protobuf.Empty Address = 8; + google.protobuf.Empty Signer = 9; + TypeTag vector = 10; + StructTag struct = 11; + } +} + +message MoveStructValue { + optional StructTag struct_type = 1; + repeated MoveField fields = 2; +} + +message MoveField { + optional Identifier name = 1; + optional MoveValue value = 2; +} + +message MoveVariant { + optional StructTag enum_type = 1; + optional Identifier variant_name = 2; + optional uint32 tag = 3; + repeated MoveField fields = 4; +} + +message MoveValue { + oneof kind { + bool bool = 2; + uint32 u8 = 3; + uint32 u16 = 4; + uint32 u32 = 5; + uint64 u64 = 6; + U128 u128 = 7; + U256 u256 = 8; + Address address = 9; + MoveVector vector = 10; + MoveStructValue struct = 11; + Address signer = 12; + MoveVariant variant = 13; + } +} + +message MoveVector { + repeated MoveValue values = 1; +} + +// End Move }}} + +// Transaction {{{ + +message Transaction { + message TransactionV1 { + optional TransactionKind kind = 1; + optional Address sender = 2; + optional GasPayment gas_payment = 3; + optional TransactionExpiration expiration = 4; + } + + oneof version { + TransactionV1 v1 = 1; + } +} + +message GasPayment { + repeated ObjectReference objects = 1; + optional Address owner = 2; + optional uint64 price = 3; + optional uint64 budget = 4; +} + +message TransactionExpiration { + oneof expiration { + google.protobuf.Empty none = 1; + uint64 epoch = 2; + } +} + +message RandomnessStateUpdate { + optional uint64 epoch = 1; + optional uint64 randomness_round = 2; + optional bytes random_bytes = 3; + optional uint64 randomness_object_initial_shared_version = 4; +} + +message TransactionKind { + oneof kind { + ProgrammableTransaction programmable_transaction = 1; + ChangeEpoch change_epoch = 2; + GenesisTransaction genesis = 200; + ConsensusCommitPrologue consensus_commit_prologue_v1 = 201; + AuthenticatorStateUpdate authenticator_state_update = 3; + EndOfEpochTransaction end_of_epoch = 4; + RandomnessStateUpdate randomness_state_update = 5; + ConsensusCommitPrologue consensus_commit_prologue_v2 = 202; + ConsensusCommitPrologue consensus_commit_prologue_v3 = 6; + } +} + +message ProgrammableTransaction { + repeated Input inputs = 1; + repeated Command commands = 2; +} + +message Input { + oneof kind { + bytes pure = 1; + ObjectReference immutable_or_owned = 2; + SharedObjectInput shared = 3; + ObjectReference receiving = 4; + } +} + +message SharedObjectInput { + optional ObjectId object_id = 1; + optional uint64 initial_shared_version = 2; + optional bool mutable = 3; +} + +message Command { + oneof command { + MoveCall move_call = 1; + TransferObjects transfer_objects = 2; + SplitCoins split_coins = 3; + MergeCoins merge_coins = 4; + Publish publish = 5; + MakeMoveVector make_move_vector = 6; + Upgrade upgrade = 7; + } +} + +message MoveCall { + optional ObjectId package = 1; + optional Identifier module = 2; + optional Identifier function = 3; + repeated TypeTag type_arguments = 4; + repeated Argument arguments = 5; +} + +message TransferObjects { + repeated Argument objects = 1; + optional Argument address = 2; +} + +message SplitCoins { + optional Argument coin = 1; + repeated Argument amounts = 2; +} + +message MergeCoins { + optional Argument coin = 1; + repeated Argument coins_to_merge = 2; +} + +message Publish { + repeated bytes modules = 1; + repeated ObjectId dependencies = 2; +} + +message MakeMoveVector { + optional TypeTag element_type = 1; + repeated Argument elements = 2; +} + +message Upgrade { + repeated bytes modules = 1; + repeated ObjectId dependencies = 2; + optional ObjectId package = 3; + optional Argument ticket = 4; +} + +message Argument { + oneof kind { + google.protobuf.Empty gas = 1; + uint32 input = 2; + uint32 result = 3; + NestedResult nested_result = 4; + } +} + +message NestedResult { + optional uint32 result = 1; + optional uint32 subresult = 2; +} + +message ChangeEpoch { + // The next (to become) epoch ID. + optional uint64 epoch = 1; + // The protocol version in effect in the new epoch. + optional uint64 protocol_version = 2; + // The total amount of gas charged for storage during the epoch. + optional uint64 storage_charge = 3; + // The total amount of gas charged for computation during the epoch. + optional uint64 computation_charge = 4; + // The amount of storage rebate refunded to the txn senders. + optional uint64 storage_rebate = 5; + // The non-refundable storage fee. + optional uint64 non_refundable_storage_fee = 6; + // Unix timestamp when epoch started + optional uint64 epoch_start_timestamp_ms = 7; + // System packages (specifically framework and move stdlib) that are written before the new + // epoch starts. This tracks framework upgrades on chain. When executing the ChangeEpoch txn, + // the validator must write out the modules below. Modules are provided with the version they + // will be upgraded to, their modules in serialized form (which include their package ID), and + // a list of their transitive dependencies. + repeated SystemPackage system_packages = 8; +} + +message SystemPackage { + optional uint64 version = 1; + repeated bytes modules = 2; + repeated ObjectId dependencies = 3; +} + +message GenesisTransaction { + repeated GenesisObject objects = 1; +} + +message ConsensusCommitPrologue { + optional uint64 epoch = 1; + optional uint64 round = 2; + optional uint64 commit_timestamp_ms = 3; + optional Digest consensus_commit_digest = 4; + optional uint64 sub_dag_index = 5; + optional ConsensusDeterminedVersionAssignments consensus_determined_version_assignments = 6; +} + +message VersionAssignment { + optional ObjectId object_id = 1; + optional uint64 version = 2; +} + +message CancelledTransaction { + optional Digest digest = 1; + repeated VersionAssignment version_assignments = 2; +} + +message CancelledTransactions { + repeated CancelledTransaction cancelled_transactions = 1; +} + +message ConsensusDeterminedVersionAssignments { + oneof kind { + CancelledTransactions cancelled_transactions = 1; + } +} + +message AuthenticatorStateUpdate { + optional uint64 epoch = 1; + optional uint64 round = 2; + repeated ActiveJwk new_active_jwks = 3; + optional uint64 authenticator_object_initial_shared_version = 4; +} + +message ActiveJwk { + optional JwkId id = 1; + optional Jwk jwk = 2; + optional uint64 epoch = 3; +} + +message JwkId { + optional bytes iss = 1; + optional bytes kid = 2; +} + +message Jwk { + // Key type parameter, + optional bytes kty = 1; + // RSA public exponent, + optional bytes e = 2; + // RSA modulus, + optional bytes n = 3; + // Algorithm parameter, + optional bytes alg = 4; +} + +message EndOfEpochTransaction { + repeated EndOfEpochTransactionKind transactions = 1; +} + +message EndOfEpochTransactionKind { + oneof kind { + ChangeEpoch change_epoch = 1; + AuthenticatorStateExpire authenticator_state_expire = 2; + + // Use higher field numbers for kinds which happen infrequently + google.protobuf.Empty authenticator_state_create = 200; + google.protobuf.Empty randomness_state_create = 201; + google.protobuf.Empty deny_list_state_create = 202; + Digest bridge_state_create = 203; + uint64 bridge_committee_init = 204; + } +} + +message AuthenticatorStateExpire { + optional uint64 min_epoch = 1; + optional uint64 authenticator_object_initial_shared_version = 2; +} + +// End Transaction }}} + +// TransactionEffects {{{ + +message TransactionEffects { + oneof version { + TransactionEffectsV1 v1 = 1; + TransactionEffectsV2 v2 = 2; + } +} + +message TransactionEffectsV1 { + /// The status of the execution + optional ExecutionStatus status = 1; + /// The epoch when this transaction was executed. + optional uint64 epoch = 2; + optional GasCostSummary gas_used = 3; + /// The version that every modified (mutated or deleted) object had before it was modified by + /// this transaction. + repeated ModifiedAtVersion modified_at_versions = 4; + /// The object references of the shared objects used in this transaction. Empty if no shared objects were used. + repeated ObjectReference shared_objects = 5; + /// The transaction digest + optional Digest transaction_digest = 6; + + /// ObjectReference and owner of new objects created. + repeated ObjectReferenceWithOwner created = 7; + /// ObjectReference and owner of mutated objects, including gas object. + repeated ObjectReferenceWithOwner mutated = 8; + /// ObjectReference and owner of objects that are unwrapped in this transaction. + /// Unwrapped objects are objects that were wrapped into other objects in the past, + /// and just got extracted out. + repeated ObjectReferenceWithOwner unwrapped = 9; + /// Object Refs of objects now deleted (the new refs). + repeated ObjectReference deleted = 10; + /// Object refs of objects previously wrapped in other objects but now deleted. + repeated ObjectReference unwrapped_then_deleted = 11; + /// Object refs of objects now wrapped in other objects. + repeated ObjectReference wrapped = 12; + /// The updated gas object reference. Have a dedicated field for convenient access. + /// It's also included in mutated. + optional ObjectReferenceWithOwner gas_object = 13; + /// The digest of the events emitted during execution, + /// can be None if the transaction does not emit any event. + optional Digest events_digest = 14; + /// The set of transaction digests this transaction depends on. + repeated Digest dependencies = 15; +} + +message ObjectReferenceWithOwner { + optional ObjectReference reference = 1; + optional Owner owner = 2; +} + +message ModifiedAtVersion { + optional ObjectId object_id = 1; + optional uint64 version = 2; +} + +message TransactionEffectsV2 { + /// The status of the execution + optional ExecutionStatus status = 1; + /// The epoch when this transaction was executed. + optional uint64 epoch = 2; + optional GasCostSummary gas_used = 3; + /// The transaction digest + optional Digest transaction_digest = 4; + /// The updated gas object reference, as an index into the `changed_objects` vector. + /// Having a dedicated field for convenient access. + /// System transaction that don't require gas will leave this as None. + optional uint32 gas_object_index = 5; + + /// The digest of the events emitted during execution, + /// can be None if the transaction does not emit any event. + optional Digest events_digest = 6; + + /// The set of transaction digests this transaction depends on. + repeated Digest dependencies = 7; + + /// The version number of all the written Move objects by this transaction. + optional uint64 lamport_version = 8; + + /// Objects whose state are changed in the object store. + repeated ChangedObject changed_objects = 9; + + /// Shared objects that are not mutated in this transaction. Unlike owned objects, + /// read-only shared objects' version are not committed in the transaction, + /// and in order for a node to catch up and execute it without consensus sequencing, + /// the version needs to be committed in the effects. + repeated UnchangedSharedObject unchanged_shared_objects = 10; + + /// Auxiliary data that are not protocol-critical, generated as part of the effects but are stored separately. + /// Storing it separately allows us to avoid bloating the effects with data that are not critical. + /// It also provides more flexibility on the format and type of the data. + optional Digest auxiliary_data_digest = 11; +} + +message ChangedObject { + optional ObjectId object_id = 1; + + oneof input_state { + google.protobuf.Empty not_exist = 2; + ObjectExist exist = 3; + } + + oneof output_state { + google.protobuf.Empty removed = 4; + ObjectWrite object_write = 5; + PackageWrite package_write = 6; + } + + oneof id_operation { + google.protobuf.Empty none = 7; + google.protobuf.Empty created = 8; + google.protobuf.Empty deleted = 9; + } +} + +message ObjectExist { + optional uint64 version = 1; + optional Digest digest = 2; + optional Owner owner = 3; +} + +message ObjectWrite { + optional Digest digest = 2; + optional Owner owner = 3; +} + +message PackageWrite { + optional uint64 version = 1; + optional Digest digest = 2; +} + +message UnchangedSharedObject { + optional ObjectId object_id = 1; + + oneof kind { + ReadOnlyRoot read_only_root = 2; + uint64 mutate_deleted = 3; + uint64 read_deleted = 4; + uint64 cancelled = 5; + google.protobuf.Empty per_epoch_config = 6; + } +} + +message ReadOnlyRoot { + optional uint64 version = 1; + optional Digest digest = 2; +} + +// End TransactionEffects }}} + +// ExecutionStatus {{{ + +message ExecutionStatus { + optional bool success = 1; + optional FailureStatus status = 2; +} + +message SizeError { + optional uint64 size = 1; + optional uint64 max_size = 2; +} + +message MoveError { + optional MoveLocation location = 1; + optional uint64 abort_code = 2; +} + +message FailureStatus { + optional uint64 command = 1; + oneof execution_error { + /// Insufficient Gas + google.protobuf.Empty insufficient_gas = 2; + /// Invalid Gas Object. + google.protobuf.Empty invalid_gas_object = 3; + /// Invariant Violation + google.protobuf.Empty invariant_violation = 4; + /// Attempted to used feature that is not supported yet + google.protobuf.Empty feature_not_yet_supported = 5; + /// Move object is larger than the maximum allowed size + SizeError object_too_big = 6; + /// Package is larger than the maximum allowed size + SizeError package_too_big = 7; + /// Circular Object Ownership + ObjectId circular_object_ownership = 8; + + // + // Coin errors + // + /// Insufficient coin balance for requested operation + google.protobuf.Empty insufficient_coin_balance = 9; + /// Coin balance overflowed an u64 + google.protobuf.Empty coin_balance_overflow = 10; + + // + // Publish/Upgrade errors + // + /// Publish Error, Non-zero Address. + /// The modules in the package must have their self-addresses set to zero. + google.protobuf.Empty publish_error_non_zero_address = 11; + + /// Sui Move Bytecode Verification Error. + google.protobuf.Empty sui_move_verification_error = 12; + + // + // MoveVm Errors + // + /// Error from a non-abort instruction. + /// Possible causes: + /// Arithmetic error, stack overflow, max value depth, etc." + MoveError move_primitive_runtime_error = 13; + /// Move runtime abort + MoveError move_abort = 14; + /// Bytecode verification error. + google.protobuf.Empty vm_verification_or_deserialization_error = 15; + /// MoveVm invariant violation + google.protobuf.Empty vm_invariant_violation = 16; + + // + // Programmable Transaction Errors + // + /// Function not found + google.protobuf.Empty function_not_found = 17; + /// Arity mismatch for Move function. + /// The number of arguments does not match the number of parameters + google.protobuf.Empty arity_mismatch = 18; + /// Type arity mismatch for Move function. + /// Mismatch between the number of actual versus expected type arguments. + google.protobuf.Empty type_arity_mismatch = 19; + /// Non Entry Function Invoked. Move Call must start with an entry function. + google.protobuf.Empty non_entry_function_invoked = 20; + /// Invalid command argument + CommandArgumentError command_argument_error = 21; + /// Type argument error + TypeArgumentError type_argument_error = 22; + /// Unused result without the drop ability. + NestedResult unused_value_without_drop = 23; + /// Invalid public Move function signature. + /// Unsupported return type for return value + uint32 invalid_public_function_return_type = 24; + /// Invalid Transfer Object, object does not have public transfer. + google.protobuf.Empty invalid_transfer_object = 25; + + // + // Post-execution errors + // + /// Effects from the transaction are too large + SizeError effects_too_large = 26; + + /// Publish or Upgrade is missing dependency + google.protobuf.Empty publish_upgrade_missing_dependency = 27; + + /// Publish or Upgrade dependency downgrade. + /// + /// Indirect (transitive) dependency of published or upgraded package has been assigned an + /// on-chain version that is less than the version required by one of the package's + /// transitive dependencies. + google.protobuf.Empty publish_upgrade_dependency_downgrade = 28; + + /// Invalid package upgrade + PackageUpgradeError package_upgrade_error = 29; + + /// Indicates the transaction tried to write objects too large to storage + SizeError written_objects_too_large = 30; + + /// Certificate is on the deny list + google.protobuf.Empty certificate_denied = 31; + + /// Sui Move Bytecode verification timed out. + google.protobuf.Empty sui_move_verification_timedout = 32; + + /// The requested shared object operation is not allowed + google.protobuf.Empty shared_object_operation_not_allowed = 33; + + /// Requested shared object has been deleted + google.protobuf.Empty input_object_deleted = 34; + + /// Certificate is cancelled due to congestion on shared objects + CongestedObjectsError execution_cancelled_due_to_shared_object_congestion = 35; + + /// Address is denied for this coin type + AddressDeniedForCoinError address_denied_for_coin = 36; + + /// Coin type is globally paused for use + string coin_type_global_pause = 37; + + /// Certificate is cancelled because randomness could not be generated this epoch + google.protobuf.Empty execution_cancelled_due_to_randomness_unavailable = 38; + } +} + +message AddressDeniedForCoinError { + optional Address address = 1; + optional string coin_type = 2; +} + +message CongestedObjectsError { + repeated ObjectId congested_objects = 1; +} + +message MoveLocation { + optional ObjectId package = 1; + optional Identifier module = 2; + optional uint32 function = 3; + optional uint32 instruction = 4; + optional Identifier function_name = 5; +} + +message CommandArgumentError { + optional uint32 argument = 1; + + oneof kind { + /// The type of the value does not match the expected type + google.protobuf.Empty type_mismatch = 2; + /// The argument cannot be deserialized into a value of the specified type + google.protobuf.Empty invalid_bcs_bytes = 3; + /// The argument cannot be instantiated from raw bytes + google.protobuf.Empty invalid_usage_of_pure_argument = 4; + /// Invalid argument to private entry function. + /// Private entry functions cannot take arguments from other Move functions. + google.protobuf.Empty invalid_argument_to_private_entry_function = 5; + /// Out of bounds access to input or results + uint32 index_out_of_bounds = 6; + /// Out of bounds access to subresult + NestedResult secondary_index_out_of_bounds = 7; + /// Invalid usage of result. + /// Expected a single result but found either no return value or multiple. + uint32 invalid_result_arity = 8; + /// Invalid usage of Gas coin. + /// The Gas coin can only be used by-value with a TransferObjects command. + google.protobuf.Empty invalid_gas_coin_usage = 9; + /// Invalid usage of move value. + // Mutably borrowed values require unique usage. + // Immutably borrowed values cannot be taken or borrowed mutably. + // Taken values cannot be used again. + google.protobuf.Empty invalid_value_usage = 10; + /// Immutable objects cannot be passed by-value. + google.protobuf.Empty invalid_object_by_value = 11; + /// Immutable objects cannot be passed by mutable reference, &mut. + google.protobuf.Empty invalid_object_by_mut_ref = 12; + /// Shared object operations such a wrapping, freezing, or converting to owned are not + /// allowed. + google.protobuf.Empty shared_object_operation_not_allowed = 13; + } +} + +message PackageUpgradeError { + oneof kind { + ObjectId unable_to_fetch_package = 2; + ObjectId not_a_package = 3; + google.protobuf.Empty incompatible_upgrade = 4; + Digest digets_does_not_match = 5; + uint32 unknown_upgrade_policy = 6; + PackageIdDoesNotMatch package_id_does_not_match = 7; + } +} + +message PackageIdDoesNotMatch { + optional ObjectId package_id = 1; + optional ObjectId object_id = 2; +} + +message TypeArgumentError { + optional uint32 type_argument = 1; + + oneof kind { + google.protobuf.Empty type_not_found = 2; + google.protobuf.Empty constraint_not_satisfied = 3; + } +} + +// End ExecutionStatus }}} + +// Signatures {{{ + +message UserSignature { + oneof signature { + SimpleSignature simple = 1; + MultisigAggregatedSignature multisig = 2; + ZkLoginAuthenticator zklogin = 3; + PasskeyAuthenticator passkey = 4; + } +} + +// note: values do not match their bcs serialized values +enum SignatureScheme { + SIGNATURE_SCHEME_UNKNOWN = 0; + SIGNATURE_SCHEME_ED25519 = 1; + SIGNATURE_SCHEME_SECP256K1 = 2; + SIGNATURE_SCHEME_SECP256R1 = 3; + SIGNATURE_SCHEME_MULTISIG = 4; + SIGNATURE_SCHEME_BLS12381 = 5; + SIGNATURE_SCHEME_ZKLOGIN = 6; + SIGNATURE_SCHEME_PASSKEY = 7; +} + +message SimpleSignature { + optional SignatureScheme scheme = 1; + optional bytes signature = 2; + optional bytes public_key = 3; +} + +message ZkLoginPublicIdentifier { + optional bytes iss = 1; + optional Bn254FieldElement address_seed = 2; +} + +message MultisigMemberPublicKey { + oneof scheme { + bytes ed25519 = 1; + bytes secp256k1 = 2; + bytes secp256r1 = 3; + ZkLoginPublicIdentifier zklogin = 4; + } +} + +message MultisigMember { + optional MultisigMemberPublicKey public_key = 1; + optional uint32 weight = 2; +} + +message MultisigCommittee { + repeated MultisigMember members = 1; + optional uint32 threshold = 2; +} + +message MultisigAggregatedSignature { + repeated MultisigMemberSignature signatures = 1; + optional uint32 bitmap = 2; + optional RoaringBitmap legacy_bitmap = 3; + optional MultisigCommittee committee = 4; +} + +message MultisigMemberSignature { + oneof signature { + bytes ed25519 = 1; + bytes secp256k1 = 2; + bytes secp256r1 = 3; + ZkLoginAuthenticator zklogin = 4; + } +} + +message ZkLoginAuthenticator { + optional ZkLoginInputs inputs = 1; + optional uint64 max_epoch = 2; + optional SimpleSignature signature = 3; +} + +message ZkLoginInputs { + optional ZkLoginProof proof_points = 1; + optional ZkLoginClaim iss_base64_details = 2; + optional bytes header_base64 = 3; + optional Bn254FieldElement address_seed = 4; +} + +message ZkLoginProof { + optional CircomG1 a = 1; + optional CircomG2 b = 2; + optional CircomG1 c = 3; +} + +message ZkLoginClaim { + optional bytes value = 1; + optional uint32 index_mod_4 = 2; +} + +message CircomG1 { + optional Bn254FieldElement e0 = 1; + optional Bn254FieldElement e1 = 2; + optional Bn254FieldElement e2 = 3; +} + +message CircomG2 { + optional Bn254FieldElement e00 = 1; + optional Bn254FieldElement e01 = 2; + + optional Bn254FieldElement e10 = 3; + optional Bn254FieldElement e11 = 4; + + optional Bn254FieldElement e20 = 5; + optional Bn254FieldElement e21 = 6; +} + +message Bn254FieldElement { + optional bytes element = 1; +} + +message PasskeyAuthenticator { + optional bytes authenticator_data = 1; + optional bytes client_data_json = 2; + optional SimpleSignature signature = 3; +} + +message ValidatorCommittee { + optional uint64 epoch = 1; + repeated ValidatorCommitteeMember members = 2; +} + +message ValidatorCommitteeMember { + optional bytes public_key = 1; + optional uint64 stake = 2; +} + +message ValidatorAggregatedSignature { + optional uint64 epoch = 1; + optional bytes signature = 2; + optional RoaringBitmap bitmap = 3; +} + +message RoaringBitmap { + optional bytes bitmap = 1; +} + +// End Signatures }}} diff --git a/crates/sui-rpc-api/src/proto/generated/sui.node.v2.rs b/crates/sui-rpc-api/src/proto/generated/sui.node.v2.rs new file mode 100644 index 0000000000000..50757016c38a4 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/generated/sui.node.v2.rs @@ -0,0 +1,1178 @@ +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetNodeInfoResponse { + /// The chain identifier of the chain that this Node is on + #[prost(message, optional, tag = "1")] + pub chain_id: ::core::option::Option, + /// Human readable name of the chain that this Node is on + #[prost(string, optional, tag = "2")] + pub chain: ::core::option::Option<::prost::alloc::string::String>, + /// Current epoch of the Node based on its highest executed checkpoint + #[prost(uint64, optional, tag = "3")] + pub epoch: ::core::option::Option, + /// Checkpoint height of the most recently executed checkpoint + #[prost(uint64, optional, tag = "4")] + pub checkpoint_height: ::core::option::Option, + /// Unix timestamp of the most recently executed checkpoint + #[prost(message, optional, tag = "5")] + pub timestamp: ::core::option::Option<::prost_types::Timestamp>, + /// The lowest checkpoint for which checkpoints and transaction data is available + #[prost(uint64, optional, tag = "6")] + pub lowest_available_checkpoint: ::core::option::Option, + /// The lowest checkpoint for which object data is available + #[prost(uint64, optional, tag = "7")] + pub lowest_available_checkpoint_objects: ::core::option::Option, + #[prost(string, optional, tag = "8")] + pub software_version: ::core::option::Option<::prost::alloc::string::String>, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GetCommitteeRequest { + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetCommitteeResponse { + #[prost(message, optional, tag = "1")] + pub committee: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTransactionRequest { + #[prost(message, optional, tag = "1")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub options: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GetTransactionOptions { + /// Include the sui.types.Transaction message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "1")] + pub transaction: ::core::option::Option, + /// Include the Transaction formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "2")] + pub transaction_bcs: ::core::option::Option, + /// Include the set of sui.types.UserSignature's in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "3")] + pub signatures: ::core::option::Option, + /// Include the sui.types.TransactionEffects message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "4")] + pub effects: ::core::option::Option, + /// Include the TransactionEffects formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "5")] + pub effects_bcs: ::core::option::Option, + /// Include the sui.types.TransactionEvents message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "6")] + pub events: ::core::option::Option, + /// Include the TransactionEvents formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "7")] + pub events_bcs: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTransactionResponse { + /// The digest of this transaction + #[prost(message, optional, tag = "1")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub transaction: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub transaction_bcs: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub signatures: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub effects: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub effects_bcs: ::core::option::Option, + #[prost(message, optional, tag = "7")] + pub events: ::core::option::Option, + #[prost(message, optional, tag = "8")] + pub events_bcs: ::core::option::Option, + #[prost(uint64, optional, tag = "9")] + pub checkpoint: ::core::option::Option, + #[prost(message, optional, tag = "10")] + pub timestamp: ::core::option::Option<::prost_types::Timestamp>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UserSignatures { + #[prost(message, repeated, tag = "1")] + pub signatures: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetObjectRequest { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub options: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GetObjectOptions { + /// Include the sui.types.Object message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "1")] + pub object: ::core::option::Option, + /// Include the Object formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "2")] + pub object_bcs: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetObjectResponse { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, + /// The digest of this object + #[prost(message, optional, tag = "3")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub object: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub object_bcs: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetCheckpointRequest { + #[prost(uint64, optional, tag = "1")] + pub sequence_number: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub options: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GetCheckpointOptions { + /// Include the sui.types.CheckpointSummary in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "3")] + pub summary: ::core::option::Option, + /// Include the CheckpointSummary formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "4")] + pub summary_bcs: ::core::option::Option, + /// Include the sui.types.ValidatorAggregatedSignature in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "5")] + pub signature: ::core::option::Option, + /// Include the sui.types.CheckpointContents message in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "6")] + pub contents: ::core::option::Option, + /// Include the CheckpointContents formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "7")] + pub contents_bcs: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetCheckpointResponse { + /// The sequence number of this Checkpoint + #[prost(uint64, optional, tag = "1")] + pub sequence_number: ::core::option::Option, + /// The digest of this Checkpoint's CheckpointSummary + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub summary: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub summary_bcs: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub signature: ::core::option::Option< + super::super::types::ValidatorAggregatedSignature, + >, + #[prost(message, optional, tag = "6")] + pub contents: ::core::option::Option, + #[prost(message, optional, tag = "7")] + pub contents_bcs: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetFullCheckpointRequest { + #[prost(uint64, optional, tag = "1")] + pub sequence_number: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub options: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GetFullCheckpointOptions { + /// Include the sui.types.CheckpointSummary in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "3")] + pub summary: ::core::option::Option, + /// Include the CheckpointSummary formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "4")] + pub summary_bcs: ::core::option::Option, + /// Include the sui.types.ValidatorAggregatedSignature in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "5")] + pub signature: ::core::option::Option, + /// Include the sui.types.CheckpointContents message in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "6")] + pub contents: ::core::option::Option, + /// Include the CheckpointContents formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "7")] + pub contents_bcs: ::core::option::Option, + /// Include the sui.types.Transaction message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "8")] + pub transaction: ::core::option::Option, + /// Include the Transaction formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "9")] + pub transaction_bcs: ::core::option::Option, + /// Include the sui.types.TransactionEffects message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "10")] + pub effects: ::core::option::Option, + /// Include the TransactionEffects formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "11")] + pub effects_bcs: ::core::option::Option, + /// Include the sui.types.TransactionEvents message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "12")] + pub events: ::core::option::Option, + /// Include the TransactionEvents formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "13")] + pub events_bcs: ::core::option::Option, + #[prost(bool, optional, tag = "14")] + pub input_objects: ::core::option::Option, + #[prost(bool, optional, tag = "15")] + pub output_objects: ::core::option::Option, + /// Include the sui.types.Object message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "16")] + pub object: ::core::option::Option, + /// Include the Object formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "17")] + pub object_bcs: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetFullCheckpointResponse { + /// The sequence number of this Checkpoint + #[prost(uint64, optional, tag = "1")] + pub sequence_number: ::core::option::Option, + /// The digest of this Checkpoint's CheckpointSummary + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub summary: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub summary_bcs: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub signature: ::core::option::Option< + super::super::types::ValidatorAggregatedSignature, + >, + #[prost(message, optional, tag = "6")] + pub contents: ::core::option::Option, + #[prost(message, optional, tag = "7")] + pub contents_bcs: ::core::option::Option, + #[prost(message, repeated, tag = "8")] + pub transactions: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FullCheckpointTransaction { + /// The digest of this transaction + #[prost(message, optional, tag = "1")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub transaction: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub transaction_bcs: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub effects: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub effects_bcs: ::core::option::Option, + #[prost(message, optional, tag = "7")] + pub events: ::core::option::Option, + #[prost(message, optional, tag = "8")] + pub events_bcs: ::core::option::Option, + #[prost(message, optional, tag = "11")] + pub input_objects: ::core::option::Option, + #[prost(message, optional, tag = "12")] + pub output_objects: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FullCheckpointObjects { + #[prost(message, repeated, tag = "1")] + pub objects: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FullCheckpointObject { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, + /// The digest of this object + #[prost(message, optional, tag = "3")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub object: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub object_bcs: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceChange { + #[prost(message, optional, tag = "1")] + pub address: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub coin_type: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub amount: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceChanges { + #[prost(message, repeated, tag = "4")] + pub balance_changes: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EffectsFinality { + #[prost(oneof = "effects_finality::Finality", tags = "1, 2, 3")] + pub finality: ::core::option::Option, +} +/// Nested message and enum types in `EffectsFinality`. +pub mod effects_finality { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Finality { + #[prost(message, tag = "1")] + Certified(super::super::super::types::ValidatorAggregatedSignature), + #[prost(uint64, tag = "2")] + Checkpointed(u64), + #[prost(message, tag = "3")] + QuorumExecuted(()), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ExecuteTransactionResponse { + #[prost(message, optional, tag = "1")] + pub finality: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub effects: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub effects_bcs: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub events: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub events_bcs: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub balance_changes: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ExecuteTransactionRequest { + #[prost(message, optional, tag = "1")] + pub transaction: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub transaction_bcs: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub signatures: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "4")] + pub options: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct ExecuteTransactionOptions { + /// Include the sui.types.TransactionEffects message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "4")] + pub effects: ::core::option::Option, + /// Include the TransactionEffects formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "5")] + pub effects_bcs: ::core::option::Option, + /// Include the sui.types.TransactionEvents message in the response. + /// + /// Defaults to true if not included + #[prost(bool, optional, tag = "6")] + pub events: ::core::option::Option, + /// Include the TransactionEvents formatted as BCS in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "7")] + pub events_bcs: ::core::option::Option, + /// Include the BalanceChanges in the response. + /// + /// Defaults to false if not included + #[prost(bool, optional, tag = "8")] + pub balance_changes: ::core::option::Option, +} +/// Generated client implementations. +pub mod node_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct NodeClient { + inner: tonic::client::Grpc, + } + impl NodeClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl NodeClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> NodeClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + NodeClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn get_node_info( + &mut self, + request: impl tonic::IntoRequest<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.node.v2.Node/GetNodeInfo", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("sui.node.v2.Node", "GetNodeInfo")); + self.inner.unary(req, path, codec).await + } + pub async fn get_committee( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.node.v2.Node/GetCommittee", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("sui.node.v2.Node", "GetCommittee")); + self.inner.unary(req, path, codec).await + } + pub async fn get_object( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.node.v2.Node/GetObject", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("sui.node.v2.Node", "GetObject")); + self.inner.unary(req, path, codec).await + } + pub async fn get_transaction( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.node.v2.Node/GetTransaction", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("sui.node.v2.Node", "GetTransaction")); + self.inner.unary(req, path, codec).await + } + pub async fn get_checkpoint( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.node.v2.Node/GetCheckpoint", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("sui.node.v2.Node", "GetCheckpoint")); + self.inner.unary(req, path, codec).await + } + pub async fn get_full_checkpoint( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.node.v2.Node/GetFullCheckpoint", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("sui.node.v2.Node", "GetFullCheckpoint")); + self.inner.unary(req, path, codec).await + } + pub async fn execute_transaction( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.node.v2.Node/ExecuteTransaction", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("sui.node.v2.Node", "ExecuteTransaction")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod node_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with NodeServer. + #[async_trait] + pub trait Node: std::marker::Send + std::marker::Sync + 'static { + async fn get_node_info( + &self, + request: tonic::Request<()>, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_committee( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_object( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_transaction( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_checkpoint( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_full_checkpoint( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn execute_transaction( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct NodeServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl NodeServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for NodeServer + where + T: Node, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/sui.node.v2.Node/GetNodeInfo" => { + #[allow(non_camel_case_types)] + struct GetNodeInfoSvc(pub Arc); + impl tonic::server::UnaryService<()> for GetNodeInfoSvc { + type Response = super::GetNodeInfoResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call(&mut self, request: tonic::Request<()>) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_node_info(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetNodeInfoSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sui.node.v2.Node/GetCommittee" => { + #[allow(non_camel_case_types)] + struct GetCommitteeSvc(pub Arc); + impl tonic::server::UnaryService + for GetCommitteeSvc { + type Response = super::GetCommitteeResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_committee(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetCommitteeSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sui.node.v2.Node/GetObject" => { + #[allow(non_camel_case_types)] + struct GetObjectSvc(pub Arc); + impl tonic::server::UnaryService + for GetObjectSvc { + type Response = super::GetObjectResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_object(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetObjectSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sui.node.v2.Node/GetTransaction" => { + #[allow(non_camel_case_types)] + struct GetTransactionSvc(pub Arc); + impl< + T: Node, + > tonic::server::UnaryService + for GetTransactionSvc { + type Response = super::GetTransactionResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_transaction(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetTransactionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sui.node.v2.Node/GetCheckpoint" => { + #[allow(non_camel_case_types)] + struct GetCheckpointSvc(pub Arc); + impl< + T: Node, + > tonic::server::UnaryService + for GetCheckpointSvc { + type Response = super::GetCheckpointResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_checkpoint(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetCheckpointSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sui.node.v2.Node/GetFullCheckpoint" => { + #[allow(non_camel_case_types)] + struct GetFullCheckpointSvc(pub Arc); + impl< + T: Node, + > tonic::server::UnaryService + for GetFullCheckpointSvc { + type Response = super::GetFullCheckpointResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_full_checkpoint(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetFullCheckpointSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sui.node.v2.Node/ExecuteTransaction" => { + #[allow(non_camel_case_types)] + struct ExecuteTransactionSvc(pub Arc); + impl< + T: Node, + > tonic::server::UnaryService + for ExecuteTransactionSvc { + type Response = super::ExecuteTransactionResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::execute_transaction(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ExecuteTransactionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + let mut response = http::Response::new(empty_body()); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }) + } + } + } + } + impl Clone for NodeServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "sui.node.v2.Node"; + impl tonic::server::NamedService for NodeServer { + const NAME: &'static str = SERVICE_NAME; + } +} diff --git a/crates/sui-rpc-api/src/proto/generated/sui.types.rs b/crates/sui-rpc-api/src/proto/generated/sui.types.rs new file mode 100644 index 0000000000000..fd14675edd166 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/generated/sui.types.rs @@ -0,0 +1,1553 @@ +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Address { + #[prost(bytes = "bytes", optional, tag = "1")] + pub address: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ObjectId { + #[prost(bytes = "bytes", optional, tag = "1")] + pub object_id: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Digest { + #[prost(bytes = "bytes", optional, tag = "1")] + pub digest: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Bcs { + #[prost(bytes = "bytes", optional, tag = "1")] + pub bcs: ::core::option::Option<::prost::bytes::Bytes>, +} +/// Little-endian encoded u128 +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct U128 { + #[prost(bytes = "bytes", optional, tag = "1")] + pub bytes: ::core::option::Option<::prost::bytes::Bytes>, +} +/// Little-endian encoded i128 +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct I128 { + #[prost(bytes = "bytes", optional, tag = "1")] + pub bytes: ::core::option::Option<::prost::bytes::Bytes>, +} +/// Little-endian encoded u256 +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct U256 { + #[prost(bytes = "bytes", optional, tag = "1")] + pub bytes: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CheckpointSummary { + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub sequence_number: ::core::option::Option, + #[prost(uint64, optional, tag = "3")] + pub total_network_transactions: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub content_digest: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub previous_digest: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub epoch_rolling_gas_cost_summary: ::core::option::Option, + #[prost(uint64, optional, tag = "7")] + pub timestamp_ms: ::core::option::Option, + #[prost(message, repeated, tag = "8")] + pub commitments: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "9")] + pub end_of_epoch_data: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "10")] + pub version_specific_data: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CheckpointCommitment { + #[prost(oneof = "checkpoint_commitment::Commitment", tags = "1")] + pub commitment: ::core::option::Option, +} +/// Nested message and enum types in `CheckpointCommitment`. +pub mod checkpoint_commitment { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Commitment { + #[prost(message, tag = "1")] + EcmhLiveObjectSet(super::Digest), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EndOfEpochData { + #[prost(message, repeated, tag = "1")] + pub next_epoch_committee: ::prost::alloc::vec::Vec, + #[prost(uint64, optional, tag = "2")] + pub next_epoch_protocol_version: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub epoch_commitments: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CheckpointedTransactionInfo { + /// TransactionDigest + #[prost(message, optional, tag = "1")] + pub transaction: ::core::option::Option, + /// EffectsDigest + #[prost(message, optional, tag = "2")] + pub effects: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub signatures: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CheckpointContents { + #[prost(oneof = "checkpoint_contents::Contents", tags = "1")] + pub contents: ::core::option::Option, +} +/// Nested message and enum types in `CheckpointContents`. +pub mod checkpoint_contents { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct V1 { + #[prost(message, repeated, tag = "1")] + pub transactions: ::prost::alloc::vec::Vec, + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Contents { + #[prost(message, tag = "1")] + V1(V1), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionEvents { + #[prost(message, repeated, tag = "1")] + pub events: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Event { + #[prost(message, optional, tag = "1")] + pub package_id: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub module: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub sender: ::core::option::Option
, + #[prost(message, optional, tag = "4")] + pub event_type: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "5")] + pub contents: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ObjectReference { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub digest: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MovePackage { + #[prost(message, optional, tag = "1")] + pub id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub modules: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "4")] + pub type_origin_table: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "5")] + pub linkage_table: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveModule { + #[prost(message, optional, tag = "1")] + pub name: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "2")] + pub contents: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TypeOrigin { + #[prost(message, optional, tag = "1")] + pub module_name: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub struct_name: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub package_id: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpgradeInfo { + #[prost(message, optional, tag = "1")] + pub original_id: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub upgraded_id: ::core::option::Option, + #[prost(uint64, optional, tag = "3")] + pub upgraded_version: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Owner { + #[prost(oneof = "owner::Kind", tags = "1, 2, 3, 4")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `Owner`. +pub mod owner { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "1")] + Address(super::Address), + #[prost(message, tag = "2")] + Object(super::ObjectId), + #[prost(uint64, tag = "3")] + Shared(u64), + #[prost(message, tag = "4")] + Immutable(()), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveStruct { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub object_type: ::core::option::Option, + #[prost(bool, optional, tag = "3")] + pub has_public_transfer: ::core::option::Option, + #[prost(uint64, optional, tag = "4")] + pub version: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "5")] + pub contents: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Object { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub owner: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub object: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub previous_transaction: ::core::option::Option, + #[prost(uint64, optional, tag = "6")] + pub storage_rebate: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ObjectData { + #[prost(oneof = "object_data::Kind", tags = "1, 2")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `ObjectData`. +pub mod object_data { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "1")] + Struct(super::MoveStruct), + #[prost(message, tag = "2")] + Package(super::MovePackage), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GenesisObject { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub owner: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub object: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GasCostSummary { + #[prost(uint64, optional, tag = "1")] + pub computation_cost: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub storage_cost: ::core::option::Option, + #[prost(uint64, optional, tag = "3")] + pub storage_rebate: ::core::option::Option, + #[prost(uint64, optional, tag = "4")] + pub non_refundable_storage_fee: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Identifier { + #[prost(bytes = "bytes", optional, tag = "1")] + pub identifier: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StructTag { + #[prost(message, optional, tag = "1")] + pub address: ::core::option::Option
, + #[prost(message, optional, tag = "2")] + pub module: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub name: ::core::option::Option, + #[prost(message, repeated, tag = "4")] + pub type_parameters: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TypeTag { + #[prost(oneof = "type_tag::Tag", tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11")] + pub tag: ::core::option::Option, +} +/// Nested message and enum types in `TypeTag`. +pub mod type_tag { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Tag { + #[prost(message, tag = "1")] + U8(()), + #[prost(message, tag = "2")] + U16(()), + #[prost(message, tag = "3")] + U32(()), + #[prost(message, tag = "4")] + U64(()), + #[prost(message, tag = "5")] + U128(()), + #[prost(message, tag = "6")] + U256(()), + #[prost(message, tag = "7")] + Bool(()), + #[prost(message, tag = "8")] + Address(()), + #[prost(message, tag = "9")] + Signer(()), + #[prost(message, tag = "10")] + Vector(::prost::alloc::boxed::Box), + #[prost(message, tag = "11")] + Struct(super::StructTag), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveStructValue { + #[prost(message, optional, tag = "1")] + pub struct_type: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub fields: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveField { + #[prost(message, optional, tag = "1")] + pub name: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub value: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveVariant { + #[prost(message, optional, tag = "1")] + pub enum_type: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub variant_name: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub tag: ::core::option::Option, + #[prost(message, repeated, tag = "4")] + pub fields: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveValue { + #[prost(oneof = "move_value::Kind", tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `MoveValue`. +pub mod move_value { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(bool, tag = "2")] + Bool(bool), + #[prost(uint32, tag = "3")] + U8(u32), + #[prost(uint32, tag = "4")] + U16(u32), + #[prost(uint32, tag = "5")] + U32(u32), + #[prost(uint64, tag = "6")] + U64(u64), + #[prost(message, tag = "7")] + U128(super::U128), + #[prost(message, tag = "8")] + U256(super::U256), + #[prost(message, tag = "9")] + Address(super::Address), + #[prost(message, tag = "10")] + Vector(super::MoveVector), + #[prost(message, tag = "11")] + Struct(super::MoveStructValue), + #[prost(message, tag = "12")] + Signer(super::Address), + #[prost(message, tag = "13")] + Variant(super::MoveVariant), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveVector { + #[prost(message, repeated, tag = "1")] + pub values: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Transaction { + #[prost(oneof = "transaction::Version", tags = "1")] + pub version: ::core::option::Option, +} +/// Nested message and enum types in `Transaction`. +pub mod transaction { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct TransactionV1 { + #[prost(message, optional, tag = "1")] + pub kind: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub sender: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub gas_payment: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub expiration: ::core::option::Option, + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Version { + #[prost(message, tag = "1")] + V1(TransactionV1), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GasPayment { + #[prost(message, repeated, tag = "1")] + pub objects: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "2")] + pub owner: ::core::option::Option
, + #[prost(uint64, optional, tag = "3")] + pub price: ::core::option::Option, + #[prost(uint64, optional, tag = "4")] + pub budget: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct TransactionExpiration { + #[prost(oneof = "transaction_expiration::Expiration", tags = "1, 2")] + pub expiration: ::core::option::Option, +} +/// Nested message and enum types in `TransactionExpiration`. +pub mod transaction_expiration { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Expiration { + #[prost(message, tag = "1")] + None(()), + #[prost(uint64, tag = "2")] + Epoch(u64), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RandomnessStateUpdate { + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub randomness_round: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "3")] + pub random_bytes: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(uint64, optional, tag = "4")] + pub randomness_object_initial_shared_version: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionKind { + #[prost(oneof = "transaction_kind::Kind", tags = "1, 2, 200, 201, 3, 4, 5, 202, 6")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `TransactionKind`. +pub mod transaction_kind { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "1")] + ProgrammableTransaction(super::ProgrammableTransaction), + #[prost(message, tag = "2")] + ChangeEpoch(super::ChangeEpoch), + #[prost(message, tag = "200")] + Genesis(super::GenesisTransaction), + #[prost(message, tag = "201")] + ConsensusCommitPrologueV1(super::ConsensusCommitPrologue), + #[prost(message, tag = "3")] + AuthenticatorStateUpdate(super::AuthenticatorStateUpdate), + #[prost(message, tag = "4")] + EndOfEpoch(super::EndOfEpochTransaction), + #[prost(message, tag = "5")] + RandomnessStateUpdate(super::RandomnessStateUpdate), + #[prost(message, tag = "202")] + ConsensusCommitPrologueV2(super::ConsensusCommitPrologue), + #[prost(message, tag = "6")] + ConsensusCommitPrologueV3(super::ConsensusCommitPrologue), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProgrammableTransaction { + #[prost(message, repeated, tag = "1")] + pub inputs: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "2")] + pub commands: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Input { + #[prost(oneof = "input::Kind", tags = "1, 2, 3, 4")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `Input`. +pub mod input { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(bytes, tag = "1")] + Pure(::prost::bytes::Bytes), + #[prost(message, tag = "2")] + ImmutableOrOwned(super::ObjectReference), + #[prost(message, tag = "3")] + Shared(super::SharedObjectInput), + #[prost(message, tag = "4")] + Receiving(super::ObjectReference), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SharedObjectInput { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub initial_shared_version: ::core::option::Option, + #[prost(bool, optional, tag = "3")] + pub mutable: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Command { + #[prost(oneof = "command::Command", tags = "1, 2, 3, 4, 5, 6, 7")] + pub command: ::core::option::Option, +} +/// Nested message and enum types in `Command`. +pub mod command { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Command { + #[prost(message, tag = "1")] + MoveCall(super::MoveCall), + #[prost(message, tag = "2")] + TransferObjects(super::TransferObjects), + #[prost(message, tag = "3")] + SplitCoins(super::SplitCoins), + #[prost(message, tag = "4")] + MergeCoins(super::MergeCoins), + #[prost(message, tag = "5")] + Publish(super::Publish), + #[prost(message, tag = "6")] + MakeMoveVector(super::MakeMoveVector), + #[prost(message, tag = "7")] + Upgrade(super::Upgrade), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveCall { + #[prost(message, optional, tag = "1")] + pub package: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub module: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub function: ::core::option::Option, + #[prost(message, repeated, tag = "4")] + pub type_arguments: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "5")] + pub arguments: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransferObjects { + #[prost(message, repeated, tag = "1")] + pub objects: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "2")] + pub address: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SplitCoins { + #[prost(message, optional, tag = "1")] + pub coin: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub amounts: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MergeCoins { + #[prost(message, optional, tag = "1")] + pub coin: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub coins_to_merge: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Publish { + #[prost(bytes = "bytes", repeated, tag = "1")] + pub modules: ::prost::alloc::vec::Vec<::prost::bytes::Bytes>, + #[prost(message, repeated, tag = "2")] + pub dependencies: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MakeMoveVector { + #[prost(message, optional, tag = "1")] + pub element_type: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub elements: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Upgrade { + #[prost(bytes = "bytes", repeated, tag = "1")] + pub modules: ::prost::alloc::vec::Vec<::prost::bytes::Bytes>, + #[prost(message, repeated, tag = "2")] + pub dependencies: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "3")] + pub package: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub ticket: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct Argument { + #[prost(oneof = "argument::Kind", tags = "1, 2, 3, 4")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `Argument`. +pub mod argument { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "1")] + Gas(()), + #[prost(uint32, tag = "2")] + Input(u32), + #[prost(uint32, tag = "3")] + Result(u32), + #[prost(message, tag = "4")] + NestedResult(super::NestedResult), + } +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct NestedResult { + #[prost(uint32, optional, tag = "1")] + pub result: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub subresult: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChangeEpoch { + /// The next (to become) epoch ID. + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, + /// The protocol version in effect in the new epoch. + #[prost(uint64, optional, tag = "2")] + pub protocol_version: ::core::option::Option, + /// The total amount of gas charged for storage during the epoch. + #[prost(uint64, optional, tag = "3")] + pub storage_charge: ::core::option::Option, + /// The total amount of gas charged for computation during the epoch. + #[prost(uint64, optional, tag = "4")] + pub computation_charge: ::core::option::Option, + /// The amount of storage rebate refunded to the txn senders. + #[prost(uint64, optional, tag = "5")] + pub storage_rebate: ::core::option::Option, + /// The non-refundable storage fee. + #[prost(uint64, optional, tag = "6")] + pub non_refundable_storage_fee: ::core::option::Option, + /// Unix timestamp when epoch started + #[prost(uint64, optional, tag = "7")] + pub epoch_start_timestamp_ms: ::core::option::Option, + /// System packages (specifically framework and move stdlib) that are written before the new + /// epoch starts. This tracks framework upgrades on chain. When executing the ChangeEpoch txn, + /// the validator must write out the modules below. Modules are provided with the version they + /// will be upgraded to, their modules in serialized form (which include their package ID), and + /// a list of their transitive dependencies. + #[prost(message, repeated, tag = "8")] + pub system_packages: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SystemPackage { + #[prost(uint64, optional, tag = "1")] + pub version: ::core::option::Option, + #[prost(bytes = "bytes", repeated, tag = "2")] + pub modules: ::prost::alloc::vec::Vec<::prost::bytes::Bytes>, + #[prost(message, repeated, tag = "3")] + pub dependencies: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GenesisTransaction { + #[prost(message, repeated, tag = "1")] + pub objects: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsensusCommitPrologue { + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub round: ::core::option::Option, + #[prost(uint64, optional, tag = "3")] + pub commit_timestamp_ms: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub consensus_commit_digest: ::core::option::Option, + #[prost(uint64, optional, tag = "5")] + pub sub_dag_index: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub consensus_determined_version_assignments: ::core::option::Option< + ConsensusDeterminedVersionAssignments, + >, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VersionAssignment { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CancelledTransaction { + #[prost(message, optional, tag = "1")] + pub digest: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub version_assignments: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CancelledTransactions { + #[prost(message, repeated, tag = "1")] + pub cancelled_transactions: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsensusDeterminedVersionAssignments { + #[prost(oneof = "consensus_determined_version_assignments::Kind", tags = "1")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `ConsensusDeterminedVersionAssignments`. +pub mod consensus_determined_version_assignments { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "1")] + CancelledTransactions(super::CancelledTransactions), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AuthenticatorStateUpdate { + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub round: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub new_active_jwks: ::prost::alloc::vec::Vec, + #[prost(uint64, optional, tag = "4")] + pub authenticator_object_initial_shared_version: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ActiveJwk { + #[prost(message, optional, tag = "1")] + pub id: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub jwk: ::core::option::Option, + #[prost(uint64, optional, tag = "3")] + pub epoch: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct JwkId { + #[prost(bytes = "bytes", optional, tag = "1")] + pub iss: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(bytes = "bytes", optional, tag = "2")] + pub kid: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Jwk { + /// Key type parameter, <> + #[prost(bytes = "bytes", optional, tag = "1")] + pub kty: ::core::option::Option<::prost::bytes::Bytes>, + /// RSA public exponent, <> + #[prost(bytes = "bytes", optional, tag = "2")] + pub e: ::core::option::Option<::prost::bytes::Bytes>, + /// RSA modulus, <> + #[prost(bytes = "bytes", optional, tag = "3")] + pub n: ::core::option::Option<::prost::bytes::Bytes>, + /// Algorithm parameter, <> + #[prost(bytes = "bytes", optional, tag = "4")] + pub alg: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EndOfEpochTransaction { + #[prost(message, repeated, tag = "1")] + pub transactions: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EndOfEpochTransactionKind { + #[prost( + oneof = "end_of_epoch_transaction_kind::Kind", + tags = "1, 2, 200, 201, 202, 203, 204" + )] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `EndOfEpochTransactionKind`. +pub mod end_of_epoch_transaction_kind { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "1")] + ChangeEpoch(super::ChangeEpoch), + #[prost(message, tag = "2")] + AuthenticatorStateExpire(super::AuthenticatorStateExpire), + /// Use higher field numbers for kinds which happen infrequently + #[prost(message, tag = "200")] + AuthenticatorStateCreate(()), + #[prost(message, tag = "201")] + RandomnessStateCreate(()), + #[prost(message, tag = "202")] + DenyListStateCreate(()), + #[prost(message, tag = "203")] + BridgeStateCreate(super::Digest), + #[prost(uint64, tag = "204")] + BridgeCommitteeInit(u64), + } +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct AuthenticatorStateExpire { + #[prost(uint64, optional, tag = "1")] + pub min_epoch: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub authenticator_object_initial_shared_version: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionEffects { + #[prost(oneof = "transaction_effects::Version", tags = "1, 2")] + pub version: ::core::option::Option, +} +/// Nested message and enum types in `TransactionEffects`. +pub mod transaction_effects { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Version { + #[prost(message, tag = "1")] + V1(super::TransactionEffectsV1), + #[prost(message, tag = "2")] + V2(super::TransactionEffectsV2), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionEffectsV1 { + /// / The status of the execution + #[prost(message, optional, tag = "1")] + pub status: ::core::option::Option, + /// / The epoch when this transaction was executed. + #[prost(uint64, optional, tag = "2")] + pub epoch: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub gas_used: ::core::option::Option, + /// / The version that every modified (mutated or deleted) object had before it was modified by + /// / this transaction. + #[prost(message, repeated, tag = "4")] + pub modified_at_versions: ::prost::alloc::vec::Vec, + /// / The object references of the shared objects used in this transaction. Empty if no shared objects were used. + #[prost(message, repeated, tag = "5")] + pub shared_objects: ::prost::alloc::vec::Vec, + /// / The transaction digest + #[prost(message, optional, tag = "6")] + pub transaction_digest: ::core::option::Option, + /// / ObjectReference and owner of new objects created. + #[prost(message, repeated, tag = "7")] + pub created: ::prost::alloc::vec::Vec, + /// / ObjectReference and owner of mutated objects, including gas object. + #[prost(message, repeated, tag = "8")] + pub mutated: ::prost::alloc::vec::Vec, + /// / ObjectReference and owner of objects that are unwrapped in this transaction. + /// / Unwrapped objects are objects that were wrapped into other objects in the past, + /// / and just got extracted out. + #[prost(message, repeated, tag = "9")] + pub unwrapped: ::prost::alloc::vec::Vec, + /// / Object Refs of objects now deleted (the new refs). + #[prost(message, repeated, tag = "10")] + pub deleted: ::prost::alloc::vec::Vec, + /// / Object refs of objects previously wrapped in other objects but now deleted. + #[prost(message, repeated, tag = "11")] + pub unwrapped_then_deleted: ::prost::alloc::vec::Vec, + /// / Object refs of objects now wrapped in other objects. + #[prost(message, repeated, tag = "12")] + pub wrapped: ::prost::alloc::vec::Vec, + /// / The updated gas object reference. Have a dedicated field for convenient access. + /// / It's also included in mutated. + #[prost(message, optional, tag = "13")] + pub gas_object: ::core::option::Option, + /// / The digest of the events emitted during execution, + /// / can be None if the transaction does not emit any event. + #[prost(message, optional, tag = "14")] + pub events_digest: ::core::option::Option, + /// / The set of transaction digests this transaction depends on. + #[prost(message, repeated, tag = "15")] + pub dependencies: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ObjectReferenceWithOwner { + #[prost(message, optional, tag = "1")] + pub reference: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub owner: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ModifiedAtVersion { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub version: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionEffectsV2 { + /// / The status of the execution + #[prost(message, optional, tag = "1")] + pub status: ::core::option::Option, + /// / The epoch when this transaction was executed. + #[prost(uint64, optional, tag = "2")] + pub epoch: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub gas_used: ::core::option::Option, + /// / The transaction digest + #[prost(message, optional, tag = "4")] + pub transaction_digest: ::core::option::Option, + /// / The updated gas object reference, as an index into the `changed_objects` vector. + /// / Having a dedicated field for convenient access. + /// / System transaction that don't require gas will leave this as None. + #[prost(uint32, optional, tag = "5")] + pub gas_object_index: ::core::option::Option, + /// / The digest of the events emitted during execution, + /// / can be None if the transaction does not emit any event. + #[prost(message, optional, tag = "6")] + pub events_digest: ::core::option::Option, + /// / The set of transaction digests this transaction depends on. + #[prost(message, repeated, tag = "7")] + pub dependencies: ::prost::alloc::vec::Vec, + /// / The version number of all the written Move objects by this transaction. + #[prost(uint64, optional, tag = "8")] + pub lamport_version: ::core::option::Option, + /// / Objects whose state are changed in the object store. + #[prost(message, repeated, tag = "9")] + pub changed_objects: ::prost::alloc::vec::Vec, + /// / Shared objects that are not mutated in this transaction. Unlike owned objects, + /// / read-only shared objects' version are not committed in the transaction, + /// / and in order for a node to catch up and execute it without consensus sequencing, + /// / the version needs to be committed in the effects. + #[prost(message, repeated, tag = "10")] + pub unchanged_shared_objects: ::prost::alloc::vec::Vec, + /// / Auxiliary data that are not protocol-critical, generated as part of the effects but are stored separately. + /// / Storing it separately allows us to avoid bloating the effects with data that are not critical. + /// / It also provides more flexibility on the format and type of the data. + #[prost(message, optional, tag = "11")] + pub auxiliary_data_digest: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChangedObject { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(oneof = "changed_object::InputState", tags = "2, 3")] + pub input_state: ::core::option::Option, + #[prost(oneof = "changed_object::OutputState", tags = "4, 5, 6")] + pub output_state: ::core::option::Option, + #[prost(oneof = "changed_object::IdOperation", tags = "7, 8, 9")] + pub id_operation: ::core::option::Option, +} +/// Nested message and enum types in `ChangedObject`. +pub mod changed_object { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum InputState { + #[prost(message, tag = "2")] + NotExist(()), + #[prost(message, tag = "3")] + Exist(super::ObjectExist), + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum OutputState { + #[prost(message, tag = "4")] + Removed(()), + #[prost(message, tag = "5")] + ObjectWrite(super::ObjectWrite), + #[prost(message, tag = "6")] + PackageWrite(super::PackageWrite), + } + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum IdOperation { + #[prost(message, tag = "7")] + None(()), + #[prost(message, tag = "8")] + Created(()), + #[prost(message, tag = "9")] + Deleted(()), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ObjectExist { + #[prost(uint64, optional, tag = "1")] + pub version: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub owner: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ObjectWrite { + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub owner: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PackageWrite { + #[prost(uint64, optional, tag = "1")] + pub version: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UnchangedSharedObject { + #[prost(message, optional, tag = "1")] + pub object_id: ::core::option::Option, + #[prost(oneof = "unchanged_shared_object::Kind", tags = "2, 3, 4, 5, 6")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `UnchangedSharedObject`. +pub mod unchanged_shared_object { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "2")] + ReadOnlyRoot(super::ReadOnlyRoot), + #[prost(uint64, tag = "3")] + MutateDeleted(u64), + #[prost(uint64, tag = "4")] + ReadDeleted(u64), + #[prost(uint64, tag = "5")] + Cancelled(u64), + #[prost(message, tag = "6")] + PerEpochConfig(()), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ReadOnlyRoot { + #[prost(uint64, optional, tag = "1")] + pub version: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub digest: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ExecutionStatus { + #[prost(bool, optional, tag = "1")] + pub success: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub status: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct SizeError { + #[prost(uint64, optional, tag = "1")] + pub size: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub max_size: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveError { + #[prost(message, optional, tag = "1")] + pub location: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub abort_code: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FailureStatus { + #[prost(uint64, optional, tag = "1")] + pub command: ::core::option::Option, + #[prost( + oneof = "failure_status::ExecutionError", + tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38" + )] + pub execution_error: ::core::option::Option, +} +/// Nested message and enum types in `FailureStatus`. +pub mod failure_status { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum ExecutionError { + /// / Insufficient Gas + #[prost(message, tag = "2")] + InsufficientGas(()), + /// / Invalid Gas Object. + #[prost(message, tag = "3")] + InvalidGasObject(()), + /// / Invariant Violation + #[prost(message, tag = "4")] + InvariantViolation(()), + /// / Attempted to used feature that is not supported yet + #[prost(message, tag = "5")] + FeatureNotYetSupported(()), + /// / Move object is larger than the maximum allowed size + #[prost(message, tag = "6")] + ObjectTooBig(super::SizeError), + /// / Package is larger than the maximum allowed size + #[prost(message, tag = "7")] + PackageTooBig(super::SizeError), + /// / Circular Object Ownership + #[prost(message, tag = "8")] + CircularObjectOwnership(super::ObjectId), + /// + /// Coin errors + /// + /// / Insufficient coin balance for requested operation + #[prost(message, tag = "9")] + InsufficientCoinBalance(()), + /// / Coin balance overflowed an u64 + #[prost(message, tag = "10")] + CoinBalanceOverflow(()), + /// + /// Publish/Upgrade errors + /// + /// / Publish Error, Non-zero Address. + /// / The modules in the package must have their self-addresses set to zero. + #[prost(message, tag = "11")] + PublishErrorNonZeroAddress(()), + /// / Sui Move Bytecode Verification Error. + #[prost(message, tag = "12")] + SuiMoveVerificationError(()), + /// + /// MoveVm Errors + /// + /// / Error from a non-abort instruction. + /// / Possible causes: + /// / Arithmetic error, stack overflow, max value depth, etc." + #[prost(message, tag = "13")] + MovePrimitiveRuntimeError(super::MoveError), + /// / Move runtime abort + #[prost(message, tag = "14")] + MoveAbort(super::MoveError), + /// / Bytecode verification error. + #[prost(message, tag = "15")] + VmVerificationOrDeserializationError(()), + /// / MoveVm invariant violation + #[prost(message, tag = "16")] + VmInvariantViolation(()), + /// + /// Programmable Transaction Errors + /// + /// / Function not found + #[prost(message, tag = "17")] + FunctionNotFound(()), + /// / Arity mismatch for Move function. + /// / The number of arguments does not match the number of parameters + #[prost(message, tag = "18")] + ArityMismatch(()), + /// / Type arity mismatch for Move function. + /// / Mismatch between the number of actual versus expected type arguments. + #[prost(message, tag = "19")] + TypeArityMismatch(()), + /// / Non Entry Function Invoked. Move Call must start with an entry function. + #[prost(message, tag = "20")] + NonEntryFunctionInvoked(()), + /// / Invalid command argument + #[prost(message, tag = "21")] + CommandArgumentError(super::CommandArgumentError), + /// / Type argument error + #[prost(message, tag = "22")] + TypeArgumentError(super::TypeArgumentError), + /// / Unused result without the drop ability. + #[prost(message, tag = "23")] + UnusedValueWithoutDrop(super::NestedResult), + /// / Invalid public Move function signature. + /// / Unsupported return type for return value + #[prost(uint32, tag = "24")] + InvalidPublicFunctionReturnType(u32), + /// / Invalid Transfer Object, object does not have public transfer. + #[prost(message, tag = "25")] + InvalidTransferObject(()), + /// + /// Post-execution errors + /// + /// / Effects from the transaction are too large + #[prost(message, tag = "26")] + EffectsTooLarge(super::SizeError), + /// / Publish or Upgrade is missing dependency + #[prost(message, tag = "27")] + PublishUpgradeMissingDependency(()), + /// / Publish or Upgrade dependency downgrade. + /// / + /// / Indirect (transitive) dependency of published or upgraded package has been assigned an + /// / on-chain version that is less than the version required by one of the package's + /// / transitive dependencies. + #[prost(message, tag = "28")] + PublishUpgradeDependencyDowngrade(()), + /// / Invalid package upgrade + #[prost(message, tag = "29")] + PackageUpgradeError(super::PackageUpgradeError), + /// / Indicates the transaction tried to write objects too large to storage + #[prost(message, tag = "30")] + WrittenObjectsTooLarge(super::SizeError), + /// / Certificate is on the deny list + #[prost(message, tag = "31")] + CertificateDenied(()), + /// / Sui Move Bytecode verification timed out. + #[prost(message, tag = "32")] + SuiMoveVerificationTimedout(()), + /// / The requested shared object operation is not allowed + #[prost(message, tag = "33")] + SharedObjectOperationNotAllowed(()), + /// / Requested shared object has been deleted + #[prost(message, tag = "34")] + InputObjectDeleted(()), + /// / Certificate is cancelled due to congestion on shared objects + #[prost(message, tag = "35")] + ExecutionCancelledDueToSharedObjectCongestion(super::CongestedObjectsError), + /// / Address is denied for this coin type + #[prost(message, tag = "36")] + AddressDeniedForCoin(super::AddressDeniedForCoinError), + /// / Coin type is globally paused for use + #[prost(string, tag = "37")] + CoinTypeGlobalPause(::prost::alloc::string::String), + /// / Certificate is cancelled because randomness could not be generated this epoch + #[prost(message, tag = "38")] + ExecutionCancelledDueToRandomnessUnavailable(()), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AddressDeniedForCoinError { + #[prost(message, optional, tag = "1")] + pub address: ::core::option::Option
, + #[prost(string, optional, tag = "2")] + pub coin_type: ::core::option::Option<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CongestedObjectsError { + #[prost(message, repeated, tag = "1")] + pub congested_objects: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MoveLocation { + #[prost(message, optional, tag = "1")] + pub package: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub module: ::core::option::Option, + #[prost(uint32, optional, tag = "3")] + pub function: ::core::option::Option, + #[prost(uint32, optional, tag = "4")] + pub instruction: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub function_name: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct CommandArgumentError { + #[prost(uint32, optional, tag = "1")] + pub argument: ::core::option::Option, + #[prost( + oneof = "command_argument_error::Kind", + tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13" + )] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `CommandArgumentError`. +pub mod command_argument_error { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Kind { + /// / The type of the value does not match the expected type + #[prost(message, tag = "2")] + TypeMismatch(()), + /// / The argument cannot be deserialized into a value of the specified type + #[prost(message, tag = "3")] + InvalidBcsBytes(()), + /// / The argument cannot be instantiated from raw bytes + #[prost(message, tag = "4")] + InvalidUsageOfPureArgument(()), + /// / Invalid argument to private entry function. + /// / Private entry functions cannot take arguments from other Move functions. + #[prost(message, tag = "5")] + InvalidArgumentToPrivateEntryFunction(()), + /// / Out of bounds access to input or results + #[prost(uint32, tag = "6")] + IndexOutOfBounds(u32), + /// / Out of bounds access to subresult + #[prost(message, tag = "7")] + SecondaryIndexOutOfBounds(super::NestedResult), + /// / Invalid usage of result. + /// / Expected a single result but found either no return value or multiple. + #[prost(uint32, tag = "8")] + InvalidResultArity(u32), + /// / Invalid usage of Gas coin. + /// / The Gas coin can only be used by-value with a TransferObjects command. + #[prost(message, tag = "9")] + InvalidGasCoinUsage(()), + /// / Invalid usage of move value. + /// Mutably borrowed values require unique usage. + /// Immutably borrowed values cannot be taken or borrowed mutably. + /// Taken values cannot be used again. + #[prost(message, tag = "10")] + InvalidValueUsage(()), + /// / Immutable objects cannot be passed by-value. + #[prost(message, tag = "11")] + InvalidObjectByValue(()), + /// / Immutable objects cannot be passed by mutable reference, &mut. + #[prost(message, tag = "12")] + InvalidObjectByMutRef(()), + /// / Shared object operations such a wrapping, freezing, or converting to owned are not + /// / allowed. + #[prost(message, tag = "13")] + SharedObjectOperationNotAllowed(()), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PackageUpgradeError { + #[prost(oneof = "package_upgrade_error::Kind", tags = "2, 3, 4, 5, 6, 7")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `PackageUpgradeError`. +pub mod package_upgrade_error { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "2")] + UnableToFetchPackage(super::ObjectId), + #[prost(message, tag = "3")] + NotAPackage(super::ObjectId), + #[prost(message, tag = "4")] + IncompatibleUpgrade(()), + #[prost(message, tag = "5")] + DigetsDoesNotMatch(super::Digest), + #[prost(uint32, tag = "6")] + UnknownUpgradePolicy(u32), + #[prost(message, tag = "7")] + PackageIdDoesNotMatch(super::PackageIdDoesNotMatch), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PackageIdDoesNotMatch { + #[prost(message, optional, tag = "1")] + pub package_id: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub object_id: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct TypeArgumentError { + #[prost(uint32, optional, tag = "1")] + pub type_argument: ::core::option::Option, + #[prost(oneof = "type_argument_error::Kind", tags = "2, 3")] + pub kind: ::core::option::Option, +} +/// Nested message and enum types in `TypeArgumentError`. +pub mod type_argument_error { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Kind { + #[prost(message, tag = "2")] + TypeNotFound(()), + #[prost(message, tag = "3")] + ConstraintNotSatisfied(()), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UserSignature { + #[prost(oneof = "user_signature::Signature", tags = "1, 2, 3, 4")] + pub signature: ::core::option::Option, +} +/// Nested message and enum types in `UserSignature`. +pub mod user_signature { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Signature { + #[prost(message, tag = "1")] + Simple(super::SimpleSignature), + #[prost(message, tag = "2")] + Multisig(super::MultisigAggregatedSignature), + #[prost(message, tag = "3")] + Zklogin(super::ZkLoginAuthenticator), + #[prost(message, tag = "4")] + Passkey(super::PasskeyAuthenticator), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SimpleSignature { + #[prost(enumeration = "SignatureScheme", optional, tag = "1")] + pub scheme: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "2")] + pub signature: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(bytes = "bytes", optional, tag = "3")] + pub public_key: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ZkLoginPublicIdentifier { + #[prost(bytes = "bytes", optional, tag = "1")] + pub iss: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(message, optional, tag = "2")] + pub address_seed: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigMemberPublicKey { + #[prost(oneof = "multisig_member_public_key::Scheme", tags = "1, 2, 3, 4")] + pub scheme: ::core::option::Option, +} +/// Nested message and enum types in `MultisigMemberPublicKey`. +pub mod multisig_member_public_key { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Scheme { + #[prost(bytes, tag = "1")] + Ed25519(::prost::bytes::Bytes), + #[prost(bytes, tag = "2")] + Secp256k1(::prost::bytes::Bytes), + #[prost(bytes, tag = "3")] + Secp256r1(::prost::bytes::Bytes), + #[prost(message, tag = "4")] + Zklogin(super::ZkLoginPublicIdentifier), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigMember { + #[prost(message, optional, tag = "1")] + pub public_key: ::core::option::Option, + #[prost(uint32, optional, tag = "2")] + pub weight: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigCommittee { + #[prost(message, repeated, tag = "1")] + pub members: ::prost::alloc::vec::Vec, + #[prost(uint32, optional, tag = "2")] + pub threshold: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigAggregatedSignature { + #[prost(message, repeated, tag = "1")] + pub signatures: ::prost::alloc::vec::Vec, + #[prost(uint32, optional, tag = "2")] + pub bitmap: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub legacy_bitmap: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub committee: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigMemberSignature { + #[prost(oneof = "multisig_member_signature::Signature", tags = "1, 2, 3, 4")] + pub signature: ::core::option::Option, +} +/// Nested message and enum types in `MultisigMemberSignature`. +pub mod multisig_member_signature { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Signature { + #[prost(bytes, tag = "1")] + Ed25519(::prost::bytes::Bytes), + #[prost(bytes, tag = "2")] + Secp256k1(::prost::bytes::Bytes), + #[prost(bytes, tag = "3")] + Secp256r1(::prost::bytes::Bytes), + #[prost(message, tag = "4")] + Zklogin(super::ZkLoginAuthenticator), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ZkLoginAuthenticator { + #[prost(message, optional, tag = "1")] + pub inputs: ::core::option::Option, + #[prost(uint64, optional, tag = "2")] + pub max_epoch: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub signature: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ZkLoginInputs { + #[prost(message, optional, tag = "1")] + pub proof_points: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub iss_base64_details: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "3")] + pub header_base64: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(message, optional, tag = "4")] + pub address_seed: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ZkLoginProof { + #[prost(message, optional, tag = "1")] + pub a: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub b: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub c: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ZkLoginClaim { + #[prost(bytes = "bytes", optional, tag = "1")] + pub value: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(uint32, optional, tag = "2")] + pub index_mod_4: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CircomG1 { + #[prost(message, optional, tag = "1")] + pub e0: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub e1: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub e2: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CircomG2 { + #[prost(message, optional, tag = "1")] + pub e00: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub e01: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub e10: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub e11: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub e20: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub e21: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Bn254FieldElement { + #[prost(bytes = "bytes", optional, tag = "1")] + pub element: ::core::option::Option<::prost::bytes::Bytes>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PasskeyAuthenticator { + #[prost(bytes = "bytes", optional, tag = "1")] + pub authenticator_data: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(bytes = "bytes", optional, tag = "2")] + pub client_data_json: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(message, optional, tag = "3")] + pub signature: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidatorCommittee { + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub members: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidatorCommitteeMember { + #[prost(bytes = "bytes", optional, tag = "1")] + pub public_key: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(uint64, optional, tag = "2")] + pub stake: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidatorAggregatedSignature { + #[prost(uint64, optional, tag = "1")] + pub epoch: ::core::option::Option, + #[prost(bytes = "bytes", optional, tag = "2")] + pub signature: ::core::option::Option<::prost::bytes::Bytes>, + #[prost(message, optional, tag = "3")] + pub bitmap: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RoaringBitmap { + #[prost(bytes = "bytes", optional, tag = "1")] + pub bitmap: ::core::option::Option<::prost::bytes::Bytes>, +} +/// note: values do not match their bcs serialized values +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum SignatureScheme { + Unknown = 0, + Ed25519 = 1, + Secp256k1 = 2, + Secp256r1 = 3, + Multisig = 4, + Bls12381 = 5, + Zklogin = 6, + Passkey = 7, +} +impl SignatureScheme { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unknown => "SIGNATURE_SCHEME_UNKNOWN", + Self::Ed25519 => "SIGNATURE_SCHEME_ED25519", + Self::Secp256k1 => "SIGNATURE_SCHEME_SECP256K1", + Self::Secp256r1 => "SIGNATURE_SCHEME_SECP256R1", + Self::Multisig => "SIGNATURE_SCHEME_MULTISIG", + Self::Bls12381 => "SIGNATURE_SCHEME_BLS12381", + Self::Zklogin => "SIGNATURE_SCHEME_ZKLOGIN", + Self::Passkey => "SIGNATURE_SCHEME_PASSKEY", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SIGNATURE_SCHEME_UNKNOWN" => Some(Self::Unknown), + "SIGNATURE_SCHEME_ED25519" => Some(Self::Ed25519), + "SIGNATURE_SCHEME_SECP256K1" => Some(Self::Secp256k1), + "SIGNATURE_SCHEME_SECP256R1" => Some(Self::Secp256r1), + "SIGNATURE_SCHEME_MULTISIG" => Some(Self::Multisig), + "SIGNATURE_SCHEME_BLS12381" => Some(Self::Bls12381), + "SIGNATURE_SCHEME_ZKLOGIN" => Some(Self::Zklogin), + "SIGNATURE_SCHEME_PASSKEY" => Some(Self::Passkey), + _ => None, + } + } +} diff --git a/crates/sui-rpc-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs index 539c2c6dab0ab..d9a6c7342e51f 100644 --- a/crates/sui-rpc-api/src/proto/mod.rs +++ b/crates/sui-rpc-api/src/proto/mod.rs @@ -1,618 +1,66 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 +pub mod node; +pub mod types; -#[path = "generated/sui.rest.rs"] -mod generated; -pub use generated::*; -use tap::Pipe; +type BoxError = Box; -// -// Transaction -// - -impl TryFrom<&sui_sdk_types::types::Transaction> for Transaction { - type Error = bcs::Error; - - fn try_from(value: &sui_sdk_types::types::Transaction) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - transaction: bytes.into(), - }) - } -} - -impl TryFrom<&Transaction> for sui_sdk_types::types::Transaction { - type Error = bcs::Error; - - fn try_from(value: &Transaction) -> Result { - bcs::from_bytes(&value.transaction) - } -} - -impl TryFrom<&sui_types::transaction::TransactionData> for Transaction { - type Error = bcs::Error; - - fn try_from(value: &sui_types::transaction::TransactionData) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - transaction: bytes.into(), - }) - } -} - -impl TryFrom<&Transaction> for sui_types::transaction::TransactionData { - type Error = bcs::Error; - - fn try_from(value: &Transaction) -> Result { - bcs::from_bytes(&value.transaction) - } -} - -// -// TransactionEffects -// - -impl TryFrom<&sui_sdk_types::types::TransactionEffects> for TransactionEffects { - type Error = bcs::Error; - - fn try_from(value: &sui_sdk_types::types::TransactionEffects) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - effects: bytes.into(), - }) - } -} - -impl TryFrom<&TransactionEffects> for sui_sdk_types::types::TransactionEffects { - type Error = bcs::Error; - - fn try_from(value: &TransactionEffects) -> Result { - bcs::from_bytes(&value.effects) - } -} - -impl TryFrom<&sui_types::effects::TransactionEffects> for TransactionEffects { - type Error = bcs::Error; - - fn try_from(value: &sui_types::effects::TransactionEffects) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - effects: bytes.into(), - }) - } -} - -impl TryFrom<&TransactionEffects> for sui_types::effects::TransactionEffects { - type Error = bcs::Error; - - fn try_from(value: &TransactionEffects) -> Result { - bcs::from_bytes(&value.effects) - } -} - -// -// TransactionEvents -// - -impl TryFrom<&sui_sdk_types::types::TransactionEvents> for TransactionEvents { - type Error = bcs::Error; - - fn try_from(value: &sui_sdk_types::types::TransactionEvents) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - events: bytes.into(), - }) - } -} - -impl TryFrom<&TransactionEvents> for sui_sdk_types::types::TransactionEvents { - type Error = bcs::Error; - - fn try_from(value: &TransactionEvents) -> Result { - bcs::from_bytes(&value.events) - } -} - -impl TryFrom<&sui_types::effects::TransactionEvents> for TransactionEvents { - type Error = bcs::Error; - - fn try_from(value: &sui_types::effects::TransactionEvents) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - events: bytes.into(), - }) - } -} - -impl TryFrom<&TransactionEvents> for sui_types::effects::TransactionEvents { - type Error = bcs::Error; - - fn try_from(value: &TransactionEvents) -> Result { - bcs::from_bytes(&value.events) - } -} - -// -// Object -// - -impl TryFrom<&sui_sdk_types::types::Object> for Object { - type Error = bcs::Error; - - fn try_from(value: &sui_sdk_types::types::Object) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - object: bytes.into(), - }) - } -} - -impl TryFrom<&Object> for sui_sdk_types::types::Object { - type Error = bcs::Error; - - fn try_from(value: &Object) -> Result { - bcs::from_bytes(&value.object) - } -} - -impl TryFrom<&sui_types::object::Object> for Object { - type Error = bcs::Error; - - fn try_from(value: &sui_types::object::Object) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - object: bytes.into(), - }) - } -} - -impl TryFrom<&Object> for sui_types::object::Object { - type Error = bcs::Error; - - fn try_from(value: &Object) -> Result { - bcs::from_bytes(&value.object) - } -} - -// -// CheckpointSummary -// - -impl TryFrom<&sui_sdk_types::types::CheckpointSummary> for CheckpointSummary { - type Error = bcs::Error; - - fn try_from(value: &sui_sdk_types::types::CheckpointSummary) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - summary: bytes.into(), - }) - } +#[derive(Debug)] +pub struct TryFromProtoError { + missing_field: Option<&'static str>, + source: Option, } -impl TryFrom<&CheckpointSummary> for sui_sdk_types::types::CheckpointSummary { - type Error = bcs::Error; +impl std::fmt::Display for TryFromProtoError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "error converting from protobuf")?; - fn try_from(value: &CheckpointSummary) -> Result { - bcs::from_bytes(&value.summary) - } -} - -impl TryFrom<&sui_types::messages_checkpoint::CheckpointSummary> for CheckpointSummary { - type Error = bcs::Error; - - fn try_from( - value: &sui_types::messages_checkpoint::CheckpointSummary, - ) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - summary: bytes.into(), - }) - } -} - -impl TryFrom<&CheckpointSummary> for sui_types::messages_checkpoint::CheckpointSummary { - type Error = bcs::Error; - - fn try_from(value: &CheckpointSummary) -> Result { - bcs::from_bytes(&value.summary) - } -} - -// -// CheckpointContents -// - -impl TryFrom<&sui_sdk_types::types::CheckpointContents> for CheckpointContents { - type Error = bcs::Error; - - fn try_from(value: &sui_sdk_types::types::CheckpointContents) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - contents: bytes.into(), - }) - } -} - -impl TryFrom<&CheckpointContents> for sui_sdk_types::types::CheckpointContents { - type Error = bcs::Error; - - fn try_from(value: &CheckpointContents) -> Result { - bcs::from_bytes(&value.contents) - } -} - -impl TryFrom<&sui_types::messages_checkpoint::CheckpointContents> for CheckpointContents { - type Error = bcs::Error; - - fn try_from( - value: &sui_types::messages_checkpoint::CheckpointContents, - ) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - contents: bytes.into(), - }) - } -} - -impl TryFrom<&CheckpointContents> for sui_types::messages_checkpoint::CheckpointContents { - type Error = bcs::Error; - - fn try_from(value: &CheckpointContents) -> Result { - bcs::from_bytes(&value.contents) - } -} - -// -// ValidatorAggregatedSignature -// - -impl TryFrom<&sui_sdk_types::types::ValidatorAggregatedSignature> for ValidatorAggregatedSignature { - type Error = bcs::Error; - - fn try_from( - value: &sui_sdk_types::types::ValidatorAggregatedSignature, - ) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - signature: bytes.into(), - }) - } -} - -impl TryFrom<&ValidatorAggregatedSignature> for sui_sdk_types::types::ValidatorAggregatedSignature { - type Error = bcs::Error; - - fn try_from(value: &ValidatorAggregatedSignature) -> Result { - bcs::from_bytes(&value.signature) - } -} - -impl TryFrom<&sui_types::crypto::AuthorityStrongQuorumSignInfo> for ValidatorAggregatedSignature { - type Error = bcs::Error; - - fn try_from( - value: &sui_types::crypto::AuthorityStrongQuorumSignInfo, - ) -> Result { - bcs::to_bytes(&value).map(|bytes| Self { - signature: bytes.into(), - }) - } -} - -impl TryFrom<&ValidatorAggregatedSignature> for sui_types::crypto::AuthorityStrongQuorumSignInfo { - type Error = bcs::Error; - - fn try_from(value: &ValidatorAggregatedSignature) -> Result { - bcs::from_bytes(&value.signature) - } -} - -// -// UserSignature -// - -impl TryFrom<&sui_sdk_types::types::UserSignature> for UserSignature { - type Error = bcs::Error; - - fn try_from(value: &sui_sdk_types::types::UserSignature) -> Result { - Ok(Self { - signature: value.to_bytes().into(), - }) - } -} - -impl TryFrom<&UserSignature> for sui_sdk_types::types::UserSignature { - type Error = bcs::Error; - - fn try_from(value: &UserSignature) -> Result { - Self::from_bytes(&value.signature).map_err(|e| bcs::Error::Custom(e.to_string())) - } -} - -impl TryFrom<&sui_types::signature::GenericSignature> for UserSignature { - type Error = bcs::Error; - - fn try_from(value: &sui_types::signature::GenericSignature) -> Result { - Ok(Self { - signature: sui_types::crypto::ToFromBytes::as_bytes(value) - .to_vec() - .into(), - }) - } -} - -impl TryFrom<&UserSignature> for sui_types::signature::GenericSignature { - type Error = bcs::Error; - - fn try_from(value: &UserSignature) -> Result { - sui_types::crypto::ToFromBytes::from_bytes(&value.signature) - .map_err(|e| bcs::Error::Custom(e.to_string())) - } -} - -// -// CheckpointTransaction -// - -impl TryFrom for CheckpointTransaction { - type Error = bcs::Error; - - fn try_from( - transaction: sui_types::full_checkpoint_content::CheckpointTransaction, - ) -> Result { - Ok(Self { - transaction: Some(Transaction::try_from( - &transaction.transaction.intent_message().value, - )?), - signatures: transaction - .transaction - .tx_signatures() - .iter() - .map(UserSignature::try_from) - .collect::>()?, - effects: Some(TransactionEffects::try_from(&transaction.effects)?), - events: transaction - .events - .as_ref() - .map(TransactionEvents::try_from) - .transpose()?, - input_objects: transaction - .input_objects - .iter() - .map(Object::try_from) - .collect::>()?, - output_objects: transaction - .output_objects - .iter() - .map(Object::try_from) - .collect::>()?, - }) - } -} - -impl TryFrom for sui_types::full_checkpoint_content::CheckpointTransaction { - type Error = bcs::Error; - - fn try_from(transaction: CheckpointTransaction) -> Result { - let transaction_data = transaction - .transaction - .ok_or_else(|| bcs::Error::Custom("missing transaction".into()))? - .pipe_ref(TryInto::try_into)?; - let user_signatures = transaction - .signatures - .iter() - .map(TryInto::try_into) - .collect::>()?; - - Ok(Self { - transaction: sui_types::transaction::Transaction::new( - sui_types::transaction::SenderSignedData::new(transaction_data, user_signatures), - ), - effects: transaction - .effects - .ok_or_else(|| bcs::Error::Custom("missing Effects".into()))? - .pipe_ref(TryInto::try_into)?, - events: transaction - .events - .as_ref() - .map(TryInto::try_into) - .transpose()?, - input_objects: transaction - .input_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - output_objects: transaction - .output_objects - .iter() - .map(TryInto::try_into) - .collect::>()?, - }) - } -} - -// -// FullCheckpoint -// - -impl TryFrom for FullCheckpoint { - type Error = bcs::Error; - - fn try_from( - c: sui_types::full_checkpoint_content::CheckpointData, - ) -> Result { - Ok(Self { - summary: Some(CheckpointSummary::try_from(c.checkpoint_summary.data())?), - signature: Some(ValidatorAggregatedSignature::try_from( - c.checkpoint_summary.auth_sig(), - )?), - contents: Some(CheckpointContents::try_from(&c.checkpoint_contents)?), - transactions: c - .transactions - .into_iter() - .map(TryInto::try_into) - .collect::>()?, - }) - } -} - -impl TryFrom for sui_types::full_checkpoint_content::CheckpointData { - type Error = bcs::Error; - - fn try_from(checkpoint: FullCheckpoint) -> Result { - let summary = checkpoint - .summary - .ok_or_else(|| bcs::Error::Custom("missing summary".into()))? - .pipe_ref(TryInto::try_into)?; - let signature = checkpoint - .signature - .ok_or_else(|| bcs::Error::Custom("missing signature".into()))? - .pipe_ref(TryInto::try_into)?; - let checkpoint_summary = - sui_types::messages_checkpoint::CertifiedCheckpointSummary::new_from_data_and_sig( - summary, signature, - ); - - let contents = checkpoint - .contents - .ok_or_else(|| bcs::Error::Custom("missing checkpoint contents".into()))? - .pipe_ref(TryInto::try_into)?; - - let transactions = checkpoint - .transactions - .into_iter() - .map(TryInto::try_into) - .collect::>()?; - - Ok(Self { - checkpoint_summary, - checkpoint_contents: contents, - transactions, - }) - } -} - -// -// Address -// - -impl From<&sui_sdk_types::types::Address> for Address { - fn from(value: &sui_sdk_types::types::Address) -> Self { - Self { - address: value.as_bytes().to_vec().into(), + if let Some(missing_field) = &self.missing_field { + write!(f, "missing_field: {missing_field}")?; } - } -} -impl TryFrom<&Address> for sui_sdk_types::types::Address { - type Error = bcs::Error; - - fn try_from(value: &Address) -> Result { - Self::from_bytes(&value.address).map_err(|e| bcs::Error::Custom(e.to_string())) - } -} - -impl TryFrom<&Address> for sui_types::base_types::SuiAddress { - type Error = bcs::Error; + if let Some(source) = &self.source { + write!(f, "source: {source}")?; + } - fn try_from(value: &Address) -> Result { - Self::from_bytes(&value.address).map_err(|e| bcs::Error::Custom(e.to_string())) + Ok(()) } } -// -// TypeTag -// - -impl From<&sui_sdk_types::types::TypeTag> for TypeTag { - fn from(value: &sui_sdk_types::types::TypeTag) -> Self { +impl TryFromProtoError { + pub fn missing(field: &'static str) -> Self { Self { - type_tag: value.to_string(), + missing_field: Some(field), + source: None, } } -} - -impl TryFrom<&TypeTag> for sui_sdk_types::types::TypeTag { - type Error = sui_sdk_types::types::TypeParseError; - - fn try_from(value: &TypeTag) -> Result { - value.type_tag.parse() - } -} - -impl TryFrom<&TypeTag> for sui_types::TypeTag { - type Error = bcs::Error; - - fn try_from(value: &TypeTag) -> Result { - value - .type_tag - .parse::() - .map_err(|e| bcs::Error::Custom(e.to_string())) - } -} - -// -// I128 -// -impl From for I128 { - fn from(value: i128) -> Self { + pub fn from_error>(error: E) -> Self { Self { - little_endian_bytes: value.to_le_bytes().to_vec().into(), + missing_field: None, + source: Some(error.into()), } } } -impl TryFrom<&I128> for i128 { - type Error = std::array::TryFromSliceError; - - fn try_from(value: &I128) -> Result { - Ok(i128::from_le_bytes( - value.little_endian_bytes.as_ref().try_into()?, - )) +impl From for TryFromProtoError { + fn from(value: std::num::TryFromIntError) -> Self { + Self::from_error(value) } } -// -// ValidatorCommitteeMember -// - -impl From<&sui_sdk_types::types::ValidatorCommitteeMember> for ValidatorCommitteeMember { - fn from(value: &sui_sdk_types::types::ValidatorCommitteeMember) -> Self { - Self { - public_key: value.public_key.as_bytes().to_vec().into(), - stake: value.stake, - } +impl From for TryFromProtoError { + fn from(value: std::str::Utf8Error) -> Self { + Self::from_error(value) } } -impl TryFrom for sui_sdk_types::types::ValidatorCommitteeMember { - type Error = bcs::Error; - - fn try_from(value: ValidatorCommitteeMember) -> Result { - Ok(Self { - public_key: sui_sdk_types::types::Bls12381PublicKey::from_bytes(&value.public_key) - .map_err(|e| bcs::Error::Custom(e.to_string()))?, - stake: value.stake, - }) +impl From for TryFromProtoError { + fn from(value: std::array::TryFromSliceError) -> Self { + Self::from_error(value) } } -// -// ValidatorCommittee -// - -impl From for ValidatorCommittee { - fn from(value: sui_sdk_types::types::ValidatorCommittee) -> Self { - Self { - epoch: value.epoch, - members: value - .members - .iter() - .map(ValidatorCommitteeMember::from) - .collect(), - } - } -} - -impl TryFrom for sui_sdk_types::types::ValidatorCommittee { - type Error = bcs::Error; - - fn try_from(value: ValidatorCommittee) -> Result { - Ok(Self { - epoch: value.epoch, - members: value - .members - .into_iter() - .map(TryInto::try_into) - .collect::>()?, - }) +impl From for TryFromProtoError { + fn from(_value: std::convert::Infallible) -> Self { + unreachable!() } } diff --git a/crates/sui-rpc-api/src/proto/node.rs b/crates/sui-rpc-api/src/proto/node.rs new file mode 100644 index 0000000000000..38cacb8506c04 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/node.rs @@ -0,0 +1,966 @@ +use super::types::proto_to_timestamp_ms; +use super::types::timestamp_ms_to_proto; +use super::TryFromProtoError; +use tap::Pipe; + +#[rustfmt::skip] +#[path = "generated/sui.node.v2.rs"] +mod generated; +pub use generated::*; + +// +// BalanceChange +// + +impl From for BalanceChange { + fn from(value: sui_sdk_types::types::BalanceChange) -> Self { + Self { + address: Some(value.address.into()), + coin_type: Some(value.coin_type.into()), + amount: Some(value.amount.into()), + } + } +} + +impl TryFrom<&BalanceChange> for sui_sdk_types::types::BalanceChange { + type Error = TryFromProtoError; + + fn try_from(value: &BalanceChange) -> Result { + let address = value + .address + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("address"))? + .pipe(TryInto::try_into)?; + let coin_type = value + .coin_type + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("coin_type"))? + .pipe(TryInto::try_into)?; + let amount = value + .amount + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("amount"))? + .pipe(TryInto::try_into)?; + Ok(Self { + address, + coin_type, + amount, + }) + } +} + +// +// NodeInfo +// + +impl From for GetNodeInfoResponse { + fn from( + crate::types::NodeInfo { + chain_id, + chain, + epoch, + checkpoint_height, + timestamp_ms, + lowest_available_checkpoint, + lowest_available_checkpoint_objects, + software_version, + }: crate::types::NodeInfo, + ) -> Self { + Self { + chain_id: Some(chain_id.into()), + chain: Some(chain.into()), + epoch: Some(epoch), + checkpoint_height: Some(checkpoint_height), + timestamp: Some(timestamp_ms_to_proto(timestamp_ms)), + lowest_available_checkpoint, + lowest_available_checkpoint_objects, + software_version: Some(software_version.into()), + } + } +} + +impl TryFrom<&GetNodeInfoResponse> for crate::types::NodeInfo { + type Error = TryFromProtoError; + + fn try_from( + GetNodeInfoResponse { + chain_id, + chain, + epoch, + checkpoint_height, + timestamp, + lowest_available_checkpoint, + lowest_available_checkpoint_objects, + software_version, + }: &GetNodeInfoResponse, + ) -> Result { + let chain_id = chain_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("chain_id"))? + .pipe(TryInto::try_into)?; + let chain = chain + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("chain"))? + .to_owned() + .into(); + let timestamp_ms = timestamp + .ok_or_else(|| TryFromProtoError::missing("timestamp"))? + .pipe(proto_to_timestamp_ms)?; + + let epoch = epoch.ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let checkpoint_height = + checkpoint_height.ok_or_else(|| TryFromProtoError::missing("checkpoint_height"))?; + + let software_version = software_version + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("software_version"))? + .to_owned() + .into(); + + Self { + chain_id, + chain, + epoch, + checkpoint_height, + timestamp_ms, + lowest_available_checkpoint: *lowest_available_checkpoint, + lowest_available_checkpoint_objects: *lowest_available_checkpoint_objects, + software_version, + } + .pipe(Ok) + } +} + +// +// GetObjectOptions +// + +impl From for GetObjectOptions { + fn from( + crate::types::GetObjectOptions { object, object_bcs }: crate::types::GetObjectOptions, + ) -> Self { + Self { object, object_bcs } + } +} + +impl From for crate::types::GetObjectOptions { + fn from(GetObjectOptions { object, object_bcs }: GetObjectOptions) -> Self { + Self { object, object_bcs } + } +} + +// +// ObjectResponse +// + +impl From for GetObjectResponse { + fn from( + crate::types::ObjectResponse { + object_id, + version, + digest, + object, + object_bcs, + }: crate::types::ObjectResponse, + ) -> Self { + Self { + object_id: Some(object_id.into()), + version: Some(version), + digest: Some(digest.into()), + object: object.map(Into::into), + object_bcs: object_bcs.map(Into::into), + } + } +} + +impl TryFrom<&GetObjectResponse> for crate::types::ObjectResponse { + type Error = TryFromProtoError; + + fn try_from( + GetObjectResponse { + object_id, + version, + digest, + object, + object_bcs, + }: &GetObjectResponse, + ) -> Result { + let object_id = object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .pipe(TryInto::try_into)?; + let version = version.ok_or_else(|| TryFromProtoError::missing("version"))?; + let digest = digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .pipe(TryInto::try_into)?; + + let object = object.as_ref().map(TryInto::try_into).transpose()?; + let object_bcs = object_bcs.as_ref().map(Into::into); + + Self { + object_id, + version, + digest, + object, + object_bcs, + } + .pipe(Ok) + } +} + +// +// GetCheckpointOptions +// + +impl From for GetCheckpointOptions { + fn from( + crate::types::GetCheckpointOptions { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + }: crate::types::GetCheckpointOptions, + ) -> Self { + Self { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + } + } +} + +impl From for crate::types::GetCheckpointOptions { + fn from( + GetCheckpointOptions { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + }: GetCheckpointOptions, + ) -> Self { + Self { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + } + } +} + +// +// GetTransactionOptions +// + +impl From for GetTransactionOptions { + fn from( + crate::types::GetTransactionOptions { + transaction, + transaction_bcs, + signatures, + effects, + effects_bcs, + events, + events_bcs, + }: crate::types::GetTransactionOptions, + ) -> Self { + Self { + transaction, + transaction_bcs, + signatures, + effects, + effects_bcs, + events, + events_bcs, + } + } +} + +impl From for crate::types::GetTransactionOptions { + fn from( + GetTransactionOptions { + transaction, + transaction_bcs, + signatures, + effects, + effects_bcs, + events, + events_bcs, + }: GetTransactionOptions, + ) -> Self { + Self { + transaction, + transaction_bcs, + signatures, + effects, + effects_bcs, + events, + events_bcs, + } + } +} + +// +// ExecuteTransactionOptions +// + +impl From for ExecuteTransactionOptions { + fn from( + crate::types::ExecuteTransactionOptions { + effects, + effects_bcs, + events, + events_bcs, + balance_changes, + }: crate::types::ExecuteTransactionOptions, + ) -> Self { + Self { + effects, + effects_bcs, + events, + events_bcs, + balance_changes, + } + } +} + +impl From for crate::types::ExecuteTransactionOptions { + fn from( + ExecuteTransactionOptions { + effects, + effects_bcs, + events, + events_bcs, + balance_changes, + }: ExecuteTransactionOptions, + ) -> Self { + Self { + effects, + effects_bcs, + events, + events_bcs, + balance_changes, + } + } +} + +// +// GetFullCheckpointOptions +// + +impl From for GetFullCheckpointOptions { + fn from( + crate::types::GetFullCheckpointOptions { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + object, + object_bcs, + }: crate::types::GetFullCheckpointOptions, + ) -> Self { + Self { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + object, + object_bcs, + } + } +} + +impl From for crate::types::GetFullCheckpointOptions { + fn from( + GetFullCheckpointOptions { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + object, + object_bcs, + }: GetFullCheckpointOptions, + ) -> Self { + Self { + summary, + summary_bcs, + signature, + contents, + contents_bcs, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + object, + object_bcs, + } + } +} + +// +// TransactionResponse +// + +impl From for GetTransactionResponse { + fn from( + crate::types::TransactionResponse { + digest, + transaction, + transaction_bcs, + signatures, + effects, + effects_bcs, + events, + events_bcs, + checkpoint, + timestamp_ms, + }: crate::types::TransactionResponse, + ) -> Self { + let signatures = signatures.map(|signatures| UserSignatures { + signatures: signatures.into_iter().map(Into::into).collect(), + }); + + Self { + digest: Some(digest.into()), + transaction: transaction.map(Into::into), + transaction_bcs: transaction_bcs.map(Into::into), + signatures, + effects: effects.map(Into::into), + effects_bcs: effects_bcs.map(Into::into), + events: events.map(Into::into), + events_bcs: events_bcs.map(Into::into), + checkpoint, + timestamp: timestamp_ms.map(timestamp_ms_to_proto), + } + } +} + +impl TryFrom<&GetTransactionResponse> for crate::types::TransactionResponse { + type Error = TryFromProtoError; + + fn try_from( + GetTransactionResponse { + digest, + transaction, + transaction_bcs, + signatures, + effects, + effects_bcs, + events, + events_bcs, + checkpoint, + timestamp, + }: &GetTransactionResponse, + ) -> Result { + let digest = digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .pipe(TryInto::try_into)?; + + let transaction = transaction.as_ref().map(TryInto::try_into).transpose()?; + let transaction_bcs = transaction_bcs.as_ref().map(Into::into); + + let signatures = signatures + .as_ref() + .map(|signatures| { + signatures + .signatures + .iter() + .map(TryInto::try_into) + .collect::, _>>() + }) + .transpose()?; + + let effects = effects.as_ref().map(TryInto::try_into).transpose()?; + let effects_bcs = effects_bcs.as_ref().map(Into::into); + + let events = events.as_ref().map(TryInto::try_into).transpose()?; + let events_bcs = events_bcs.as_ref().map(Into::into); + + let timestamp_ms = timestamp.map(proto_to_timestamp_ms).transpose()?; + + Self { + digest, + transaction, + transaction_bcs, + signatures, + effects, + effects_bcs, + events, + events_bcs, + checkpoint: *checkpoint, + timestamp_ms, + } + .pipe(Ok) + } +} + +// +// CheckpointResponse +// + +impl From for GetCheckpointResponse { + fn from( + crate::types::CheckpointResponse { + sequence_number, + digest, + summary, + summary_bcs, + signature, + contents, + contents_bcs, + }: crate::types::CheckpointResponse, + ) -> Self { + Self { + sequence_number: Some(sequence_number), + digest: Some(digest.into()), + summary: summary.map(Into::into), + summary_bcs: summary_bcs.map(Into::into), + signature: signature.map(Into::into), + contents: contents.map(Into::into), + contents_bcs: contents_bcs.map(Into::into), + } + } +} + +impl TryFrom<&GetCheckpointResponse> for crate::types::CheckpointResponse { + type Error = TryFromProtoError; + + fn try_from( + GetCheckpointResponse { + sequence_number, + digest, + summary, + summary_bcs, + signature, + contents, + contents_bcs, + }: &GetCheckpointResponse, + ) -> Result { + let sequence_number = + sequence_number.ok_or_else(|| TryFromProtoError::missing("sequence_number"))?; + let digest = digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .pipe(TryInto::try_into)?; + + let summary = summary.as_ref().map(TryInto::try_into).transpose()?; + let summary_bcs = summary_bcs.as_ref().map(Into::into); + + let signature = signature.as_ref().map(TryInto::try_into).transpose()?; + + let contents = contents.as_ref().map(TryInto::try_into).transpose()?; + let contents_bcs = contents_bcs.as_ref().map(Into::into); + + Self { + sequence_number, + digest, + summary, + summary_bcs, + signature, + contents, + contents_bcs, + } + .pipe(Ok) + } +} + +// +// FullCheckpointResponse +// + +impl From for GetFullCheckpointResponse { + fn from( + crate::types::FullCheckpointResponse { + sequence_number, + digest, + summary, + summary_bcs, + signature, + contents, + contents_bcs, + transactions, + }: crate::types::FullCheckpointResponse, + ) -> Self { + Self { + sequence_number: Some(sequence_number), + digest: Some(digest.into()), + summary: summary.map(Into::into), + summary_bcs: summary_bcs.map(Into::into), + signature: signature.map(Into::into), + contents: contents.map(Into::into), + contents_bcs: contents_bcs.map(Into::into), + transactions: transactions.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&GetFullCheckpointResponse> for crate::types::FullCheckpointResponse { + type Error = TryFromProtoError; + + fn try_from( + GetFullCheckpointResponse { + sequence_number, + digest, + summary, + summary_bcs, + signature, + contents, + contents_bcs, + transactions, + }: &GetFullCheckpointResponse, + ) -> Result { + let sequence_number = + sequence_number.ok_or_else(|| TryFromProtoError::missing("sequence_number"))?; + let digest = digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .pipe(TryInto::try_into)?; + + let summary = summary.as_ref().map(TryInto::try_into).transpose()?; + let summary_bcs = summary_bcs.as_ref().map(Into::into); + + let signature = signature.as_ref().map(TryInto::try_into).transpose()?; + + let contents = contents.as_ref().map(TryInto::try_into).transpose()?; + let contents_bcs = contents_bcs.as_ref().map(Into::into); + + let transactions = transactions + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Self { + sequence_number, + digest, + summary, + summary_bcs, + signature, + contents, + contents_bcs, + transactions, + } + .pipe(Ok) + } +} + +// +// FullCheckpointObject +// + +impl From for FullCheckpointObject { + fn from( + crate::types::FullCheckpointObject { + object_id, + version, + digest, + object, + object_bcs, + }: crate::types::FullCheckpointObject, + ) -> Self { + Self { + object_id: Some(object_id.into()), + version: Some(version), + digest: Some(digest.into()), + object: object.map(Into::into), + object_bcs: object_bcs.map(Into::into), + } + } +} + +impl TryFrom<&FullCheckpointObject> for crate::types::FullCheckpointObject { + type Error = TryFromProtoError; + + fn try_from( + FullCheckpointObject { + object_id, + version, + digest, + object, + object_bcs, + }: &FullCheckpointObject, + ) -> Result { + let object_id = object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .pipe(TryInto::try_into)?; + let version = version.ok_or_else(|| TryFromProtoError::missing("version"))?; + let digest = digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .pipe(TryInto::try_into)?; + + let object = object.as_ref().map(TryInto::try_into).transpose()?; + let object_bcs = object_bcs.as_ref().map(Into::into); + + Self { + object_id, + version, + digest, + object, + object_bcs, + } + .pipe(Ok) + } +} + +// +// FullCheckpointTransaction +// + +impl From for FullCheckpointTransaction { + fn from( + crate::types::FullCheckpointTransaction { + digest, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + }: crate::types::FullCheckpointTransaction, + ) -> Self { + let input_objects = input_objects.map(|objects| FullCheckpointObjects { + objects: objects.into_iter().map(Into::into).collect(), + }); + let output_objects = output_objects.map(|objects| FullCheckpointObjects { + objects: objects.into_iter().map(Into::into).collect(), + }); + Self { + digest: Some(digest.into()), + transaction: transaction.map(Into::into), + transaction_bcs: transaction_bcs.map(Into::into), + effects: effects.map(Into::into), + effects_bcs: effects_bcs.map(Into::into), + events: events.map(Into::into), + events_bcs: events_bcs.map(Into::into), + input_objects, + output_objects, + } + } +} + +impl TryFrom<&FullCheckpointTransaction> for crate::types::FullCheckpointTransaction { + type Error = TryFromProtoError; + + fn try_from( + FullCheckpointTransaction { + digest, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + }: &FullCheckpointTransaction, + ) -> Result { + let digest = digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .pipe(TryInto::try_into)?; + + let transaction = transaction.as_ref().map(TryInto::try_into).transpose()?; + let transaction_bcs = transaction_bcs.as_ref().map(Into::into); + + let effects = effects.as_ref().map(TryInto::try_into).transpose()?; + let effects_bcs = effects_bcs.as_ref().map(Into::into); + + let events = events.as_ref().map(TryInto::try_into).transpose()?; + let events_bcs = events_bcs.as_ref().map(Into::into); + + let input_objects = input_objects + .as_ref() + .map(|objects| { + objects + .objects + .iter() + .map(TryInto::try_into) + .collect::>() + }) + .transpose()?; + + let output_objects = output_objects + .as_ref() + .map(|objects| { + objects + .objects + .iter() + .map(TryInto::try_into) + .collect::>() + }) + .transpose()?; + + Self { + digest, + transaction, + transaction_bcs, + effects, + effects_bcs, + events, + events_bcs, + input_objects, + output_objects, + } + .pipe(Ok) + } +} + +// +// ExecuteTransactionResponse +// + +impl From for ExecuteTransactionResponse { + fn from( + crate::types::ExecuteTransactionResponse { + finality, + effects, + effects_bcs, + events, + events_bcs, + balance_changes, + }: crate::types::ExecuteTransactionResponse, + ) -> Self { + let balance_changes = balance_changes.map(|balance_changes| BalanceChanges { + balance_changes: balance_changes.into_iter().map(Into::into).collect(), + }); + Self { + finality: Some(finality.into()), + effects: effects.map(Into::into), + effects_bcs: effects_bcs.map(Into::into), + events: events.map(Into::into), + events_bcs: events_bcs.map(Into::into), + balance_changes, + } + } +} + +impl TryFrom<&ExecuteTransactionResponse> for crate::types::ExecuteTransactionResponse { + type Error = TryFromProtoError; + + fn try_from( + ExecuteTransactionResponse { + finality, + effects, + effects_bcs, + events, + events_bcs, + balance_changes, + }: &ExecuteTransactionResponse, + ) -> Result { + let finality = finality + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("finality"))? + .pipe(TryInto::try_into)?; + + let effects = effects.as_ref().map(TryInto::try_into).transpose()?; + let effects_bcs = effects_bcs.as_ref().map(Into::into); + + let events = events.as_ref().map(TryInto::try_into).transpose()?; + let events_bcs = events_bcs.as_ref().map(Into::into); + + let balance_changes = balance_changes + .as_ref() + .map(|balance_changes| { + balance_changes + .balance_changes + .iter() + .map(TryInto::try_into) + .collect::>() + }) + .transpose()?; + + Self { + finality, + effects, + effects_bcs, + events, + events_bcs, + balance_changes, + } + .pipe(Ok) + } +} + +// +// EffectsFinality +// + +impl From for crate::proto::node::EffectsFinality { + fn from(value: crate::types::EffectsFinality) -> Self { + use crate::proto::node::effects_finality::Finality; + use crate::types::EffectsFinality::*; + + let finality = match value { + Certified { signature } => Finality::Certified(signature.into()), + Checkpointed { checkpoint } => Finality::Checkpointed(checkpoint), + QuorumExecuted => Finality::QuorumExecuted(()), + }; + + Self { + finality: Some(finality), + } + } +} + +impl TryFrom<&crate::proto::node::EffectsFinality> for crate::types::EffectsFinality { + type Error = crate::proto::TryFromProtoError; + + fn try_from(value: &crate::proto::node::EffectsFinality) -> Result { + use crate::proto::node::effects_finality::Finality; + + match value + .finality + .as_ref() + .ok_or_else(|| crate::proto::TryFromProtoError::missing("finality"))? + { + Finality::Certified(signature) => Self::Certified { + signature: signature.try_into()?, + }, + Finality::Checkpointed(checkpoint) => Self::Checkpointed { + checkpoint: *checkpoint, + }, + Finality::QuorumExecuted(()) => Self::QuorumExecuted, + } + .pipe(Ok) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/checkpoint.rs b/crates/sui-rpc-api/src/proto/types/checkpoint.rs new file mode 100644 index 0000000000000..255d5b62a60ef --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/checkpoint.rs @@ -0,0 +1,320 @@ +use super::TryFromProtoError; +use tap::Pipe; + +// +// CheckpointSummary +// + +impl From for super::CheckpointSummary { + fn from( + sui_sdk_types::types::CheckpointSummary { + epoch, + sequence_number, + network_total_transactions, + content_digest, + previous_digest, + epoch_rolling_gas_cost_summary, + timestamp_ms, + checkpoint_commitments, + end_of_epoch_data, + version_specific_data, + }: sui_sdk_types::types::CheckpointSummary, + ) -> Self { + Self { + epoch: Some(epoch), + sequence_number: Some(sequence_number), + total_network_transactions: Some(network_total_transactions), + content_digest: Some(content_digest.into()), + previous_digest: previous_digest.map(Into::into), + epoch_rolling_gas_cost_summary: Some(epoch_rolling_gas_cost_summary.into()), + timestamp_ms: Some(timestamp_ms), + commitments: checkpoint_commitments.into_iter().map(Into::into).collect(), + end_of_epoch_data: end_of_epoch_data.map(Into::into), + version_specific_data: Some(version_specific_data.into()), + } + } +} + +impl TryFrom<&super::CheckpointSummary> for sui_sdk_types::types::CheckpointSummary { + type Error = TryFromProtoError; + + fn try_from( + super::CheckpointSummary { + epoch, + sequence_number, + total_network_transactions, + content_digest, + previous_digest, + epoch_rolling_gas_cost_summary, + timestamp_ms, + commitments, + end_of_epoch_data, + version_specific_data, + }: &super::CheckpointSummary, + ) -> Result { + let epoch = epoch.ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let sequence_number = + sequence_number.ok_or_else(|| TryFromProtoError::missing("sequence_number"))?; + let network_total_transactions = total_network_transactions + .ok_or_else(|| TryFromProtoError::missing("total_network_transactions"))?; + let content_digest = content_digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("content_digest"))? + .try_into()?; + let previous_digest = previous_digest + .as_ref() + .map(TryInto::try_into) + .transpose()?; + let epoch_rolling_gas_cost_summary = epoch_rolling_gas_cost_summary + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("epoch_rolling_gas_cost_summary"))? + .try_into()?; + + let timestamp_ms = + timestamp_ms.ok_or_else(|| TryFromProtoError::missing("timestamp_ms"))?; + + let checkpoint_commitments = commitments + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let end_of_epoch_data = end_of_epoch_data + .as_ref() + .map(TryInto::try_into) + .transpose()?; + + let version_specific_data = version_specific_data + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("version_specific_data"))? + .to_vec(); + + Ok(Self { + epoch, + sequence_number, + network_total_transactions, + content_digest, + previous_digest, + epoch_rolling_gas_cost_summary, + timestamp_ms, + checkpoint_commitments, + end_of_epoch_data, + version_specific_data, + }) + } +} + +// +// GasCostSummary +// + +impl From for super::GasCostSummary { + fn from( + sui_sdk_types::types::GasCostSummary { + computation_cost, + storage_cost, + storage_rebate, + non_refundable_storage_fee, + }: sui_sdk_types::types::GasCostSummary, + ) -> Self { + Self { + computation_cost: Some(computation_cost), + storage_cost: Some(storage_cost), + storage_rebate: Some(storage_rebate), + non_refundable_storage_fee: Some(non_refundable_storage_fee), + } + } +} + +impl TryFrom<&super::GasCostSummary> for sui_sdk_types::types::GasCostSummary { + type Error = TryFromProtoError; + + fn try_from( + super::GasCostSummary { + computation_cost, + storage_cost, + storage_rebate, + non_refundable_storage_fee, + }: &super::GasCostSummary, + ) -> Result { + let computation_cost = + computation_cost.ok_or_else(|| TryFromProtoError::missing("computation_cost"))?; + let storage_cost = + storage_cost.ok_or_else(|| TryFromProtoError::missing("storage_cost"))?; + let storage_rebate = + storage_rebate.ok_or_else(|| TryFromProtoError::missing("storage_rebate"))?; + let non_refundable_storage_fee = non_refundable_storage_fee + .ok_or_else(|| TryFromProtoError::missing("non_refundable_storage_fee"))?; + Ok(Self { + computation_cost, + storage_cost, + storage_rebate, + non_refundable_storage_fee, + }) + } +} + +// +// CheckpointCommitment +// + +impl From for super::CheckpointCommitment { + fn from(value: sui_sdk_types::types::CheckpointCommitment) -> Self { + let commitment = match value { + sui_sdk_types::types::CheckpointCommitment::EcmhLiveObjectSet { digest } => { + super::checkpoint_commitment::Commitment::EcmhLiveObjectSet(digest.into()) + } + }; + + Self { + commitment: Some(commitment), + } + } +} + +impl TryFrom<&super::CheckpointCommitment> for sui_sdk_types::types::CheckpointCommitment { + type Error = TryFromProtoError; + + fn try_from(value: &super::CheckpointCommitment) -> Result { + match value + .commitment + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("commitment"))? + { + super::checkpoint_commitment::Commitment::EcmhLiveObjectSet(digest) => { + Self::EcmhLiveObjectSet { + digest: digest.try_into()?, + } + } + } + .pipe(Ok) + } +} + +// +// EndOfEpochData +// + +impl From for super::EndOfEpochData { + fn from( + sui_sdk_types::types::EndOfEpochData { + next_epoch_committee, + next_epoch_protocol_version, + epoch_commitments, + }: sui_sdk_types::types::EndOfEpochData, + ) -> Self { + Self { + next_epoch_committee: next_epoch_committee.into_iter().map(Into::into).collect(), + next_epoch_protocol_version: Some(next_epoch_protocol_version), + epoch_commitments: epoch_commitments.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::EndOfEpochData> for sui_sdk_types::types::EndOfEpochData { + type Error = TryFromProtoError; + + fn try_from( + super::EndOfEpochData { + next_epoch_committee, + next_epoch_protocol_version, + epoch_commitments, + }: &super::EndOfEpochData, + ) -> Result { + let next_epoch_protocol_version = next_epoch_protocol_version + .ok_or_else(|| TryFromProtoError::missing("next_epoch_protocol_version"))?; + + Ok(Self { + next_epoch_committee: next_epoch_committee + .iter() + .map(TryInto::try_into) + .collect::>()?, + next_epoch_protocol_version, + epoch_commitments: epoch_commitments + .iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +// +// CheckpointedTransactionInfo +// + +impl From for super::CheckpointedTransactionInfo { + fn from(value: sui_sdk_types::types::CheckpointTransactionInfo) -> Self { + Self { + transaction: Some(value.transaction.into()), + effects: Some(value.effects.into()), + signatures: value.signatures.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::CheckpointedTransactionInfo> + for sui_sdk_types::types::CheckpointTransactionInfo +{ + type Error = TryFromProtoError; + + fn try_from(value: &super::CheckpointedTransactionInfo) -> Result { + let transaction = value + .transaction + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("transaction"))? + .try_into()?; + + let effects = value + .effects + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("effects"))? + .try_into()?; + + let signatures = value + .signatures + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + transaction, + effects, + signatures, + }) + } +} + +// +// CheckpointContents +// + +impl From for super::CheckpointContents { + fn from(value: sui_sdk_types::types::CheckpointContents) -> Self { + let contents = super::checkpoint_contents::Contents::V1(super::checkpoint_contents::V1 { + transactions: value.into_v1().into_iter().map(Into::into).collect(), + }); + + Self { + contents: Some(contents), + } + } +} + +impl TryFrom<&super::CheckpointContents> for sui_sdk_types::types::CheckpointContents { + type Error = TryFromProtoError; + + fn try_from(value: &super::CheckpointContents) -> Result { + match value + .contents + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("commitment"))? + { + super::checkpoint_contents::Contents::V1(v1) => Self::new( + v1.transactions + .iter() + .map(TryInto::try_into) + .collect::>()?, + ), + } + .pipe(Ok) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/effects.rs b/crates/sui-rpc-api/src/proto/types/effects.rs new file mode 100644 index 0000000000000..1c20d4acef63e --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/effects.rs @@ -0,0 +1,634 @@ +use super::TryFromProtoError; +use tap::Pipe; + +// +// TransactionEffects +// + +impl From for super::TransactionEffects { + fn from(value: sui_sdk_types::types::TransactionEffects) -> Self { + use super::transaction_effects::Version; + use sui_sdk_types::types::TransactionEffects::*; + + let version = match value { + V1(v1) => Version::V1((*v1).into()), + V2(v2) => Version::V2((*v2).into()), + }; + + Self { + version: Some(version), + } + } +} + +impl TryFrom<&super::TransactionEffects> for sui_sdk_types::types::TransactionEffects { + type Error = TryFromProtoError; + + fn try_from(value: &super::TransactionEffects) -> Result { + use super::transaction_effects::Version::*; + + match value + .version + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("version"))? + { + V1(v1) => Self::V1(Box::new(v1.try_into()?)), + V2(v2) => Self::V2(Box::new(v2.try_into()?)), + } + .pipe(Ok) + } +} + +// +// TransactionEffectsV1 +// + +impl From for super::TransactionEffectsV1 { + fn from( + sui_sdk_types::types::TransactionEffectsV1 { + status, + epoch, + gas_used, + modified_at_versions, + shared_objects, + transaction_digest, + created, + mutated, + unwrapped, + deleted, + unwrapped_then_deleted, + wrapped, + gas_object, + events_digest, + dependencies, + }: sui_sdk_types::types::TransactionEffectsV1, + ) -> Self { + Self { + status: Some(status.into()), + epoch: Some(epoch), + gas_used: Some(gas_used.into()), + modified_at_versions: modified_at_versions.into_iter().map(Into::into).collect(), + shared_objects: shared_objects.into_iter().map(Into::into).collect(), + transaction_digest: Some(transaction_digest.into()), + created: created.into_iter().map(Into::into).collect(), + mutated: mutated.into_iter().map(Into::into).collect(), + unwrapped: unwrapped.into_iter().map(Into::into).collect(), + deleted: deleted.into_iter().map(Into::into).collect(), + unwrapped_then_deleted: unwrapped_then_deleted.into_iter().map(Into::into).collect(), + wrapped: wrapped.into_iter().map(Into::into).collect(), + gas_object: Some(gas_object.into()), + events_digest: events_digest.map(Into::into), + dependencies: dependencies.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::TransactionEffectsV1> for sui_sdk_types::types::TransactionEffectsV1 { + type Error = TryFromProtoError; + + fn try_from( + super::TransactionEffectsV1 { + status, + epoch, + gas_used, + modified_at_versions, + shared_objects, + transaction_digest, + created, + mutated, + unwrapped, + deleted, + unwrapped_then_deleted, + wrapped, + gas_object, + events_digest, + dependencies, + }: &super::TransactionEffectsV1, + ) -> Result { + let status = status + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("status"))? + .try_into()?; + + let epoch = epoch.ok_or_else(|| TryFromProtoError::missing("epoch"))?; + + let gas_used = gas_used + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("gas_used"))? + .try_into()?; + + let transaction_digest = transaction_digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("transaction_digest"))? + .try_into()?; + + let modified_at_versions = modified_at_versions + .iter() + .map(TryInto::try_into) + .collect::>()?; + let shared_objects = shared_objects + .iter() + .map(TryInto::try_into) + .collect::>()?; + let created = created + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let mutated = mutated + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let unwrapped = unwrapped + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let deleted = deleted + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let unwrapped_then_deleted = unwrapped_then_deleted + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let wrapped = wrapped + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let gas_object = gas_object + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("gas_object"))? + .try_into()?; + + let events_digest = events_digest.as_ref().map(TryInto::try_into).transpose()?; + + let dependencies = dependencies + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + status, + epoch, + gas_used, + modified_at_versions, + shared_objects, + transaction_digest, + created, + mutated, + unwrapped, + deleted, + unwrapped_then_deleted, + wrapped, + gas_object, + events_digest, + dependencies, + }) + } +} + +// +// TransactionEffectsV2 +// + +impl From for super::TransactionEffectsV2 { + fn from( + sui_sdk_types::types::TransactionEffectsV2 { + status, + epoch, + gas_used, + transaction_digest, + gas_object_index, + events_digest, + dependencies, + lamport_version, + changed_objects, + unchanged_shared_objects, + auxiliary_data_digest, + }: sui_sdk_types::types::TransactionEffectsV2, + ) -> Self { + Self { + status: Some(status.into()), + epoch: Some(epoch), + gas_used: Some(gas_used.into()), + transaction_digest: Some(transaction_digest.into()), + gas_object_index, + events_digest: events_digest.map(Into::into), + dependencies: dependencies.into_iter().map(Into::into).collect(), + lamport_version: Some(lamport_version), + changed_objects: changed_objects.into_iter().map(Into::into).collect(), + unchanged_shared_objects: unchanged_shared_objects + .into_iter() + .map(Into::into) + .collect(), + auxiliary_data_digest: auxiliary_data_digest.map(Into::into), + } + } +} + +impl TryFrom<&super::TransactionEffectsV2> for sui_sdk_types::types::TransactionEffectsV2 { + type Error = TryFromProtoError; + + fn try_from( + super::TransactionEffectsV2 { + status, + epoch, + gas_used, + transaction_digest, + gas_object_index, + events_digest, + dependencies, + lamport_version, + changed_objects, + unchanged_shared_objects, + auxiliary_data_digest, + }: &super::TransactionEffectsV2, + ) -> Result { + let status = status + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("status"))? + .try_into()?; + let epoch = epoch.ok_or_else(|| TryFromProtoError::missing("epoch"))?; + + let gas_used = gas_used + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("gas_used"))? + .try_into()?; + + let transaction_digest = transaction_digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("transaction_digest"))? + .try_into()?; + + let events_digest = events_digest.as_ref().map(TryInto::try_into).transpose()?; + + let dependencies = dependencies + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let lamport_version = + lamport_version.ok_or_else(|| TryFromProtoError::missing("lamport_version"))?; + + let changed_objects = changed_objects + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let unchanged_shared_objects = unchanged_shared_objects + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let auxiliary_data_digest = auxiliary_data_digest + .as_ref() + .map(TryInto::try_into) + .transpose()?; + + Ok(Self { + status, + epoch, + gas_used, + transaction_digest, + gas_object_index: *gas_object_index, + events_digest, + dependencies, + lamport_version, + changed_objects, + unchanged_shared_objects, + auxiliary_data_digest, + }) + } +} + +// +// ModifiedAtVersion +// + +impl From for super::ModifiedAtVersion { + fn from(value: sui_sdk_types::types::ModifiedAtVersion) -> Self { + Self { + object_id: Some(value.object_id.into()), + version: Some(value.version), + } + } +} + +impl TryFrom<&super::ModifiedAtVersion> for sui_sdk_types::types::ModifiedAtVersion { + type Error = TryFromProtoError; + + fn try_from(value: &super::ModifiedAtVersion) -> Result { + let object_id = value + .object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .try_into()?; + let version = value + .version + .ok_or_else(|| TryFromProtoError::missing("version"))?; + + Ok(Self { object_id, version }) + } +} + +// +// ObjectReferenceWithOwner +// + +impl From for super::ObjectReferenceWithOwner { + fn from(value: sui_sdk_types::types::ObjectReferenceWithOwner) -> Self { + Self { + reference: Some(value.reference.into()), + owner: Some(value.owner.into()), + } + } +} + +impl TryFrom<&super::ObjectReferenceWithOwner> for sui_sdk_types::types::ObjectReferenceWithOwner { + type Error = TryFromProtoError; + + fn try_from(value: &super::ObjectReferenceWithOwner) -> Result { + let reference = value + .reference + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("reference"))? + .try_into()?; + + let owner = value + .owner + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("owner"))? + .try_into()?; + + Ok(Self { reference, owner }) + } +} + +// +// ChangedObject +// + +impl From for super::ChangedObject { + fn from(value: sui_sdk_types::types::ChangedObject) -> Self { + Self { + object_id: Some(value.object_id.into()), + input_state: Some(value.change.input_state.into()), + output_state: Some(value.change.output_state.into()), + id_operation: Some(value.change.id_operation.into()), + } + } +} + +impl TryFrom<&super::ChangedObject> for sui_sdk_types::types::ChangedObject { + type Error = TryFromProtoError; + + fn try_from(value: &super::ChangedObject) -> Result { + let object_id = value + .object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .try_into()?; + + let input_state = value + .input_state + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("input_state"))? + .try_into()?; + + let output_state = value + .output_state + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("output_state"))? + .try_into()?; + + let id_operation = value + .id_operation + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("id_operation"))? + .try_into()?; + + Ok(Self { + object_id, + change: sui_sdk_types::types::EffectsObjectChange { + input_state, + output_state, + id_operation, + }, + }) + } +} + +// +// InputState +// + +impl From for super::changed_object::InputState { + fn from(value: sui_sdk_types::types::ObjectIn) -> Self { + match value { + sui_sdk_types::types::ObjectIn::NotExist => Self::NotExist(()), + sui_sdk_types::types::ObjectIn::Exist { + version, + digest, + owner, + } => Self::Exist(super::ObjectExist { + version: Some(version), + digest: Some(digest.into()), + owner: Some(owner.into()), + }), + } + } +} + +impl TryFrom<&super::changed_object::InputState> for sui_sdk_types::types::ObjectIn { + type Error = TryFromProtoError; + + fn try_from(value: &super::changed_object::InputState) -> Result { + use super::changed_object::InputState::*; + + match value { + NotExist(()) => Self::NotExist, + Exist(super::ObjectExist { + version, + digest, + owner, + }) => Self::Exist { + version: version.ok_or_else(|| TryFromProtoError::missing("version"))?, + digest: digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .try_into()?, + owner: owner + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("owner"))? + .try_into()?, + }, + } + .pipe(Ok) + } +} + +// +// OutputState +// + +impl From for super::changed_object::OutputState { + fn from(value: sui_sdk_types::types::ObjectOut) -> Self { + use sui_sdk_types::types::ObjectOut::*; + match value { + NotExist => Self::Removed(()), + ObjectWrite { digest, owner } => Self::ObjectWrite(super::ObjectWrite { + digest: Some(digest.into()), + owner: Some(owner.into()), + }), + PackageWrite { version, digest } => Self::PackageWrite(super::PackageWrite { + version: Some(version), + digest: Some(digest.into()), + }), + } + } +} + +impl TryFrom<&super::changed_object::OutputState> for sui_sdk_types::types::ObjectOut { + type Error = TryFromProtoError; + + fn try_from(value: &super::changed_object::OutputState) -> Result { + use super::changed_object::OutputState::*; + + match value { + Removed(()) => Self::NotExist, + ObjectWrite(super::ObjectWrite { digest, owner }) => Self::ObjectWrite { + digest: digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .try_into()?, + + owner: owner + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("owner"))? + .try_into()?, + }, + PackageWrite(super::PackageWrite { version, digest }) => Self::PackageWrite { + version: version.ok_or_else(|| TryFromProtoError::missing("version"))?, + digest: digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .try_into()?, + }, + } + .pipe(Ok) + } +} + +// +// IdOperation +// + +impl From for super::changed_object::IdOperation { + fn from(value: sui_sdk_types::types::IdOperation) -> Self { + use sui_sdk_types::types::IdOperation::*; + + match value { + None => Self::None(()), + Created => Self::Created(()), + Deleted => Self::Deleted(()), + } + } +} + +impl TryFrom<&super::changed_object::IdOperation> for sui_sdk_types::types::IdOperation { + type Error = TryFromProtoError; + + fn try_from(value: &super::changed_object::IdOperation) -> Result { + use super::changed_object::IdOperation; + + match value { + IdOperation::None(()) => Self::None, + IdOperation::Created(()) => Self::Created, + IdOperation::Deleted(()) => Self::Deleted, + } + .pipe(Ok) + } +} + +// +// UnchangedSharedObject +// + +impl From for super::UnchangedSharedObject { + fn from(value: sui_sdk_types::types::UnchangedSharedObject) -> Self { + Self { + object_id: Some(value.object_id.into()), + kind: Some(value.kind.into()), + } + } +} + +impl TryFrom<&super::UnchangedSharedObject> for sui_sdk_types::types::UnchangedSharedObject { + type Error = TryFromProtoError; + + fn try_from(value: &super::UnchangedSharedObject) -> Result { + let object_id = value + .object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .try_into()?; + + let kind = value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + .try_into()?; + + Ok(Self { object_id, kind }) + } +} + +// +// UnchangedSharedKind +// + +impl From for super::unchanged_shared_object::Kind { + fn from(value: sui_sdk_types::types::UnchangedSharedKind) -> Self { + use sui_sdk_types::types::UnchangedSharedKind::*; + + match value { + ReadOnlyRoot { version, digest } => Self::ReadOnlyRoot(super::ReadOnlyRoot { + version: Some(version), + digest: Some(digest.into()), + }), + MutateDeleted { version } => Self::MutateDeleted(version), + ReadDeleted { version } => Self::ReadDeleted(version), + Cancelled { version } => Self::Cancelled(version), + PerEpochConfig => Self::PerEpochConfig(()), + } + } +} + +impl TryFrom<&super::unchanged_shared_object::Kind> for sui_sdk_types::types::UnchangedSharedKind { + type Error = TryFromProtoError; + + fn try_from(value: &super::unchanged_shared_object::Kind) -> Result { + use super::unchanged_shared_object::Kind::*; + + match value { + ReadOnlyRoot(super::ReadOnlyRoot { version, digest }) => Self::ReadOnlyRoot { + version: version.ok_or_else(|| TryFromProtoError::missing("version"))?, + + digest: digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .try_into()?, + }, + MutateDeleted(version) => Self::MutateDeleted { version: *version }, + ReadDeleted(version) => Self::ReadDeleted { version: *version }, + Cancelled(version) => Self::Cancelled { version: *version }, + PerEpochConfig(()) => Self::PerEpochConfig, + } + .pipe(Ok) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/events.rs b/crates/sui-rpc-api/src/proto/types/events.rs new file mode 100644 index 0000000000000..3b0b9e057c4cf --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/events.rs @@ -0,0 +1,87 @@ +use super::TryFromProtoError; + +// +// Event +// + +impl From for super::Event { + fn from(value: sui_sdk_types::types::Event) -> Self { + Self { + package_id: Some(value.package_id.into()), + module: Some(value.module.into()), + sender: Some(value.sender.into()), + event_type: Some(value.type_.into()), + contents: Some(value.contents.into()), + } + } +} + +impl TryFrom<&super::Event> for sui_sdk_types::types::Event { + type Error = TryFromProtoError; + + fn try_from(value: &super::Event) -> Result { + let package_id = value + .package_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("package_id"))? + .try_into()?; + + let module = value + .module + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("module"))? + .try_into()?; + + let sender = value + .sender + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("sender"))? + .try_into()?; + + let type_ = value + .event_type + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("event_type"))? + .try_into()?; + + let contents = value + .contents + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("contents"))? + .to_vec(); + + Ok(Self { + package_id, + module, + sender, + type_, + contents, + }) + } +} + +// +// TransactionEvents +// + +impl From for super::TransactionEvents { + fn from(value: sui_sdk_types::types::TransactionEvents) -> Self { + Self { + events: value.0.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::TransactionEvents> for sui_sdk_types::types::TransactionEvents { + type Error = TryFromProtoError; + + fn try_from(value: &super::TransactionEvents) -> Result { + Ok(Self( + value + .events + .iter() + .map(TryInto::try_into) + .collect::>()?, + )) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/execution_status.rs b/crates/sui-rpc-api/src/proto/types/execution_status.rs new file mode 100644 index 0000000000000..8c0586452c200 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/execution_status.rs @@ -0,0 +1,520 @@ +use super::TryFromProtoError; +use tap::Pipe; + +// +// ExecutionStatus +// + +impl From for super::ExecutionStatus { + fn from(value: sui_sdk_types::types::ExecutionStatus) -> Self { + match value { + sui_sdk_types::types::ExecutionStatus::Success => Self { + success: Some(true), + status: None, + }, + sui_sdk_types::types::ExecutionStatus::Failure { error, command } => Self { + success: Some(false), + status: Some(super::FailureStatus { + command, + execution_error: Some(error.into()), + }), + }, + } + } +} + +impl TryFrom<&super::ExecutionStatus> for sui_sdk_types::types::ExecutionStatus { + type Error = TryFromProtoError; + + fn try_from(value: &super::ExecutionStatus) -> Result { + let success = value + .success + .ok_or_else(|| TryFromProtoError::missing("success"))?; + match (success, &value.status) { + (true, None) => Self::Success, + ( + false, + Some(super::FailureStatus { + command, + execution_error, + }), + ) => Self::Failure { + error: execution_error + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("execution_error"))? + .try_into()?, + command: *command, + }, + (true, Some(_)) | (false, None) => { + return Err(TryFromProtoError::from_error("invalid execution status")) + } + } + .pipe(Ok) + } +} + +// +// ExecutionError +// + +impl From for super::failure_status::ExecutionError { + fn from(value: sui_sdk_types::types::ExecutionError) -> Self { + use sui_sdk_types::types::ExecutionError::*; + match value { + InsufficientGas => Self::InsufficientGas(()), + InvalidGasObject => Self::InvalidGasObject(()), + InvariantViolation => Self::InvariantViolation(()), + FeatureNotYetSupported => Self::FeatureNotYetSupported(()), + ObjectTooBig { + object_size, + max_object_size, + } => Self::ObjectTooBig(super::SizeError { + size: Some(object_size), + max_size: Some(max_object_size), + }), + PackageTooBig { + object_size, + max_object_size, + } => Self::PackageTooBig(super::SizeError { + size: Some(object_size), + max_size: Some(max_object_size), + }), + CircularObjectOwnership { object } => Self::CircularObjectOwnership(object.into()), + InsufficientCoinBalance => Self::InsufficientCoinBalance(()), + CoinBalanceOverflow => Self::CoinBalanceOverflow(()), + PublishErrorNonZeroAddress => Self::PublishErrorNonZeroAddress(()), + SuiMoveVerificationError => Self::SuiMoveVerificationError(()), + MovePrimitiveRuntimeError { location } => { + Self::MovePrimitiveRuntimeError(super::MoveError { + location: location.map(Into::into), + abort_code: None, + }) + } + MoveAbort { location, code } => Self::MoveAbort(super::MoveError { + location: Some(location.into()), + abort_code: Some(code), + }), + VmVerificationOrDeserializationError => Self::VmVerificationOrDeserializationError(()), + VmInvariantViolation => Self::VmInvariantViolation(()), + FunctionNotFound => Self::FunctionNotFound(()), + ArityMismatch => Self::ArityMismatch(()), + TypeArityMismatch => Self::TypeArityMismatch(()), + NonEntryFunctionInvoked => Self::NonEntryFunctionInvoked(()), + CommandArgumentError { argument, kind } => { + Self::CommandArgumentError(super::CommandArgumentError { + argument: Some(argument.into()), + kind: Some(kind.into()), + }) + } + TypeArgumentError { + type_argument, + kind, + } => Self::TypeArgumentError(super::TypeArgumentError { + type_argument: Some(type_argument.into()), + kind: Some(kind.into()), + }), + UnusedValueWithoutDrop { result, subresult } => { + Self::UnusedValueWithoutDrop(super::NestedResult { + result: Some(result.into()), + subresult: Some(subresult.into()), + }) + } + InvalidPublicFunctionReturnType { index } => { + Self::InvalidPublicFunctionReturnType(index.into()) + } + InvalidTransferObject => Self::InvalidTransferObject(()), + EffectsTooLarge { + current_size, + max_size, + } => Self::EffectsTooLarge(super::SizeError { + size: Some(current_size), + max_size: Some(max_size), + }), + PublishUpgradeMissingDependency => Self::PublishUpgradeMissingDependency(()), + PublishUpgradeDependencyDowngrade => Self::PublishUpgradeDependencyDowngrade(()), + PackageUpgradeError { kind } => Self::PackageUpgradeError(super::PackageUpgradeError { + kind: Some(kind.into()), + }), + WrittenObjectsTooLarge { + object_size, + max_object_size, + } => Self::WrittenObjectsTooLarge(super::SizeError { + size: Some(object_size), + max_size: Some(max_object_size), + }), + CertificateDenied => Self::CertificateDenied(()), + SuiMoveVerificationTimedout => Self::SuiMoveVerificationTimedout(()), + SharedObjectOperationNotAllowed => Self::SharedObjectOperationNotAllowed(()), + InputObjectDeleted => Self::InputObjectDeleted(()), + ExecutionCancelledDueToSharedObjectCongestion { congested_objects } => { + Self::ExecutionCancelledDueToSharedObjectCongestion(super::CongestedObjectsError { + congested_objects: congested_objects.into_iter().map(Into::into).collect(), + }) + } + AddressDeniedForCoin { address, coin_type } => { + Self::AddressDeniedForCoin(super::AddressDeniedForCoinError { + coin_type: Some(coin_type), + address: Some(address.into()), + }) + } + CoinTypeGlobalPause { coin_type } => Self::CoinTypeGlobalPause(coin_type), + ExecutionCancelledDueToRandomnessUnavailable => { + Self::ExecutionCancelledDueToRandomnessUnavailable(()) + } + } + } +} + +impl TryFrom<&super::failure_status::ExecutionError> for sui_sdk_types::types::ExecutionError { + type Error = TryFromProtoError; + + fn try_from(value: &super::failure_status::ExecutionError) -> Result { + use super::failure_status::ExecutionError::*; + + match value { + InsufficientGas(()) => Self::InsufficientGas, + InvalidGasObject(()) => Self::InvalidGasObject, + InvariantViolation(()) => Self::InvariantViolation, + FeatureNotYetSupported(()) => Self::FeatureNotYetSupported, + ObjectTooBig(super::SizeError { size, max_size }) => Self::ObjectTooBig { + object_size: size.ok_or_else(|| TryFromProtoError::missing("size"))?, + max_object_size: max_size.ok_or_else(|| TryFromProtoError::missing("max_size"))?, + }, + PackageTooBig(super::SizeError { size, max_size }) => Self::PackageTooBig { + object_size: size.ok_or_else(|| TryFromProtoError::missing("size"))?, + max_object_size: max_size.ok_or_else(|| TryFromProtoError::missing("max_size"))?, + }, + CircularObjectOwnership(object) => Self::CircularObjectOwnership { + object: object.try_into()?, + }, + InsufficientCoinBalance(()) => Self::InsufficientCoinBalance, + CoinBalanceOverflow(()) => Self::CoinBalanceOverflow, + PublishErrorNonZeroAddress(()) => Self::PublishErrorNonZeroAddress, + SuiMoveVerificationError(()) => Self::SuiMoveVerificationError, + MovePrimitiveRuntimeError(super::MoveError { + location, + abort_code: _, + }) => Self::MovePrimitiveRuntimeError { + location: location.as_ref().map(TryInto::try_into).transpose()?, + }, + MoveAbort(super::MoveError { + location: Some(location), + abort_code: Some(abort_code), + }) => Self::MoveAbort { + location: location.try_into()?, + code: *abort_code, + }, + MoveAbort(_) => return Err(TryFromProtoError::missing("location or abort_code")), + VmVerificationOrDeserializationError(()) => Self::VmVerificationOrDeserializationError, + VmInvariantViolation(()) => Self::VmInvariantViolation, + FunctionNotFound(()) => Self::FunctionNotFound, + ArityMismatch(()) => Self::ArityMismatch, + TypeArityMismatch(()) => Self::TypeArityMismatch, + NonEntryFunctionInvoked(()) => Self::NonEntryFunctionInvoked, + CommandArgumentError(super::CommandArgumentError { argument, kind }) => { + Self::CommandArgumentError { + argument: argument + .ok_or_else(|| TryFromProtoError::missing("argument"))? + .try_into()?, + kind: kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + .try_into()?, + } + } + TypeArgumentError(super::TypeArgumentError { + type_argument, + kind, + }) => Self::TypeArgumentError { + type_argument: type_argument + .ok_or_else(|| TryFromProtoError::missing("type_argument"))? + .try_into()?, + kind: kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + .try_into()?, + }, + UnusedValueWithoutDrop(super::NestedResult { result, subresult }) => { + Self::UnusedValueWithoutDrop { + result: result + .ok_or_else(|| TryFromProtoError::missing("result"))? + .try_into()?, + subresult: subresult + .ok_or_else(|| TryFromProtoError::missing("subresult"))? + .try_into()?, + } + } + InvalidPublicFunctionReturnType(index) => Self::InvalidPublicFunctionReturnType { + index: (*index).try_into()?, + }, + InvalidTransferObject(()) => Self::InvalidTransferObject, + EffectsTooLarge(super::SizeError { size, max_size }) => Self::EffectsTooLarge { + current_size: size.ok_or_else(|| TryFromProtoError::missing("size"))?, + max_size: max_size.ok_or_else(|| TryFromProtoError::missing("max_size"))?, + }, + PublishUpgradeMissingDependency(()) => Self::PublishUpgradeMissingDependency, + PublishUpgradeDependencyDowngrade(()) => Self::PublishUpgradeDependencyDowngrade, + PackageUpgradeError(super::PackageUpgradeError { kind }) => Self::PackageUpgradeError { + kind: kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + .try_into()?, + }, + WrittenObjectsTooLarge(super::SizeError { size, max_size }) => { + Self::WrittenObjectsTooLarge { + object_size: size.ok_or_else(|| TryFromProtoError::missing("size"))?, + max_object_size: max_size + .ok_or_else(|| TryFromProtoError::missing("max_size"))?, + } + } + CertificateDenied(()) => Self::CertificateDenied, + SuiMoveVerificationTimedout(()) => Self::SuiMoveVerificationTimedout, + SharedObjectOperationNotAllowed(()) => Self::SharedObjectOperationNotAllowed, + InputObjectDeleted(()) => Self::InputObjectDeleted, + ExecutionCancelledDueToSharedObjectCongestion(super::CongestedObjectsError { + congested_objects, + }) => Self::ExecutionCancelledDueToSharedObjectCongestion { + congested_objects: congested_objects + .iter() + .map(TryInto::try_into) + .collect::>()?, + }, + AddressDeniedForCoin(super::AddressDeniedForCoinError { address, coin_type }) => { + Self::AddressDeniedForCoin { + address: address + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("address"))? + .try_into()?, + coin_type: coin_type + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("coin_type"))? + .to_owned(), + } + } + CoinTypeGlobalPause(coin_type) => Self::CoinTypeGlobalPause { + coin_type: coin_type.to_owned(), + }, + ExecutionCancelledDueToRandomnessUnavailable(()) => { + Self::ExecutionCancelledDueToRandomnessUnavailable + } + } + .pipe(Ok) + } +} + +// +// CommandArgumentError +// + +impl From for super::command_argument_error::Kind { + fn from(value: sui_sdk_types::types::CommandArgumentError) -> Self { + use sui_sdk_types::types::CommandArgumentError::*; + + match value { + TypeMismatch => Self::TypeMismatch(()), + InvalidBcsBytes => Self::InvalidBcsBytes(()), + InvalidUsageOfPureArgument => Self::InvalidUsageOfPureArgument(()), + InvalidArgumentToPrivateEntryFunction => { + Self::InvalidArgumentToPrivateEntryFunction(()) + } + IndexOutOfBounds { index } => Self::IndexOutOfBounds(index.into()), + SecondaryIndexOutOfBounds { result, subresult } => { + Self::SecondaryIndexOutOfBounds(super::NestedResult { + result: Some(result.into()), + subresult: Some(subresult.into()), + }) + } + InvalidResultArity { result } => Self::InvalidResultArity(result.into()), + InvalidGasCoinUsage => Self::InvalidGasCoinUsage(()), + InvalidValueUsage => Self::InvalidValueUsage(()), + InvalidObjectByValue => Self::InvalidObjectByValue(()), + InvalidObjectByMutRef => Self::InvalidObjectByMutRef(()), + SharedObjectOperationNotAllowed => Self::SharedObjectOperationNotAllowed(()), + } + } +} + +impl TryFrom<&super::command_argument_error::Kind> for sui_sdk_types::types::CommandArgumentError { + type Error = TryFromProtoError; + + fn try_from(value: &super::command_argument_error::Kind) -> Result { + use super::command_argument_error::Kind::*; + use super::NestedResult; + + match value { + TypeMismatch(()) => Self::TypeMismatch, + InvalidBcsBytes(()) => Self::InvalidBcsBytes, + InvalidUsageOfPureArgument(()) => Self::InvalidUsageOfPureArgument, + InvalidArgumentToPrivateEntryFunction(()) => { + Self::InvalidArgumentToPrivateEntryFunction + } + IndexOutOfBounds(index) => Self::IndexOutOfBounds { + index: (*index).try_into()?, + }, + SecondaryIndexOutOfBounds(NestedResult { result, subresult }) => { + Self::SecondaryIndexOutOfBounds { + result: result + .ok_or_else(|| TryFromProtoError::missing("result"))? + .try_into()?, + subresult: subresult + .ok_or_else(|| TryFromProtoError::missing("subresult"))? + .try_into()?, + } + } + InvalidResultArity(result) => Self::InvalidResultArity { + result: (*result).try_into()?, + }, + InvalidGasCoinUsage(()) => Self::InvalidGasCoinUsage, + InvalidValueUsage(()) => Self::InvalidValueUsage, + InvalidObjectByValue(()) => Self::InvalidObjectByValue, + InvalidObjectByMutRef(()) => Self::InvalidObjectByMutRef, + SharedObjectOperationNotAllowed(()) => Self::SharedObjectOperationNotAllowed, + } + .pipe(Ok) + } +} + +// +// TypeArgumentError +// + +impl From for super::type_argument_error::Kind { + fn from(value: sui_sdk_types::types::TypeArgumentError) -> Self { + use sui_sdk_types::types::TypeArgumentError::*; + + match value { + TypeNotFound => Self::TypeNotFound(()), + ConstraintNotSatisfied => Self::ConstraintNotSatisfied(()), + } + } +} + +impl TryFrom<&super::type_argument_error::Kind> for sui_sdk_types::types::TypeArgumentError { + type Error = TryFromProtoError; + + fn try_from(value: &super::type_argument_error::Kind) -> Result { + use super::type_argument_error::Kind::*; + + match value { + TypeNotFound(()) => Self::TypeNotFound, + ConstraintNotSatisfied(()) => Self::ConstraintNotSatisfied, + } + .pipe(Ok) + } +} + +// +// PackageUpgradeError +// + +impl From for super::package_upgrade_error::Kind { + fn from(value: sui_sdk_types::types::PackageUpgradeError) -> Self { + use sui_sdk_types::types::PackageUpgradeError::*; + + match value { + UnableToFetchPackage { package_id } => Self::UnableToFetchPackage(package_id.into()), + NotAPackage { object_id } => Self::NotAPackage(object_id.into()), + IncompatibleUpgrade => Self::IncompatibleUpgrade(()), + DigestDoesNotMatch { digest } => Self::DigetsDoesNotMatch(digest.into()), + UnknownUpgradePolicy { policy } => Self::UnknownUpgradePolicy(policy.into()), + PackageIdDoesNotMatch { + package_id, + ticket_id, + } => Self::PackageIdDoesNotMatch(super::PackageIdDoesNotMatch { + package_id: Some(package_id.into()), + object_id: Some(ticket_id.into()), + }), + } + } +} + +impl TryFrom<&super::package_upgrade_error::Kind> for sui_sdk_types::types::PackageUpgradeError { + type Error = TryFromProtoError; + + fn try_from(value: &super::package_upgrade_error::Kind) -> Result { + use super::package_upgrade_error::Kind::*; + + match value { + UnableToFetchPackage(package_id) => Self::UnableToFetchPackage { + package_id: package_id.try_into()?, + }, + NotAPackage(object_id) => Self::NotAPackage { + object_id: object_id.try_into()?, + }, + IncompatibleUpgrade(()) => Self::IncompatibleUpgrade, + DigetsDoesNotMatch(digest) => Self::DigestDoesNotMatch { + digest: digest.try_into()?, + }, + UnknownUpgradePolicy(policy) => Self::UnknownUpgradePolicy { + policy: (*policy).try_into()?, + }, + PackageIdDoesNotMatch(super::PackageIdDoesNotMatch { + package_id: Some(package_id), + object_id: Some(ticket_id), + }) => Self::PackageIdDoesNotMatch { + package_id: package_id.try_into()?, + ticket_id: ticket_id.try_into()?, + }, + PackageIdDoesNotMatch(_) => { + return Err(TryFromProtoError::missing( + "missing package_id or ticket_id", + )) + } + } + .pipe(Ok) + } +} + +// +// MoveLocation +// + +impl From for super::MoveLocation { + fn from(value: sui_sdk_types::types::MoveLocation) -> Self { + Self { + package: Some(value.package.into()), + module: Some(value.module.into()), + function: Some(value.function.into()), + instruction: Some(value.instruction.into()), + function_name: value.function_name.map(Into::into), + } + } +} + +impl TryFrom<&super::MoveLocation> for sui_sdk_types::types::MoveLocation { + type Error = TryFromProtoError; + + fn try_from(value: &super::MoveLocation) -> Result { + let package = value + .package + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("package"))? + .try_into()?; + let module = value + .module + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("module"))? + .try_into()?; + let function = value + .function + .ok_or_else(|| TryFromProtoError::missing("function"))? + .try_into()?; + let instruction = value + .instruction + .ok_or_else(|| TryFromProtoError::missing("instruction"))? + .try_into()?; + let function_name = value + .function_name + .as_ref() + .map(TryFrom::try_from) + .transpose()?; + + Ok(Self { + package, + module, + function, + instruction, + function_name, + }) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/mod.rs b/crates/sui-rpc-api/src/proto/types/mod.rs new file mode 100644 index 0000000000000..c0614f2a44e87 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/mod.rs @@ -0,0 +1,241 @@ +use super::TryFromProtoError; + +#[rustfmt::skip] +#[path = "../generated/sui.types.rs"] +pub mod generated; +pub use generated::*; + +mod checkpoint; +mod effects; +mod events; +mod execution_status; +mod move_types; +mod object; +mod signatures; +mod transaction_convert; + +// +// Address +// + +impl From for Address { + fn from(value: sui_sdk_types::types::Address) -> Self { + Self { + address: Some(value.as_bytes().to_vec().into()), + } + } +} + +impl TryFrom<&Address> for sui_sdk_types::types::Address { + type Error = TryFromProtoError; + + fn try_from(Address { address }: &Address) -> Result { + let address = address + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("address"))? + .as_ref() + .try_into()?; + + Ok(Self::new(address)) + } +} + +// +// ObjectId +// + +impl From for ObjectId { + fn from(value: sui_sdk_types::types::ObjectId) -> Self { + Self { + object_id: Some(value.as_bytes().to_vec().into()), + } + } +} + +impl TryFrom<&ObjectId> for sui_sdk_types::types::ObjectId { + type Error = TryFromProtoError; + + fn try_from(ObjectId { object_id }: &ObjectId) -> Result { + let object_id = object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .as_ref() + .try_into()?; + + Ok(Self::new(object_id)) + } +} + +// +// Digest +// + +impl From for Digest { + fn from(value: sui_sdk_types::types::Digest) -> Self { + Self { + digest: Some(value.as_bytes().to_vec().into()), + } + } +} + +impl TryFrom<&Digest> for sui_sdk_types::types::Digest { + type Error = TryFromProtoError; + + fn try_from(Digest { digest }: &Digest) -> Result { + let digest = digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .as_ref() + .try_into()?; + + Ok(Self::new(digest)) + } +} + +macro_rules! impl_digest_proto { + ($t:ident) => { + impl From for Digest { + fn from(value: sui_sdk_types::types::$t) -> Self { + sui_sdk_types::types::Digest::from(value).into() + } + } + + impl TryFrom<&Digest> for sui_sdk_types::types::$t { + type Error = TryFromProtoError; + + fn try_from(digest: &Digest) -> Result { + sui_sdk_types::types::Digest::try_from(digest).map(Into::into) + } + } + }; +} + +impl_digest_proto!(CheckpointDigest); +impl_digest_proto!(CheckpointContentsDigest); +impl_digest_proto!(TransactionDigest); +impl_digest_proto!(TransactionEffectsDigest); +impl_digest_proto!(TransactionEventsDigest); +impl_digest_proto!(ObjectDigest); +impl_digest_proto!(ConsensusCommitDigest); +impl_digest_proto!(EffectsAuxiliaryDataDigest); + +// +// TimeStamp +// + +pub fn timestamp_ms_to_proto(timestamp_ms: u64) -> prost_types::Timestamp { + let timestamp = std::time::Duration::from_millis(timestamp_ms); + prost_types::Timestamp { + seconds: timestamp.as_secs() as i64, + nanos: timestamp.subsec_nanos() as i32, + } +} + +pub fn proto_to_timestamp_ms(timestamp: prost_types::Timestamp) -> Result { + let seconds = std::time::Duration::from_secs(timestamp.seconds.try_into()?); + let nanos = std::time::Duration::from_nanos(timestamp.nanos.try_into()?); + + Ok((seconds + nanos).as_millis().try_into()?) +} + +// +// Bcs +// + +impl Bcs { + pub fn serialize(value: &T) -> Result { + bcs::to_bytes(value).map(|bcs| Self { + bcs: Some(bcs.into()), + }) + } + + pub fn deserialize<'de, T: serde::Deserialize<'de>>(&'de self) -> Result { + bcs::from_bytes(self.bcs.as_deref().unwrap_or(&[])) + } +} + +impl From> for Bcs { + fn from(value: Vec) -> Self { + Self { + bcs: Some(value.into()), + } + } +} + +impl From<&Bcs> for Vec { + fn from(value: &Bcs) -> Self { + value + .bcs + .as_ref() + .map(|bytes| bytes.to_vec()) + .unwrap_or_default() + } +} + +impl From for Vec { + fn from(value: Bcs) -> Self { + value + .bcs + .as_ref() + .map(|bytes| bytes.to_vec()) + .unwrap_or_default() + } +} + +impl From for Bcs { + fn from(value: prost::bytes::Bytes) -> Self { + Self { bcs: Some(value) } + } +} + +impl From<&Bcs> for prost::bytes::Bytes { + fn from(value: &Bcs) -> Self { + value.bcs.clone().unwrap_or_default() + } +} + +impl From for prost::bytes::Bytes { + fn from(value: Bcs) -> Self { + value.bcs.unwrap_or_default() + } +} + +// +// U128 +// + +impl From for U128 { + fn from(value: u128) -> Self { + Self { + bytes: Some(value.to_le_bytes().to_vec().into()), + } + } +} + +impl TryFrom<&U128> for u128 { + type Error = std::array::TryFromSliceError; + + fn try_from(value: &U128) -> Result { + Ok(u128::from_le_bytes(value.bytes().try_into()?)) + } +} + +// +// I128 +// + +impl From for I128 { + fn from(value: i128) -> Self { + Self { + bytes: Some(value.to_le_bytes().to_vec().into()), + } + } +} + +impl TryFrom<&I128> for i128 { + type Error = std::array::TryFromSliceError; + + fn try_from(value: &I128) -> Result { + Ok(i128::from_le_bytes(value.bytes().try_into()?)) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/move_types.rs b/crates/sui-rpc-api/src/proto/types/move_types.rs new file mode 100644 index 0000000000000..7862c63b981ab --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/move_types.rs @@ -0,0 +1,132 @@ +use super::TryFromProtoError; +use tap::Pipe; + +// +// Identifier +// + +impl From for super::Identifier { + fn from(value: sui_sdk_types::types::Identifier) -> Self { + Self { + identifier: Some(value.into_inner().into_boxed_bytes().into()), + } + } +} + +impl TryFrom<&super::Identifier> for sui_sdk_types::types::Identifier { + type Error = TryFromProtoError; + + fn try_from(value: &super::Identifier) -> Result { + value + .identifier + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("identifier"))? + .as_ref() + .pipe(std::str::from_utf8)? + .pipe(Self::new) + .map_err(TryFromProtoError::from_error) + } +} + +// +// StructTag +// + +impl From for super::StructTag { + fn from(value: sui_sdk_types::types::StructTag) -> Self { + Self { + address: Some(value.address.into()), + module: Some(value.module.into()), + name: Some(value.name.into()), + type_parameters: value.type_params.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::StructTag> for sui_sdk_types::types::StructTag { + type Error = TryFromProtoError; + + fn try_from(value: &super::StructTag) -> Result { + let address = value + .address + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("address"))? + .pipe(TryFrom::try_from)?; + let module = value + .module + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("module"))? + .pipe(TryFrom::try_from)?; + let name = value + .name + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("name"))? + .pipe(TryFrom::try_from)?; + let type_params = value + .type_parameters + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + address, + module, + name, + type_params, + }) + } +} + +// +// TypeTag +// + +impl From for super::TypeTag { + fn from(value: sui_sdk_types::types::TypeTag) -> Self { + use super::type_tag::Tag; + use sui_sdk_types::types::TypeTag; + + let tag = match value { + TypeTag::U8 => Tag::U8(()), + TypeTag::U16 => Tag::U16(()), + TypeTag::U32 => Tag::U32(()), + TypeTag::U64 => Tag::U64(()), + TypeTag::U128 => Tag::U128(()), + TypeTag::U256 => Tag::U256(()), + TypeTag::Bool => Tag::Bool(()), + TypeTag::Address => Tag::Address(()), + TypeTag::Signer => Tag::Signer(()), + TypeTag::Vector(type_tag) => Tag::Vector(Box::new((*type_tag).into())), + TypeTag::Struct(struct_tag) => Tag::Struct((*struct_tag).into()), + }; + + Self { tag: Some(tag) } + } +} + +impl TryFrom<&super::TypeTag> for sui_sdk_types::types::TypeTag { + type Error = TryFromProtoError; + + fn try_from(value: &super::TypeTag) -> Result { + use super::type_tag::Tag; + + match value + .tag + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("type_tag"))? + { + Tag::U8(()) => Self::U8, + Tag::U16(()) => Self::U16, + Tag::U32(()) => Self::U32, + Tag::U64(()) => Self::U64, + Tag::U128(()) => Self::U128, + Tag::U256(()) => Self::U256, + Tag::Bool(()) => Self::Bool, + Tag::Address(()) => Self::Address, + Tag::Signer(()) => Self::Signer, + Tag::Vector(type_tag) => Self::Vector(Box::new(type_tag.as_ref().try_into()?)), + Tag::Struct(struct_tag) => Self::Struct(Box::new(struct_tag.try_into()?)), + } + .pipe(Ok) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/object.rs b/crates/sui-rpc-api/src/proto/types/object.rs new file mode 100644 index 0000000000000..6a7f434d40a0b --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/object.rs @@ -0,0 +1,422 @@ +use super::TryFromProtoError; +use tap::Pipe; + +// +// ObjectReference +// + +impl From for super::ObjectReference { + fn from(value: sui_sdk_types::types::ObjectReference) -> Self { + let (object_id, version, digest) = value.into_parts(); + Self { + object_id: Some(object_id.into()), + version: Some(version), + digest: Some(digest.into()), + } + } +} + +impl TryFrom<&super::ObjectReference> for sui_sdk_types::types::ObjectReference { + type Error = TryFromProtoError; + + fn try_from(value: &super::ObjectReference) -> Result { + let object_id = value + .object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .try_into()?; + + let version = value + .version + .ok_or_else(|| TryFromProtoError::missing("version"))?; + + let digest = value + .digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .try_into()?; + + Ok(Self::new(object_id, version, digest)) + } +} + +// +// Object +// + +impl From for super::Object { + fn from(value: sui_sdk_types::types::Object) -> Self { + Self { + object_id: Some(value.object_id().into()), + version: Some(value.version()), + owner: Some(value.owner().to_owned().into()), + object: Some(value.data().to_owned().into()), + previous_transaction: Some(value.previous_transaction().into()), + storage_rebate: Some(value.storage_rebate()), + } + } +} + +impl TryFrom<&super::Object> for sui_sdk_types::types::Object { + type Error = TryFromProtoError; + + fn try_from(value: &super::Object) -> Result { + let owner = value + .owner + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("owner"))? + .try_into()?; + let object_data = value + .object + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_data"))? + .try_into()?; + + let previous_transaction = value + .previous_transaction + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("previous_transaction"))? + .try_into()?; + let storage_rebate = value + .storage_rebate + .ok_or_else(|| TryFromProtoError::missing("storage_rebate"))?; + + Ok(Self::new( + object_data, + owner, + previous_transaction, + storage_rebate, + )) + } +} + +// +// Owner +// + +impl From for super::Owner { + fn from(value: sui_sdk_types::types::Owner) -> Self { + use super::owner::Kind; + use sui_sdk_types::types::Owner::*; + + let kind = match value { + Address(address) => Kind::Address(address.into()), + Object(object) => Kind::Object(object.into()), + Shared(version) => Kind::Shared(version), + Immutable => Kind::Immutable(()), + }; + + Self { kind: Some(kind) } + } +} + +impl TryFrom<&super::Owner> for sui_sdk_types::types::Owner { + type Error = TryFromProtoError; + + fn try_from(value: &super::Owner) -> Result { + use super::owner::Kind::*; + + match value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + { + Address(address) => Self::Address(address.try_into()?), + Object(object) => Self::Object(object.try_into()?), + Shared(version) => Self::Shared(*version), + Immutable(()) => Self::Immutable, + } + .pipe(Ok) + } +} + +// +// ObjectData +// + +impl From for super::ObjectData { + fn from(value: sui_sdk_types::types::ObjectData) -> Self { + use super::object_data::Kind; + use sui_sdk_types::types::ObjectData::*; + + let kind = match value { + Struct(s) => Kind::Struct(s.into()), + Package(p) => Kind::Package(p.into()), + }; + + Self { kind: Some(kind) } + } +} + +impl TryFrom<&super::ObjectData> for sui_sdk_types::types::ObjectData { + type Error = TryFromProtoError; + + fn try_from(value: &super::ObjectData) -> Result { + use super::object_data::Kind::*; + + match value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + { + Struct(s) => Self::Struct(s.try_into()?), + Package(p) => Self::Package(p.try_into()?), + } + .pipe(Ok) + } +} + +// +// MoveStruct +// + +impl From for super::MoveStruct { + fn from(value: sui_sdk_types::types::MoveStruct) -> Self { + Self { + object_id: Some(value.object_id().into()), + object_type: Some(value.object_type().to_owned().into()), + has_public_transfer: Some(value.has_public_transfer()), + version: Some(value.version()), + contents: Some(value.contents().to_vec().into()), + } + } +} + +impl TryFrom<&super::MoveStruct> for sui_sdk_types::types::MoveStruct { + type Error = TryFromProtoError; + + fn try_from( + super::MoveStruct { + object_id: _, + object_type, + has_public_transfer, + version, + contents, + }: &super::MoveStruct, + ) -> Result { + let object_type = object_type + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_type"))? + .try_into()?; + + let has_public_transfer = + has_public_transfer.ok_or_else(|| TryFromProtoError::missing("has_public_transfer"))?; + let version = version.ok_or_else(|| TryFromProtoError::missing("version"))?; + let contents = contents + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("contents"))? + .to_vec(); + + Self::new(object_type, has_public_transfer, version, contents) + .ok_or_else(|| TryFromProtoError::from_error("contents missing object_id")) + } +} + +// +// MovePackage +// + +impl From for super::MovePackage { + fn from(value: sui_sdk_types::types::MovePackage) -> Self { + let modules = value + .modules + .into_iter() + .map(|(name, contents)| super::MoveModule { + name: Some(name.into()), + contents: Some(contents.into()), + }) + .collect(); + + let type_origin_table = value + .type_origin_table + .into_iter() + .map(Into::into) + .collect(); + + let linkage_table = value + .linkage_table + .into_iter() + .map( + |( + original_id, + sui_sdk_types::types::UpgradeInfo { + upgraded_id, + upgraded_version, + }, + )| { + super::UpgradeInfo { + original_id: Some(original_id.into()), + upgraded_id: Some(upgraded_id.into()), + upgraded_version: Some(upgraded_version), + } + }, + ) + .collect(); + + Self { + id: Some(value.id.into()), + version: Some(value.version), + modules, + type_origin_table, + linkage_table, + } + } +} + +impl TryFrom<&super::MovePackage> for sui_sdk_types::types::MovePackage { + type Error = TryFromProtoError; + + fn try_from(value: &super::MovePackage) -> Result { + let id = value + .id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("id"))? + .try_into()?; + + let modules = value + .modules + .iter() + .map(|module| { + let name = module + .name + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("name"))? + .try_into()?; + + let contents = module + .contents + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("contents"))? + .to_vec(); + + Ok((name, contents)) + }) + .collect::>()?; + + let type_origin_table = value + .type_origin_table + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let linkage_table = value + .linkage_table + .iter() + .map(|upgrade_info| { + let original_id = upgrade_info + .original_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("original_id"))? + .try_into()?; + + let upgraded_id = upgrade_info + .upgraded_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("upgraded_id"))? + .try_into()?; + let upgraded_version = upgrade_info + .upgraded_version + .ok_or_else(|| TryFromProtoError::missing("upgraded_version"))?; + + Ok(( + original_id, + sui_sdk_types::types::UpgradeInfo { + upgraded_id, + upgraded_version, + }, + )) + }) + .collect::>()?; + + let version = value + .version + .ok_or_else(|| TryFromProtoError::missing("version"))?; + + Ok(Self { + id, + version, + modules, + type_origin_table, + linkage_table, + }) + } +} + +// +// TypeOrigin +// + +impl From for super::TypeOrigin { + fn from(value: sui_sdk_types::types::TypeOrigin) -> Self { + Self { + module_name: Some(value.module_name.into()), + struct_name: Some(value.struct_name.into()), + package_id: Some(value.package.into()), + } + } +} + +impl TryFrom<&super::TypeOrigin> for sui_sdk_types::types::TypeOrigin { + type Error = TryFromProtoError; + + fn try_from(value: &super::TypeOrigin) -> Result { + let module_name = value + .module_name + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("module_name"))? + .try_into()?; + + let struct_name = value + .struct_name + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("struct_name"))? + .try_into()?; + + let package = value + .package_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("package_id"))? + .try_into()?; + + Ok(Self { + module_name, + struct_name, + package, + }) + } +} + +// +// GenesisObject +// + +impl From for super::GenesisObject { + fn from(value: sui_sdk_types::types::GenesisObject) -> Self { + Self { + object_id: Some(value.object_id().into()), + version: Some(value.version()), + owner: Some(value.owner().to_owned().into()), + object: Some(value.data().to_owned().into()), + } + } +} + +impl TryFrom<&super::GenesisObject> for sui_sdk_types::types::GenesisObject { + type Error = TryFromProtoError; + + fn try_from(value: &super::GenesisObject) -> Result { + let object_data = value + .object + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_data"))? + .try_into()?; + + let owner = value + .owner + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("owner"))? + .try_into()?; + + Ok(Self::new(object_data, owner)) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/signatures.rs b/crates/sui-rpc-api/src/proto/types/signatures.rs new file mode 100644 index 0000000000000..faaa3f3175e72 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/signatures.rs @@ -0,0 +1,883 @@ +use super::TryFromProtoError; +use bytes::{BufMut, BytesMut}; +use tap::Pipe; + +// +// ValidatorAggregatedSignature +// + +impl From + for super::ValidatorAggregatedSignature +{ + fn from(value: sui_sdk_types::types::ValidatorAggregatedSignature) -> Self { + Self { + epoch: Some(value.epoch), + signature: Some(value.signature.as_bytes().to_vec().into()), + bitmap: Some(value.bitmap.into()), + } + } +} + +impl TryFrom<&super::ValidatorAggregatedSignature> + for sui_sdk_types::types::ValidatorAggregatedSignature +{ + type Error = TryFromProtoError; + + fn try_from(value: &super::ValidatorAggregatedSignature) -> Result { + let epoch = value + .epoch + .ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let signature = value + .signature + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("signature"))? + .as_ref() + .pipe(sui_sdk_types::types::Bls12381Signature::from_bytes) + .map_err(TryFromProtoError::from_error)?; + let bitmap = value + .bitmap + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("bitmap"))? + .try_into()?; + + Ok(Self { + epoch, + signature, + bitmap, + }) + } +} + +// +// RoaringBitmap +// + +impl From for super::RoaringBitmap { + fn from(value: roaring::RoaringBitmap) -> Self { + Self::from(&value) + } +} + +impl From<&roaring::RoaringBitmap> for super::RoaringBitmap { + fn from(value: &roaring::RoaringBitmap) -> Self { + let mut buf = BytesMut::new().writer(); + value + .serialize_into(&mut buf) + .expect("writing to BytesMut can't fail"); + Self { + bitmap: Some(buf.into_inner().freeze()), + } + } +} + +impl TryFrom<&super::RoaringBitmap> for roaring::RoaringBitmap { + type Error = TryFromProtoError; + + fn try_from(value: &super::RoaringBitmap) -> Result { + value + .bitmap + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("bitmap"))? + .as_ref() + .pipe(roaring::RoaringBitmap::deserialize_from) + .map_err(TryFromProtoError::from_error) + } +} + +// +// ValidatorCommitteeMember +// + +impl From for super::ValidatorCommitteeMember { + fn from(value: sui_sdk_types::types::ValidatorCommitteeMember) -> Self { + Self { + public_key: Some(value.public_key.as_bytes().to_vec().into()), + stake: Some(value.stake), + } + } +} + +impl TryFrom<&super::ValidatorCommitteeMember> for sui_sdk_types::types::ValidatorCommitteeMember { + type Error = TryFromProtoError; + + fn try_from( + super::ValidatorCommitteeMember { public_key, stake }: &super::ValidatorCommitteeMember, + ) -> Result { + let public_key = public_key + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("public_key"))? + .as_ref() + .pipe(sui_sdk_types::types::Bls12381PublicKey::from_bytes) + .map_err(TryFromProtoError::from_error)?; + let stake = stake.ok_or_else(|| TryFromProtoError::missing("stake"))?; + Ok(Self { public_key, stake }) + } +} + +// +// ValidatorCommittee +// + +impl From for super::ValidatorCommittee { + fn from(value: sui_sdk_types::types::ValidatorCommittee) -> Self { + Self { + epoch: Some(value.epoch), + members: value.members.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::ValidatorCommittee> for sui_sdk_types::types::ValidatorCommittee { + type Error = TryFromProtoError; + + fn try_from(value: &super::ValidatorCommittee) -> Result { + let epoch = value + .epoch + .ok_or_else(|| TryFromProtoError::missing("epoch"))?; + Ok(Self { + epoch, + members: value + .members + .iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +// +// Bn254FieldElement +// + +impl From for super::Bn254FieldElement { + fn from(value: sui_sdk_types::types::Bn254FieldElement) -> Self { + Self { + element: Some(value.padded().to_vec().into()), + } + } +} + +impl TryFrom<&super::Bn254FieldElement> for sui_sdk_types::types::Bn254FieldElement { + type Error = TryFromProtoError; + + fn try_from(value: &super::Bn254FieldElement) -> Result { + Ok(Self::new( + value + .element + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("element"))? + .as_ref() + .try_into() + .map_err(TryFromProtoError::from_error)?, + )) + } +} + +// +// CircomG1 +// + +impl From for super::CircomG1 { + fn from(value: sui_sdk_types::types::CircomG1) -> Self { + let [e0, e1, e2] = value.0; + + Self { + e0: Some(e0.into()), + e1: Some(e1.into()), + e2: Some(e2.into()), + } + } +} + +impl TryFrom<&super::CircomG1> for sui_sdk_types::types::CircomG1 { + type Error = TryFromProtoError; + + fn try_from(value: &super::CircomG1) -> Result { + let e0 = value + .e0 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e0"))? + .try_into()?; + let e1 = value + .e1 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e1"))? + .try_into()?; + let e2 = value + .e2 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e2"))? + .try_into()?; + + Ok(Self([e0, e1, e2])) + } +} + +// +// CircomG2 +// + +impl From for super::CircomG2 { + fn from(value: sui_sdk_types::types::CircomG2) -> Self { + let [[e00, e01], [e10, e11], [e20, e21]] = value.0; + + Self { + e00: Some(e00.into()), + e01: Some(e01.into()), + e10: Some(e10.into()), + e11: Some(e11.into()), + e20: Some(e20.into()), + e21: Some(e21.into()), + } + } +} + +impl TryFrom<&super::CircomG2> for sui_sdk_types::types::CircomG2 { + type Error = TryFromProtoError; + + fn try_from(value: &super::CircomG2) -> Result { + let e00 = value + .e00 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e00"))? + .try_into()?; + let e01 = value + .e01 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e01"))? + .try_into()?; + + let e10 = value + .e10 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e10"))? + .try_into()?; + let e11 = value + .e11 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e11"))? + .try_into()?; + + let e20 = value + .e20 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e20"))? + .try_into()?; + let e21 = value + .e21 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e21"))? + .try_into()?; + + Ok(Self([[e00, e01], [e10, e11], [e20, e21]])) + } +} + +// +// ZkLoginClaim +// + +impl From for super::ZkLoginClaim { + fn from(value: sui_sdk_types::types::Claim) -> Self { + Self { + value: Some(value.value.into_bytes().into()), + index_mod_4: Some(value.index_mod_4.into()), + } + } +} + +impl TryFrom<&super::ZkLoginClaim> for sui_sdk_types::types::Claim { + type Error = TryFromProtoError; + + fn try_from( + super::ZkLoginClaim { value, index_mod_4 }: &super::ZkLoginClaim, + ) -> Result { + let value = value + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("value"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + let index_mod_4 = index_mod_4 + .ok_or_else(|| TryFromProtoError::missing("index_mod_4"))? + .try_into()?; + + Ok(Self { value, index_mod_4 }) + } +} + +// +// ZkLoginProof +// + +impl From for super::ZkLoginProof { + fn from(value: sui_sdk_types::types::ZkLoginProof) -> Self { + Self { + a: Some(value.a.into()), + b: Some(value.b.into()), + c: Some(value.c.into()), + } + } +} + +impl TryFrom<&super::ZkLoginProof> for sui_sdk_types::types::ZkLoginProof { + type Error = TryFromProtoError; + + fn try_from(value: &super::ZkLoginProof) -> Result { + let a = value + .a + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("a"))? + .try_into()?; + let b = value + .b + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("b"))? + .try_into()?; + let c = value + .c + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("c"))? + .try_into()?; + + Ok(Self { a, b, c }) + } +} + +// +// ZkLoginInputs +// + +impl From for super::ZkLoginInputs { + fn from(value: sui_sdk_types::types::ZkLoginInputs) -> Self { + Self { + proof_points: Some(value.proof_points.into()), + iss_base64_details: Some(value.iss_base64_details.into()), + header_base64: Some(value.header_base64.into_bytes().into()), + address_seed: Some(value.address_seed.into()), + } + } +} + +impl TryFrom<&super::ZkLoginInputs> for sui_sdk_types::types::ZkLoginInputs { + type Error = TryFromProtoError; + + fn try_from(value: &super::ZkLoginInputs) -> Result { + let proof_points = value + .proof_points + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("proof_points"))? + .try_into()?; + let iss_base64_details = value + .iss_base64_details + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("iss_base64_details"))? + .try_into()?; + let header_base64 = value + .header_base64 + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("header_base64"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + let address_seed = value + .address_seed + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("address_seed"))? + .try_into()?; + + Ok(Self { + proof_points, + iss_base64_details, + header_base64, + address_seed, + }) + } +} + +// +// ZkLoginAuthenticator +// + +impl From for super::ZkLoginAuthenticator { + fn from(value: sui_sdk_types::types::ZkLoginAuthenticator) -> Self { + Self { + inputs: Some(value.inputs.into()), + max_epoch: Some(value.max_epoch), + signature: Some(value.signature.into()), + } + } +} + +impl TryFrom<&super::ZkLoginAuthenticator> for sui_sdk_types::types::ZkLoginAuthenticator { + type Error = TryFromProtoError; + + fn try_from(value: &super::ZkLoginAuthenticator) -> Result { + let inputs = value + .inputs + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("inputs"))? + .try_into()?; + let max_epoch = value + .max_epoch + .ok_or_else(|| TryFromProtoError::missing("max_epoch"))?; + let signature = value + .signature + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("signature"))? + .try_into()?; + + Ok(Self { + inputs, + max_epoch, + signature, + }) + } +} + +// +// ZkLoginPublicIdentifier +// + +impl From<&sui_sdk_types::types::ZkLoginPublicIdentifier> for super::ZkLoginPublicIdentifier { + fn from(value: &sui_sdk_types::types::ZkLoginPublicIdentifier) -> Self { + Self { + iss: Some(value.iss().to_owned().into_bytes().into()), + address_seed: Some(value.address_seed().to_owned().into()), + } + } +} + +impl TryFrom<&super::ZkLoginPublicIdentifier> for sui_sdk_types::types::ZkLoginPublicIdentifier { + type Error = TryFromProtoError; + + fn try_from(value: &super::ZkLoginPublicIdentifier) -> Result { + let iss = value + .iss + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("iss"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + let address_seed = value + .address_seed + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("address_seed"))? + .try_into()?; + + Self::new(iss, address_seed) + .ok_or_else(|| TryFromProtoError::from_error("invalid iss"))? + .pipe(Ok) + } +} + +// +// SignatureScheme +// + +impl From for super::SignatureScheme { + fn from(value: sui_sdk_types::types::SignatureScheme) -> Self { + use sui_sdk_types::types::SignatureScheme::*; + + match value { + Ed25519 => Self::Ed25519, + Secp256k1 => Self::Secp256k1, + Secp256r1 => Self::Secp256r1, + Multisig => Self::Multisig, + Bls12381 => Self::Bls12381, + ZkLogin => Self::Zklogin, + Passkey => Self::Passkey, + } + } +} + +impl TryFrom<&super::SignatureScheme> for sui_sdk_types::types::SignatureScheme { + type Error = TryFromProtoError; + + fn try_from(value: &super::SignatureScheme) -> Result { + use super::SignatureScheme::*; + + match value { + Unknown => { + return Err(TryFromProtoError::missing( + "unknown SignatureScheme variant", + )) + } + Ed25519 => Self::Ed25519, + Secp256k1 => Self::Secp256k1, + Secp256r1 => Self::Secp256r1, + Multisig => Self::Multisig, + Bls12381 => Self::Bls12381, + Zklogin => Self::ZkLogin, + Passkey => Self::Passkey, + } + .pipe(Ok) + } +} + +// +// SimpleSignature +// + +impl From for super::SimpleSignature { + fn from(value: sui_sdk_types::types::SimpleSignature) -> Self { + let scheme: super::SignatureScheme = value.scheme().into(); + let (signature, public_key) = match &value { + sui_sdk_types::types::SimpleSignature::Ed25519 { + signature, + public_key, + } => (signature.as_bytes(), public_key.as_bytes()), + sui_sdk_types::types::SimpleSignature::Secp256k1 { + signature, + public_key, + } => (signature.as_bytes(), public_key.as_bytes()), + sui_sdk_types::types::SimpleSignature::Secp256r1 { + signature, + public_key, + } => (signature.as_bytes(), public_key.as_bytes()), + }; + + Self { + scheme: Some(scheme.into()), + signature: Some(signature.to_vec().into()), + public_key: Some(public_key.to_vec().into()), + } + } +} + +impl TryFrom<&super::SimpleSignature> for sui_sdk_types::types::SimpleSignature { + type Error = TryFromProtoError; + + fn try_from(value: &super::SimpleSignature) -> Result { + use super::SignatureScheme::*; + use sui_sdk_types::types::{Ed25519PublicKey, Ed25519Signature}; + use sui_sdk_types::types::{ + Secp256k1PublicKey, Secp256k1Signature, Secp256r1PublicKey, Secp256r1Signature, + }; + + let signature = value + .signature + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("signature"))?; + let public_key = value + .public_key + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("public_key"))?; + + match value.scheme() { + Ed25519 => Self::Ed25519 { + signature: Ed25519Signature::from_bytes(signature)?, + public_key: Ed25519PublicKey::from_bytes(public_key)?, + }, + Secp256k1 => Self::Secp256k1 { + signature: Secp256k1Signature::from_bytes(signature)?, + public_key: Secp256k1PublicKey::from_bytes(public_key)?, + }, + Secp256r1 => Self::Secp256r1 { + signature: Secp256r1Signature::from_bytes(signature)?, + public_key: Secp256r1PublicKey::from_bytes(public_key)?, + }, + Unknown | Multisig | Bls12381 | Zklogin | Passkey => { + return Err(TryFromProtoError::from_error( + "invalid or unknown signature scheme", + )) + } + } + .pipe(Ok) + } +} + +// +// PasskeyAuthenticator +// + +impl From for super::PasskeyAuthenticator { + fn from(value: sui_sdk_types::types::PasskeyAuthenticator) -> Self { + Self { + authenticator_data: Some(value.authenticator_data().to_vec().into()), + client_data_json: Some(value.client_data_json().as_bytes().to_vec().into()), + signature: Some(value.signature().into()), + } + } +} + +impl TryFrom<&super::PasskeyAuthenticator> for sui_sdk_types::types::PasskeyAuthenticator { + type Error = TryFromProtoError; + + fn try_from(value: &super::PasskeyAuthenticator) -> Result { + let authenticator_data = value + .authenticator_data + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("authenticator_data"))? + .to_vec(); + let client_data_json = value + .client_data_json + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("client_data_json"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + + let signature = value + .signature + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("signature"))? + .try_into()?; + + Self::new(authenticator_data, client_data_json, signature) + .ok_or_else(|| TryFromProtoError::from_error("invalid passkey")) + } +} + +// +// MultisigMemberPublicKey +// + +impl From<&sui_sdk_types::types::MultisigMemberPublicKey> for super::MultisigMemberPublicKey { + fn from(value: &sui_sdk_types::types::MultisigMemberPublicKey) -> Self { + use super::multisig_member_public_key::Scheme; + use sui_sdk_types::types::MultisigMemberPublicKey::*; + + let scheme = match value { + Ed25519(public_key) => Scheme::Ed25519(public_key.as_bytes().to_vec().into()), + Secp256k1(public_key) => Scheme::Secp256k1(public_key.as_bytes().to_vec().into()), + Secp256r1(public_key) => Scheme::Secp256r1(public_key.as_bytes().to_vec().into()), + ZkLogin(zklogin_id) => Scheme::Zklogin(zklogin_id.into()), + }; + + Self { + scheme: Some(scheme), + } + } +} + +impl TryFrom<&super::MultisigMemberPublicKey> for sui_sdk_types::types::MultisigMemberPublicKey { + type Error = TryFromProtoError; + + fn try_from(value: &super::MultisigMemberPublicKey) -> Result { + use super::multisig_member_public_key::Scheme; + use sui_sdk_types::types::{Ed25519PublicKey, Secp256k1PublicKey, Secp256r1PublicKey}; + + match value + .scheme + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("scheme"))? + { + Scheme::Ed25519(public_key) => Self::Ed25519(Ed25519PublicKey::from_bytes(public_key)?), + Scheme::Secp256k1(public_key) => { + Self::Secp256k1(Secp256k1PublicKey::from_bytes(public_key)?) + } + Scheme::Secp256r1(public_key) => { + Self::Secp256r1(Secp256r1PublicKey::from_bytes(public_key)?) + } + Scheme::Zklogin(zklogin_id) => Self::ZkLogin(zklogin_id.try_into()?), + } + .pipe(Ok) + } +} + +// +// MultisigMember +// + +impl From<&sui_sdk_types::types::MultisigMember> for super::MultisigMember { + fn from(value: &sui_sdk_types::types::MultisigMember) -> Self { + Self { + public_key: Some(value.public_key().into()), + weight: Some(value.weight().into()), + } + } +} + +impl TryFrom<&super::MultisigMember> for sui_sdk_types::types::MultisigMember { + type Error = TryFromProtoError; + + fn try_from(value: &super::MultisigMember) -> Result { + let public_key = value + .public_key + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("public_key"))? + .try_into()?; + let weight = value + .weight + .ok_or_else(|| TryFromProtoError::missing("weight"))? + .try_into()?; + + Ok(Self::new(public_key, weight)) + } +} + +// +// MultisigCommittee +// + +impl From<&sui_sdk_types::types::MultisigCommittee> for super::MultisigCommittee { + fn from(value: &sui_sdk_types::types::MultisigCommittee) -> Self { + Self { + members: value.members().iter().map(Into::into).collect(), + threshold: Some(value.threshold().into()), + } + } +} + +impl TryFrom<&super::MultisigCommittee> for sui_sdk_types::types::MultisigCommittee { + type Error = TryFromProtoError; + + fn try_from(value: &super::MultisigCommittee) -> Result { + let members = value + .members + .iter() + .map(TryInto::try_into) + .collect::>()?; + let threshold = value + .threshold + .ok_or_else(|| TryFromProtoError::missing("threshold"))? + .try_into()?; + + Ok(Self::new(members, threshold)) + } +} + +// +// MultisigMemberSignature +// + +impl From<&sui_sdk_types::types::MultisigMemberSignature> for super::MultisigMemberSignature { + fn from(value: &sui_sdk_types::types::MultisigMemberSignature) -> Self { + use super::multisig_member_signature::Signature; + use sui_sdk_types::types::MultisigMemberSignature::*; + + let signature = match value { + Ed25519(signautre) => Signature::Ed25519(signautre.as_bytes().to_vec().into()), + Secp256k1(signautre) => Signature::Secp256k1(signautre.as_bytes().to_vec().into()), + Secp256r1(signautre) => Signature::Secp256r1(signautre.as_bytes().to_vec().into()), + ZkLogin(zklogin_id) => Signature::Zklogin((**zklogin_id).clone().into()), + }; + + Self { + signature: Some(signature), + } + } +} + +impl TryFrom<&super::MultisigMemberSignature> for sui_sdk_types::types::MultisigMemberSignature { + type Error = TryFromProtoError; + + fn try_from(value: &super::MultisigMemberSignature) -> Result { + use super::multisig_member_signature::Signature; + use sui_sdk_types::types::{Ed25519Signature, Secp256k1Signature, Secp256r1Signature}; + + match value + .signature + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("signature"))? + { + Signature::Ed25519(signautre) => { + Self::Ed25519(Ed25519Signature::from_bytes(signautre)?) + } + Signature::Secp256k1(signautre) => { + Self::Secp256k1(Secp256k1Signature::from_bytes(signautre)?) + } + Signature::Secp256r1(signautre) => { + Self::Secp256r1(Secp256r1Signature::from_bytes(signautre)?) + } + Signature::Zklogin(zklogin_id) => Self::ZkLogin(Box::new(zklogin_id.try_into()?)), + } + .pipe(Ok) + } +} + +// +// MultisigAggregatedSignature +// + +impl From<&sui_sdk_types::types::MultisigAggregatedSignature> + for super::MultisigAggregatedSignature +{ + fn from(value: &sui_sdk_types::types::MultisigAggregatedSignature) -> Self { + Self { + signatures: value.signatures().iter().map(Into::into).collect(), + bitmap: Some(value.bitmap().into()), + legacy_bitmap: value.legacy_bitmap().map(Into::into), + committee: Some(value.committee().into()), + } + } +} + +impl TryFrom<&super::MultisigAggregatedSignature> + for sui_sdk_types::types::MultisigAggregatedSignature +{ + type Error = TryFromProtoError; + + fn try_from(value: &super::MultisigAggregatedSignature) -> Result { + let signatures = value + .signatures + .iter() + .map(TryInto::try_into) + .collect::>()?; + let bitmap = value + .bitmap + .ok_or_else(|| TryFromProtoError::missing("bitmap"))? + .try_into()?; + let legacy_bitmap = value + .legacy_bitmap + .as_ref() + .map(TryInto::try_into) + .transpose()?; + let committee = value + .committee + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("committee"))? + .try_into()?; + + let mut signature = Self::new(committee, signatures, bitmap); + + if let Some(legacy_bitmap) = legacy_bitmap { + signature.with_legacy_bitmap(legacy_bitmap); + } + + Ok(signature) + } +} + +// +// UserSignature +// + +impl From for super::UserSignature { + fn from(value: sui_sdk_types::types::UserSignature) -> Self { + use super::user_signature::Signature; + use sui_sdk_types::types::UserSignature::*; + + let signature = match value { + Simple(simple) => Signature::Simple(simple.into()), + Multisig(ref multisig) => Signature::Multisig(multisig.into()), + ZkLogin(zklogin) => Signature::Zklogin((*zklogin).into()), + Passkey(passkey) => Signature::Passkey(passkey.into()), + }; + + Self { + signature: Some(signature), + } + } +} + +impl TryFrom<&super::UserSignature> for sui_sdk_types::types::UserSignature { + type Error = TryFromProtoError; + + fn try_from(value: &super::UserSignature) -> Result { + use super::user_signature::Signature; + + match value + .signature + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("signature"))? + { + Signature::Simple(simple) => Self::Simple(simple.try_into()?), + Signature::Multisig(multisig) => Self::Multisig(multisig.try_into()?), + Signature::Zklogin(zklogin) => Self::ZkLogin(Box::new(zklogin.try_into()?)), + Signature::Passkey(passkey) => Self::Passkey(passkey.try_into()?), + } + .pipe(Ok) + } +} diff --git a/crates/sui-rpc-api/src/proto/types/transaction_convert.rs b/crates/sui-rpc-api/src/proto/types/transaction_convert.rs new file mode 100644 index 0000000000000..8e75493060744 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/types/transaction_convert.rs @@ -0,0 +1,1388 @@ +use super::TryFromProtoError; +use tap::Pipe; + +// +// Transaction +// + +impl From for super::Transaction { + fn from(value: sui_sdk_types::types::Transaction) -> Self { + let version = super::transaction::Version::V1(value.into()); + + Self { + version: Some(version), + } + } +} + +impl TryFrom<&super::Transaction> for sui_sdk_types::types::Transaction { + type Error = TryFromProtoError; + + fn try_from(value: &super::Transaction) -> Result { + match value + .version + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("version"))? + { + super::transaction::Version::V1(v1) => Self::try_from(v1)?, + } + .pipe(Ok) + } +} + +// +// TransactionV1 +// + +impl From for super::transaction::TransactionV1 { + fn from(value: sui_sdk_types::types::Transaction) -> Self { + Self { + kind: Some(value.kind.into()), + sender: Some(value.sender.into()), + gas_payment: Some(value.gas_payment.into()), + expiration: Some(value.expiration.into()), + } + } +} + +impl TryFrom<&super::transaction::TransactionV1> for sui_sdk_types::types::Transaction { + type Error = TryFromProtoError; + + fn try_from(value: &super::transaction::TransactionV1) -> Result { + let kind = value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + .try_into()?; + + let sender = value + .sender + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("sender"))? + .try_into()?; + + let gas_payment = value + .gas_payment + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("gas_payment"))? + .try_into()?; + + let expiration = value + .expiration + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("expiration"))? + .try_into()?; + + Ok(Self { + kind, + sender, + gas_payment, + expiration, + }) + } +} + +// +// GasPayment +// + +impl From for super::GasPayment { + fn from(value: sui_sdk_types::types::GasPayment) -> Self { + Self { + objects: value.objects.into_iter().map(Into::into).collect(), + owner: Some(value.owner.into()), + price: Some(value.price), + budget: Some(value.budget), + } + } +} + +impl TryFrom<&super::GasPayment> for sui_sdk_types::types::GasPayment { + type Error = TryFromProtoError; + + fn try_from(value: &super::GasPayment) -> Result { + let objects = value + .objects + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let owner = value + .owner + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("owner"))? + .try_into()?; + let price = value + .price + .ok_or_else(|| TryFromProtoError::missing("price"))?; + let budget = value + .budget + .ok_or_else(|| TryFromProtoError::missing("budget"))?; + Ok(Self { + objects, + owner, + price, + budget, + }) + } +} + +// +// TransactionExpiration +// + +impl From for super::TransactionExpiration { + fn from(value: sui_sdk_types::types::TransactionExpiration) -> Self { + use super::transaction_expiration::Expiration; + use sui_sdk_types::types::TransactionExpiration::*; + + let expiration = match value { + None => Expiration::None(()), + Epoch(epoch) => Expiration::Epoch(epoch), + }; + + Self { + expiration: Some(expiration), + } + } +} + +impl TryFrom<&super::TransactionExpiration> for sui_sdk_types::types::TransactionExpiration { + type Error = TryFromProtoError; + + fn try_from(value: &super::TransactionExpiration) -> Result { + use super::transaction_expiration::Expiration; + + match value + .expiration + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("expiration"))? + { + Expiration::None(()) => Self::None, + Expiration::Epoch(epoch) => Self::Epoch(*epoch), + } + .pipe(Ok) + } +} + +// +// TransactionKind +// + +impl From for super::TransactionKind { + fn from(value: sui_sdk_types::types::TransactionKind) -> Self { + use super::transaction_kind::Kind; + use sui_sdk_types::types::TransactionKind::*; + + let kind = match value { + ProgrammableTransaction(ptb) => Kind::ProgrammableTransaction(ptb.into()), + ChangeEpoch(change_epoch) => Kind::ChangeEpoch(change_epoch.into()), + Genesis(genesis) => Kind::Genesis(genesis.into()), + ConsensusCommitPrologue(prologue) => Kind::ConsensusCommitPrologueV1(prologue.into()), + AuthenticatorStateUpdate(update) => Kind::AuthenticatorStateUpdate(update.into()), + EndOfEpoch(transactions) => Kind::EndOfEpoch(super::EndOfEpochTransaction { + transactions: transactions.into_iter().map(Into::into).collect(), + }), + RandomnessStateUpdate(update) => Kind::RandomnessStateUpdate(update.into()), + ConsensusCommitPrologueV2(prologue) => Kind::ConsensusCommitPrologueV2(prologue.into()), + ConsensusCommitPrologueV3(prologue) => Kind::ConsensusCommitPrologueV3(prologue.into()), + }; + + Self { kind: Some(kind) } + } +} + +impl TryFrom<&super::TransactionKind> for sui_sdk_types::types::TransactionKind { + type Error = TryFromProtoError; + + fn try_from(value: &super::TransactionKind) -> Result { + use super::transaction_kind::Kind; + + match value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + { + Kind::ProgrammableTransaction(ptb) => Self::ProgrammableTransaction(ptb.try_into()?), + Kind::ChangeEpoch(change_epoch) => Self::ChangeEpoch(change_epoch.try_into()?), + Kind::Genesis(genesis) => Self::Genesis(genesis.try_into()?), + Kind::ConsensusCommitPrologueV1(prologue) => { + Self::ConsensusCommitPrologue(prologue.try_into()?) + } + Kind::AuthenticatorStateUpdate(update) => { + Self::AuthenticatorStateUpdate(update.try_into()?) + } + Kind::EndOfEpoch(super::EndOfEpochTransaction { transactions }) => Self::EndOfEpoch( + transactions + .iter() + .map(TryInto::try_into) + .collect::>()?, + ), + Kind::RandomnessStateUpdate(update) => Self::RandomnessStateUpdate(update.try_into()?), + Kind::ConsensusCommitPrologueV2(prologue) => { + Self::ConsensusCommitPrologueV2(prologue.try_into()?) + } + Kind::ConsensusCommitPrologueV3(prologue) => { + Self::ConsensusCommitPrologueV3(prologue.try_into()?) + } + } + .pipe(Ok) + } +} + +// +// ConsensusCommitPrologue +// + +impl From for super::ConsensusCommitPrologue { + fn from(value: sui_sdk_types::types::ConsensusCommitPrologue) -> Self { + Self { + epoch: Some(value.epoch), + round: Some(value.round), + commit_timestamp_ms: Some(value.commit_timestamp_ms), + consensus_commit_digest: None, + sub_dag_index: None, + consensus_determined_version_assignments: None, + } + } +} + +impl TryFrom<&super::ConsensusCommitPrologue> for sui_sdk_types::types::ConsensusCommitPrologue { + type Error = TryFromProtoError; + + fn try_from(value: &super::ConsensusCommitPrologue) -> Result { + let epoch = value + .epoch + .ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let round = value + .round + .ok_or_else(|| TryFromProtoError::missing("round"))?; + let commit_timestamp_ms = value + .commit_timestamp_ms + .ok_or_else(|| TryFromProtoError::missing("commit_timestamp_ms"))?; + + Ok(Self { + epoch, + round, + commit_timestamp_ms, + }) + } +} + +impl From for super::ConsensusCommitPrologue { + fn from(value: sui_sdk_types::types::ConsensusCommitPrologueV2) -> Self { + Self { + epoch: Some(value.epoch), + round: Some(value.round), + commit_timestamp_ms: Some(value.commit_timestamp_ms), + consensus_commit_digest: Some(value.consensus_commit_digest.into()), + sub_dag_index: None, + consensus_determined_version_assignments: None, + } + } +} + +impl TryFrom<&super::ConsensusCommitPrologue> for sui_sdk_types::types::ConsensusCommitPrologueV2 { + type Error = TryFromProtoError; + + fn try_from(value: &super::ConsensusCommitPrologue) -> Result { + let epoch = value + .epoch + .ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let round = value + .round + .ok_or_else(|| TryFromProtoError::missing("round"))?; + let commit_timestamp_ms = value + .commit_timestamp_ms + .ok_or_else(|| TryFromProtoError::missing("commit_timestamp_ms"))?; + + let consensus_commit_digest = value + .consensus_commit_digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("consensus_commit_digest"))? + .try_into()?; + + Ok(Self { + epoch, + round, + commit_timestamp_ms, + consensus_commit_digest, + }) + } +} + +impl From for super::ConsensusCommitPrologue { + fn from(value: sui_sdk_types::types::ConsensusCommitPrologueV3) -> Self { + Self { + epoch: Some(value.epoch), + round: Some(value.round), + commit_timestamp_ms: Some(value.commit_timestamp_ms), + consensus_commit_digest: Some(value.consensus_commit_digest.into()), + sub_dag_index: value.sub_dag_index, + consensus_determined_version_assignments: Some( + value.consensus_determined_version_assignments.into(), + ), + } + } +} + +impl TryFrom<&super::ConsensusCommitPrologue> for sui_sdk_types::types::ConsensusCommitPrologueV3 { + type Error = TryFromProtoError; + + fn try_from(value: &super::ConsensusCommitPrologue) -> Result { + let epoch = value + .epoch + .ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let round = value + .round + .ok_or_else(|| TryFromProtoError::missing("round"))?; + let commit_timestamp_ms = value + .commit_timestamp_ms + .ok_or_else(|| TryFromProtoError::missing("commit_timestamp_ms"))?; + + let consensus_commit_digest = value + .consensus_commit_digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("consensus_commit_digest"))? + .try_into()?; + + let consensus_determined_version_assignments = value + .consensus_determined_version_assignments + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("consensus_determined_version_assignments"))? + .try_into()?; + + Ok(Self { + epoch, + round, + commit_timestamp_ms, + sub_dag_index: value.sub_dag_index, + consensus_commit_digest, + consensus_determined_version_assignments, + }) + } +} + +// +// ConsensusDeterminedVersionAssignments +// + +impl From + for super::ConsensusDeterminedVersionAssignments +{ + fn from(value: sui_sdk_types::types::ConsensusDeterminedVersionAssignments) -> Self { + use super::consensus_determined_version_assignments::Kind; + use sui_sdk_types::types::ConsensusDeterminedVersionAssignments::*; + + let kind = match value { + CancelledTransactions { + cancelled_transactions, + } => Kind::CancelledTransactions(super::CancelledTransactions { + cancelled_transactions: cancelled_transactions + .into_iter() + .map(Into::into) + .collect(), + }), + }; + + Self { kind: Some(kind) } + } +} + +impl TryFrom<&super::ConsensusDeterminedVersionAssignments> + for sui_sdk_types::types::ConsensusDeterminedVersionAssignments +{ + type Error = TryFromProtoError; + + fn try_from(value: &super::ConsensusDeterminedVersionAssignments) -> Result { + use super::consensus_determined_version_assignments::Kind; + + match value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + { + Kind::CancelledTransactions(super::CancelledTransactions { + cancelled_transactions, + }) => Self::CancelledTransactions { + cancelled_transactions: cancelled_transactions + .iter() + .map(TryInto::try_into) + .collect::>()?, + }, + } + .pipe(Ok) + } +} + +// +// CancelledTransaction +// + +impl From for super::CancelledTransaction { + fn from(value: sui_sdk_types::types::CancelledTransaction) -> Self { + Self { + digest: Some(value.digest.into()), + version_assignments: value + .version_assignments + .into_iter() + .map(Into::into) + .collect(), + } + } +} + +impl TryFrom<&super::CancelledTransaction> for sui_sdk_types::types::CancelledTransaction { + type Error = TryFromProtoError; + + fn try_from(value: &super::CancelledTransaction) -> Result { + let digest = value + .digest + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("digest"))? + .try_into()?; + + let version_assignments = value + .version_assignments + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + digest, + version_assignments, + }) + } +} + +// +// VersionAssignment +// + +impl From for super::VersionAssignment { + fn from(value: sui_sdk_types::types::VersionAssignment) -> Self { + Self { + object_id: Some(value.object_id.into()), + version: Some(value.version), + } + } +} + +impl TryFrom<&super::VersionAssignment> for sui_sdk_types::types::VersionAssignment { + type Error = TryFromProtoError; + + fn try_from(value: &super::VersionAssignment) -> Result { + let object_id = value + .object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .try_into()?; + let version = value + .version + .ok_or_else(|| TryFromProtoError::missing("version"))?; + + Ok(Self { object_id, version }) + } +} + +// +// GenesisTransaction +// + +impl From for super::GenesisTransaction { + fn from(value: sui_sdk_types::types::GenesisTransaction) -> Self { + Self { + objects: value.objects.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::GenesisTransaction> for sui_sdk_types::types::GenesisTransaction { + type Error = TryFromProtoError; + + fn try_from(value: &super::GenesisTransaction) -> Result { + let objects = value + .objects + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { objects }) + } +} + +// +// RandomnessStateUpdate +// + +impl From for super::RandomnessStateUpdate { + fn from(value: sui_sdk_types::types::RandomnessStateUpdate) -> Self { + Self { + epoch: Some(value.epoch), + randomness_round: Some(value.randomness_round), + random_bytes: Some(value.random_bytes.into()), + randomness_object_initial_shared_version: Some( + value.randomness_obj_initial_shared_version, + ), + } + } +} + +impl TryFrom<&super::RandomnessStateUpdate> for sui_sdk_types::types::RandomnessStateUpdate { + type Error = TryFromProtoError; + + fn try_from( + super::RandomnessStateUpdate { + epoch, + randomness_round, + random_bytes, + randomness_object_initial_shared_version, + }: &super::RandomnessStateUpdate, + ) -> Result { + let epoch = epoch.ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let randomness_round = + randomness_round.ok_or_else(|| TryFromProtoError::missing("randomness_round"))?; + let random_bytes = random_bytes + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("random_bytes"))? + .to_vec(); + let randomness_obj_initial_shared_version = randomness_object_initial_shared_version + .ok_or_else(|| { + TryFromProtoError::missing("randomness_object_initial_shared_version") + })?; + Ok(Self { + epoch, + randomness_round, + random_bytes, + randomness_obj_initial_shared_version, + }) + } +} + +// +// AuthenticatorStateUpdate +// + +impl From for super::AuthenticatorStateUpdate { + fn from(value: sui_sdk_types::types::AuthenticatorStateUpdate) -> Self { + Self { + epoch: Some(value.epoch), + round: Some(value.round), + new_active_jwks: value.new_active_jwks.into_iter().map(Into::into).collect(), + authenticator_object_initial_shared_version: Some( + value.authenticator_obj_initial_shared_version, + ), + } + } +} + +impl TryFrom<&super::AuthenticatorStateUpdate> for sui_sdk_types::types::AuthenticatorStateUpdate { + type Error = TryFromProtoError; + + fn try_from( + super::AuthenticatorStateUpdate { + epoch, + round, + new_active_jwks, + authenticator_object_initial_shared_version, + }: &super::AuthenticatorStateUpdate, + ) -> Result { + let epoch = epoch.ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let round = round.ok_or_else(|| TryFromProtoError::missing("round"))?; + let authenticator_obj_initial_shared_version = authenticator_object_initial_shared_version + .ok_or_else(|| { + TryFromProtoError::missing("authenticator_object_initial_shared_version") + })?; + Ok(Self { + epoch, + round, + new_active_jwks: new_active_jwks + .iter() + .map(TryInto::try_into) + .collect::>()?, + authenticator_obj_initial_shared_version, + }) + } +} + +// +// Jwk +// + +impl From for super::Jwk { + fn from(value: sui_sdk_types::types::Jwk) -> Self { + Self { + kty: Some(value.kty.into_bytes().into()), + e: Some(value.e.into_bytes().into()), + n: Some(value.n.into_bytes().into()), + alg: Some(value.alg.into_bytes().into()), + } + } +} + +impl TryFrom<&super::Jwk> for sui_sdk_types::types::Jwk { + type Error = TryFromProtoError; + + fn try_from(super::Jwk { kty, e, n, alg }: &super::Jwk) -> Result { + let kty = kty + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kty"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + let e = e + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("e"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + let n = n + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("n"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + let alg = alg + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("alg"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + Ok(Self { kty, e, n, alg }) + } +} + +// +// JwkId +// + +impl From for super::JwkId { + fn from(value: sui_sdk_types::types::JwkId) -> Self { + Self { + iss: Some(value.iss.into_bytes().into()), + kid: Some(value.kid.into_bytes().into()), + } + } +} + +impl TryFrom<&super::JwkId> for sui_sdk_types::types::JwkId { + type Error = TryFromProtoError; + + fn try_from(super::JwkId { iss, kid }: &super::JwkId) -> Result { + let iss = iss + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("iss"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + let kid = kid + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kid"))? + .as_ref() + .pipe(std::str::from_utf8)? + .into(); + Ok(Self { iss, kid }) + } +} + +// +// ActiveJwk +// + +impl From for super::ActiveJwk { + fn from(value: sui_sdk_types::types::ActiveJwk) -> Self { + Self { + id: Some(value.jwk_id.into()), + jwk: Some(value.jwk.into()), + epoch: Some(value.epoch), + } + } +} + +impl TryFrom<&super::ActiveJwk> for sui_sdk_types::types::ActiveJwk { + type Error = TryFromProtoError; + + fn try_from(value: &super::ActiveJwk) -> Result { + let jwk_id = value + .id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("id"))? + .try_into()?; + + let jwk = value + .jwk + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("jwk"))? + .try_into()?; + + let epoch = value + .epoch + .ok_or_else(|| TryFromProtoError::missing("epoch"))?; + + Ok(Self { jwk_id, jwk, epoch }) + } +} + +// +// ChangeEpoch +// + +impl From for super::ChangeEpoch { + fn from(value: sui_sdk_types::types::ChangeEpoch) -> Self { + Self { + epoch: Some(value.epoch), + protocol_version: Some(value.protocol_version), + storage_charge: Some(value.storage_charge), + computation_charge: Some(value.computation_charge), + storage_rebate: Some(value.storage_rebate), + non_refundable_storage_fee: Some(value.non_refundable_storage_fee), + epoch_start_timestamp_ms: Some(value.epoch_start_timestamp_ms), + system_packages: value.system_packages.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::ChangeEpoch> for sui_sdk_types::types::ChangeEpoch { + type Error = TryFromProtoError; + + fn try_from( + super::ChangeEpoch { + epoch, + protocol_version, + storage_charge, + computation_charge, + storage_rebate, + non_refundable_storage_fee, + epoch_start_timestamp_ms, + system_packages, + }: &super::ChangeEpoch, + ) -> Result { + let epoch = epoch.ok_or_else(|| TryFromProtoError::missing("epoch"))?; + let protocol_version = + protocol_version.ok_or_else(|| TryFromProtoError::missing("protocol_version"))?; + let storage_charge = + storage_charge.ok_or_else(|| TryFromProtoError::missing("storage_charge"))?; + let computation_charge = + computation_charge.ok_or_else(|| TryFromProtoError::missing("computation_charge"))?; + let storage_rebate = + storage_rebate.ok_or_else(|| TryFromProtoError::missing("storage_rebate"))?; + let non_refundable_storage_fee = non_refundable_storage_fee + .ok_or_else(|| TryFromProtoError::missing("non_refundable_storage_fee"))?; + let epoch_start_timestamp_ms = epoch_start_timestamp_ms + .ok_or_else(|| TryFromProtoError::missing("epoch_start_timestamp_ms"))?; + + Ok(Self { + epoch, + protocol_version, + storage_charge, + computation_charge, + storage_rebate, + non_refundable_storage_fee, + epoch_start_timestamp_ms, + system_packages: system_packages + .iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +// +// SystemPackage +// + +impl From for super::SystemPackage { + fn from(value: sui_sdk_types::types::SystemPackage) -> Self { + Self { + version: Some(value.version), + modules: value.modules.into_iter().map(Into::into).collect(), + dependencies: value.dependencies.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::SystemPackage> for sui_sdk_types::types::SystemPackage { + type Error = TryFromProtoError; + + fn try_from(value: &super::SystemPackage) -> Result { + Ok(Self { + version: value + .version + .ok_or_else(|| TryFromProtoError::missing("version"))?, + modules: value.modules.iter().map(|bytes| bytes.to_vec()).collect(), + dependencies: value + .dependencies + .iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +// +// EndOfEpochTransactionkind +// + +impl From for super::EndOfEpochTransactionKind { + fn from(value: sui_sdk_types::types::EndOfEpochTransactionKind) -> Self { + use super::end_of_epoch_transaction_kind::Kind; + use sui_sdk_types::types::EndOfEpochTransactionKind::*; + + let kind = match value { + ChangeEpoch(change_epoch) => Kind::ChangeEpoch(change_epoch.into()), + AuthenticatorStateCreate => Kind::AuthenticatorStateCreate(()), + AuthenticatorStateExpire(expire) => Kind::AuthenticatorStateExpire(expire.into()), + RandomnessStateCreate => Kind::RandomnessStateCreate(()), + DenyListStateCreate => Kind::DenyListStateCreate(()), + BridgeStateCreate { chain_id } => Kind::BridgeStateCreate(chain_id.into()), + BridgeCommitteeInit { + bridge_object_version, + } => Kind::BridgeCommitteeInit(bridge_object_version), + }; + + Self { kind: Some(kind) } + } +} + +impl TryFrom<&super::EndOfEpochTransactionKind> + for sui_sdk_types::types::EndOfEpochTransactionKind +{ + type Error = TryFromProtoError; + + fn try_from(value: &super::EndOfEpochTransactionKind) -> Result { + use super::end_of_epoch_transaction_kind::Kind; + + match value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + { + Kind::ChangeEpoch(change_epoch) => Self::ChangeEpoch(change_epoch.try_into()?), + Kind::AuthenticatorStateExpire(expire) => { + Self::AuthenticatorStateExpire(expire.try_into()?) + } + Kind::AuthenticatorStateCreate(()) => Self::AuthenticatorStateCreate, + Kind::RandomnessStateCreate(()) => Self::RandomnessStateCreate, + Kind::DenyListStateCreate(()) => Self::DenyListStateCreate, + Kind::BridgeStateCreate(digest) => Self::BridgeStateCreate { + chain_id: digest.try_into()?, + }, + Kind::BridgeCommitteeInit(version) => Self::BridgeCommitteeInit { + bridge_object_version: *version, + }, + } + .pipe(Ok) + } +} + +// +// AuthenticatorStateExpire +// + +impl From for super::AuthenticatorStateExpire { + fn from(value: sui_sdk_types::types::AuthenticatorStateExpire) -> Self { + Self { + min_epoch: Some(value.min_epoch), + authenticator_object_initial_shared_version: Some( + value.authenticator_object_initial_shared_version, + ), + } + } +} + +impl TryFrom<&super::AuthenticatorStateExpire> for sui_sdk_types::types::AuthenticatorStateExpire { + type Error = TryFromProtoError; + + fn try_from( + super::AuthenticatorStateExpire { + min_epoch, + authenticator_object_initial_shared_version, + }: &super::AuthenticatorStateExpire, + ) -> Result { + let min_epoch = min_epoch.ok_or_else(|| TryFromProtoError::missing("min_epoch"))?; + let authenticator_object_initial_shared_version = + authenticator_object_initial_shared_version.ok_or_else(|| { + TryFromProtoError::missing("authenticator_object_initial_shared_version") + })?; + Ok(Self { + min_epoch, + authenticator_object_initial_shared_version, + }) + } +} + +// +// ProgrammableTransaction +// + +impl From for super::ProgrammableTransaction { + fn from(value: sui_sdk_types::types::ProgrammableTransaction) -> Self { + Self { + inputs: value.inputs.into_iter().map(Into::into).collect(), + commands: value.commands.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::ProgrammableTransaction> for sui_sdk_types::types::ProgrammableTransaction { + type Error = TryFromProtoError; + + fn try_from(value: &super::ProgrammableTransaction) -> Result { + Ok(Self { + inputs: value + .inputs + .iter() + .map(TryInto::try_into) + .collect::>()?, + commands: value + .commands + .iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +// +// Input +// + +impl From for super::Input { + fn from(value: sui_sdk_types::types::Input) -> Self { + use super::input::Kind; + use sui_sdk_types::types::Input::*; + + let kind = match value { + Pure { value } => Kind::Pure(value.into()), + ImmutableOrOwned(reference) => Kind::ImmutableOrOwned(reference.into()), + Shared { + object_id, + initial_shared_version, + mutable, + } => Kind::Shared(super::SharedObjectInput { + object_id: Some(object_id.into()), + initial_shared_version: Some(initial_shared_version), + mutable: Some(mutable), + }), + Receiving(reference) => Kind::Receiving(reference.into()), + }; + + Self { kind: Some(kind) } + } +} + +impl TryFrom<&super::Input> for sui_sdk_types::types::Input { + type Error = TryFromProtoError; + + fn try_from(value: &super::Input) -> Result { + use super::input::Kind; + + match value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + { + Kind::Pure(value) => Self::Pure { + value: value.to_vec(), + }, + Kind::ImmutableOrOwned(reference) => Self::ImmutableOrOwned(reference.try_into()?), + Kind::Shared(shared) => { + let object_id = shared + .object_id + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("object_id"))? + .try_into()?; + Self::Shared { + object_id, + initial_shared_version: shared + .initial_shared_version + .ok_or_else(|| TryFromProtoError::missing("initial_shared_version"))?, + mutable: shared + .mutable + .ok_or_else(|| TryFromProtoError::missing("mutable"))?, + } + } + Kind::Receiving(reference) => Self::Receiving(reference.try_into()?), + } + .pipe(Ok) + } +} + +// +// Argument +// + +impl From for super::Argument { + fn from(value: sui_sdk_types::types::Argument) -> Self { + use super::argument::Kind; + use sui_sdk_types::types::Argument::*; + + let kind = match value { + Gas => Kind::Gas(()), + Input(input) => Kind::Input(input.into()), + Result(result) => Kind::Result(result.into()), + NestedResult(result, subresult) => Kind::NestedResult(super::NestedResult { + result: Some(result.into()), + subresult: Some(subresult.into()), + }), + }; + + Self { kind: Some(kind) } + } +} + +impl TryFrom<&super::Argument> for sui_sdk_types::types::Argument { + type Error = TryFromProtoError; + + fn try_from(value: &super::Argument) -> Result { + use super::argument::Kind; + + match value + .kind + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("kind"))? + { + Kind::Gas(()) => Self::Gas, + Kind::Input(input) => Self::Input((*input).try_into()?), + Kind::Result(result) => Self::Result((*result).try_into()?), + Kind::NestedResult(super::NestedResult { result, subresult }) => Self::NestedResult( + result + .ok_or_else(|| TryFromProtoError::missing("result"))? + .try_into()?, + subresult + .ok_or_else(|| TryFromProtoError::missing("subresult"))? + .try_into()?, + ), + } + .pipe(Ok) + } +} + +// +// Command +// + +impl From for super::Command { + fn from(value: sui_sdk_types::types::Command) -> Self { + use super::command::Command; + use sui_sdk_types::types::Command::*; + + let command = match value { + MoveCall(move_call) => Command::MoveCall(move_call.into()), + TransferObjects(transfer_objects) => Command::TransferObjects(transfer_objects.into()), + SplitCoins(split_coins) => Command::SplitCoins(split_coins.into()), + MergeCoins(merge_coins) => Command::MergeCoins(merge_coins.into()), + Publish(publish) => Command::Publish(publish.into()), + MakeMoveVector(make_move_vector) => Command::MakeMoveVector(make_move_vector.into()), + Upgrade(upgrade) => Command::Upgrade(upgrade.into()), + }; + + Self { + command: Some(command), + } + } +} + +impl TryFrom<&super::Command> for sui_sdk_types::types::Command { + type Error = TryFromProtoError; + + fn try_from(value: &super::Command) -> Result { + use super::command::Command; + + match value + .command + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("command"))? + { + Command::MoveCall(move_call) => Self::MoveCall(move_call.try_into()?), + Command::TransferObjects(transfer_objects) => { + Self::TransferObjects(transfer_objects.try_into()?) + } + Command::SplitCoins(split_coins) => Self::SplitCoins(split_coins.try_into()?), + Command::MergeCoins(merge_coins) => Self::MergeCoins(merge_coins.try_into()?), + Command::Publish(publish) => Self::Publish(publish.try_into()?), + Command::MakeMoveVector(make_move_vector) => { + Self::MakeMoveVector(make_move_vector.try_into()?) + } + Command::Upgrade(upgrade) => Self::Upgrade(upgrade.try_into()?), + } + .pipe(Ok) + } +} + +// +// MoveCall +// + +impl From for super::MoveCall { + fn from(value: sui_sdk_types::types::MoveCall) -> Self { + Self { + package: Some(value.package.into()), + module: Some(value.module.into()), + function: Some(value.function.into()), + type_arguments: value.type_arguments.into_iter().map(Into::into).collect(), + arguments: value.arguments.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::MoveCall> for sui_sdk_types::types::MoveCall { + type Error = TryFromProtoError; + + fn try_from(value: &super::MoveCall) -> Result { + let package = value + .package + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("package"))? + .try_into()?; + + let module = value + .module + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("module"))? + .try_into()?; + + let function = value + .function + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("function"))? + .try_into()?; + + let type_arguments = value + .type_arguments + .iter() + .map(TryInto::try_into) + .collect::>()?; + let arguments = value + .arguments + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + package, + module, + function, + type_arguments, + arguments, + }) + } +} + +// +// TransferObjects +// + +impl From for super::TransferObjects { + fn from(value: sui_sdk_types::types::TransferObjects) -> Self { + Self { + objects: value.objects.into_iter().map(Into::into).collect(), + address: Some(value.address.into()), + } + } +} + +impl TryFrom<&super::TransferObjects> for sui_sdk_types::types::TransferObjects { + type Error = TryFromProtoError; + + fn try_from(value: &super::TransferObjects) -> Result { + let objects = value + .objects + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let address = value + .address + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("address"))? + .try_into()?; + + Ok(Self { objects, address }) + } +} + +// +// SplitCoins +// + +impl From for super::SplitCoins { + fn from(value: sui_sdk_types::types::SplitCoins) -> Self { + Self { + coin: Some(value.coin.into()), + amounts: value.amounts.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::SplitCoins> for sui_sdk_types::types::SplitCoins { + type Error = TryFromProtoError; + + fn try_from(value: &super::SplitCoins) -> Result { + let coin = value + .coin + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("coin"))? + .try_into()?; + + let amounts = value + .amounts + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { coin, amounts }) + } +} + +// +// MergeCoins +// + +impl From for super::MergeCoins { + fn from(value: sui_sdk_types::types::MergeCoins) -> Self { + Self { + coin: Some(value.coin.into()), + coins_to_merge: value.coins_to_merge.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::MergeCoins> for sui_sdk_types::types::MergeCoins { + type Error = TryFromProtoError; + + fn try_from(value: &super::MergeCoins) -> Result { + let coin = value + .coin + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("coin"))? + .try_into()?; + + let coins_to_merge = value + .coins_to_merge + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + coin, + coins_to_merge, + }) + } +} + +// +// Publish +// + +impl From for super::Publish { + fn from(value: sui_sdk_types::types::Publish) -> Self { + Self { + modules: value.modules.into_iter().map(Into::into).collect(), + dependencies: value.dependencies.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::Publish> for sui_sdk_types::types::Publish { + type Error = TryFromProtoError; + + fn try_from(value: &super::Publish) -> Result { + let modules = value.modules.iter().map(|bytes| bytes.to_vec()).collect(); + + let dependencies = value + .dependencies + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + modules, + dependencies, + }) + } +} + +// +// MakeMoveVector +// + +impl From for super::MakeMoveVector { + fn from(value: sui_sdk_types::types::MakeMoveVector) -> Self { + Self { + element_type: value.type_.map(Into::into), + elements: value.elements.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom<&super::MakeMoveVector> for sui_sdk_types::types::MakeMoveVector { + type Error = TryFromProtoError; + + fn try_from(value: &super::MakeMoveVector) -> Result { + let element_type = value + .element_type + .as_ref() + .map(TryInto::try_into) + .transpose()?; + + let elements = value + .elements + .iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(Self { + type_: element_type, + elements, + }) + } +} + +// +// Upgrade +// + +impl From for super::Upgrade { + fn from(value: sui_sdk_types::types::Upgrade) -> Self { + Self { + modules: value.modules.into_iter().map(Into::into).collect(), + dependencies: value.dependencies.into_iter().map(Into::into).collect(), + package: Some(value.package.into()), + ticket: Some(value.ticket.into()), + } + } +} + +impl TryFrom<&super::Upgrade> for sui_sdk_types::types::Upgrade { + type Error = TryFromProtoError; + + fn try_from(value: &super::Upgrade) -> Result { + let modules = value.modules.iter().map(|bytes| bytes.to_vec()).collect(); + + let dependencies = value + .dependencies + .iter() + .map(TryInto::try_into) + .collect::>()?; + + let package = value + .package + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("package"))? + .try_into()?; + + let ticket = value + .ticket + .as_ref() + .ok_or_else(|| TryFromProtoError::missing("ticket"))? + .try_into()?; + + Ok(Self { + modules, + dependencies, + package, + ticket, + }) + } +} diff --git a/crates/sui-rpc-api/tests/bootstrap.rs b/crates/sui-rpc-api/tests/bootstrap.rs index d5e606dc0a446..08e3669ccd42e 100644 --- a/crates/sui-rpc-api/tests/bootstrap.rs +++ b/crates/sui-rpc-api/tests/bootstrap.rs @@ -1,7 +1,8 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use std::{fs, path::PathBuf, process::Command}; +use std::fs; +use std::path::PathBuf; #[test] fn bootstrap() { @@ -34,15 +35,17 @@ fn bootstrap() { let out_dir = root_dir.join("src").join("proto").join("generated"); - if let Err(error) = prost_build::Config::new() + if let Err(error) = tonic_build::configure() + .build_client(true) + .build_server(true) .bytes(["."]) .out_dir(&out_dir) .compile_protos(&proto_files[..], &[proto_dir]) { - panic!("failed to compile `rest` protobuf: {}", error); + panic!("failed to compile `sui` protos: {}", error); } - let status = Command::new("git") + let status = std::process::Command::new("git") .arg("diff") .arg("--exit-code") .arg("--") From a29e6eb990545c89d504d607c86db571d431afa1 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 3 Dec 2024 09:00:07 -0600 Subject: [PATCH 26/28] rpc: add grpc server implementation Implement the sui.node.v2.Node gRPC service and serve it off the rpc endpoint. --- Cargo.lock | 2 + crates/sui-rpc-api/Cargo.toml | 2 + crates/sui-rpc-api/src/error.rs | 6 + crates/sui-rpc-api/src/grpc.rs | 253 ++++++++++++++++++++++++++++++++ crates/sui-rpc-api/src/lib.rs | 10 ++ 5 files changed, 273 insertions(+) create mode 100644 crates/sui-rpc-api/src/grpc.rs diff --git a/Cargo.lock b/Cargo.lock index 3b22e064b3e6d..06a6b0c1b73f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15197,6 +15197,7 @@ dependencies = [ "diffy", "documented", "fastcrypto", + "http 1.1.0", "itertools 0.13.0", "mime", "move-binary-format", @@ -15223,6 +15224,7 @@ dependencies = [ "tokio", "tonic 0.12.3", "tonic-build", + "tower 0.4.13", "url", ] diff --git a/crates/sui-rpc-api/Cargo.toml b/crates/sui-rpc-api/Cargo.toml index 24863b48ec454..c75c3dd315279 100644 --- a/crates/sui-rpc-api/Cargo.toml +++ b/crates/sui-rpc-api/Cargo.toml @@ -27,6 +27,8 @@ prometheus.workspace = true openapiv3 = { git = "https://github.com/bmwill/openapiv3.git", rev = "ca4b4845b7c159a39f5c68ad8f7f76cb6f4d6963" } schemars.workspace = true documented = "0.6.0" +http.workspace = true +tower.workspace = true fastcrypto.workspace = true sui-types.workspace = true diff --git a/crates/sui-rpc-api/src/error.rs b/crates/sui-rpc-api/src/error.rs index bc751118198e0..b0f4277673b7d 100644 --- a/crates/sui-rpc-api/src/error.rs +++ b/crates/sui-rpc-api/src/error.rs @@ -43,6 +43,12 @@ impl axum::response::IntoResponse for RpcServiceError { } } +impl From for tonic::Status { + fn from(value: RpcServiceError) -> Self { + tonic::Status::new(tonic::Code::Unknown, value.message.as_deref().unwrap_or("")) + } +} + impl From for RpcServiceError { fn from(value: sui_types::storage::error::Error) -> Self { Self { diff --git a/crates/sui-rpc-api/src/grpc.rs b/crates/sui-rpc-api/src/grpc.rs new file mode 100644 index 0000000000000..a9308dc425046 --- /dev/null +++ b/crates/sui-rpc-api/src/grpc.rs @@ -0,0 +1,253 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use http::{Request, Response}; +use std::convert::Infallible; +use tap::Pipe; +use tonic::{ + body::{boxed, BoxBody}, + server::NamedService, +}; +use tower::{Service, ServiceExt}; + +pub type BoxError = Box; + +#[derive(Default)] +pub struct Services { + router: axum::Router, +} + +impl Services { + pub fn new() -> Self { + Self::default() + } + + /// Add a new service. + pub fn add_service(mut self, svc: S) -> Self + where + S: Service, Response = Response, Error = Infallible> + + NamedService + + Clone + + Send + + 'static, + S::Future: Send + 'static, + S::Error: Into + Send, + { + self.router = self.router.route_service( + &format!("/{}/*rest", S::NAME), + svc.map_request(|req: Request| req.map(boxed)), + ); + self + } + + pub fn into_router(self) -> axum::Router { + self.router + } +} + +#[tonic::async_trait] +impl crate::proto::node::node_server::Node for crate::RpcService { + async fn get_node_info( + &self, + _request: tonic::Request<()>, + ) -> Result, tonic::Status> { + self.get_node_info() + .map(Into::into) + .map(tonic::Response::new) + .map_err(Into::into) + } + + async fn get_committee( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> + { + let committee = self.get_committee(request.into_inner().epoch)?; + + crate::proto::node::GetCommitteeResponse { + committee: Some(committee.into()), + } + .pipe(tonic::Response::new) + .pipe(Ok) + } + + async fn get_object( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> + { + let request = request.into_inner(); + let object_id = request + .object_id + .as_ref() + .ok_or_else(|| tonic::Status::new(tonic::Code::InvalidArgument, "missing object_id"))? + .try_into() + .map_err(|_| tonic::Status::new(tonic::Code::InvalidArgument, "invalid object_id"))?; + let version = request.version; + let options = request.options.unwrap_or_default().into(); + + self.get_object(object_id, version, options) + .map(Into::into) + .map(tonic::Response::new) + .map_err(Into::into) + } + + async fn get_transaction( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + let request = request.into_inner(); + let transaction_digest = request + .digest + .as_ref() + .ok_or_else(|| { + tonic::Status::new(tonic::Code::InvalidArgument, "missing transaction_digest") + })? + .try_into() + .map_err(|_| { + tonic::Status::new(tonic::Code::InvalidArgument, "invalid transaction_digest") + })?; + + let options = request.options.unwrap_or_default().into(); + + self.get_transaction(transaction_digest, &options) + .map(Into::into) + .map(tonic::Response::new) + .map_err(Into::into) + } + + async fn get_checkpoint( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + let request = request.into_inner(); + let checkpoint = match (request.sequence_number, request.digest) { + (Some(_sequence_number), Some(_digest)) => { + return Err(tonic::Status::new( + tonic::Code::InvalidArgument, + "only one of `sequence_number` or `digest` can be provided", + )) + } + (Some(sequence_number), None) => Some( + crate::service::checkpoints::CheckpointId::SequenceNumber(sequence_number), + ), + (None, Some(digest)) => Some(crate::service::checkpoints::CheckpointId::Digest( + (&digest).try_into().map_err(|_| { + tonic::Status::new(tonic::Code::InvalidArgument, "invalid digest") + })?, + )), + (None, None) => None, + }; + + let options = request.options.unwrap_or_default().into(); + + self.get_checkpoint(checkpoint, options) + .map(Into::into) + .map(tonic::Response::new) + .map_err(Into::into) + } + + async fn get_full_checkpoint( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + let request = request.into_inner(); + let checkpoint = match (request.sequence_number, request.digest) { + (Some(_sequence_number), Some(_digest)) => { + return Err(tonic::Status::new( + tonic::Code::InvalidArgument, + "only one of `sequence_number` or `digest` can be provided", + )) + } + (Some(sequence_number), None) => { + crate::service::checkpoints::CheckpointId::SequenceNumber(sequence_number) + } + + (None, Some(digest)) => { + crate::service::checkpoints::CheckpointId::Digest((&digest).try_into().map_err( + |_| tonic::Status::new(tonic::Code::InvalidArgument, "invalid digest"), + )?) + } + (None, None) => { + return Err(tonic::Status::new( + tonic::Code::InvalidArgument, + "must provided one of `sequence_number` or `digest`", + )) + } + }; + + let options = request.options.unwrap_or_default().into(); + + self.get_full_checkpoint(checkpoint, &options) + .map(Into::into) + .map(tonic::Response::new) + .map_err(Into::into) + } + + async fn execute_transaction( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + let request = request.into_inner(); + let transaction = match (request.transaction, request.transaction_bcs) { + (Some(_), Some(_)) => { + return Err(tonic::Status::new( + tonic::Code::InvalidArgument, + "only one of `transaction` or `transaction_bcs` can be provided", + )) + } + (Some(transaction), None) => (&transaction).try_into().map_err(|e| { + tonic::Status::new( + tonic::Code::InvalidArgument, + format!("invalid transaction: {e}"), + ) + })?, + + (None, Some(bcs)) => bcs::from_bytes(bcs.bcs()).map_err(|_| { + tonic::Status::new(tonic::Code::InvalidArgument, "invalid transaction bcs") + })?, + + (None, None) => { + return Err(tonic::Status::new( + tonic::Code::InvalidArgument, + "one of `transaction` or `transaction_bcs` must be provided", + )) + } + }; + let signatures = request + .signatures + .iter() + .map(TryInto::try_into) + .collect::>() + .map_err(|e| { + tonic::Status::new( + tonic::Code::InvalidArgument, + format!("invalid signature: {e}"), + ) + })?; + let signed_transaction = sui_sdk_types::types::SignedTransaction { + transaction, + signatures, + }; + + let options = request.options.unwrap_or_default().into(); + + self.execute_transaction(signed_transaction, None, &options) + .await + .map(Into::into) + .map(tonic::Response::new) + .map_err(Into::into) + } +} diff --git a/crates/sui-rpc-api/src/lib.rs b/crates/sui-rpc-api/src/lib.rs index 281ad243dde7b..44a4dd3239db4 100644 --- a/crates/sui-rpc-api/src/lib.rs +++ b/crates/sui-rpc-api/src/lib.rs @@ -12,6 +12,7 @@ use tap::Pipe; pub mod client; mod config; mod error; +mod grpc; mod metrics; pub mod proto; mod reader; @@ -80,7 +81,16 @@ impl RpcService { let rest_router = build_rest_router(self.clone()); + let grpc_router = { + grpc::Services::new() + .add_service(crate::proto::node::node_server::NodeServer::new( + self.clone(), + )) + .into_router() + }; + rest_router + .merge(grpc_router) .layer(axum::middleware::map_response_with_state( self, response::append_info_headers, From 6078eec7ae19f0475b7fd2cd7578d673b65478ca Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 3 Dec 2024 15:18:37 -0600 Subject: [PATCH 27/28] rpc: convert core client to use gRPC --- .../src/package_store.rs | 2 +- crates/sui-data-ingestion-core/src/reader.rs | 4 +- crates/sui-e2e-tests/tests/rpc/checkpoints.rs | 4 +- crates/sui-e2e-tests/tests/rpc/execute.rs | 2 +- crates/sui-e2e-tests/tests/rpc/objects.rs | 2 +- crates/sui-e2e-tests/tests/rpc/resolve.rs | 39 +- crates/sui-rpc-api/src/client/mod.rs | 344 ++++++++++++++---- crates/sui-rpc-api/src/client/sdk.rs | 6 +- crates/sui-rpc-api/src/proto/mod.rs | 2 + 9 files changed, 296 insertions(+), 109 deletions(-) diff --git a/crates/sui-analytics-indexer/src/package_store.rs b/crates/sui-analytics-indexer/src/package_store.rs index 7060ac8082806..b5c82c9f69dd6 100644 --- a/crates/sui-analytics-indexer/src/package_store.rs +++ b/crates/sui-analytics-indexer/src/package_store.rs @@ -76,7 +76,7 @@ impl LocalDBPackageStore { pub fn new(path: &Path, rest_url: &str) -> Self { Self { package_store_tables: PackageStoreTables::new(path), - fallback_client: Client::new(rest_url), + fallback_client: Client::new(rest_url).unwrap(), } } diff --git a/crates/sui-data-ingestion-core/src/reader.rs b/crates/sui-data-ingestion-core/src/reader.rs index f5771f372d548..f32730adc95c1 100644 --- a/crates/sui-data-ingestion-core/src/reader.rs +++ b/crates/sui-data-ingestion-core/src/reader.rs @@ -187,9 +187,9 @@ impl CheckpointReader { self.options.timeout_secs, ) .expect("failed to create remote store client"); - RemoteStore::Hybrid(object_store, sui_rpc_api::Client::new(fn_url)) + RemoteStore::Hybrid(object_store, sui_rpc_api::Client::new(fn_url).unwrap()) } else if url.ends_with("/rest") { - RemoteStore::Rest(sui_rpc_api::Client::new(url)) + RemoteStore::Rest(sui_rpc_api::Client::new(url).unwrap()) } else { let object_store = create_remote_store_client( url, diff --git a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs index 1c89aa06856ca..32649b5df5015 100644 --- a/crates/sui-e2e-tests/tests/rpc/checkpoints.rs +++ b/crates/sui-e2e-tests/tests/rpc/checkpoints.rs @@ -17,7 +17,7 @@ async fn list_checkpoint() { let _transaction_digest = transfer_coin(&test_cluster.wallet).await; let client = Client::new(test_cluster.rpc_url()).unwrap(); - let core_client = CoreClient::new(test_cluster.rpc_url()); + let core_client = CoreClient::new(test_cluster.rpc_url()).unwrap(); let checkpoints = client .list_checkpoints(&Default::default()) @@ -82,7 +82,7 @@ async fn get_full_checkpoint() { let _transaction_digest = transfer_coin(&test_cluster.wallet).await; let client = Client::new(test_cluster.rpc_url()).unwrap(); - let core_client = CoreClient::new(test_cluster.rpc_url()); + let core_client = CoreClient::new(test_cluster.rpc_url()).unwrap(); let latest = client.get_latest_checkpoint().await.unwrap().into_inner(); let _ = client diff --git a/crates/sui-e2e-tests/tests/rpc/execute.rs b/crates/sui-e2e-tests/tests/rpc/execute.rs index 7f33a7cf09cc8..0999327df1d6d 100644 --- a/crates/sui-e2e-tests/tests/rpc/execute.rs +++ b/crates/sui-e2e-tests/tests/rpc/execute.rs @@ -15,7 +15,7 @@ use test_cluster::TestClusterBuilder; async fn execute_transaction_transfer() { let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); + let client = Client::new(test_cluster.rpc_url()).unwrap(); let address = SuiAddress::random_for_testing_only(); let amount = 9; diff --git a/crates/sui-e2e-tests/tests/rpc/objects.rs b/crates/sui-e2e-tests/tests/rpc/objects.rs index d1a671f65ea20..8506f46480cf8 100644 --- a/crates/sui-e2e-tests/tests/rpc/objects.rs +++ b/crates/sui-e2e-tests/tests/rpc/objects.rs @@ -13,7 +13,7 @@ async fn get_object() { let test_cluster = TestClusterBuilder::new().build().await; let client = Client::new(test_cluster.rpc_url()).unwrap(); - let core_client = CoreClient::new(test_cluster.rpc_url()); + let core_client = CoreClient::new(test_cluster.rpc_url()).unwrap(); let _object = client.get_object("0x5".parse().unwrap()).await.unwrap(); let _object = core_client diff --git a/crates/sui-e2e-tests/tests/rpc/resolve.rs b/crates/sui-e2e-tests/tests/rpc/resolve.rs index 15b3fb66aef4b..6de508bcfd4c7 100644 --- a/crates/sui-e2e-tests/tests/rpc/resolve.rs +++ b/crates/sui-e2e-tests/tests/rpc/resolve.rs @@ -5,6 +5,7 @@ use shared_crypto::intent::Intent; use sui_keys::keystore::AccountKeystore; use sui_macros::sim_test; use sui_rpc_api::client::reqwest::StatusCode; +use sui_rpc_api::client::sdk::Client as RestClient; use sui_rpc_api::rest::transactions::ResolveTransactionQueryParameters; use sui_rpc_api::Client; use sui_sdk_types::types::unresolved; @@ -19,7 +20,8 @@ use test_cluster::TestClusterBuilder; async fn resolve_transaction_simple_transfer() { let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); + let client = Client::new(test_cluster.rpc_url()).unwrap(); + let rest_client = RestClient::new(test_cluster.rpc_url()).unwrap(); let recipient = SuiAddress::random_for_testing_only(); let (sender, mut gas) = test_cluster.wallet.get_one_account().await.unwrap(); @@ -50,8 +52,7 @@ async fn resolve_transaction_simple_transfer() { expiration: TransactionExpiration::None, }; - let resolved = client - .inner() + let resolved = rest_client .resolve_transaction_with_parameters( &unresolved_transaction, &ResolveTransactionQueryParameters { @@ -83,7 +84,8 @@ async fn resolve_transaction_simple_transfer() { async fn resolve_transaction_transfer_with_sponsor() { let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); + let client = Client::new(test_cluster.rpc_url()).unwrap(); + let rest_client = RestClient::new(test_cluster.rpc_url()).unwrap(); let recipient = SuiAddress::random_for_testing_only(); let (sender, gas) = test_cluster.wallet.get_one_account().await.unwrap(); @@ -119,8 +121,7 @@ async fn resolve_transaction_transfer_with_sponsor() { expiration: TransactionExpiration::None, }; - let resolved = client - .inner() + let resolved = rest_client .resolve_transaction_with_parameters( &unresolved_transaction, &ResolveTransactionQueryParameters { @@ -167,7 +168,8 @@ async fn resolve_transaction_transfer_with_sponsor() { async fn resolve_transaction_borrowed_shared_object() { let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); + let client = Client::new(test_cluster.rpc_url()).unwrap(); + let rest_client = RestClient::new(test_cluster.rpc_url()).unwrap(); let sender = test_cluster.wallet.get_addresses()[0]; @@ -190,8 +192,7 @@ async fn resolve_transaction_borrowed_shared_object() { expiration: TransactionExpiration::None, }; - let resolved = client - .inner() + let resolved = rest_client .resolve_transaction_with_parameters( &unresolved_transaction, &ResolveTransactionQueryParameters { @@ -219,13 +220,13 @@ async fn resolve_transaction_borrowed_shared_object() { async fn resolve_transaction_mutable_shared_object() { let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); + let client = Client::new(test_cluster.rpc_url()).unwrap(); + let rest_client = RestClient::new(test_cluster.rpc_url()).unwrap(); let (sender, mut gas) = test_cluster.wallet.get_one_account().await.unwrap(); gas.sort_by_key(|object_ref| object_ref.0); let obj_to_stake = gas.first().unwrap().0; - let validator_address = client - .inner() + let validator_address = rest_client .get_system_state_summary() .await .unwrap() @@ -264,8 +265,7 @@ async fn resolve_transaction_mutable_shared_object() { expiration: TransactionExpiration::None, }; - let resolved = client - .inner() + let resolved = rest_client .resolve_transaction_with_parameters( &unresolved_transaction, &ResolveTransactionQueryParameters { @@ -296,7 +296,7 @@ async fn resolve_transaction_mutable_shared_object() { #[sim_test] async fn resolve_transaction_insufficient_gas() { let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); + let rest_client = RestClient::new(test_cluster.rpc_url()).unwrap(); // Test the case where we don't have enough coins/gas for the required budget let unresolved_transaction = unresolved::Transaction { @@ -318,8 +318,7 @@ async fn resolve_transaction_insufficient_gas() { expiration: TransactionExpiration::None, }; - let error = client - .inner() + let error = rest_client .resolve_transaction(&unresolved_transaction) .await .unwrap_err(); @@ -341,7 +340,8 @@ fn assert_contains(haystack: &str, needle: &str) { async fn resolve_transaction_with_raw_json() { let test_cluster = TestClusterBuilder::new().build().await; - let client = Client::new(test_cluster.rpc_url()); + let client = Client::new(test_cluster.rpc_url()).unwrap(); + let rest_client = RestClient::new(test_cluster.rpc_url()).unwrap(); let recipient = SuiAddress::random_for_testing_only(); let (sender, mut gas) = test_cluster.wallet.get_one_account().await.unwrap(); @@ -387,8 +387,7 @@ async fn resolve_transaction_with_raw_json() { "sender": sender }); - let resolved = client - .inner() + let resolved = rest_client .resolve_transaction_with_parameters( &serde_json::from_value(unresolved_transaction).unwrap(), &ResolveTransactionQueryParameters { diff --git a/crates/sui-rpc-api/src/client/mod.rs b/crates/sui-rpc-api/src/client/mod.rs index 3d9ac332708df..2b5babf77cf7d 100644 --- a/crates/sui-rpc-api/src/client/mod.rs +++ b/crates/sui-rpc-api/src/client/mod.rs @@ -2,11 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 pub mod sdk; +use sdk::BoxError; +use sdk::Error; use sdk::Result; pub use reqwest; use tap::Pipe; +use crate::proto::node::node_client::NodeClient; use crate::types::ExecuteTransactionOptions; use sui_types::base_types::{ObjectID, SequenceNumber}; use sui_types::effects::{TransactionEffects, TransactionEvents}; @@ -15,70 +18,213 @@ use sui_types::messages_checkpoint::{CertifiedCheckpointSummary, CheckpointSeque use sui_types::object::Object; use sui_types::transaction::Transaction; -use self::sdk::Response; - #[derive(Clone)] pub struct Client { - inner: sdk::Client, + #[allow(unused)] + uri: http::Uri, + channel: tonic::transport::Channel, } impl Client { - pub fn new>(base_url: S) -> Self { - Self { - inner: sdk::Client::new(base_url.as_ref()).unwrap(), - } + pub fn new(uri: T) -> Result + where + T: TryInto, + T::Error: Into, + { + let uri = uri.try_into().map_err(Error::from_error)?; + let channel = tonic::transport::Endpoint::from(uri.clone()).connect_lazy(); + + Ok(Self { uri, channel }) } - pub fn inner(&self) -> &sdk::Client { - &self.inner + pub fn raw_client(&self) -> NodeClient { + NodeClient::new(self.channel.clone()) } pub async fn get_latest_checkpoint(&self) -> Result { - self.inner - .get_latest_checkpoint() - .await - .map(Response::into_inner) - .and_then(|checkpoint| checkpoint.try_into().map_err(Into::into)) + self.get_checkpoint_internal(None).await } - pub async fn get_full_checkpoint( + pub async fn get_checkpoint_summary( &self, - checkpoint_sequence_number: CheckpointSequenceNumber, - ) -> Result { - let url = self - .inner - .url() - .join(&format!("checkpoints/{checkpoint_sequence_number}/full"))?; + sequence_number: CheckpointSequenceNumber, + ) -> Result { + self.get_checkpoint_internal(Some(sequence_number)).await + } + + async fn get_checkpoint_internal( + &self, + sequence_number: Option, + ) -> Result { + let request = crate::proto::node::GetCheckpointRequest { + sequence_number, + digest: None, + options: Some(crate::proto::node::GetCheckpointOptions { + summary: Some(false), + summary_bcs: Some(true), + signature: Some(true), + contents: Some(false), + contents_bcs: Some(false), + }), + }; - let request = self.inner.client().get(url); + let crate::proto::node::GetCheckpointResponse { + summary_bcs, + signature, + .. + } = self + .raw_client() + .get_checkpoint(request) + .await + .map_err(Error::from_error)? + .into_inner(); + + let summary = summary_bcs + .ok_or_else(|| Error::from_error("missing summary"))? + .deserialize()?; - self.inner.bcs(request).await.map(Response::into_inner) + let signature = sui_types::crypto::AuthorityStrongQuorumSignInfo::from( + sui_sdk_types::types::ValidatorAggregatedSignature::try_from( + &signature.ok_or_else(|| Error::from_error("missing signautre"))?, + ) + .map_err(Error::from_error)?, + ); + + Ok(CertifiedCheckpointSummary::new_from_data_and_sig( + summary, signature, + )) } - pub async fn get_checkpoint_summary( + pub async fn get_full_checkpoint( &self, - checkpoint_sequence_number: CheckpointSequenceNumber, - ) -> Result { - self.inner - .get_checkpoint(checkpoint_sequence_number) + sequence_number: CheckpointSequenceNumber, + ) -> Result { + let request = crate::proto::node::GetFullCheckpointRequest { + sequence_number: Some(sequence_number), + digest: None, + options: Some(crate::proto::node::GetFullCheckpointOptions { + summary: Some(false), + summary_bcs: Some(true), + signature: Some(true), + contents: Some(false), + contents_bcs: Some(true), + transaction: Some(false), + transaction_bcs: Some(true), + effects: Some(false), + effects_bcs: Some(true), + events: Some(false), + events_bcs: Some(true), + input_objects: Some(true), + output_objects: Some(true), + object: Some(false), + object_bcs: Some(true), + }), + }; + + let crate::proto::node::GetFullCheckpointResponse { + summary_bcs, + signature, + contents_bcs, + transactions, + .. + } = self + .raw_client() + .get_full_checkpoint(request) .await - .map(Response::into_inner) - .and_then(|checkpoint| { - sui_sdk_types::types::SignedCheckpointSummary { - checkpoint: checkpoint.summary.unwrap(), - signature: checkpoint.signature.unwrap(), - } - .try_into() - .map_err(Into::into) - }) + .map_err(Error::from_error)? + .into_inner(); + + let summary = summary_bcs + .ok_or_else(|| Error::from_error("missing summary"))? + .deserialize()?; + let signature = sui_types::crypto::AuthorityStrongQuorumSignInfo::from( + sui_sdk_types::types::ValidatorAggregatedSignature::try_from( + &signature.ok_or_else(|| Error::from_error("missing signautre"))?, + ) + .map_err(Error::from_error)?, + ); + let checkpoint_summary = + CertifiedCheckpointSummary::new_from_data_and_sig(summary, signature); + + let checkpoint_contents = contents_bcs + .ok_or_else(|| Error::from_error("missing contents"))? + .deserialize::()?; + + let transactions = transactions + .into_iter() + .zip( + checkpoint_contents + .clone() + .into_iter_with_signatures() + .map(|(_digests, signatures)| signatures), + ) + .map( + |( + crate::proto::node::FullCheckpointTransaction { + transaction_bcs, + effects_bcs, + events_bcs, + input_objects, + output_objects, + .. + }, + signatures, + )| { + let transaction = transaction_bcs + .ok_or_else(|| Error::from_error("missing transaction"))? + .deserialize()?; + let transaction = Transaction::from_generic_sig_data(transaction, signatures); + let effects = effects_bcs + .ok_or_else(|| Error::from_error("missing effects"))? + .deserialize()?; + let events = events_bcs.map(|bcs| bcs.deserialize()).transpose()?; + let input_objects = input_objects + .ok_or_else(|| Error::from_error("missing input_objects"))? + .objects + .into_iter() + .map(|object| { + object + .object_bcs + .as_ref() + .ok_or_else(|| Error::from_error("missing object"))? + .deserialize::() + .map_err(Into::into) + }) + .collect::>()?; + + let output_objects = output_objects + .ok_or_else(|| Error::from_error("missing output_objects"))? + .objects + .into_iter() + .map(|object| { + object + .object_bcs + .ok_or_else(|| Error::from_error("missing object"))? + .deserialize::() + .map_err(Into::into) + }) + .collect::>()?; + + Result::<_>::Ok(sui_types::full_checkpoint_content::CheckpointTransaction { + transaction, + effects, + events, + input_objects, + output_objects, + }) + }, + ) + .collect::>()?; + + Ok(CheckpointData { + checkpoint_summary, + checkpoint_contents, + transactions, + }) } pub async fn get_object(&self, object_id: ObjectID) -> Result { - self.inner - .get_object(object_id.into()) - .await - .map(Response::into_inner) - .and_then(|object| object.try_into().map_err(Into::into)) + self.get_object_internal(object_id, None).await } pub async fn get_object_with_version( @@ -86,11 +232,35 @@ impl Client { object_id: ObjectID, version: SequenceNumber, ) -> Result { - self.inner - .get_object_with_version(object_id.into(), version.into()) + self.get_object_internal(object_id, Some(version.value())) .await - .map(Response::into_inner) - .and_then(|object| object.try_into().map_err(Into::into)) + } + + async fn get_object_internal( + &self, + object_id: ObjectID, + version: Option, + ) -> Result { + let request = crate::proto::node::GetObjectRequest { + object_id: Some(sui_sdk_types::types::ObjectId::from(object_id).into()), + version, + options: Some(crate::proto::node::GetObjectOptions { + object: Some(false), + object_bcs: Some(true), + }), + }; + + let crate::proto::node::GetObjectResponse { object_bcs, .. } = self + .raw_client() + .get_object(request) + .await + .map_err(Error::from_error)? + .into_inner(); + + object_bcs + .ok_or_else(|| Error::from_error("missing object"))? + .deserialize() + .map_err(Into::into) } pub async fn execute_transaction( @@ -98,49 +268,69 @@ impl Client { parameters: &ExecuteTransactionOptions, transaction: &Transaction, ) -> Result { - let signed_transaction = sui_sdk_types::types::SignedTransaction { - transaction: transaction - .inner() - .intent_message - .value - .clone() - .try_into()?, - signatures: transaction - .inner() - .tx_signatures - .clone() - .into_iter() - .map(TryInto::try_into) - .collect::>()?, - }; + let signatures = transaction + .inner() + .tx_signatures + .clone() + .into_iter() + .map(sui_sdk_types::types::UserSignature::try_from) + .collect::, _>>()?; - let options = ExecuteTransactionOptions { - effects_bcs: Some(true), - events_bcs: Some(true), - ..(parameters.to_owned()) + let request = crate::proto::node::ExecuteTransactionRequest { + transaction: None, + transaction_bcs: Some(crate::proto::types::Bcs::serialize( + &transaction.inner().intent_message.value, + )?), + signatures: signatures.into_iter().map(Into::into).collect(), + + options: Some(crate::proto::node::ExecuteTransactionOptions { + effects: Some(false), + effects_bcs: Some(true), + events: Some(false), + events_bcs: Some(true), + ..(parameters.to_owned().into()) + }), }; - let crate::types::ExecuteTransactionResponse { + let crate::proto::node::ExecuteTransactionResponse { finality, - effects: _, effects_bcs, - events: _, events_bcs, balance_changes, + .. } = self - .inner - .execute_transaction(&options, &signed_transaction) - .await? + .raw_client() + .execute_transaction(request) + .await + .map_err(Error::from_error)? .into_inner(); + let finality = finality + .as_ref() + .ok_or_else(|| Error::from_error("missing finality"))? + .pipe(TryInto::try_into) + .map_err(Error::from_error)?; + + let effects = effects_bcs + .ok_or_else(|| Error::from_error("missing effects"))? + .deserialize()?; + let events = events_bcs.map(|bcs| bcs.deserialize()).transpose()?; + + let balance_changes = balance_changes + .map(|balance_changes| { + balance_changes + .balance_changes + .iter() + .map(TryInto::try_into) + .collect::>() + }) + .transpose() + .map_err(Error::from_error)?; + TransactionExecutionResponse { finality, - effects: bcs::from_bytes( - effects_bcs - .as_deref() - .ok_or_else(|| sdk::Error::from_error("missing effects"))?, - )?, - events: events_bcs.as_deref().map(bcs::from_bytes).transpose()?, + effects, + events, balance_changes, } .pipe(Ok) diff --git a/crates/sui-rpc-api/src/client/sdk.rs b/crates/sui-rpc-api/src/client/sdk.rs index e231df5040698..180258130fe55 100644 --- a/crates/sui-rpc-api/src/client/sdk.rs +++ b/crates/sui-rpc-api/src/client/sdk.rs @@ -83,10 +83,6 @@ impl Client { .pipe(Ok) } - pub(super) fn client(&self) -> &reqwest::Client { - &self.inner - } - pub fn url(&self) -> &Url { &self.url } @@ -553,7 +549,7 @@ impl Response { pub type Result = std::result::Result; -type BoxError = Box; +pub(super) type BoxError = Box; #[derive(Debug)] pub struct Error { diff --git a/crates/sui-rpc-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs index d9a6c7342e51f..20699c0c75ebf 100644 --- a/crates/sui-rpc-api/src/proto/mod.rs +++ b/crates/sui-rpc-api/src/proto/mod.rs @@ -25,6 +25,8 @@ impl std::fmt::Display for TryFromProtoError { } } +impl std::error::Error for TryFromProtoError {} + impl TryFromProtoError { pub fn missing(field: &'static str) -> Self { Self { From 00c2a874fc0dde4a78025ba99d71289442153069 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Fri, 6 Dec 2024 11:08:19 -0600 Subject: [PATCH 28/28] rpc: add proptests for converting between rust and protobuf types --- Cargo.lock | 313 ++++++++++++---------- crates/sui-rpc-api/Cargo.toml | 4 + crates/sui-rpc-api/src/proto/mod.rs | 3 + crates/sui-rpc-api/src/proto/proptests.rs | 47 ++++ 4 files changed, 227 insertions(+), 140 deletions(-) create mode 100644 crates/sui-rpc-api/src/proto/proptests.rs diff --git a/Cargo.lock b/Cargo.lock index 06a6b0c1b73f5..b8f86ded9c16f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,7 +213,7 @@ source = "git+https://github.com/mystenlabs/anemo.git?rev=e609f7697ed6169bf07608 dependencies = [ "prettyplease", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -404,7 +404,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -417,7 +417,7 @@ dependencies = [ "num-bigint 0.4.4", "num-traits", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -490,7 +490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -787,7 +787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", "synstructure", ] @@ -799,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -923,7 +923,7 @@ dependencies = [ "darling 0.20.3", "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "strum 0.25.0", "syn 2.0.79", "thiserror", @@ -970,7 +970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -992,7 +992,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -1008,7 +1008,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -1082,7 +1082,7 @@ checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" dependencies = [ "proc-macro-error", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -1672,7 +1672,7 @@ checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ "heck 0.4.1", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -1896,7 +1896,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3deeecb812ca5300b7d3f66f730cc2ebd3511c3d36c691dd79c165d5b19a26e3" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -1950,7 +1950,7 @@ dependencies = [ "peeking_take_while", "prettyplease", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "regex", "rustc-hash 1.1.0", "shlex", @@ -2338,7 +2338,7 @@ dependencies = [ "cached_proc_macro_types", "darling 0.14.2", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -2568,7 +2568,7 @@ checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck 0.5.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -3267,7 +3267,7 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3303,7 +3303,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -3342,7 +3342,7 @@ dependencies = [ "codespan-reporting", "once_cell", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "scratch", "syn 1.0.107", ] @@ -3360,7 +3360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3391,7 +3391,7 @@ dependencies = [ "once_cell", "ouroboros 0.18.4", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "strsim 0.10.0", "syn 2.0.79", "thiserror", @@ -3416,7 +3416,7 @@ checksum = "25a69ecdf4aa110fed1c0c8de290bc8ccb2835388733cf2f418f0abdf6ff3899" dependencies = [ "cynic-codegen", "darling 0.20.3", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -3459,7 +3459,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "strsim 0.10.0", "syn 1.0.107", ] @@ -3473,7 +3473,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "strsim 0.10.0", "syn 1.0.107", ] @@ -3487,7 +3487,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "strsim 0.10.0", "syn 2.0.79", ] @@ -3499,7 +3499,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3510,7 +3510,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" dependencies = [ "darling_core 0.14.2", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3521,7 +3521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -3661,7 +3661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3672,7 +3672,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3683,7 +3683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cdeb9ec472d588e539a818b2dee436825730da08ad0017c4b1a17676bdc8b7" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3704,7 +3704,7 @@ checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ "darling 0.14.2", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -3726,7 +3726,7 @@ checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case 0.4.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "rustc_version", "syn 1.0.107", ] @@ -3747,7 +3747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", "unicode-xid 0.2.4", ] @@ -3807,7 +3807,7 @@ dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -3957,7 +3957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -4030,7 +4030,7 @@ dependencies = [ "convert_case 0.6.0", "optfield", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -4062,7 +4062,7 @@ dependencies = [ "either", "heck 0.5.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -4278,7 +4278,7 @@ checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ "heck 0.4.1", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -4297,7 +4297,7 @@ checksum = "1693044dcf452888dd3a6a6a0dab67f0652094e3920dfe029a54d2f37d9b7394" dependencies = [ "once_cell", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -4340,7 +4340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf679796c0322556351f287a51b49e48f7c4986e727b5dd78c972d30e2e16cc" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -4541,7 +4541,7 @@ dependencies = [ "eyre", "prettyplease", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "regex", "reqwest 0.11.20", "serde", @@ -4562,7 +4562,7 @@ dependencies = [ "ethers-contract-abigen", "ethers-core", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "serde_json", "syn 2.0.79", ] @@ -4846,7 +4846,7 @@ name = "fastcrypto-derive" version = "0.1.3" source = "git+https://github.com/MystenLabs/fastcrypto?rev=69d496c71fb37e3d22fe85e5bbfd4256d61422b9#69d496c71fb37e3d22fe85e5bbfd4256d61422b9" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -4987,7 +4987,7 @@ dependencies = [ "num-integer", "num-traits", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -5005,7 +5005,7 @@ checksum = "cca4fdab1b9b7e274e7de51202e37f9cfa542b28c77f8d09b817d77a726b4807" dependencies = [ "darling 0.13.4", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -5236,7 +5236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -5409,7 +5409,7 @@ checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -6178,7 +6178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -6199,7 +6199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", ] [[package]] @@ -6616,7 +6616,7 @@ dependencies = [ "heck 0.4.1", "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -7069,7 +7069,7 @@ dependencies = [ "fnv", "lazy_static", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "regex-syntax 0.8.2", "syn 2.0.79", ] @@ -7273,7 +7273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279def6bf114a34b3cf887489eb440d4dfcf709ab3ce9955e4a6f957ce5cce77" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -7295,7 +7295,7 @@ checksum = "ffb161cc72176cb37aa47f1fc520d3ef02263d67d661f44f05d05a079e1237fd" dependencies = [ "migrations_internals", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", ] [[package]] @@ -7364,7 +7364,7 @@ checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" dependencies = [ "cfg-if", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -7854,7 +7854,7 @@ name = "move-proc-macros" version = "0.1.0" dependencies = [ "enum-compat-util", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -8211,7 +8211,7 @@ source = "git+https://github.com/MystenLabs/mysten-sim.git?rev=9c6636c399d5c60a1 dependencies = [ "darling 0.14.2", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -8281,7 +8281,7 @@ dependencies = [ "proc-macro-crate", "proc-macro-error", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", "synstructure", ] @@ -8947,7 +8947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be7d33be719c6f4d09e64e27c1ef4e73485dc4cc1f4d22201f89860a7fe22e22" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -8959,7 +8959,7 @@ checksum = "066b468120587a402f0b47d8f80035c921f6a46f8209efd0632a89a16f5188a4" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -9050,7 +9050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -9160,7 +9160,7 @@ checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -9172,7 +9172,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -9290,7 +9290,7 @@ checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" dependencies = [ "bytes", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -9401,7 +9401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa59f025cde9c698fcb4fcb3533db4621795374065bee908215263488f2d2a1d" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -9451,7 +9451,7 @@ dependencies = [ "heck 0.4.1", "proc-macro-error", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -9465,7 +9465,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2 1.0.87", "proc-macro2-diagnostics", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -9570,7 +9570,7 @@ checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -9582,7 +9582,7 @@ checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -9754,9 +9754,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "path-slash" @@ -9874,7 +9874,7 @@ dependencies = [ "pest", "pest_meta", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -9948,7 +9948,7 @@ dependencies = [ "phf_generator", "phf_shared 0.11.1", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -9986,7 +9986,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -10295,7 +10295,7 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", "version_check", ] @@ -10307,7 +10307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "version_check", ] @@ -10342,7 +10342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", "version_check", "yansi 1.0.1", @@ -10399,20 +10399,19 @@ dependencies = [ [[package]] name = "proptest" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.4.1", "lazy_static", "num-traits", - "quick-error 2.0.1", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.6.28", + "regex-syntax 0.8.2", "rusty-fork", "tempfile", "unarray", @@ -10479,7 +10478,7 @@ dependencies = [ "anyhow", "itertools 0.11.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -10492,7 +10491,7 @@ dependencies = [ "anyhow", "itertools 0.13.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -10571,12 +10570,6 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quick-js" version = "0.4.1" @@ -10655,9 +10648,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2 1.0.87", ] @@ -10822,7 +10815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d78725e4e53781014168628ef49b2dc2fc6ae8d01a08769a5064685d34ee116c" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -10898,7 +10891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -11171,7 +11164,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -11268,7 +11261,7 @@ checksum = "7229b505ae0706e64f37ffc54a9c163e11022a6636d58fe1f3f52018257ff9f7" dependencies = [ "cfg-if", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "rustc_version", "syn 1.0.107", "unicode-ident", @@ -11654,7 +11647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" dependencies = [ "fnv", - "quick-error 1.2.3", + "quick-error", "tempfile", "wait-timeout", ] @@ -11690,7 +11683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "107c3d5d7f370ac09efa62a78375f94d94b8a33c61d8c278b96683fb4dbf2d8d" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -11738,7 +11731,7 @@ checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -11771,7 +11764,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "serde_derive_internals", "syn 2.0.79", ] @@ -12017,7 +12010,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -12028,7 +12021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -12072,7 +12065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -12148,7 +12141,7 @@ checksum = "e3452b4c0f6c1e357f73fdb87cd1efabaa12acf328c7a528e252893baeb3f4aa" dependencies = [ "darling 0.14.2", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -12160,7 +12153,7 @@ checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ "darling 0.20.3", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -12515,7 +12508,7 @@ checksum = "475b3bbe5245c26f2d8a6f62d67c1f30eb9fffeccee721c45d162c3ebbdf81b2" dependencies = [ "heck 0.4.1", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -12742,6 +12735,29 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "structmeta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" +dependencies = [ + "proc-macro2 1.0.87", + "quote 1.0.37", + "structmeta-derive", + "syn 2.0.79", +] + +[[package]] +name = "structmeta-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" +dependencies = [ + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", +] + [[package]] name = "strum" version = "0.24.1" @@ -12777,7 +12793,7 @@ checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.1", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "rustversion", "syn 1.0.107", ] @@ -12790,7 +12806,7 @@ checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" dependencies = [ "heck 0.4.1", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "rustversion", "syn 2.0.79", ] @@ -12803,7 +12819,7 @@ checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck 0.5.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "rustversion", "syn 2.0.79", ] @@ -13105,7 +13121,7 @@ name = "sui-analytics-indexer-derive" version = "1.40.0" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -13649,7 +13665,7 @@ dependencies = [ name = "sui-default-config" version = "1.40.0" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -13848,7 +13864,7 @@ dependencies = [ name = "sui-field-count-derive" version = "1.40.0" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -14908,7 +14924,7 @@ dependencies = [ "derive-syn-parse", "itertools 0.13.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", "unescape", ] @@ -15018,7 +15034,7 @@ version = "0.7.0" dependencies = [ "msim-macros", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "sui-enum-compat-util", "syn 2.0.79", ] @@ -15043,7 +15059,7 @@ name = "sui-protocol-config-macros" version = "0.1.0" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -15204,7 +15220,9 @@ dependencies = [ "move-core-types", "mysten-network", "openapiv3", + "paste", "prometheus", + "proptest", "prost 0.13.3", "prost-build", "prost-types 0.13.3", @@ -15220,6 +15238,7 @@ dependencies = [ "sui-sdk-types", "sui-types", "tap", + "test-strategy", "thiserror", "tokio", "tonic 0.12.3", @@ -15304,12 +15323,14 @@ dependencies = [ "bnum", "bs58 0.5.1", "hex", + "proptest", "roaring", "schemars", "serde", "serde_derive", "serde_json", "serde_with 3.9.0", + "test-strategy", "winnow 0.6.20", ] @@ -16146,7 +16167,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "unicode-ident", ] @@ -16157,7 +16178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "unicode-ident", ] @@ -16180,7 +16201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", "unicode-xid 0.2.4", ] @@ -16220,7 +16241,7 @@ dependencies = [ "heck 0.4.1", "proc-macro-error", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -16409,7 +16430,7 @@ checksum = "a9186daca5c58cb307d09731e0ba06b13fd6c036c90672b9bfc31cecf76cf689" dependencies = [ "cargo_metadata 0.15.4", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "serde", "strum_macros 0.24.3", ] @@ -16424,7 +16445,7 @@ dependencies = [ "if_chain", "lazy_static", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "subprocess", "syn 1.0.107", "test-fuzz-internal", @@ -16446,6 +16467,18 @@ dependencies = [ "test-fuzz-internal", ] +[[package]] +name = "test-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf41af45e3f54cc184831d629d41d5b2bda8297e29c81add7ae4f362ed5e01b" +dependencies = [ + "proc-macro2 1.0.87", + "quote 1.0.37", + "structmeta", + "syn 2.0.79", +] + [[package]] name = "textwrap" version = "0.16.0" @@ -16473,7 +16506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -16644,7 +16677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -16654,7 +16687,7 @@ version = "2.3.0" source = "git+https://github.com/mystenmark/tokio-madsim-fork.git?rev=d46208cb11118c0e6ab5dfea1a2265add36fbc15#d46208cb11118c0e6ab5dfea1a2265add36fbc15" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -16982,7 +17015,7 @@ dependencies = [ "proc-macro2 1.0.87", "prost-build", "prost-types 0.13.3", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -17170,7 +17203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -17285,7 +17318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b79e2e9c9ab44c6d7c20d5976961b47e8f49ac199154daa514b77cd1ab536625" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -17413,7 +17446,7 @@ dependencies = [ "ouroboros 0.17.2", "proc-macro2 1.0.87", "prometheus", - "quote 1.0.35", + "quote 1.0.37", "rand 0.8.5", "rocksdb", "rstest", @@ -17437,7 +17470,7 @@ version = "0.3.0" dependencies = [ "itertools 0.13.0", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -17459,7 +17492,7 @@ dependencies = [ "memchr", "nom", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "regex", "regex-syntax 0.7.2", "syn 2.0.79", @@ -17490,7 +17523,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a615d6c2764852a2e88a4f16e9ce1ea49bb776b5872956309e170d63a042a34f" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -17631,7 +17664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e7e85a0596447f0f2ac090e16bc4c516c6fe91771fb0c0ccf7fa3dae896b9c" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -17713,7 +17746,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae2faf80ac463422992abf4de234731279c058aaf33171ca70277c98406b124" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", ] @@ -17769,7 +17802,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", ] [[package]] @@ -17846,7 +17879,7 @@ dependencies = [ "log", "once_cell", "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", "wasm-bindgen-shared", ] @@ -17869,7 +17902,7 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "wasm-bindgen-macro-support", ] @@ -17880,7 +17913,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -18475,7 +18508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 2.0.79", ] @@ -18495,7 +18528,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2 1.0.87", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.107", "synstructure", ] diff --git a/crates/sui-rpc-api/Cargo.toml b/crates/sui-rpc-api/Cargo.toml index c75c3dd315279..2f3b444ad12f0 100644 --- a/crates/sui-rpc-api/Cargo.toml +++ b/crates/sui-rpc-api/Cargo.toml @@ -48,3 +48,7 @@ bytes.workspace = true diffy = "0.3" prost-build = "0.13.3" tonic-build = "0.12.3" +sui-sdk-types = { workspace = true, features = ["proptest"] } +test-strategy = "0.4.0" +proptest.workspace = true +paste = "1.0.15" diff --git a/crates/sui-rpc-api/src/proto/mod.rs b/crates/sui-rpc-api/src/proto/mod.rs index 20699c0c75ebf..56fbc4af904cb 100644 --- a/crates/sui-rpc-api/src/proto/mod.rs +++ b/crates/sui-rpc-api/src/proto/mod.rs @@ -1,6 +1,9 @@ pub mod node; pub mod types; +#[cfg(test)] +mod proptests; + type BoxError = Box; #[derive(Debug)] diff --git a/crates/sui-rpc-api/src/proto/proptests.rs b/crates/sui-rpc-api/src/proto/proptests.rs new file mode 100644 index 0000000000000..6d1eb67e18189 --- /dev/null +++ b/crates/sui-rpc-api/src/proto/proptests.rs @@ -0,0 +1,47 @@ +use super::types as proto; +use sui_sdk_types::types::*; +use test_strategy::proptest; + +macro_rules! protobuf_roundtrip_test { + ($type:ident, $proto:ty) => { + paste::item! { + #[proptest] + #[allow(non_snake_case)] + fn [< test_protobuf_roundtrip_ $type >] (instance: $type) { + assert_roundtrip::<$type, $proto>(instance); + } + } + }; +} + +/// Test that a type `T` can be roundtripped through a protobuf type `P` +fn assert_roundtrip(instance: T) +where + T: PartialEq + std::fmt::Debug + Clone, + T: for<'a> TryFrom<&'a P, Error: std::fmt::Debug>, + P: From, + P: prost::Message + Default, +{ + let proto = P::from(instance.to_owned()); + + let proto_bytes = proto.encode_to_vec(); + + let deser_from_proto = P::decode(proto_bytes.as_slice()).unwrap(); + + let t_from_p = T::try_from(&deser_from_proto).unwrap(); + + assert_eq!(instance, t_from_p); +} + +protobuf_roundtrip_test!(CheckpointSummary, proto::CheckpointSummary); +protobuf_roundtrip_test!(CheckpointContents, proto::CheckpointContents); +protobuf_roundtrip_test!(Transaction, proto::Transaction); +protobuf_roundtrip_test!(TransactionEffects, proto::TransactionEffects); +protobuf_roundtrip_test!(TransactionEvents, proto::TransactionEvents); +protobuf_roundtrip_test!(Object, proto::Object); +protobuf_roundtrip_test!(UserSignature, proto::UserSignature); +protobuf_roundtrip_test!( + ValidatorAggregatedSignature, + proto::ValidatorAggregatedSignature +); +protobuf_roundtrip_test!(ExecutionStatus, proto::ExecutionStatus);