We are from Lumina, a Celestia light node written in Rust. When we started the project we forkedtendermint-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:
jsonrpsee firsts deserializes to serde_json::Value and from there to SyncState.
<&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.
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 astendermint::Hash
.Any struct that uses
tendermint::Hash
internally (e.g.SyncState
) fails to deserialize and gives the following error:We debugged the issue and this happens because:
jsonrpsee
firsts deserializes toserde_json::Value
and from there toSyncState
.tendermint::Hash
uses<&str>::deserialize(deserializer)
.<&str>::deserialize(deserializer)
can not be used onserde_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
Definition of "done"
We need to stop using
<&str>::deserialize
. One way is to useString
but allocates. Another way is to use theCowStr
we implemented in our fork, which allocates on demand.