Fix versioned message json deserialization (#34808)

This commit is contained in:
Justin Starry 2024-01-18 10:31:05 +08:00 committed by GitHub
parent 6dbcdc063f
commit 747df9c105
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 34 additions and 20 deletions

View File

@ -8,7 +8,7 @@ use {
short_vec,
},
serde::{
de::{self, Deserializer, SeqAccess, Visitor},
de::{self, Deserializer, SeqAccess, Unexpected, Visitor},
ser::{SerializeTuple, Serializer},
Deserialize, Serialize,
},
@ -198,7 +198,16 @@ impl<'de> Deserialize<'de> for MessagePrefix {
formatter.write_str("message prefix byte")
}
fn visit_u8<E>(self, byte: u8) -> Result<MessagePrefix, E> {
// Serde's integer visitors bubble up to u64 so check the prefix
// with this function instead of visit_u8. This approach is
// necessary because serde_json directly calls visit_u64 for
// unsigned integers.
fn visit_u64<E: de::Error>(self, value: u64) -> Result<MessagePrefix, E> {
if value > u8::MAX as u64 {
Err(de::Error::invalid_type(Unexpected::Unsigned(value), &self))?;
}
let byte = value as u8;
if byte & MESSAGE_VERSION_PREFIX != 0 {
Ok(MessagePrefix::Versioned(byte & !MESSAGE_VERSION_PREFIX))
} else {
@ -331,26 +340,32 @@ mod tests {
let mut message = LegacyMessage::new(&instructions, Some(&id1));
message.recent_blockhash = Hash::new_unique();
let wrapped_message = VersionedMessage::Legacy(message.clone());
let bytes1 = bincode::serialize(&message).unwrap();
let bytes2 = bincode::serialize(&VersionedMessage::Legacy(message.clone())).unwrap();
// bincode
{
let bytes = bincode::serialize(&message).unwrap();
assert_eq!(bytes, bincode::serialize(&wrapped_message).unwrap());
assert_eq!(bytes1, bytes2);
let message_from_bytes: LegacyMessage = bincode::deserialize(&bytes).unwrap();
let wrapped_message_from_bytes: VersionedMessage =
bincode::deserialize(&bytes).unwrap();
let message1: LegacyMessage = bincode::deserialize(&bytes1).unwrap();
let message2: VersionedMessage = bincode::deserialize(&bytes2).unwrap();
assert_eq!(message, message_from_bytes);
assert_eq!(wrapped_message, wrapped_message_from_bytes);
}
if let VersionedMessage::Legacy(message2) = message2 {
assert_eq!(message, message1);
assert_eq!(message1, message2);
} else {
panic!("should deserialize to legacy message");
// serde_json
{
let string = serde_json::to_string(&message).unwrap();
let message_from_string: LegacyMessage = serde_json::from_str(&string).unwrap();
assert_eq!(message, message_from_string);
}
}
#[test]
fn test_versioned_message_serialization() {
let message = v0::Message {
let message = VersionedMessage::V0(v0::Message {
header: MessageHeader {
num_required_signatures: 1,
num_readonly_signed_accounts: 0,
@ -375,15 +390,14 @@ mod tests {
accounts: vec![0, 2, 3, 4],
data: vec![],
}],
};
});
let bytes = bincode::serialize(&VersionedMessage::V0(message.clone())).unwrap();
let bytes = bincode::serialize(&message).unwrap();
let message_from_bytes: VersionedMessage = bincode::deserialize(&bytes).unwrap();
assert_eq!(message, message_from_bytes);
if let VersionedMessage::V0(message_from_bytes) = message_from_bytes {
assert_eq!(message, message_from_bytes);
} else {
panic!("should deserialize to versioned message");
}
let string = serde_json::to_string(&message).unwrap();
let message_from_string: VersionedMessage = serde_json::from_str(&string).unwrap();
assert_eq!(message, message_from_string);
}
}