1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use crate::*;

use solana_sdk::signature::{Signature, Signer};
use std::str::FromStr;
use std::sync::Arc;

/// This message is passed by the ServiceWorker to the service to verify the service is permitted to run.
// TODO: we should incorporate the timestamp somehow - or use a recent solana epoch?
#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct ServiceWorkerVerifyMessage {
    pub service: Pubkey,
    pub service_worker: Pubkey,
    pub enclave_size: u64,
    pub cpu: u64,
    // pub epoch: u64,
}
impl ServiceWorkerVerifyMessage {
    /// Converts the struct to a JSON string and then to a byte array
    fn to_msg_bytes<'a>(&'a self) -> Vec<u8> {
        serde_json::to_string(&self).unwrap().as_bytes().to_vec()
    }

    /// Get the base58 signature of the message after being signed by the worker authority keypair.
    /// This signature is used to verify the service is permitted to run.
    pub fn sign(&self, worker_authority: &Keypair) -> Signature {
        worker_authority.sign_message(&self.to_msg_bytes())
    }

    /// Verify the signature of the message using the worker authority public key.
    pub fn verify(&self, worker_authority: &Pubkey, signature: &str) -> Result<(), SbError> {
        let signature = solana_sdk::signature::Signature::from_str(signature).map_err(|err| {
            SbError::CustomError {
                message: format!("Failed to deserialize signature"),
                source: Arc::new(err),
            }
        })?;

        if signature.verify(
            worker_authority.as_ref(),
            serde_json::to_string(&self).unwrap().as_bytes(),
        ) {
            Ok(())
        } else {
            Err(SbError::Message("Failed to verify signature"))
        }
    }
}