Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tendermint::Hash can not be used as a return value when used with jsonrpsee #1474

Open
oblique opened this issue Nov 18, 2024 · 0 comments · May be fixed by #1475
Open

tendermint::Hash can not be used as a return value when used with jsonrpsee #1474

oblique opened this issue Nov 18, 2024 · 0 comments · May be fixed by #1475
Labels
bug Something isn't working

Comments

@oblique
Copy link

oblique commented Nov 18, 2024

We are from Lumina, a Celestia light node written in Rust. When we started the project we forked tendermint-rs to adjust it to Celestia's modifications. Now we are looking to migrate away form our fork.

What went wrong?

We are using jsonrpsee for calling into Celestia's node API. The API is using some types from tendermint-rs, such as tendermint::Hash.

Any struct that uses tendermint::Hash internally (e.g. SyncState) fails to deserialize and gives the following error:

thread 'sync_state' panicked at rpc/tests/header.rs:109:51:
called `Result::unwrap()` on an `Err` value: ParseError(Error("invalid type: string \"0AAC13B8406BDC81049B4E2F382F75754C5436F7DAC702256E9282EE33A242C4\", expected a borrowed string", line: 0, column: 0))

We debugged the issue and this happens because:

  1. jsonrpsee firsts deserializes to serde_json::Value and from there to SyncState.
  2. tendermint::Hash uses <&str>::deserialize(deserializer).
  3. <&str>::deserialize(deserializer) can not be used on serde_json::Value due to borrowing issues.

The pattern that jsonrpsee uses (i.e. &str -> serde_json::Value -> T) is valid and it may be used from other crates too.

Steps to reproduce

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct HashTest {
    hash: tendermint::Hash,
}

fn main() {
    let s = r#"{"hash": "9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08"}"#;

    // Works
    serde_json::from_str::<HashTest>(s).unwrap();

    // Fails
    let json_value = serde_json::from_str::<serde_json::Value>(s).unwrap();
    serde_json::from_value::<HashTest>(json_value).unwrap();
}

Definition of "done"

We need to stop using <&str>::deserialize. One way is to use String but allocates. Another way is to use the CowStr we implemented in our fork, which allocates on demand.

@oblique oblique added the bug Something isn't working label Nov 18, 2024
@oblique oblique linked a pull request Nov 18, 2024 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant