diff --git a/crates/nox-tests/tests/builtin.rs b/crates/nox-tests/tests/builtin.rs index f3333a6267..e7ae077f90 100644 --- a/crates/nox-tests/tests/builtin.rs +++ b/crates/nox-tests/tests/builtin.rs @@ -2201,7 +2201,7 @@ async fn subnet_resolve() { // expect to receive this exact body in POST // .match_body(r#"{"jsonrpc":"2.0","id":0,"method":"eth_getLogs","params":[{"fromBlock":"0x52","toBlock":"0x246","address":"0x6328bb918a01603adc91eae689b848a9ecaef26d","topics":["0x55e61a24ecdae954582245e5e611fb06905d6af967334fff4db72793bebc72a9","0x7a82a5feefcaad4a89c689412031e5f87c02b29e3fced583be5f05c7077354b7"]}]}"#) // expect exactly 1 POST request - .expect(1) + .expect(2) .with_status(200) .with_header("content-type", "application/json") .create(); @@ -2230,8 +2230,14 @@ async fn subnet_resolve() { client.send_particle( r#" (seq - (call relay ("subnet" "resolve") ["0x6dD1aFfe90415C61AeDf5c0ACcA9Cf5fD5031517"] subnet) - (call %init_peer_id% ("op" "return") [subnet]) + (seq + (call relay ("subnet" "resolve") ["6dD1aFfe90415C61AeDf5c0ACcA9Cf5fD5031517"] subnet1) + (seq + (call relay ("subnet" "resolve") ["0x6dD1aFfe90415C61AeDf5c0ACcA9Cf5fD5031517"] subnet2) + (call relay ("subnet" "resolve") ["invalid_deal_id"] invalid) + ) + ) + (call %init_peer_id% ("op" "return") [subnet1 subnet2 invalid]) ) "#, hashmap! { @@ -2242,6 +2248,17 @@ async fn subnet_resolve() { let mut result = client.receive_args().await.unwrap(); let subnet: SubnetResolveResult = serde_json::from_value(result.remove(0)).unwrap(); + let subnet_second: SubnetResolveResult = serde_json::from_value(result.remove(0)).unwrap(); + let invalid: SubnetResolveResult = serde_json::from_value(result.remove(0)).unwrap(); + + assert!(!invalid.success, "invalid should be failed"); + assert_eq!(invalid.error.len(), 1); + assert_eq!( + invalid.error[0], + "Invalid deal id 'invalid_deal_id': invalid length" + ); + + assert_eq!(subnet, subnet_second); assert!(subnet.success, "{:?}", subnet.error); assert_eq!(subnet.error.len(), 0); diff --git a/crates/subnet-resolver/src/error.rs b/crates/subnet-resolver/src/error.rs index bc17d065d5..f91789aa12 100644 --- a/crates/subnet-resolver/src/error.rs +++ b/crates/subnet-resolver/src/error.rs @@ -27,4 +27,6 @@ pub enum ResolveSubnetError { Empty, #[error("'{1}' from getPATs is not a valid PeerId")] InvalidPeerId(#[source] ParseError, &'static str), + #[error("Invalid deal id '{0}': invalid length")] + InvalidDealId(String), } diff --git a/crates/subnet-resolver/src/resolve.rs b/crates/subnet-resolver/src/resolve.rs index 1d2427369b..73b2034b1e 100644 --- a/crates/subnet-resolver/src/resolve.rs +++ b/crates/subnet-resolver/src/resolve.rs @@ -35,13 +35,13 @@ pub fn parse_chain_data(data: &str) -> Result, ChainDataError> { Ok(ethabi::decode(&[signature], &data)?) } -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct Worker { pub pat_id: String, pub host_id: String, pub worker_id: Vec, } -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct SubnetResolveResult { pub success: bool, pub workers: Vec, @@ -92,8 +92,20 @@ fn decode_pats(data: String) -> Result, ResolveSubnetError> { Ok(result) } +pub fn validate_deal_id(deal_id: String) -> Result { + // 40 hex chars + 2 for "0x" prefix + if deal_id.len() == 42 && deal_id.starts_with("0x") { + Ok(deal_id) + } else if deal_id.len() == 40 { + Ok(format!("0x{}", deal_id)) + } else { + Err(ResolveSubnetError::InvalidDealId(deal_id)) + } +} + pub fn resolve_subnet(deal_id: String, api_endpoint: &str) -> SubnetResolveResult { let res: Result<_, ResolveSubnetError> = try { + let deal_id = validate_deal_id(deal_id)?; // Description of the `getPATs` function from the `chain.workers` smart contract on chain #[allow(deprecated)] let input = Function {