nucypher_core/
revocation_order.rs

1use alloc::boxed::Box;
2use alloc::string::String;
3
4use serde::{Deserialize, Serialize};
5use umbral_pre::{PublicKey, Signature, Signer};
6
7use crate::address::Address;
8use crate::key_frag::EncryptedKeyFrag;
9use crate::versioning::{
10    messagepack_deserialize, messagepack_serialize, ProtocolObject, ProtocolObjectInner,
11};
12use crate::VerificationError;
13
14/// Represents a string used by characters to perform a revocation on a specific Ursula.
15#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
16pub struct RevocationOrder {
17    /// The address of the Ursula that is being revoked.
18    staking_provider_address: Address,
19    encrypted_kfrag: EncryptedKeyFrag,
20    signature: Signature,
21}
22
23impl RevocationOrder {
24    /// Create and sign a new revocation order.
25    pub fn new(
26        signer: &Signer,
27        staking_provider_address: &Address,
28        encrypted_kfrag: &EncryptedKeyFrag,
29    ) -> Self {
30        Self {
31            staking_provider_address: *staking_provider_address,
32            encrypted_kfrag: encrypted_kfrag.clone(),
33            signature: signer.sign(
34                &[
35                    staking_provider_address.as_ref(),
36                    &encrypted_kfrag.to_bytes(),
37                ]
38                .concat(),
39            ),
40        }
41    }
42
43    /// Verifies the revocation order against Alice's key.
44    /// On success, returns the staking provider address and the encrypted keyfrag.
45    pub fn verify(
46        self,
47        alice_verifying_key: &PublicKey,
48    ) -> Result<(Address, EncryptedKeyFrag), VerificationError> {
49        let message = [
50            self.staking_provider_address.as_ref(),
51            &self.encrypted_kfrag.to_bytes(),
52        ]
53        .concat();
54        if self.signature.verify(alice_verifying_key, &message) {
55            Ok((self.staking_provider_address, self.encrypted_kfrag))
56        } else {
57            Err(VerificationError)
58        }
59    }
60}
61
62impl<'a> ProtocolObjectInner<'a> for RevocationOrder {
63    fn brand() -> [u8; 4] {
64        *b"Revo"
65    }
66
67    fn version() -> (u16, u16) {
68        (3, 0)
69    }
70
71    fn unversioned_to_bytes(&self) -> Box<[u8]> {
72        messagepack_serialize(&self)
73    }
74
75    fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
76        if minor_version == 0 {
77            Some(messagepack_deserialize(bytes))
78        } else {
79            None
80        }
81    }
82}
83
84impl<'a> ProtocolObject<'a> for RevocationOrder {}