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, short_vec,
}, },
serde::{ serde::{
de::{self, Deserializer, SeqAccess, Visitor}, de::{self, Deserializer, SeqAccess, Unexpected, Visitor},
ser::{SerializeTuple, Serializer}, ser::{SerializeTuple, Serializer},
Deserialize, Serialize, Deserialize, Serialize,
}, },
@ -198,7 +198,16 @@ impl<'de> Deserialize<'de> for MessagePrefix {
formatter.write_str("message prefix byte") 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 { if byte & MESSAGE_VERSION_PREFIX != 0 {
Ok(MessagePrefix::Versioned(byte & !MESSAGE_VERSION_PREFIX)) Ok(MessagePrefix::Versioned(byte & !MESSAGE_VERSION_PREFIX))
} else { } else {
@ -331,26 +340,32 @@ mod tests {
let mut message = LegacyMessage::new(&instructions, Some(&id1)); let mut message = LegacyMessage::new(&instructions, Some(&id1));
message.recent_blockhash = Hash::new_unique(); message.recent_blockhash = Hash::new_unique();
let wrapped_message = VersionedMessage::Legacy(message.clone());
let bytes1 = bincode::serialize(&message).unwrap(); // bincode
let bytes2 = bincode::serialize(&VersionedMessage::Legacy(message.clone())).unwrap(); {
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(); assert_eq!(message, message_from_bytes);
let message2: VersionedMessage = bincode::deserialize(&bytes2).unwrap(); assert_eq!(wrapped_message, wrapped_message_from_bytes);
}
if let VersionedMessage::Legacy(message2) = message2 { // serde_json
assert_eq!(message, message1); {
assert_eq!(message1, message2); let string = serde_json::to_string(&message).unwrap();
} else { let message_from_string: LegacyMessage = serde_json::from_str(&string).unwrap();
panic!("should deserialize to legacy message"); assert_eq!(message, message_from_string);
} }
} }
#[test] #[test]
fn test_versioned_message_serialization() { fn test_versioned_message_serialization() {
let message = v0::Message { let message = VersionedMessage::V0(v0::Message {
header: MessageHeader { header: MessageHeader {
num_required_signatures: 1, num_required_signatures: 1,
num_readonly_signed_accounts: 0, num_readonly_signed_accounts: 0,
@ -375,15 +390,14 @@ mod tests {
accounts: vec![0, 2, 3, 4], accounts: vec![0, 2, 3, 4],
data: vec![], 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(); 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 { let string = serde_json::to_string(&message).unwrap();
assert_eq!(message, message_from_bytes); let message_from_string: VersionedMessage = serde_json::from_str(&string).unwrap();
} else { assert_eq!(message, message_from_string);
panic!("should deserialize to versioned message");
}
} }
} }