#[cfg(test)]
use crate::move_bindings::{
move_std::option::Option as MoveOption,
sui_framework::{object::UID, table::Table as MoveTable, vec_set::VecSet},
};
use crate::{
move_bindings::{
registry::network_auth::{
IdentityKey,
KeyBinding,
KeyBindingInnerV1,
KeyRecord,
NetworkAuth,
NetworkAuthInnerV1,
},
sui_framework::object::ID,
},
sui,
};
impl IdentityKey {
pub fn leader(leader_cap_id: sui::types::Address) -> Self {
Self::Leader {
leader_cap_id: ID {
bytes: leader_cap_id,
},
}
}
pub fn tool(tool_id: sui::types::Address) -> Self {
Self::Tool {
tool_id: ID { bytes: tool_id },
}
}
pub fn leader_cap_id(&self) -> Option<sui::types::Address> {
match self {
Self::Leader { leader_cap_id } => Some(leader_cap_id.bytes),
Self::Tool { .. } => None,
}
}
pub fn tool_id(&self) -> Option<sui::types::Address> {
match self {
Self::Leader { .. } => None,
Self::Tool { tool_id } => Some(tool_id.bytes),
}
}
}
impl KeyBinding {
pub fn object_id(&self) -> sui::types::Address {
self.id.id.bytes
}
}
impl KeyBindingInnerV1 {
pub fn description(&self) -> Option<&[u8]> {
self.description.as_option().map(Vec::as_slice)
}
pub fn active_key_id(&self) -> Option<u64> {
self.active_key_id.copied_option()
}
pub fn key_table_id(&self) -> sui::types::Address {
self.keys.id()
}
pub fn key_table_size(&self) -> usize {
self.keys.size()
}
#[cfg(test)]
pub(crate) fn new_for_test(
identity: IdentityKey,
description: Option<Vec<u8>>,
next_key_id: u64,
active_key_id: Option<u64>,
keys: MoveTable<u64, KeyRecord>,
) -> Self {
Self {
identity,
description: MoveOption::from_option(description),
next_key_id,
active_key_id: MoveOption::from_option(active_key_id),
keys,
}
}
}
impl KeyRecord {
pub fn revoked_at_ms(&self) -> Option<u64> {
self.revoked_at_ms.copied_option()
}
#[cfg(test)]
pub(crate) fn new_for_test(
scheme: u8,
public_key: Vec<u8>,
added_at_ms: u64,
revoked_at_ms: Option<u64>,
) -> Self {
Self {
scheme,
public_key,
added_at_ms,
revoked_at_ms: MoveOption::from_option(revoked_at_ms),
}
}
}
impl NetworkAuth {
pub fn object_id(&self) -> sui::types::Address {
self.id.id.bytes
}
}
impl NetworkAuthInnerV1 {
pub fn leader_cap_ids(&self) -> impl Iterator<Item = sui::types::Address> + '_ {
self.identities
.contents
.iter()
.filter_map(IdentityKey::leader_cap_id)
}
#[cfg(test)]
pub(crate) fn new_for_test(identities: Vec<IdentityKey>) -> Self {
Self {
registered_key_witness: UID::new(sui::types::Address::ZERO),
identities: VecSet {
contents: identities,
},
}
}
}
#[cfg(test)]
mod tests {
use {super::*, bcs};
#[test]
fn identity_key_helpers_use_move_shape() {
let mut rng = rand::thread_rng();
let address = sui::types::Address::generate(&mut rng);
let leader = IdentityKey::leader(address);
assert_eq!(leader.leader_cap_id(), Some(address));
assert_eq!(leader.tool_id(), None);
let tool = IdentityKey::tool(address);
assert_eq!(tool.leader_cap_id(), None);
assert_eq!(tool.tool_id(), Some(address));
}
#[test]
fn identity_key_bcs_roundtrip() {
let mut rng = rand::thread_rng();
let address = sui::types::Address::generate(&mut rng);
let key = IdentityKey::leader(address);
let bytes = bcs::to_bytes(&key).unwrap();
let decoded: IdentityKey = bcs::from_bytes(&bytes).unwrap();
assert_eq!(decoded, key);
assert_eq!(decoded.leader_cap_id(), Some(address));
}
#[test]
fn key_binding_bcs_roundtrip() {
let mut rng = rand::thread_rng();
let active_key_id = Some(4);
let binding = KeyBindingInnerV1::new_for_test(
IdentityKey::leader(sui::types::Address::generate(&mut rng)),
Some(b"nexus".to_vec()),
7,
active_key_id,
MoveTable::new(sui::types::Address::generate(&mut rng), 2),
);
let bytes = bcs::to_bytes(&binding).unwrap();
let decoded: KeyBindingInnerV1 = bcs::from_bytes(&bytes).unwrap();
assert_eq!(decoded.key_table_id(), binding.key_table_id());
assert_eq!(decoded.key_table_size(), 2);
assert_eq!(decoded.next_key_id, binding.next_key_id);
assert_eq!(decoded.active_key_id(), active_key_id);
assert_eq!(decoded.description(), Some(b"nexus".as_slice()));
}
#[test]
fn key_record_and_network_auth_helpers_use_move_shape() {
let mut rng = rand::thread_rng();
let id = sui::types::Address::generate(&mut rng);
let first_leader = sui::types::Address::generate(&mut rng);
let second_leader = sui::types::Address::generate(&mut rng);
let record = KeyRecord::new_for_test(1, vec![1, 2, 3], 10, Some(20));
assert_eq!(record.revoked_at_ms(), Some(20));
assert_eq!(
NetworkAuthInnerV1::new_for_test(vec![
IdentityKey::leader(first_leader),
IdentityKey::tool(id),
IdentityKey::leader(second_leader),
],)
.leader_cap_ids()
.collect::<Vec<_>>(),
vec![first_leader, second_leader]
);
assert!(NetworkAuthInnerV1::new_for_test(vec![])
.leader_cap_ids()
.next()
.is_none());
}
}