2024-02-23 22:28:52 +00:00
|
|
|
mod cli;
|
|
|
|
|
2024-02-26 21:57:54 +00:00
|
|
|
use std::{
|
2024-02-26 22:43:44 +00:00
|
|
|
error::Error,
|
2024-02-26 21:57:54 +00:00
|
|
|
fs::{read_to_string, File},
|
2024-02-27 00:15:42 +00:00
|
|
|
io::{Read, Write},
|
2024-02-26 21:57:54 +00:00
|
|
|
process::Command,
|
|
|
|
};
|
2024-02-23 22:28:52 +00:00
|
|
|
|
|
|
|
use clap::Parser;
|
2024-02-27 00:15:42 +00:00
|
|
|
use cosmos_sdk_proto::{
|
|
|
|
cosmos::{
|
|
|
|
auth::v1beta1::{
|
|
|
|
query_client::QueryClient as AuthQueryClient, BaseAccount as RawBaseAccount,
|
|
|
|
QueryAccountRequest,
|
|
|
|
},
|
|
|
|
tx::v1beta1::{service_client::ServiceClient, BroadcastMode, BroadcastTxRequest},
|
|
|
|
},
|
|
|
|
traits::Message,
|
|
|
|
Any,
|
|
|
|
};
|
|
|
|
use cosmrs::{
|
|
|
|
auth::BaseAccount,
|
|
|
|
cosmwasm::MsgExecuteContract,
|
|
|
|
crypto::secp256k1::{SigningKey, VerifyingKey},
|
|
|
|
tendermint::{account::Id as TmAccountId, chain::Id as TmChainId},
|
|
|
|
tx,
|
|
|
|
tx::{Fee, Msg, SignDoc, SignerInfo},
|
|
|
|
AccountId, Coin,
|
|
|
|
};
|
|
|
|
use ecies::{PublicKey, SecretKey};
|
|
|
|
use quartz_cw::msg::{
|
|
|
|
execute::attested::{Attested, EpidAttestation},
|
|
|
|
instantiate::{CoreInstantiate, RawInstantiate},
|
|
|
|
InstantiateMsg,
|
|
|
|
};
|
2024-02-23 22:28:52 +00:00
|
|
|
use quartz_proto::quartz::{core_client::CoreClient, InstantiateRequest};
|
|
|
|
use quartz_relayer::types::InstantiateResponse;
|
2024-02-27 00:15:42 +00:00
|
|
|
use quartz_tee_ra::IASReport;
|
2024-02-26 22:43:44 +00:00
|
|
|
use serde_json::{json, Value};
|
2024-02-27 00:15:42 +00:00
|
|
|
use subtle_encoding::base64;
|
|
|
|
use tendermint::public_key::Secp256k1 as TmPublicKey;
|
2024-02-23 22:28:52 +00:00
|
|
|
|
2024-02-26 21:57:54 +00:00
|
|
|
use crate::cli::Cli;
|
2024-02-20 16:42:04 +00:00
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
2024-02-23 22:28:52 +00:00
|
|
|
let args = Cli::parse();
|
2024-02-20 16:42:04 +00:00
|
|
|
|
2024-02-27 00:15:42 +00:00
|
|
|
let mut client = CoreClient::connect(args.enclave_addr.uri().to_string()).await?;
|
2024-02-23 22:28:52 +00:00
|
|
|
let response = client.instantiate(InstantiateRequest {}).await?;
|
|
|
|
let response: InstantiateResponse = response.into_inner().try_into()?;
|
2024-02-27 00:15:42 +00:00
|
|
|
let (config, quote) = response.into_message().into_tuple();
|
2024-02-20 16:42:04 +00:00
|
|
|
|
2024-02-27 00:15:42 +00:00
|
|
|
let ias_report = gramine_sgx_ias_report("e)?;
|
2024-02-26 22:43:44 +00:00
|
|
|
println!(
|
|
|
|
"{}",
|
|
|
|
serde_json::to_string(&ias_report).expect("infallible serializer")
|
|
|
|
);
|
2024-02-27 00:15:42 +00:00
|
|
|
let ias_report: IASReport = serde_json::from_str(&ias_report.to_string())?;
|
2024-02-28 18:46:35 +00:00
|
|
|
let attestation = EpidAttestation::new(ias_report);
|
2024-02-27 00:15:42 +00:00
|
|
|
let cw_instantiate_msg = Attested::new(CoreInstantiate::new(config), attestation);
|
|
|
|
|
|
|
|
// Read the TSP secret
|
|
|
|
let secret = {
|
|
|
|
let mut secret = Vec::new();
|
|
|
|
let mut tsp_sk_file = File::open(args.secret)?;
|
|
|
|
tsp_sk_file.read_to_end(secret.as_mut())?;
|
|
|
|
let secret = base64::decode(secret).unwrap();
|
|
|
|
SecretKey::parse_slice(&secret).unwrap()
|
|
|
|
};
|
|
|
|
let tm_pubkey = {
|
|
|
|
let pubkey = PublicKey::from_secret_key(&secret);
|
|
|
|
TmPublicKey::from_sec1_bytes(&pubkey.serialize()).unwrap()
|
|
|
|
};
|
|
|
|
let sender = {
|
|
|
|
let tm_key = TmAccountId::from(tm_pubkey);
|
|
|
|
AccountId::new("wasm", tm_key.as_bytes()).unwrap()
|
|
|
|
};
|
|
|
|
|
|
|
|
let msgs = vec![MsgExecuteContract {
|
|
|
|
sender: sender.clone(),
|
|
|
|
contract: args.contract.clone(),
|
|
|
|
msg: serde_json::to_string::<RawInstantiate>(&InstantiateMsg(cw_instantiate_msg).into())?
|
|
|
|
.into_bytes(),
|
|
|
|
funds: vec![],
|
|
|
|
}
|
|
|
|
.to_any()
|
|
|
|
.unwrap()];
|
|
|
|
|
|
|
|
let account = account_info(args.node_addr.uri().clone(), sender.clone()).await?;
|
|
|
|
let amount = Coin {
|
|
|
|
amount: 0u128,
|
|
|
|
denom: "cosm".parse()?,
|
|
|
|
};
|
|
|
|
let tx_bytes = tx_bytes(
|
|
|
|
&secret,
|
|
|
|
amount,
|
|
|
|
args.gas_limit,
|
|
|
|
tm_pubkey,
|
|
|
|
msgs,
|
|
|
|
account.sequence,
|
|
|
|
account.account_number,
|
|
|
|
&args.chain_id,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
send_tx(args.node_addr.uri().clone(), tx_bytes).await?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn account_info(
|
|
|
|
node: impl ToString,
|
|
|
|
address: impl ToString,
|
|
|
|
) -> Result<BaseAccount, Box<dyn Error>> {
|
|
|
|
let mut client = AuthQueryClient::connect(node.to_string()).await?;
|
|
|
|
let request = tonic::Request::new(QueryAccountRequest {
|
|
|
|
address: address.to_string(),
|
|
|
|
});
|
|
|
|
let response = client.account(request).await?;
|
|
|
|
let response = RawBaseAccount::decode(response.into_inner().account.unwrap().value.as_slice())?;
|
|
|
|
let account = BaseAccount::try_from(response)?;
|
|
|
|
Ok(account)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
|
|
pub fn tx_bytes(
|
|
|
|
secret: &SecretKey,
|
|
|
|
amount: Coin,
|
|
|
|
gas: u64,
|
|
|
|
tm_pubkey: VerifyingKey,
|
|
|
|
msgs: Vec<Any>,
|
|
|
|
sequence_number: u64,
|
|
|
|
account_number: u64,
|
|
|
|
chain_id: &TmChainId,
|
|
|
|
) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
|
|
let tx_body = tx::Body::new(msgs, "", 0u16);
|
|
|
|
let signer_info = SignerInfo::single_direct(Some(tm_pubkey.into()), sequence_number);
|
|
|
|
let auth_info = signer_info.auth_info(Fee::from_amount_and_gas(amount, gas));
|
|
|
|
let sign_doc = SignDoc::new(&tx_body, &auth_info, chain_id, account_number)?;
|
|
|
|
let tx_signed = sign_doc.sign(&SigningKey::from_bytes(&secret.serialize()).unwrap())?;
|
|
|
|
Ok(tx_signed.to_bytes()?)
|
|
|
|
}
|
2024-02-26 22:43:44 +00:00
|
|
|
|
2024-02-27 00:15:42 +00:00
|
|
|
pub async fn send_tx(node: impl ToString, tx_bytes: Vec<u8>) -> Result<(), Box<dyn Error>> {
|
|
|
|
let mut client = ServiceClient::connect(node.to_string()).await?;
|
|
|
|
let request = tonic::Request::new(BroadcastTxRequest {
|
|
|
|
tx_bytes,
|
|
|
|
mode: BroadcastMode::Block.into(),
|
|
|
|
});
|
|
|
|
let _response = client.broadcast_tx(request).await?;
|
2024-02-26 22:43:44 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gramine_sgx_ias_report(quote: &[u8]) -> Result<Value, Box<dyn Error>> {
|
2024-02-26 21:57:54 +00:00
|
|
|
let dir = tempfile::tempdir()?;
|
|
|
|
let quote_file_path = dir.path().join("test.quote");
|
|
|
|
let datareport_file_path = dir.path().join("datareport");
|
|
|
|
let datareportsig_file_path = dir.path().join("datareportsig");
|
|
|
|
|
2024-02-26 22:10:45 +00:00
|
|
|
let mut quote_file = File::create(quote_file_path.clone())?;
|
2024-02-26 22:43:44 +00:00
|
|
|
quote_file.write_all(quote)?;
|
2024-02-20 16:42:04 +00:00
|
|
|
|
2024-02-23 22:49:21 +00:00
|
|
|
let gramine_sgx_ias_request_output = Command::new("gramine-sgx-ias-request")
|
|
|
|
.arg("report")
|
|
|
|
.args(["-g", "51CAF5A48B450D624AEFE3286D314894"])
|
|
|
|
.args(["-k", "669244b3e6364b5888289a11d2a1726d"])
|
2024-02-26 22:10:45 +00:00
|
|
|
.args(["-q", "e_file_path.display().to_string()])
|
|
|
|
.args(["-r", &datareport_file_path.display().to_string()])
|
|
|
|
.args(["-s", &datareportsig_file_path.display().to_string()])
|
2024-02-23 22:49:21 +00:00
|
|
|
.output()?;
|
|
|
|
println!("{gramine_sgx_ias_request_output:?}");
|
|
|
|
|
2024-02-26 21:57:54 +00:00
|
|
|
let report = read_to_string(datareport_file_path)?;
|
|
|
|
let report_sig = read_to_string(datareportsig_file_path)?;
|
2024-02-23 22:49:21 +00:00
|
|
|
let ias_report = json!({"report": report, "reportsig": report_sig});
|
2024-02-26 22:43:44 +00:00
|
|
|
Ok(ias_report)
|
2024-02-20 16:42:04 +00:00
|
|
|
}
|