use crate::machines::mob_machine::{
ExternalPeerEdge, MobMachineEffect, MobMachineTransition, PeerId,
};
struct GeneratedAuthorityBridgeToken;
static GENERATED_AUTHORITY_BRIDGE_TOKEN: GeneratedAuthorityBridgeToken =
GeneratedAuthorityBridgeToken;
pub(crate) fn generated_authority_bridge_token() -> &'static (dyn std::any::Any + Send + Sync) {
&GENERATED_AUTHORITY_BRIDGE_TOKEN
}
#[doc(hidden)]
#[allow(improper_ctypes_definitions, unsafe_code)]
#[unsafe(export_name = concat!("__meerkat_mob_generated_authority_bridge_token_is_valid_v1_mob_external_peer_trust_unwiring_", env!("MEERKAT_GENERATED_AUTHORITY_BRIDGE_SYMBOL_SUFFIX")))]
pub extern "Rust" fn generated_authority_bridge_token_is_valid(
token: &(dyn std::any::Any + Send + Sync),
) -> bool {
token.is::<GeneratedAuthorityBridgeToken>()
}
#[derive(Debug, Clone)]
pub struct MobTopologyFreshnessAuthority {
topology_epoch: Option<std::sync::Arc<std::sync::atomic::AtomicU64>>,
source_owner_token: Option<std::sync::Arc<dyn std::any::Any + Send + Sync>>,
}
impl MobTopologyFreshnessAuthority {
pub(crate) fn from_live_topology_epoch(
topology_epoch: std::sync::Arc<std::sync::atomic::AtomicU64>,
source_owner_token: std::sync::Arc<dyn std::any::Any + Send + Sync>,
) -> Self {
Self {
topology_epoch: Some(topology_epoch),
source_owner_token: Some(source_owner_token),
}
}
fn missing() -> Self {
Self {
topology_epoch: None,
source_owner_token: None,
}
}
fn source_owner_token(&self) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> {
self.source_owner_token.as_ref().map(std::sync::Arc::clone)
}
fn validate_topology_epoch(
&self,
expected_epoch: u64,
allow_next_epoch: bool,
) -> Result<(), String> {
let Some(topology_epoch) = &self.topology_epoch else {
return Err("generated MobMachine topology freshness authority is absent".to_string());
};
let current_epoch = topology_epoch.load(std::sync::atomic::Ordering::Acquire);
let matches_current = current_epoch == expected_epoch;
let matches_next = allow_next_epoch && current_epoch.checked_add(1) == Some(expected_epoch);
if matches_current || matches_next {
Ok(())
} else {
Err(format!(
"stale generated MobMachine trust obligation at epoch {expected_epoch} (current {current_epoch})"
))
}
}
}
#[derive(Debug, Clone)]
pub struct MobExternalPeerTrustUnwiringObligation {
edge: ExternalPeerEdge,
local_peer_id: PeerId,
peer_id: PeerId,
epoch: u64,
comms_trust_authority_claims:
std::sync::Arc<std::sync::Mutex<std::collections::BTreeSet<String>>>,
mob_topology_freshness_authority: MobTopologyFreshnessAuthority,
}
impl MobExternalPeerTrustUnwiringObligation {
pub fn edge(&self) -> &ExternalPeerEdge {
&self.edge
}
pub fn local_peer_id(&self) -> &PeerId {
&self.local_peer_id
}
pub fn peer_id(&self) -> &PeerId {
&self.peer_id
}
pub fn epoch(&self) -> u64 {
self.epoch
}
}
impl MobExternalPeerTrustUnwiringObligation {
#[allow(unsafe_code)]
fn authorize_comms_trust_authority(
&self,
operation: meerkat_core::comms::GeneratedCommsTrustAuthorityOperation,
peer_id: &str,
peer_descriptor: Option<meerkat_core::comms::TrustedPeerDescriptor>,
) -> Result<meerkat_core::comms::CommsTrustMutationAuthority, String> {
use meerkat_core::comms::GeneratedCommsTrustAuthorityOperation as Operation;
if !matches!(operation, Operation::PublicRemove) {
return Err(format!(
"generated comms trust source cannot authorize operation {operation:?}"
));
}
self.mob_topology_freshness_authority
.validate_topology_epoch(self.epoch, false)?;
if self.peer_id.0 != peer_id {
return Err(format!(
"MobMachine external trust obligation peer_id {:?} does not match requested peer {peer_id:?}",
self.peer_id.0
));
}
let claim_key = format!("{operation:?}:{peer_id}");
let mut claims = self.comms_trust_authority_claims.lock().map_err(|_| {
"generated comms trust authority source claims were poisoned".to_string()
})?;
if !claims.insert(claim_key) {
return Err(format!(
"generated comms trust authority source already minted {operation:?} for peer {peer_id:?}"
));
}
#[allow(improper_ctypes_definitions, unsafe_code)]
unsafe extern "Rust" {
#[link_name = concat!("__meerkat_core_mob_generated_comms_trust_authority_build_v1_", env!("MEERKAT_GENERATED_AUTHORITY_BRIDGE_SYMBOL_SUFFIX"))]
fn core_generated_comms_trust_authority_build(
token: &'static (dyn std::any::Any + Send + Sync),
source_kind: meerkat_core::comms::GeneratedCommsTrustAuthoritySourceKind,
source_epoch: u64,
source_owner_token: Option<std::sync::Arc<dyn std::any::Any + Send + Sync>>,
trust_row_owner_kind: meerkat_core::comms::GeneratedCommsTrustAuthoritySourceKind,
operation: meerkat_core::comms::GeneratedCommsTrustAuthorityOperation,
peer_id: String,
trust_store_peer_id: Option<String>,
peer_descriptor: Option<meerkat_core::comms::TrustedPeerDescriptor>,
) -> Result<meerkat_core::comms::CommsTrustMutationAuthority, String>;
}
match operation {
Operation::PublicRemove => {
if peer_descriptor.is_some() {
return Err(format!(
"generated comms trust remove for peer {peer_id:?} must not carry a trusted peer descriptor"
));
}
let trust_store_peer_id = self.local_peer_id.0.as_str().to_string();
#[allow(unsafe_code)]
unsafe {
core_generated_comms_trust_authority_build(
generated_authority_bridge_token(),
meerkat_core::comms::GeneratedCommsTrustAuthoritySourceKind::MobMachineExternalPeerTrustUnwiring,
self.epoch,
self.mob_topology_freshness_authority.source_owner_token(),
meerkat_core::comms::GeneratedCommsTrustAuthoritySourceKind::MobMachineExternalPeerTrustWiring,
meerkat_core::comms::GeneratedCommsTrustAuthorityOperation::PublicRemove,
peer_id.to_string(),
Some(trust_store_peer_id),
None,
)
}
}
_ => unreachable!("operation checked above"),
}
}
}
pub fn extract_obligations(
transition: &MobMachineTransition,
) -> Vec<MobExternalPeerTrustUnwiringObligation> {
extract_obligations_with_freshness(transition, MobTopologyFreshnessAuthority::missing())
}
pub fn extract_obligations_with_freshness(
transition: &MobMachineTransition,
mob_topology_freshness_authority: MobTopologyFreshnessAuthority,
) -> Vec<MobExternalPeerTrustUnwiringObligation> {
transition
.effects()
.iter()
.filter_map(|effect| match effect {
MobMachineEffect::ExternalPeerTrustUnwiringRequested {
edge,
local_peer_id,
peer_id,
epoch,
} => Some(MobExternalPeerTrustUnwiringObligation {
edge: edge.clone(),
local_peer_id: local_peer_id.clone(),
peer_id: peer_id.clone(),
epoch: *epoch,
comms_trust_authority_claims: Default::default(),
mob_topology_freshness_authority: mob_topology_freshness_authority.clone(),
}),
_ => None,
})
.collect()
}
fn validate_expected_peer(
context: &'static str,
actual: &str,
expected: &str,
) -> Result<(), String> {
if actual == expected {
Ok(())
} else {
Err(format!(
"{context} peer id {actual:?} does not match expected mutation peer id {expected:?}"
))
}
}
pub fn unwiring_authority_for_peer(
obligation: &MobExternalPeerTrustUnwiringObligation,
expected_peer_id: &str,
) -> Result<meerkat_core::comms::CommsTrustMutationAuthority, String> {
validate_expected_peer(
"MobMachineExternalPeerUnwiring",
obligation.peer_id.0.as_str(),
expected_peer_id,
)?;
obligation.authorize_comms_trust_authority(
meerkat_core::comms::GeneratedCommsTrustAuthorityOperation::PublicRemove,
expected_peer_id,
None,
)
}