diff --git a/crates/key-server/src/aggregator/server.rs b/crates/key-server/src/aggregator/server.rs index 22f7f0e4b..90786d0b9 100644 --- a/crates/key-server/src/aggregator/server.rs +++ b/crates/key-server/src/aggregator/server.rs @@ -58,7 +58,12 @@ const REFRESH_INTERVAL_SECS: u64 = 30; /// Default SDK version requirement. fn default_ts_sdk_version_requirement() -> VersionReq { // TODO: Update on first aggregator compatible SDK release. - VersionReq::parse(">=1000.0.0").expect("Failed to parse default SDK version requirement") + VersionReq::parse(">=1000.0.0").expect("Failed to parse default ts SDK version requirement") +} + +/// Default SDK version requirement. +fn default_rust_sdk_version_requirement() -> VersionReq { + VersionReq::parse(">=0.0.0").expect("Failed to parse default rust SDK version requirement") } /// Default key server version requirement. @@ -88,6 +93,10 @@ struct AggregatorOptions { #[serde(default = "default_ts_sdk_version_requirement")] ts_sdk_version_requirement: VersionReq, + /// The minimum version of the SDK that is required to use this aggregator. + #[serde(default = "default_rust_sdk_version_requirement")] + rust_sdk_version_requirement: VersionReq, + /// The minimum version of the key server that is required by this aggregator. #[serde(default = "default_key_server_version_requirement")] key_server_version_requirement: VersionReq, @@ -123,19 +132,21 @@ impl AppState { fn validate_sdk_version( &self, version: &str, - sdk_type: Option<&HeaderValue>, + sdk_type: ClientSdkType, ) -> Result<(), InternalError> { let version = Version::parse(version).map_err(|_| InvalidSDKVersion)?; - let sdk_type = ClientSdkType::from_header(sdk_type.and_then(|v| v.to_str().ok())); - match sdk_type { ClientSdkType::TypeScript => { if !self.options.ts_sdk_version_requirement.matches(&version) { return Err(DeprecatedSDKVersion); } } - _ => { - // TODO: Add support for other SDK types. + ClientSdkType::Rust => { + if !self.options.rust_sdk_version_requirement.matches(&version) { + return Err(DeprecatedSDKVersion); + } + } + ClientSdkType::Aggregator | ClientSdkType::Other => { return Err(InvalidSDKType); } } @@ -246,7 +257,8 @@ async fn handle_fetch_key( // Extract headers and validate version. let version = headers.get(HEADER_CLIENT_SDK_VERSION); - let sdk_type = headers.get(HEADER_CLIENT_SDK_TYPE); + let sdk_type_header = headers.get(HEADER_CLIENT_SDK_TYPE); + let sdk_type = ClientSdkType::from_header(sdk_type_header.and_then(|t| t.to_str().ok()))?; let version_str = version .ok_or_else(|| { @@ -278,18 +290,16 @@ async fn handle_fetch_key( })?; // Track client SDK version by type - let sdk_type_enum = ClientSdkType::from_header(sdk_type.and_then(|v| v.to_str().ok())); - let sdk_type_str = sdk_type_enum.to_string(); state .aggregator_metrics .client_sdk_version - .with_label_values(&[&sdk_type_str, version_str]) + .with_label_values(&[&sdk_type.to_string(), version_str]) .inc(); // Log incoming request with structured data info!( "Aggregator request - req_id: {}, SDK version: {}, SDK type: {:?}, user: {:?}", - req_id, version_str, sdk_type_enum, request.certificate.user + req_id, version_str, sdk_type, request.certificate.user ); // Call to committee members' servers in parallel. @@ -703,6 +713,7 @@ mod tests { node_url: None, key_server_object_id: Address::from([0u8; 32]), ts_sdk_version_requirement: VersionReq::parse(">=0.9.0").unwrap(), + rust_sdk_version_requirement: VersionReq::parse(">=0.0.0").unwrap(), key_server_version_requirement: VersionReq::parse(">=0.5.14").unwrap(), api_credentials, }; @@ -744,6 +755,7 @@ mod tests { let (request, _, _) = create_test_fetch_key_request(&mut thread_rng()); let mut headers = HeaderMap::new(); + headers.insert(HEADER_CLIENT_SDK_TYPE, "typescript".parse().unwrap()); headers.insert(HEADER_CLIENT_SDK_VERSION, "0.3.0".parse().unwrap()); // Too old let result = handle_fetch_key(State(state), headers, Json(request)).await; @@ -775,6 +787,7 @@ mod tests { let (request, _, _) = create_test_fetch_key_request(&mut thread_rng()); let mut headers = HeaderMap::new(); + headers.insert(HEADER_CLIENT_SDK_TYPE, "typescript".parse().unwrap()); headers.insert(HEADER_CLIENT_SDK_VERSION, "0.9.6".parse().unwrap()); let result = handle_fetch_key(State(state), headers, Json(request)).await; @@ -806,6 +819,7 @@ mod tests { let (request, _, _) = create_test_fetch_key_request(&mut thread_rng()); let mut headers = HeaderMap::new(); + headers.insert(HEADER_CLIENT_SDK_TYPE, "typescript".parse().unwrap()); headers.insert(HEADER_CLIENT_SDK_VERSION, "0.9.6".parse().unwrap()); let result = handle_fetch_key(State(state), headers, Json(request)).await; let response = result.unwrap().into_response(); @@ -869,6 +883,7 @@ mod tests { // Call handle_fetch_key and check majority error. let mut headers = HeaderMap::new(); + headers.insert(HEADER_CLIENT_SDK_TYPE, "typescript".parse().unwrap()); headers.insert(HEADER_CLIENT_SDK_VERSION, "0.9.6".parse().unwrap()); let result = handle_fetch_key(State(state), headers, Json(request)).await; match result { diff --git a/crates/key-server/src/common.rs b/crates/key-server/src/common.rs index c7d54c614..da0552ecf 100644 --- a/crates/key-server/src/common.rs +++ b/crates/key-server/src/common.rs @@ -6,6 +6,8 @@ use axum::response::Response; use serde::{Deserialize, Serialize}; use sui_types::base_types::ObjectID; +use crate::errors::InternalError; + /// Network configuration. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Network { @@ -50,6 +52,9 @@ pub const SDK_TYPE_AGGREGATOR: &str = "aggregator"; /// SDK type value for TypeScript clients. pub const SDK_TYPE_TYPESCRIPT: &str = "typescript"; +/// SDK type value for Rust clients. +pub const SDK_TYPE_RUST: &str = "rust"; + /// Get the git version. /// Based on https://github.com/MystenLabs/walrus/blob/7e282a681e6530ae4073210b33cac915fab439fa/crates/walrus-service/src/common/utils.rs#L69 #[macro_export] @@ -80,23 +85,25 @@ macro_rules! git_version { pub enum ClientSdkType { Aggregator, TypeScript, + Rust, Other, } impl ClientSdkType { - pub fn from_header(header_value: Option<&str>) -> Self { + pub fn from_header(header_value: Option<&str>) -> Result { match header_value { - Some(SDK_TYPE_AGGREGATOR) => ClientSdkType::Aggregator, - Some(SDK_TYPE_TYPESCRIPT) => ClientSdkType::TypeScript, - Some(_) => ClientSdkType::Other, - None => ClientSdkType::TypeScript, // Default to TypeScript for backward compatibility + Some(SDK_TYPE_AGGREGATOR) => Ok(ClientSdkType::Aggregator), + Some(SDK_TYPE_TYPESCRIPT) => Ok(ClientSdkType::TypeScript), + Some(SDK_TYPE_RUST) => Ok(ClientSdkType::Rust), + _ => Ok(ClientSdkType::Other), } } pub fn as_str(&self) -> &'static str { match self { - ClientSdkType::Aggregator => "aggregator", - ClientSdkType::TypeScript => "typescript", + ClientSdkType::Aggregator => SDK_TYPE_AGGREGATOR, + ClientSdkType::TypeScript => SDK_TYPE_TYPESCRIPT, + ClientSdkType::Rust => SDK_TYPE_RUST, ClientSdkType::Other => "other", } } diff --git a/crates/key-server/src/key_server_options.rs b/crates/key-server/src/key_server_options.rs index 74fb9400c..aa7ebf0a4 100644 --- a/crates/key-server/src/key_server_options.rs +++ b/crates/key-server/src/key_server_options.rs @@ -125,6 +125,10 @@ pub struct KeyServerOptions { #[serde(default = "default_ts_sdk_version_requirement")] pub ts_sdk_version_requirement: VersionReq, + /// The minimum version of the Rust SDK that is required to use this key server. + #[serde(default = "default_rust_sdk_version_requirement")] + pub rust_sdk_version_requirement: VersionReq, + /// The minimum version of the aggregator that is required to use this key server. #[serde(default = "default_aggregator_version_requirement")] pub aggregator_version_requirement: VersionReq, @@ -184,6 +188,7 @@ impl KeyServerOptions { node_url: None, ts_sdk_version_requirement: default_ts_sdk_version_requirement(), aggregator_version_requirement: default_aggregator_version_requirement(), + rust_sdk_version_requirement: default_rust_sdk_version_requirement(), server_mode: ServerMode::Open { key_server_object_id, }, @@ -203,6 +208,7 @@ impl KeyServerOptions { node_url: None, ts_sdk_version_requirement: default_ts_sdk_version_requirement(), aggregator_version_requirement: default_aggregator_version_requirement(), + rust_sdk_version_requirement: default_rust_sdk_version_requirement(), server_mode: ServerMode::Open { key_server_object_id: ObjectID::random(), }, @@ -336,6 +342,9 @@ fn default_aggregator_version_requirement() -> VersionReq { VersionReq::parse(">=1000.0.0").expect("Failed to parse default aggregator version requirement") } +fn default_rust_sdk_version_requirement() -> VersionReq { + VersionReq::parse(">=0.0.0").expect("Failed to parse default Rust SDK version requirement") +} #[test] fn test_parse_open_config() { use std::str::FromStr; diff --git a/crates/key-server/src/server.rs b/crates/key-server/src/server.rs index 77c39ab60..d821e1ea9 100644 --- a/crates/key-server/src/server.rs +++ b/crates/key-server/src/server.rs @@ -856,7 +856,8 @@ impl MyState { let requirement = match sdk_type { ClientSdkType::Aggregator => &self.server.options.aggregator_version_requirement, ClientSdkType::TypeScript => &self.server.options.ts_sdk_version_requirement, - ClientSdkType::Other => return Ok(()), + ClientSdkType::Rust => &self.server.options.rust_sdk_version_requirement, + ClientSdkType::Other => return Ok(()), // Ignore if sdk type is unknown string or not provided }; if !requirement.matches(&version) { @@ -875,7 +876,7 @@ async fn handle_request_headers( ) -> Result { // Log the request id and SDK version let version = request.headers().get(HEADER_CLIENT_SDK_VERSION); - let sdk_type = request.headers().get(HEADER_CLIENT_SDK_TYPE); + let sdk_type_header = request.headers().get(HEADER_CLIENT_SDK_TYPE); info!( "Request id: {:?}, SDK version: {:?}, SDK type: {:?}, Target API version: {:?}", @@ -884,12 +885,11 @@ async fn handle_request_headers( .get("Request-Id") .map(|v| v.to_str().unwrap_or_default()), version, - sdk_type, + sdk_type_header, request.headers().get("Client-Target-Api-Version") ); - let sdk_type = ClientSdkType::from_header(sdk_type.and_then(|t| t.to_str().ok())); - + let sdk_type = ClientSdkType::from_header(sdk_type_header.and_then(|t| t.to_str().ok()))?; let version_str = version .ok_or(MissingRequiredHeader(HEADER_CLIENT_SDK_VERSION.to_string())) .and_then(|v| v.to_str().map_err(|_| InvalidSDKVersion)) diff --git a/crates/key-server/src/tests/mod.rs b/crates/key-server/src/tests/mod.rs index 0c74f38a6..aba352b89 100644 --- a/crates/key-server/src/tests/mod.rs +++ b/crates/key-server/src/tests/mod.rs @@ -183,6 +183,7 @@ impl SealTestCluster { rgp_update_interval: Duration::from_secs(60), ts_sdk_version_requirement: VersionReq::from_str(">=0.4.6").unwrap(), aggregator_version_requirement: VersionReq::from_str(">=0.5.15").unwrap(), + rust_sdk_version_requirement: VersionReq::from_str(">=0.0.0").unwrap(), allowed_staleness, session_key_ttl_max: from_mins(30), rpc_config: RpcConfig::default(), diff --git a/crates/key-server/src/tests/server.rs b/crates/key-server/src/tests/server.rs index a62925b91..ecc7c125e 100644 --- a/crates/key-server/src/tests/server.rs +++ b/crates/key-server/src/tests/server.rs @@ -151,6 +151,7 @@ async fn test_service() { "http://{addr}/v1/service?service_id={}", key_server_object_id.as_str() )) + .header(HEADER_CLIENT_SDK_TYPE, "typescript") .header(HEADER_CLIENT_SDK_VERSION, "0.3.0") // Too old (requires >=0.4.6) .body(Body::empty()) .unwrap(), @@ -196,6 +197,7 @@ async fn test_service() { "http://{addr}/v1/service?service_id={}", key_server_object_id.as_str() )) + .header(HEADER_CLIENT_SDK_TYPE, "typescript") .header(HEADER_CLIENT_SDK_VERSION, "0.4.11") .body(Body::empty()) .unwrap(), @@ -343,6 +345,7 @@ async fn test_fetch_key() { Request::builder() .uri(format!("http://{addr}/v1/fetch_key",)) .method("POST") + .header(HEADER_CLIENT_SDK_TYPE, "typescript") .header(HEADER_CLIENT_SDK_VERSION, "0.4.11") .header("Content-Type", "application/json") .body(Body::from(json!(request).to_string())) diff --git a/crates/key-server/src/tests/test_utils.rs b/crates/key-server/src/tests/test_utils.rs index 1c7684b2b..c6e9b3883 100644 --- a/crates/key-server/src/tests/test_utils.rs +++ b/crates/key-server/src/tests/test_utils.rs @@ -49,6 +49,7 @@ pub(crate) async fn create_test_server( metrics_host_port: 0, rgp_update_interval: Duration::from_secs(60), ts_sdk_version_requirement: VersionReq::from_str(">=0.4.6").unwrap(), + rust_sdk_version_requirement: VersionReq::from_str(">=0.0.0").unwrap(), aggregator_version_requirement: VersionReq::from_str(">=0.5.15").unwrap(), allowed_staleness: Duration::from_secs(120), session_key_ttl_max: from_mins(30), diff --git a/crates/seal-cli/src/main.rs b/crates/seal-cli/src/main.rs index 5e199cfdb..9d350c82b 100644 --- a/crates/seal-cli/src/main.rs +++ b/crates/seal-cli/src/main.rs @@ -575,7 +575,7 @@ async fn main() -> FastCryptoResult<()> { match client .post(format!("{}/v1/fetch_key", server.url)) .header("Client-Sdk-Type", "rust") - .header("Client-Sdk-Version", "1.0.0") + .header("Client-Sdk-Version", "0.0.0") .header("Content-Type", "application/json") .body(Body::from( request.to_json_string().expect("should not fail"), diff --git a/move/seal_testnet/Move.lock b/move/seal_testnet/Move.lock index a4d300dfd..d22a25dd4 100644 --- a/move/seal_testnet/Move.lock +++ b/move/seal_testnet/Move.lock @@ -2,29 +2,7 @@ # This file should be checked in. [move] -version = 3 -manifest_digest = "B153E07850EC7C7BD445C2B37390A7926AD3C299ADED88E38D8F0BB1E8393219" -deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" -dependencies = [ - { id = "Sui", name = "Sui" }, -] - -[[move.package]] -id = "MoveStdlib" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet-v1.61.2", subdir = "crates/sui-framework/packages/move-stdlib" } - -[[move.package]] -id = "Sui" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet-v1.61.2", subdir = "crates/sui-framework/packages/sui-framework" } - -dependencies = [ - { id = "MoveStdlib", name = "MoveStdlib" }, -] - -[move.toolchain-version] -compiler-version = "1.61.2" -edition = "2024.beta" -flavor = "sui" +version = 4 [pinned.testnet.MoveStdlib] source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "6c229fe6c04fb21ec98751c798e57e9a00e028e2" } @@ -43,11 +21,3 @@ source = { root = true } use_environment = "testnet" manifest_digest = "65066A1AFA6718772BD68F6AFE27843F2371E14C4CF891FC7DADDFA586DABF89" deps = { Sui = "Sui" } - -[env] - -[env.testnet] -chain-id = "4c78adac" -original-published-id = "0xbad13e742065222c16cc2936a46a5d44586b8546917fa129f65277c4bdbca03d" -latest-published-id = "0xbad13e742065222c16cc2936a46a5d44586b8546917fa129f65277c4bdbca03d" -published-version = "1"