diff --git a/light-base/src/json_rpc_service/background.rs b/light-base/src/json_rpc_service/background.rs index 4ea97679c0..ad6d61ddf3 100644 --- a/light-base/src/json_rpc_service/background.rs +++ b/light-base/src/json_rpc_service/background.rs @@ -704,16 +704,28 @@ pub(super) async fn run( WakeUpReason::IncomingJsonRpcRequest(request_json) => { // New JSON-RPC request pulled from the channel. - let Ok((request_id_json, request_parsed)) = - methods::parse_jsonrpc_client_to_server(&request_json) - else { - // Request has failed to parse. Immediately return an answer. - let _ = me - .responses_tx - .send(parse::build_parse_error_response()) - .await; - continue; - }; + let (request_id_json, request_parsed) = + match methods::parse_jsonrpc_client_to_server(&request_json) { + Ok(r) => r, + Err(methods::ParseClientToServerError::JsonRpcParse(_)) => { + // Request has failed to parse. Immediately return an answer. + let _ = me + .responses_tx + .send(parse::build_parse_error_response()) + .await; + continue; + } + Err(methods::ParseClientToServerError::Method { request_id, error }) => { + // Invalid method or parameters. Immediately return an answer. + let _ = me.responses_tx.send(error.to_json_error(request_id)).await; + continue; + } + Err(methods::ParseClientToServerError::UnknownNotification { .. }) => { + // Invalid notification-style request. As per spec, we simply + // ignore them. + continue; + } + }; // Print a warning for legacy JSON-RPC API functions. match request_parsed { diff --git a/wasm-node/CHANGELOG.md b/wasm-node/CHANGELOG.md index 39dfe6aa82..fb7d311bd6 100644 --- a/wasm-node/CHANGELOG.md +++ b/wasm-node/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixed + +- A "parse error" JSON-RPC response is no longer erroneously sent back in case of an unrecognized JSON-RPC function name or wrong parameter types. ([#2138](https://github.com/smol-dot/smoldot/pull/2138)) + ## 2.0.35 - 2025-05-27 ### Changed diff --git a/wasm-node/javascript/test/misc.mjs b/wasm-node/javascript/test/misc.mjs index 7da4f39e92..013a9a8763 100644 --- a/wasm-node/javascript/test/misc.mjs +++ b/wasm-node/javascript/test/misc.mjs @@ -40,6 +40,25 @@ test('malformed JSON-RPC request generates an error', async t => { .then(() => client.terminate()); }); +test('invalid JSON-RPC method generates an error', async t => { + const client = start({ logCallback: () => { } }); + await client + .addChain({ chainSpec: westendSpec }) + .then((chain) => { + chain.sendJsonRpc('{"jsonrpc":"2.0","id":1,"method":"this method doesnt exist","params":[]}'); + return chain; + }) + .then(async (chain) => { + const response = await chain.nextJsonRpcResponse(); + const parsed = JSON.parse(response); + if (parsed.id === 1 && parsed.error) + t.pass(); + else + t.fail(response); + }) + .then(() => client.terminate()); +}); + test('disableJsonRpc option forbids sendJsonRpc', async t => { const client = start({ logCallback: () => { } }); await client @@ -47,7 +66,7 @@ test('disableJsonRpc option forbids sendJsonRpc', async t => { .then((chain) => { try { chain.sendJsonRpc('{"jsonrpc":"2.0","id":1,"method":"system_name","params":[]}'); - } catch(error) { + } catch (error) { t.assert(error instanceof JsonRpcDisabledError); t.pass(); } @@ -62,7 +81,7 @@ test('disableJsonRpc option forbids nextJsonRpcResponse', async t => { .then(async (chain) => { try { await chain.nextJsonRpcResponse(); - } catch(error) { + } catch (error) { t.assert(error instanceof JsonRpcDisabledError); t.pass(); }