Skip to content

Commit

Permalink
serialization: explicitely define ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
TalDerei committed Dec 13, 2024
1 parent d59033e commit 02b18d0
Showing 1 changed file with 94 additions and 1 deletion.
95 changes: 94 additions & 1 deletion crates/core/keys/src/address/view.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cmp::Ordering;

use serde::{Deserialize, Serialize};

use penumbra_proto::{penumbra::core::keys::v1 as pb, DomainType};
Expand All @@ -11,7 +13,7 @@ use super::Address;
///
/// This type allows working with addresses and address indexes without knowing
/// the corresponding FVK.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(try_from = "pb::AddressView", into = "pb::AddressView")]
pub enum AddressView {
Opaque {
Expand Down Expand Up @@ -99,6 +101,97 @@ impl TryFrom<pb::AddressView> for AddressView {
}
}

// Canonical ordering for serialization
impl PartialOrd for AddressView {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
// Opaque < Decoded
match (self, other) {
(AddressView::Opaque { address: a1 }, AddressView::Opaque { address: a2 }) => {
a1.partial_cmp(a2)
}
(
AddressView::Decoded {
address: a1,
index: i1,
wallet_id: w1,
},
AddressView::Decoded {
address: a2,
index: i2,
wallet_id: w2,
},
) => match a1.partial_cmp(a2) {
Some(Ordering::Equal) => match i1.partial_cmp(i2) {
Some(Ordering::Equal) => w1.partial_cmp(w2),
ord => ord,
},
ord => ord,
},
(
AddressView::Opaque { address: _ },
AddressView::Decoded {
address: _,
index: _,
wallet_id: _,
},
) => Some(Ordering::Less),
(
AddressView::Decoded {
address: _,
index: _,
wallet_id: _,
},
AddressView::Opaque { address: _ },
) => Some(Ordering::Greater),
}
}
}

impl Ord for AddressView {
fn cmp(&self, other: &Self) -> Ordering {
// Opaque < Decoded
match (self, other) {
(AddressView::Opaque { address: a1 }, AddressView::Opaque { address: a2 }) => {
a1.cmp(a2)
}
(
AddressView::Decoded {
address: a1,
index: i1,
wallet_id: w1,
},
AddressView::Decoded {
address: a2,
index: i2,
wallet_id: w2,
},
) => match a1.cmp(a2) {
Ordering::Equal => match i1.cmp(i2) {
Ordering::Equal => w1.cmp(w2),
ord => ord,
},
ord => ord,
},
(
AddressView::Opaque { address: _ },
AddressView::Decoded {
address: _,
index: _,
wallet_id: _,
},
) => Ordering::Less,
(
AddressView::Decoded {
address: _,
index: _,
wallet_id: _,
},
AddressView::Opaque { address: _ },
) => Ordering::Greater,
}
}
}

#[cfg(test)]
mod tests {
use rand_core::OsRng;
Expand Down

0 comments on commit 02b18d0

Please sign in to comment.