working
This commit is contained in:
parent
6673c29746
commit
d2d711dd29
|
@ -12,7 +12,7 @@ pub struct AttestationQueueAccountData {
|
|||
// Authority controls adding/removing allowed enclave measurements
|
||||
pub authority: Pubkey,
|
||||
// allowed enclave measurements
|
||||
pub mr_enclaves: [[u8; 32]; 32],
|
||||
pub mr_enclaves: [MrEnclave; 32],
|
||||
pub mr_enclaves_len: u32,
|
||||
pub data: [Pubkey; 128],
|
||||
pub data_len: u32,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::QuoteAccountData;
|
||||
use crate::cfg_client;
|
||||
use crate::prelude::*;
|
||||
use crate::{cfg_client, QuoteAccountData, SWITCHBOARD_ATTESTATION_PROGRAM_ID};
|
||||
use anchor_lang::{Discriminator, Owner, ZeroCopy};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use std::cell::Ref;
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ use std::cell::Ref;
|
|||
|
||||
use crate::{QUOTE_SEED, SWITCHBOARD_ATTESTATION_PROGRAM_ID};
|
||||
|
||||
pub type MrEnclave = [u8; 32];
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub enum VerificationStatus {
|
||||
|
@ -31,7 +33,7 @@ pub struct QuoteAccountData {
|
|||
/// Queue used for attestation to verify a MRENCLAVE measurement.
|
||||
pub attestation_queue: Pubkey,
|
||||
/// The quotes MRENCLAVE measurement dictating the contents of the secure enclave.
|
||||
pub mr_enclave: [u8; 32],
|
||||
pub mr_enclave: MrEnclave,
|
||||
pub verification_status: u8,
|
||||
pub verification_timestamp: i64,
|
||||
pub valid_until: i64,
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use crate::prelude::*;
|
||||
use anchor_lang::solana_program::entrypoint::ProgramResult;
|
||||
use anchor_lang::solana_program::instruction::Instruction;
|
||||
use anchor_lang::solana_program::program::{invoke, invoke_signed};
|
||||
use anchor_lang::{Discriminator, InstructionData};
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(params: FunctionTriggerParams)] // rpc parameters hint
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
use crate::cfg_client;
|
||||
use crate::prelude::*;
|
||||
use anchor_lang::solana_program::entrypoint::ProgramResult;
|
||||
use anchor_lang::solana_program::instruction::Instruction;
|
||||
use anchor_lang::solana_program::program::{invoke, invoke_signed};
|
||||
use anchor_lang::{Discriminator, InstructionData};
|
||||
use anchor_spl::token::TokenAccount;
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(params: FunctionVerifyParams)] // rpc parameters hint
|
||||
|
@ -201,203 +195,4 @@ impl<'info> FunctionVerify<'info> {
|
|||
},
|
||||
]
|
||||
}
|
||||
|
||||
cfg_client! {
|
||||
pub async fn build(
|
||||
client: &solana_client::rpc_client::RpcClient,
|
||||
fn_signer: std::sync::Arc<solana_sdk::signer::keypair::Keypair>,
|
||||
pubkeys: &FunctionVerifyPubkeys,
|
||||
mr_enclave: [u8; 32],
|
||||
) -> std::result::Result<Instruction, switchboard_common::error::Error> {
|
||||
let fn_signer_pubkey = crate::client::to_pubkey(fn_signer)?;
|
||||
|
||||
let current_time = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
let fn_data: FunctionAccountData = load_account(&client, pubkeys.function).await?;
|
||||
|
||||
let verifier_quote: QuoteAccountData = load_account(&client, pubkeys.verifier).await?;
|
||||
|
||||
let queue_data: AttestationQueueAccountData =
|
||||
crate::client::load_account(&client, fn_data.attestation_queue).await?;
|
||||
|
||||
// let escrow = fn_data.escrow;
|
||||
let (fn_quote, _) = Pubkey::find_program_address(
|
||||
&[b"QuoteAccountData", &pubkeys.function.to_bytes()],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
let (verifier_permission, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
b"PermissionAccountData",
|
||||
&queue_data.authority.to_bytes(),
|
||||
&fn_data.attestation_queue.to_bytes(),
|
||||
&pubkeys.payer.to_bytes(),
|
||||
],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
let (fn_permission, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
b"PermissionAccountData",
|
||||
&queue_data.authority.to_bytes(),
|
||||
&fn_data.attestation_queue.to_bytes(),
|
||||
&pubkeys.function.to_bytes(),
|
||||
],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
let (state, _) =
|
||||
Pubkey::find_program_address(&[b"STATE"], &SWITCHBOARD_ATTESTATION_PROGRAM_ID);
|
||||
|
||||
let accounts = FunctionVerifyAccounts {
|
||||
function: pubkeys.function,
|
||||
fn_signer: fn_signer_pubkey,
|
||||
fn_quote,
|
||||
verifier_quote: pubkeys.verifier,
|
||||
secured_signer: verifier_quote.authority,
|
||||
attestation_queue: fn_data.attestation_queue,
|
||||
escrow: fn_data.escrow,
|
||||
receiver: pubkeys.reward_receiver,
|
||||
verifier_permission,
|
||||
fn_permission,
|
||||
state,
|
||||
token_program: anchor_spl::token::ID,
|
||||
payer: pubkeys.payer,
|
||||
system_program: anchor_lang::solana_program::system_program::ID,
|
||||
};
|
||||
|
||||
let next_allowed_timestamp = fn_data
|
||||
.next_execution_timestamp()
|
||||
.map(|x| x.timestamp())
|
||||
.unwrap_or(i64::MAX);
|
||||
|
||||
Ok(Self::build_ix(
|
||||
accounts,
|
||||
current_time,
|
||||
next_allowed_timestamp,
|
||||
false,
|
||||
mr_enclave,
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
fn build_ix(
|
||||
accounts: FunctionVerifyAccounts,
|
||||
observed_time: i64,
|
||||
next_allowed_timestamp: i64,
|
||||
is_failure: bool,
|
||||
mr_enclave: [u8; 32],
|
||||
) -> Instruction {
|
||||
Instruction {
|
||||
program_id: SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
accounts: accounts.to_account_metas(None),
|
||||
data: FunctionVerifyParams {
|
||||
observed_time,
|
||||
next_allowed_timestamp,
|
||||
is_failure,
|
||||
mr_enclave,
|
||||
}
|
||||
.data(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_client! {
|
||||
pub struct FunctionVerifyAccounts {
|
||||
pub function: Pubkey,
|
||||
pub fn_signer: Pubkey,
|
||||
pub fn_quote: Pubkey,
|
||||
pub verifier_quote: Pubkey,
|
||||
pub secured_signer: Pubkey,
|
||||
pub attestation_queue: Pubkey,
|
||||
pub escrow: Pubkey,
|
||||
pub receiver: Pubkey,
|
||||
pub verifier_permission: Pubkey,
|
||||
pub fn_permission: Pubkey,
|
||||
pub state: Pubkey,
|
||||
pub token_program: Pubkey,
|
||||
pub payer: Pubkey,
|
||||
pub system_program: Pubkey,
|
||||
}
|
||||
|
||||
impl ToAccountMetas for FunctionVerifyAccounts {
|
||||
fn to_account_metas(&self, _: Option<bool>) -> Vec<AccountMeta> {
|
||||
vec![
|
||||
AccountMeta {
|
||||
pubkey: self.function,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.fn_signer,
|
||||
is_signer: true,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.fn_quote,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.verifier_quote,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.secured_signer,
|
||||
is_signer: true,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.attestation_queue,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.escrow,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.receiver,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.verifier_permission,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.fn_permission,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.state,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.token_program,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.payer,
|
||||
is_signer: true,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.system_program,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
use crate::prelude::*;
|
||||
use anchor_lang::solana_program::instruction::Instruction;
|
||||
use anchor_lang::solana_program::message::Message;
|
||||
use anchor_lang::solana_program::pubkey::Pubkey;
|
||||
use sgx_quote::Quote;
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_sdk::commitment_config::CommitmentConfig;
|
||||
use solana_sdk::signer::keypair::Keypair;
|
||||
use std::result::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FunctionRunner {
|
||||
pub client: Arc<RpcClient>,
|
||||
|
||||
signer_keypair: Arc<Keypair>,
|
||||
pub signer: Pubkey,
|
||||
|
||||
pub function: Pubkey,
|
||||
pub quote: Pubkey,
|
||||
pub payer: Pubkey,
|
||||
pub verifier: Pubkey,
|
||||
pub reward_receiver: Pubkey,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for FunctionRunner {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"SwitchboardFunctionRunner: url: {}, signer: {}, function: {}, verifier: {}",
|
||||
self.client.url(),
|
||||
self.signer,
|
||||
self.function.to_string(),
|
||||
self.verifier.to_string()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionRunner {
|
||||
pub fn new_with_client(client: RpcClient) -> Result<Self, SwitchboardClientError> {
|
||||
let signer_keypair = generate_signer();
|
||||
let signer = signer_to_pubkey(signer_keypair.clone())?;
|
||||
|
||||
let function = load_env_pubkey("FUNCTION_KEY")?;
|
||||
let payer = load_env_pubkey("PAYER")?;
|
||||
let verifier = load_env_pubkey("VERIFIER")?;
|
||||
let reward_receiver = load_env_pubkey("REWARD_RECEIVER")?;
|
||||
|
||||
let (quote, _bump) = Pubkey::find_program_address(
|
||||
&[QUOTE_SEED, function.as_ref()],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
client: Arc::new(client),
|
||||
signer_keypair,
|
||||
signer,
|
||||
function,
|
||||
quote,
|
||||
payer,
|
||||
verifier,
|
||||
reward_receiver,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
url: &str,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Self, SwitchboardClientError> {
|
||||
Self::new_with_client(RpcClient::new_with_commitment(
|
||||
url,
|
||||
commitment.unwrap_or_default(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new_from_cluster(
|
||||
cluster: Cluster,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Self, SwitchboardClientError> {
|
||||
Self::new(cluster.url(), commitment)
|
||||
}
|
||||
|
||||
async fn build_verify_ixn(
|
||||
&self,
|
||||
mr_enclave: MrEnclave,
|
||||
) -> Result<Instruction, SwitchboardClientError> {
|
||||
let current_time = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
let fn_data: FunctionAccountData = load_account(&self.client, self.function).await?;
|
||||
|
||||
let verifier_quote: QuoteAccountData = load_account(&self.client, self.verifier).await?;
|
||||
|
||||
let queue_data: AttestationQueueAccountData =
|
||||
crate::client::load_account(&self.client, fn_data.attestation_queue).await?;
|
||||
|
||||
// let escrow = fn_data.escrow;
|
||||
let (fn_quote, _) = Pubkey::find_program_address(
|
||||
&[b"QuoteAccountData", &self.function.to_bytes()],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
let (verifier_permission, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
b"PermissionAccountData",
|
||||
&queue_data.authority.to_bytes(),
|
||||
&fn_data.attestation_queue.to_bytes(),
|
||||
&self.payer.to_bytes(), // assuming the verifier payer is also the authority
|
||||
],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
let (fn_permission, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
b"PermissionAccountData",
|
||||
&queue_data.authority.to_bytes(),
|
||||
&fn_data.attestation_queue.to_bytes(),
|
||||
&self.function.to_bytes(),
|
||||
],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
let (state, _) =
|
||||
Pubkey::find_program_address(&[b"STATE"], &SWITCHBOARD_ATTESTATION_PROGRAM_ID);
|
||||
|
||||
let pubkeys = FunctionVerifyPubkeys {
|
||||
function: self.function,
|
||||
fn_signer: self.signer,
|
||||
fn_quote,
|
||||
verifier_quote: self.verifier,
|
||||
secured_signer: verifier_quote.authority,
|
||||
attestation_queue: fn_data.attestation_queue,
|
||||
escrow: fn_data.escrow,
|
||||
receiver: self.reward_receiver,
|
||||
verifier_permission,
|
||||
fn_permission,
|
||||
state,
|
||||
token_program: anchor_spl::token::ID,
|
||||
payer: self.payer,
|
||||
system_program: anchor_lang::solana_program::system_program::ID,
|
||||
};
|
||||
|
||||
let next_allowed_timestamp = fn_data
|
||||
.next_execution_timestamp()
|
||||
.map(|x| x.timestamp())
|
||||
.unwrap_or(i64::MAX);
|
||||
|
||||
let ixn_params = FunctionVerifyParams {
|
||||
observed_time: current_time,
|
||||
next_allowed_timestamp,
|
||||
is_failure: false,
|
||||
mr_enclave,
|
||||
};
|
||||
let ixn = Instruction {
|
||||
program_id: SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
accounts: pubkeys.to_account_metas(None),
|
||||
data: ixn_params.data(),
|
||||
};
|
||||
Ok(ixn)
|
||||
}
|
||||
|
||||
async fn get_result(
|
||||
&self,
|
||||
mut ixs: Vec<Instruction>,
|
||||
) -> Result<FunctionResult, SwitchboardClientError> {
|
||||
let quote_raw = Gramine::generate_quote(&self.signer.to_bytes()).unwrap();
|
||||
let quote = Quote::parse("e_raw).unwrap();
|
||||
let mr_enclave: MrEnclave = quote.isv_report.mrenclave.try_into().unwrap();
|
||||
|
||||
let verify_ixn = self.build_verify_ixn(mr_enclave).await?;
|
||||
ixs.insert(0, verify_ixn);
|
||||
let message = Message::new(&ixs, Some(&self.payer));
|
||||
let blockhash = self.client.get_latest_blockhash().unwrap();
|
||||
let mut tx = solana_sdk::transaction::Transaction::new_unsigned(message);
|
||||
tx.partial_sign(&[self.signer_keypair.as_ref()], blockhash);
|
||||
|
||||
Ok(FunctionResult {
|
||||
version: 1,
|
||||
chain: switchboard_common::Chain::Solana,
|
||||
key: self.function.to_bytes(),
|
||||
signer: self.signer.to_bytes(),
|
||||
serialized_tx: bincode::serialize(&tx).unwrap(),
|
||||
quote: quote_raw,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn emit(&self, ixs: Vec<Instruction>) -> Result<(), SwitchboardClientError> {
|
||||
self.get_result(ixs)
|
||||
.await
|
||||
.map_err(|e| SwitchboardClientError::CustomError {
|
||||
message: "failed to run function verify".to_string(),
|
||||
source: Box::new(e),
|
||||
})
|
||||
.unwrap()
|
||||
.emit();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionVerifyPubkeys {
|
||||
pub function: Pubkey,
|
||||
pub fn_signer: Pubkey,
|
||||
pub fn_quote: Pubkey,
|
||||
pub verifier_quote: Pubkey,
|
||||
pub secured_signer: Pubkey,
|
||||
pub attestation_queue: Pubkey,
|
||||
pub escrow: Pubkey,
|
||||
pub receiver: Pubkey,
|
||||
pub verifier_permission: Pubkey,
|
||||
pub fn_permission: Pubkey,
|
||||
pub state: Pubkey,
|
||||
pub token_program: Pubkey,
|
||||
pub payer: Pubkey,
|
||||
pub system_program: Pubkey,
|
||||
}
|
||||
|
||||
impl ToAccountMetas for FunctionVerifyPubkeys {
|
||||
fn to_account_metas(&self, _: Option<bool>) -> Vec<AccountMeta> {
|
||||
vec![
|
||||
AccountMeta {
|
||||
pubkey: self.function,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.fn_signer,
|
||||
is_signer: true,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.fn_quote,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.verifier_quote,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.secured_signer,
|
||||
is_signer: true,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.attestation_queue,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.escrow,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.receiver,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.verifier_permission,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.fn_permission,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.state,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.token_program,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.payer,
|
||||
is_signer: true,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey: self.system_program,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
use anchor_lang::solana_program::instruction::Instruction;
|
||||
use anchor_lang::solana_program::message::Message;
|
||||
use anchor_lang::solana_program::pubkey::Pubkey;
|
||||
use sgx_quote::Quote;
|
||||
use solana_sdk::signer::keypair::Keypair;
|
||||
|
||||
use std::env;
|
||||
use std::result::Result;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::attestation_program::FunctionVerify;
|
||||
use crate::{QUOTE_SEED, SWITCHBOARD_ATTESTATION_PROGRAM_ID};
|
||||
|
||||
pub async fn function_verify(
|
||||
url: String,
|
||||
fn_signer: Arc<Keypair>,
|
||||
mut ixs: Vec<Instruction>,
|
||||
) -> Result<switchboard_common::FunctionResult, switchboard_common::Error> {
|
||||
let fn_signer_pubkey = crate::client::to_pubkey(fn_signer.clone())?;
|
||||
|
||||
let client = solana_client::rpc_client::RpcClient::new_with_commitment(
|
||||
url,
|
||||
solana_sdk::commitment_config::CommitmentConfig::processed(),
|
||||
);
|
||||
|
||||
let quote_raw =
|
||||
switchboard_common::Gramine::generate_quote(&fn_signer_pubkey.to_bytes()).unwrap();
|
||||
let quote = Quote::parse("e_raw).unwrap();
|
||||
|
||||
let pubkeys = FunctionVerifyPubkeys::load_from_env()?;
|
||||
|
||||
let ix = FunctionVerify::build(
|
||||
&client,
|
||||
fn_signer.clone(),
|
||||
&pubkeys,
|
||||
quote.isv_report.mrenclave.try_into().unwrap(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
ixs.insert(0, ix);
|
||||
|
||||
let message = Message::new(&ixs, Some(&pubkeys.payer));
|
||||
|
||||
let blockhash = client.get_latest_blockhash().unwrap();
|
||||
|
||||
let mut tx = solana_sdk::transaction::Transaction::new_unsigned(message);
|
||||
tx.partial_sign(&[fn_signer.as_ref()], blockhash);
|
||||
|
||||
Ok(switchboard_common::FunctionResult {
|
||||
version: 1,
|
||||
chain: switchboard_common::Chain::Solana,
|
||||
key: pubkeys.function.to_bytes(),
|
||||
signer: fn_signer_pubkey.to_bytes(),
|
||||
serialized_tx: bincode::serialize(&tx).unwrap(),
|
||||
quote: quote_raw,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub struct FunctionVerifyPubkeys {
|
||||
pub function: Pubkey,
|
||||
pub quote: Pubkey,
|
||||
pub payer: Pubkey,
|
||||
pub verifier: Pubkey,
|
||||
pub reward_receiver: Pubkey,
|
||||
}
|
||||
|
||||
impl FunctionVerifyPubkeys {
|
||||
pub fn load_from_env() -> std::result::Result<Self, switchboard_common::Error> {
|
||||
let function = Pubkey::from_str(&env::var("FUNCTION_KEY").unwrap()).unwrap();
|
||||
let payer = Pubkey::from_str(&env::var("PAYER").unwrap()).unwrap();
|
||||
|
||||
let verifier = &env::var("VERIFIER").unwrap_or(String::new());
|
||||
if verifier.is_empty() {
|
||||
return Err(switchboard_common::Error::CustomMessage(
|
||||
"verifier missing".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let (quote, _bump) = Pubkey::find_program_address(
|
||||
&[QUOTE_SEED, function.as_ref()],
|
||||
&SWITCHBOARD_ATTESTATION_PROGRAM_ID,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
function,
|
||||
quote,
|
||||
payer,
|
||||
verifier: Pubkey::from_str(verifier).map_err(|_| {
|
||||
switchboard_common::Error::CustomMessage(
|
||||
"failed to parse pubkey string".to_string(),
|
||||
)
|
||||
})?,
|
||||
reward_receiver: Pubkey::from_str(&env::var("REWARD_RECEIVER").unwrap()).unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
pub mod function_verify;
|
||||
pub mod function_runner;
|
||||
pub mod utils;
|
||||
|
||||
pub use function_verify::*;
|
||||
pub use function_runner::*;
|
||||
pub use utils::*;
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
use crate::prelude::*;
|
||||
use solana_sdk::signer::keypair::{keypair_from_seed, Keypair};
|
||||
use std::env;
|
||||
use std::result::Result;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
pub fn load_env_pubkey(key: &str) -> Result<Pubkey, SwitchboardClientError> {
|
||||
Pubkey::from_str(&env::var(key).unwrap())
|
||||
.map_err(|_| SwitchboardClientError::EnvVariableMissing(key.to_string()))
|
||||
}
|
||||
|
||||
pub fn generate_signer() -> Arc<Keypair> {
|
||||
let mut randomness = [0; 32];
|
||||
|
@ -10,9 +17,11 @@ pub fn generate_signer() -> Arc<Keypair> {
|
|||
Arc::new(keypair_from_seed(&randomness).unwrap())
|
||||
}
|
||||
|
||||
pub fn to_pubkey(signer: Arc<Keypair>) -> std::result::Result<Pubkey, switchboard_common::Error> {
|
||||
pub fn signer_to_pubkey(
|
||||
signer: Arc<Keypair>,
|
||||
) -> std::result::Result<Pubkey, SwitchboardClientError> {
|
||||
let pubkey = Pubkey::from_str(signer.to_base58_string().as_str()).map_err(|_| {
|
||||
switchboard_common::Error::CustomMessage("failed to parse pubkey string".to_string())
|
||||
SwitchboardClientError::CustomMessage("failed to parse pubkey string".to_string())
|
||||
})?;
|
||||
Ok(pubkey)
|
||||
}
|
||||
|
@ -20,10 +29,19 @@ pub fn to_pubkey(signer: Arc<Keypair>) -> std::result::Result<Pubkey, switchboar
|
|||
pub async fn load_account<T: bytemuck::Pod>(
|
||||
client: &solana_client::rpc_client::RpcClient,
|
||||
pubkey: Pubkey,
|
||||
) -> Result<T, switchboard_common::Error> {
|
||||
) -> Result<T, SwitchboardClientError> {
|
||||
let data = client
|
||||
.get_account_data(&pubkey)
|
||||
.map_err(|_| switchboard_common::Error::CustomMessage("AnchorParseError".to_string()))?;
|
||||
.map_err(|_| SwitchboardClientError::CustomMessage("AnchorParseError".to_string()))?;
|
||||
Ok(*bytemuck::try_from_bytes::<T>(&data[8..])
|
||||
.map_err(|_| switchboard_common::Error::CustomMessage("AnchorParseError".to_string()))?)
|
||||
.map_err(|_| SwitchboardClientError::CustomMessage("AnchorParseError".to_string()))?)
|
||||
}
|
||||
|
||||
pub fn unix_timestamp() -> i64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs()
|
||||
.try_into()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ pub use oracle_program::*;
|
|||
pub mod attestation_program;
|
||||
pub use attestation_program::*;
|
||||
|
||||
pub use switchboard_common::{Chain, Error as SwitchboardClientError, FunctionResult};
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub mod seeds;
|
||||
|
|
|
@ -17,6 +17,8 @@ pub use rust_decimal;
|
|||
cfg_client! {
|
||||
pub use crate::client::*;
|
||||
|
||||
pub use switchboard_common::Gramine;
|
||||
|
||||
pub use anchor_client;
|
||||
pub use anchor_client::anchor_lang;
|
||||
pub use anchor_client::solana_client;
|
||||
|
@ -24,6 +26,8 @@ cfg_client! {
|
|||
pub use anchor_client::anchor_lang::solana_program;
|
||||
pub use anchor_client::Cluster;
|
||||
|
||||
pub use solana_sdk::signer::keypair::{keypair_from_seed, Keypair};
|
||||
|
||||
pub use anchor_lang::prelude::*;
|
||||
}
|
||||
|
||||
|
@ -35,4 +39,10 @@ cfg_program! {
|
|||
}
|
||||
|
||||
pub use anchor_lang::prelude::*;
|
||||
pub use anchor_lang::{Discriminator, Owner, ZeroCopy};
|
||||
pub use anchor_lang::{
|
||||
AnchorDeserialize, AnchorSerialize, Discriminator, InstructionData, Owner, ZeroCopy,
|
||||
};
|
||||
pub use anchor_spl::token::{Mint, TokenAccount};
|
||||
pub use solana_program::entrypoint::ProgramResult;
|
||||
pub use solana_program::instruction::Instruction;
|
||||
pub use solana_program::program::{invoke, invoke_signed};
|
||||
|
|
|
@ -8,6 +8,6 @@ pub use crate::oracle_program::{
|
|||
};
|
||||
|
||||
pub use crate::attestation_program::{
|
||||
FunctionStatus, FunctionTriggerParams, FunctionVerifyParams, SwitchboardAttestationPermission,
|
||||
VerificationStatus,
|
||||
FunctionStatus, FunctionTriggerParams, FunctionVerifyParams, MrEnclave,
|
||||
SwitchboardAttestationPermission, VerificationStatus,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue