Mock attestation (#82)
Co-authored-by: Ethan Buchman <ethan@coinculture.info>
This commit is contained in:
parent
fe06f244ad
commit
4b3630adf3
33 changed files with 228 additions and 4299 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2379,6 +2379,7 @@ dependencies = [
|
|||
"quartz-proto",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"tendermint 0.36.0",
|
||||
"tendermint-light-client",
|
||||
"thiserror",
|
||||
|
|
|
@ -19,6 +19,9 @@ panic = 'abort'
|
|||
incremental = false
|
||||
overflow-checks = true
|
||||
|
||||
[features]
|
||||
mock-sgx = ["quartz-cw/mock-sgx"]
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
hex = { version = "0.4.3", default-features = false }
|
||||
|
|
|
@ -3,26 +3,26 @@ use std::collections::BTreeMap;
|
|||
use cosmwasm_schema::{cw_serde, QueryResponses};
|
||||
use cosmwasm_std::{HexBinary, Uint64};
|
||||
use quartz_cw::{
|
||||
msg::execute::attested::{RawAttested, RawAttestedMsgSansHandler, RawEpidAttestation},
|
||||
msg::execute::attested::{RawAttested, RawAttestedMsgSansHandler, RawDefaultAttestation},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use crate::state::{RawHash, SettleOff};
|
||||
|
||||
type AttestedMsg<M> = RawAttested<RawAttestedMsgSansHandler<M>, RawEpidAttestation>;
|
||||
type AttestedMsg<M, RA> = RawAttested<RawAttestedMsgSansHandler<M>, RA>;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct InstantiateMsg(pub QuartzInstantiateMsg);
|
||||
pub struct InstantiateMsg<RA = RawDefaultAttestation>(pub QuartzInstantiateMsg<RA>);
|
||||
|
||||
#[cw_serde]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum ExecuteMsg {
|
||||
pub enum ExecuteMsg<RA = RawDefaultAttestation> {
|
||||
Quartz(QuartzExecuteMsg),
|
||||
FaucetMint(execute::FaucetMintMsg),
|
||||
Transfer(execute::Cw20Transfer),
|
||||
SubmitObligation(execute::SubmitObligationMsg),
|
||||
SubmitObligations(execute::SubmitObligationsMsg),
|
||||
SubmitSetoffs(AttestedMsg<execute::SubmitSetoffsMsg>),
|
||||
SubmitSetoffs(AttestedMsg<execute::SubmitSetoffsMsg, RA>),
|
||||
InitClearing,
|
||||
SetLiquiditySources(execute::SetLiquiditySourcesMsg),
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
authors = ["Informal Systems <hello@informal.systems>"]
|
||||
|
||||
[features]
|
||||
mock-sgx = ["quartz-cw/mock-sgx", "quartz-enclave/mock-sgx"]
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
clap.workspace = true
|
||||
|
|
|
@ -28,7 +28,7 @@ use mtcs_server::MtcsService;
|
|||
use proto::clearing_server::ClearingServer as MtcsServer;
|
||||
use quartz_cw::state::{Config, LightClientOpts};
|
||||
use quartz_enclave::{
|
||||
attestor::{Attestor, EpidAttestor},
|
||||
attestor::{Attestor, DefaultAttestor},
|
||||
server::CoreService,
|
||||
};
|
||||
use quartz_proto::quartz::core_server::CoreServer;
|
||||
|
@ -53,8 +53,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
args.max_block_lag,
|
||||
)?;
|
||||
|
||||
let attestor = DefaultAttestor::default();
|
||||
|
||||
let config = Config::new(
|
||||
EpidAttestor.mr_enclave()?,
|
||||
attestor.mr_enclave()?,
|
||||
Duration::from_secs(30 * 24 * 60),
|
||||
light_client_opts,
|
||||
);
|
||||
|
@ -65,9 +67,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.add_service(CoreServer::new(CoreService::new(
|
||||
config,
|
||||
sk.clone(),
|
||||
EpidAttestor,
|
||||
attestor.clone(),
|
||||
)))
|
||||
.add_service(MtcsServer::new(MtcsService::new(sk.clone(), EpidAttestor)))
|
||||
.add_service(MtcsServer::new(MtcsService::new(sk, attestor)))
|
||||
.serve(args.rpc_addr)
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ You may want to exit and start a new terminal session to get the rust toolchain
|
|||
Now downgrade rust to v1.76.0:
|
||||
|
||||
```
|
||||
rustup install v1.76.0
|
||||
rustup default v1.76.0
|
||||
rustup install 1.76.0
|
||||
rustup default 1.76.0
|
||||
```
|
||||
|
||||
Check the version with `cargo version`.
|
||||
|
@ -61,7 +61,7 @@ git checkout v0.44.0
|
|||
go install ./cmd/wasmd
|
||||
```
|
||||
|
||||
Check that both work by running `grpccurl` and `wasmd`.
|
||||
Check that both work by running `grpcurl` and `wasmd`.
|
||||
|
||||
Finally, you neeed `websocat`:
|
||||
|
||||
|
@ -114,6 +114,19 @@ First set the `NODE_URL` variable to the address of the blockchain node. If it's
|
|||
The `scripts` dir contains some bash scripts to help run the app.
|
||||
These scripts should be replaced by a new `quartz` tool. See [issue](https://github.com/informalsystems/cycles-quartz/issues/61).
|
||||
|
||||
Note: to build/run on a non-SGX machine you must set the `MOCK_SGX` env var for all bash scripts below
|
||||
```
|
||||
# 1st Terminal
|
||||
$ export MOCK_SGX=1
|
||||
$ bash scripts/build.sh
|
||||
$ bash scripts/start.sh
|
||||
|
||||
# 2nd Terminal
|
||||
$ export MOCK_SGX=1
|
||||
$ bash scripts/deploy.sh
|
||||
$ ...
|
||||
```
|
||||
|
||||
### Build the Binaries
|
||||
|
||||
Build the enclave binary and the smart contract binary:
|
||||
|
|
|
@ -23,6 +23,9 @@ panic = 'abort'
|
|||
incremental = false
|
||||
overflow-checks = true
|
||||
|
||||
[features]
|
||||
mock-sgx = ["quartz-cw/mock-sgx"]
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
sha2 = "0.10.8"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use cosmwasm_schema::write_api;
|
||||
use transfers_contracts::msg::{ExecuteMsg, InstantiateMsg};
|
||||
use transfers_contract::msg::{ExecuteMsg, InstantiateMsg};
|
||||
|
||||
fn main() {
|
||||
write_api! {
|
||||
|
|
|
@ -1 +1,8 @@
|
|||
RUSTFLAGS='-C link-arg=-s' cargo wasm
|
||||
FEATURES=
|
||||
|
||||
if [ -n "$MOCK_SGX" ]; then
|
||||
echo "MOCK_SGX is set. Adding mock-sgx feature."
|
||||
FEATURES="--features=mock-sgx"
|
||||
fi
|
||||
|
||||
RUSTFLAGS='-C link-arg=-s' cargo wasm $FEATURES
|
||||
|
|
|
@ -60,7 +60,7 @@ TX_HASH=$(echo $RES | jq -r '.["txhash"]')
|
|||
|
||||
echo ""
|
||||
while ! $CMD query tx $TX_HASH &> /dev/null; do
|
||||
echo "... 🕐 waiting for contract to be queryable"
|
||||
echo "... 🕐 waiting for contract to be queryable from tx hash $TX_HASH"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Addr, HexBinary, Uint128};
|
||||
use quartz_cw::{
|
||||
msg::execute::attested::{RawAttested, RawEpidAttestation},
|
||||
msg::execute::attested::{RawAttested, RawDefaultAttestation},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
#[cw_serde]
|
||||
pub struct InstantiateMsg {
|
||||
pub quartz: QuartzInstantiateMsg,
|
||||
pub struct InstantiateMsg<RA = RawDefaultAttestation> {
|
||||
pub quartz: QuartzInstantiateMsg<RA>,
|
||||
pub denom: String,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum ExecuteMsg {
|
||||
pub enum ExecuteMsg<RA = RawDefaultAttestation> {
|
||||
// quartz initialization
|
||||
Quartz(QuartzExecuteMsg),
|
||||
|
||||
|
@ -28,7 +28,7 @@ pub enum ExecuteMsg {
|
|||
ClearTextTransferRequest(execute::ClearTextTransferRequestMsg),
|
||||
|
||||
// enclave msg
|
||||
Update(RawAttested<execute::RawUpdateMsg, RawEpidAttestation>),
|
||||
Update(RawAttested<execute::RawUpdateMsg, RA>),
|
||||
}
|
||||
|
||||
pub mod execute {
|
||||
|
|
4186
apps/transfers/enclave/Cargo.lock
generated
4186
apps/transfers/enclave/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -3,12 +3,15 @@ name = "quartz-app-transfers-enclave"
|
|||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Informal Systems <hello@informal.systems>"]
|
||||
autobins = false
|
||||
default-run = "quartz-app-transfers-enclave"
|
||||
|
||||
[[bin]]
|
||||
name = "encrypt"
|
||||
path = "bin/encrypt.rs"
|
||||
|
||||
[features]
|
||||
mock-sgx = ["quartz-cw/mock-sgx", "quartz-enclave/mock-sgx"]
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
anyhow.workspace = true
|
||||
|
@ -20,6 +23,7 @@ k256.workspace = true
|
|||
prost.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
sha2.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
tonic.workspace = true
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use anyhow;
|
||||
use cosmwasm_std::{Addr, HexBinary, Uint128};
|
||||
use ecies::{decrypt, encrypt};
|
||||
use k256::{
|
||||
ecdsa::{SigningKey, VerifyingKey},
|
||||
pkcs8::DecodePublicKey,
|
||||
};
|
||||
use ecies::encrypt;
|
||||
use k256::ecdsa::VerifyingKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use transfers_contract::msg::execute::ClearTextTransferRequestMsg;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Quartz manifest file
|
||||
|
||||
loader.entrypoint = "file:{{ gramine.libos }}"
|
||||
libos.entrypoint = "{{ quartz_dir }}/target/release/enclave"
|
||||
libos.entrypoint = "{{ quartz_dir }}/target/release/quartz-app-transfers-enclave"
|
||||
|
||||
loader.log_level = "{{ log_level }}"
|
||||
|
||||
|
@ -20,7 +20,7 @@ loader.env.RA_TLS_EPID_API_KEY = { passthrough = true }
|
|||
loader.env.MYAPP_DATA = { passthrough = true }
|
||||
loader.env.QUARTZ_PORT = { passthrough = true }
|
||||
|
||||
loader.argv = ["enclave",
|
||||
loader.argv = ["quartz-app-transfers-enclave",
|
||||
"--chain-id", "testing",
|
||||
"--trusted-height", "{{ trusted_height }}",
|
||||
"--trusted-hash", "{{ trusted_hash }}"]
|
||||
|
@ -43,7 +43,7 @@ sgx.ra_client_linkable = {{ 'true' if ra_client_linkable == '1' else 'false' }}
|
|||
|
||||
sgx.trusted_files = [
|
||||
"file:{{ gramine.libos }}",
|
||||
"file:{{ quartz_dir }}/target/release/enclave",
|
||||
"file:{{ quartz_dir }}/target/release/quartz-app-transfers-enclave",
|
||||
"file:{{ gramine.runtimedir() }}/",
|
||||
"file:{{ arch_libdir }}/",
|
||||
"file:/usr/{{ arch_libdir }}/",
|
||||
|
|
|
@ -51,8 +51,9 @@ pub struct Cli {
|
|||
pub max_block_lag: u64,
|
||||
}
|
||||
|
||||
|
||||
fn default_rpc_addr() -> SocketAddr {
|
||||
let port = env::var("QUARTZ_PORT").unwrap_or_else(|_| "11090".to_string());
|
||||
format!("127.0.0.1:{}", port).parse().expect("Invalid socket address")
|
||||
format!("127.0.0.1:{}", port)
|
||||
.parse()
|
||||
.expect("Invalid socket address")
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
clippy::checked_conversions,
|
||||
clippy::panic,
|
||||
clippy::panic_in_result_fn,
|
||||
missing_docs,
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
rust_2018_idioms,
|
||||
|
@ -28,7 +27,7 @@ use cli::Cli;
|
|||
use proto::settlement_server::SettlementServer as TransfersServer;
|
||||
use quartz_cw::state::{Config, LightClientOpts};
|
||||
use quartz_enclave::{
|
||||
attestor::{Attestor, EpidAttestor},
|
||||
attestor::{Attestor, DefaultAttestor},
|
||||
server::CoreService,
|
||||
};
|
||||
use quartz_proto::quartz::core_server::CoreServer;
|
||||
|
@ -54,8 +53,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
args.max_block_lag,
|
||||
)?;
|
||||
|
||||
let attestor = DefaultAttestor::default();
|
||||
|
||||
let config = Config::new(
|
||||
EpidAttestor.mr_enclave()?,
|
||||
attestor.mr_enclave()?,
|
||||
Duration::from_secs(30 * 24 * 60),
|
||||
light_client_opts,
|
||||
);
|
||||
|
@ -66,12 +67,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.add_service(CoreServer::new(CoreService::new(
|
||||
config,
|
||||
sk.clone(),
|
||||
EpidAttestor,
|
||||
)))
|
||||
.add_service(TransfersServer::new(TransfersService::<EpidAttestor>::new(
|
||||
sk.clone(),
|
||||
EpidAttestor,
|
||||
attestor.clone(),
|
||||
)))
|
||||
.add_service(TransfersServer::new(TransfersService::new(sk, attestor)))
|
||||
.serve(args.rpc_addr)
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use anyhow;
|
||||
use cosmwasm_std::{Addr, HexBinary, Uint128};
|
||||
|
|
|
@ -4,9 +4,6 @@ use std::{
|
|||
};
|
||||
|
||||
use cosmwasm_std::{Addr, HexBinary, Uint128};
|
||||
|
||||
pub type RawCipherText = HexBinary;
|
||||
|
||||
use ecies::{decrypt, encrypt};
|
||||
use k256::ecdsa::{SigningKey, VerifyingKey};
|
||||
use quartz_cw::{
|
||||
|
@ -17,13 +14,15 @@ use quartz_enclave::attestor::Attestor;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use tonic::{Request, Response, Result as TonicResult, Status};
|
||||
use transfers_contracts::msg::execute::{ClearTextTransferRequestMsg, Request as TransfersRequest};
|
||||
use transfers_contract::msg::execute::{ClearTextTransferRequestMsg, Request as TransfersRequest};
|
||||
|
||||
use crate::{
|
||||
proto::{settlement_server::Settlement, RunTransfersRequest, RunTransfersResponse},
|
||||
state::{RawState, State},
|
||||
};
|
||||
|
||||
pub type RawCipherText = HexBinary;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TransfersService<A> {
|
||||
sk: Arc<Mutex<Option<SigningKey>>>,
|
||||
|
@ -178,10 +177,11 @@ where
|
|||
};
|
||||
|
||||
// Attest to message
|
||||
let attestation = self
|
||||
let attestation: HexBinary = self
|
||||
.attestor
|
||||
.quote(msg.clone())
|
||||
.map_err(|e| Status::internal(e.to_string()))?;
|
||||
.map_err(|e| Status::internal(e.to_string()))?
|
||||
.into();
|
||||
|
||||
let attested_msg = RawAttested { msg, attestation };
|
||||
let message =
|
||||
|
|
|
@ -3,16 +3,22 @@
|
|||
set -eo pipefail
|
||||
|
||||
ROOT=${ROOT:-$HOME}
|
||||
FEATURES=
|
||||
|
||||
if [ -n "$MOCK_SGX" ]; then
|
||||
echo "MOCK_SGX is set. Adding mock-sgx feature."
|
||||
FEATURES="--features=mock-sgx"
|
||||
fi
|
||||
|
||||
echo "--------------------------------------------------------"
|
||||
echo "building enclave binary"
|
||||
|
||||
cd $ROOT/cycles-quartz/apps/transfers/enclave
|
||||
CARGO_TARGET_DIR=./target cargo build --release
|
||||
CARGO_TARGET_DIR=./target cargo build --release $FEATURES
|
||||
|
||||
echo "--------------------------------------------------------"
|
||||
echo "building cosmwasm contract binary"
|
||||
|
||||
|
||||
cd $ROOT/cycles-quartz/apps/transfers/contracts
|
||||
bash build.sh
|
||||
bash build.sh $FEATURES
|
||||
|
|
|
@ -9,12 +9,13 @@ echo "--------------------------------------------------------"
|
|||
echo "instantiate"
|
||||
cd $ROOT/cycles-quartz/relayer/
|
||||
export INSTANTIATE_MSG=$(./scripts/relay.sh Instantiate | jq '{quartz: .} + {denom: "ucosm"}' )
|
||||
echo $INSTANTIATE_MSG
|
||||
echo "--------------------------------------------------------"
|
||||
|
||||
echo "deploy contract"
|
||||
cd $ROOT/cycles-quartz/apps/transfers/contracts/
|
||||
|
||||
bash deploy-contract.sh target/wasm32-unknown-unknown/release/transfers_contracts.wasm |& tee output
|
||||
bash deploy-contract.sh target/wasm32-unknown-unknown/release/transfers_contract.wasm 2>&1 | tee output
|
||||
export CONTRACT=$(cat output | grep Address | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g')
|
||||
echo $CONTRACT
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ cd $ROOT/cycles-quartz/relayer
|
|||
|
||||
# execute SessionCreate on enclave
|
||||
export EXECUTE_CREATE=$(./scripts/relay.sh SessionCreate)
|
||||
echo $EXECUTE_CREATE
|
||||
|
||||
# submit SessionCreate to contract
|
||||
RES=$($CMD tx wasm execute "$CONTRACT" "$EXECUTE_CREATE" --from admin --chain-id testing -y --output json)
|
||||
|
@ -43,14 +44,14 @@ TX_HASH=$(echo $RES | jq -r '.["txhash"]')
|
|||
|
||||
# wait for tx to commit
|
||||
while ! $CMD query tx $TX_HASH &> /dev/null; do
|
||||
echo "... 🕐 waiting for tx"
|
||||
echo "... 🕐 waiting for tx $TX_HASH"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# need to wait another block for light client proof
|
||||
BLOCK_HEIGHT=$($CMD query block | jq .block.header.height)
|
||||
|
||||
echo "at heigh $BLOCK_HEIGHT. need to wait for a block"
|
||||
echo "at height $BLOCK_HEIGHT. need to wait for a block"
|
||||
while [[ $BLOCK_HEIGHT == $($CMD query block | jq .block.header.height) ]]; do
|
||||
echo "... 🕐 waiting for another block"
|
||||
sleep 1
|
||||
|
@ -58,7 +59,7 @@ done
|
|||
|
||||
# need to wait another block for light client proof
|
||||
BLOCK_HEIGHT=$($CMD query block | jq .block.header.height)
|
||||
echo "at heigh $BLOCK_HEIGHT. need to wait for a block"
|
||||
echo "at height $BLOCK_HEIGHT. need to wait for a block"
|
||||
while [[ $BLOCK_HEIGHT == $($CMD query block | jq .block.header.height) ]]; do
|
||||
echo "... 🕐 waiting for another block"
|
||||
sleep 1
|
||||
|
@ -78,12 +79,13 @@ fi
|
|||
|
||||
# TODO: pass this in?
|
||||
echo "trusted hash $TRUSTED_HASH"
|
||||
echo "trusted hash $TRUSTED_HEIGHT"
|
||||
echo "contract $CONTRACT"
|
||||
|
||||
# run prover to get light client proof
|
||||
# TODO: assume this binary is pre-built?
|
||||
# TODO: pass in addresses and chain id
|
||||
cargo run -vvv -- --chain-id testing \
|
||||
cargo run -- --chain-id testing \
|
||||
--primary "http://$NODE_URL" \
|
||||
--witnesses "http://$NODE_URL" \
|
||||
--trusted-height $TRUSTED_HEIGHT \
|
||||
|
@ -104,7 +106,7 @@ TX_HASH=$(echo $RES | jq -r '.["txhash"]')
|
|||
|
||||
# wait for tx to commit
|
||||
while ! $CMD query tx $TX_HASH &> /dev/null; do
|
||||
echo "... 🕐 waiting for tx"
|
||||
echo "... 🕐 waiting for tx $TX_HASH"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
|
|
|
@ -25,6 +25,14 @@ cd ""$DIR_QUARTZ_APP""
|
|||
echo "$TRUSTED_HASH" > trusted.hash
|
||||
echo "$TRUSTED_HEIGHT" > trusted.height
|
||||
|
||||
if [ -n "$MOCK_SGX" ]; then
|
||||
echo "MOCK_SGX is set. Running enclave without gramine..."
|
||||
cd $DIR_QUARTZ_ENCLAVE
|
||||
./target/release/quartz-app-transfers-enclave --chain-id "testing" --trusted-height "$TRUSTED_HEIGHT" --trusted-hash "$TRUSTED_HASH"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
echo "--------------------------------------------------------"
|
||||
echo "configure gramine"
|
||||
cd "$DIR_QUARTZ_ENCLAVE"
|
||||
|
|
|
@ -9,8 +9,8 @@ repository.workspace = true
|
|||
keywords = ["blockchain", "cosmos", "tendermint", "cycles", "quartz"]
|
||||
readme = "README.md"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
[features]
|
||||
mock-sgx = ["quartz-cw/mock-sgx"]
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
|
|
|
@ -8,6 +8,12 @@ use quartz_cw::{
|
|||
state::{MrEnclave, UserData},
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "mock-sgx"))]
|
||||
pub type DefaultAttestor = EpidAttestor;
|
||||
|
||||
#[cfg(feature = "mock-sgx")]
|
||||
pub type DefaultAttestor = MockAttestor;
|
||||
|
||||
pub trait Attestor {
|
||||
type Error: ToString;
|
||||
|
||||
|
@ -16,7 +22,7 @@ pub trait Attestor {
|
|||
fn mr_enclave(&self) -> Result<MrEnclave, Self::Error>;
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive(Clone, PartialEq, Debug, Default)]
|
||||
pub struct EpidAttestor;
|
||||
|
||||
impl Attestor for EpidAttestor {
|
||||
|
@ -38,18 +44,19 @@ impl Attestor for EpidAttestor {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive(Clone, PartialEq, Debug, Default)]
|
||||
pub struct MockAttestor;
|
||||
|
||||
impl Attestor for MockAttestor {
|
||||
type Error = String;
|
||||
|
||||
fn quote(&self, _user_data: impl HasUserData) -> Result<Vec<u8>, Self::Error> {
|
||||
Ok(vec![])
|
||||
fn quote(&self, user_data: impl HasUserData) -> Result<Vec<u8>, Self::Error> {
|
||||
let user_data = user_data.user_data();
|
||||
Ok(user_data.to_vec())
|
||||
}
|
||||
|
||||
fn mr_enclave(&self) -> Result<MrEnclave, Self::Error> {
|
||||
Ok([0u8; 32])
|
||||
Ok(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
clippy::checked_conversions,
|
||||
clippy::panic,
|
||||
clippy::panic_in_result_fn,
|
||||
missing_docs,
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
rust_2018_idioms,
|
||||
|
|
|
@ -9,6 +9,9 @@ repository.workspace = true
|
|||
keywords = ["blockchain", "cosmos", "cosmwasm", "cycles", "quartz"]
|
||||
readme = "README.md"
|
||||
|
||||
[features]
|
||||
mock-sgx = []
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
k256.workspace = true
|
||||
|
|
|
@ -7,7 +7,7 @@ use cosmwasm_std::StdError;
|
|||
|
||||
use crate::msg::{
|
||||
execute::{
|
||||
attested::{Attested, EpidAttestation, RawAttested, RawEpidAttestation},
|
||||
attested::{Attested, DefaultAttestation, RawAttested, RawDefaultAttestation},
|
||||
session_create::{RawSessionCreate, SessionCreate},
|
||||
session_set_pub_key::{RawSessionSetPubKey, SessionSetPubKey},
|
||||
},
|
||||
|
@ -15,13 +15,13 @@ use crate::msg::{
|
|||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Execute<Attestation = EpidAttestation> {
|
||||
pub enum Execute<Attestation = DefaultAttestation> {
|
||||
SessionCreate(Attested<SessionCreate, Attestation>),
|
||||
SessionSetPubKey(Attested<SessionSetPubKey, Attestation>),
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub enum RawExecute<RawAttestation = RawEpidAttestation> {
|
||||
pub enum RawExecute<RawAttestation = RawDefaultAttestation> {
|
||||
#[serde(rename = "session_create")]
|
||||
RawSessionCreate(RawAttested<RawSessionCreate, RawAttestation>),
|
||||
#[serde(rename = "session_set_pub_key")]
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
use std::{convert::Into, default::Default};
|
||||
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::StdError;
|
||||
use cosmwasm_std::{HexBinary, StdError};
|
||||
use quartz_tee_ra::IASReport;
|
||||
|
||||
#[cfg(not(feature = "mock-sgx"))]
|
||||
pub type DefaultAttestation = EpidAttestation;
|
||||
#[cfg(not(feature = "mock-sgx"))]
|
||||
pub type RawDefaultAttestation = RawEpidAttestation;
|
||||
|
||||
#[cfg(feature = "mock-sgx")]
|
||||
pub type DefaultAttestation = MockAttestation;
|
||||
#[cfg(feature = "mock-sgx")]
|
||||
pub type RawDefaultAttestation = RawMockAttestation;
|
||||
|
||||
use crate::{
|
||||
msg::HasDomainType,
|
||||
state::{MrEnclave, UserData},
|
||||
|
@ -137,22 +149,28 @@ impl Attestation for EpidAttestation {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MockAttestation;
|
||||
pub struct MockAttestation(pub UserData);
|
||||
|
||||
impl Default for MockAttestation {
|
||||
fn default() -> Self {
|
||||
Self([0u8; 64])
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct RawMockAttestation;
|
||||
pub struct RawMockAttestation(pub HexBinary);
|
||||
|
||||
impl TryFrom<RawMockAttestation> for MockAttestation {
|
||||
type Error = StdError;
|
||||
|
||||
fn try_from(_value: RawMockAttestation) -> Result<Self, Self::Error> {
|
||||
Ok(Self)
|
||||
fn try_from(value: RawMockAttestation) -> Result<Self, Self::Error> {
|
||||
Ok(Self(value.0.to_array()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MockAttestation> for RawMockAttestation {
|
||||
fn from(_value: MockAttestation) -> Self {
|
||||
Self
|
||||
fn from(value: MockAttestation) -> Self {
|
||||
Self(value.0.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,13 +180,13 @@ impl HasDomainType for RawMockAttestation {
|
|||
|
||||
impl HasUserData for MockAttestation {
|
||||
fn user_data(&self) -> UserData {
|
||||
unimplemented!("MockAttestation handler is a noop")
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Attestation for MockAttestation {
|
||||
fn mr_enclave(&self) -> MrEnclave {
|
||||
unimplemented!("MockAttestation handler is a noop")
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use sha2::{Digest, Sha256};
|
|||
use crate::{
|
||||
msg::{
|
||||
execute::attested::{
|
||||
Attested, EpidAttestation, HasUserData, RawAttested, RawEpidAttestation,
|
||||
Attested, DefaultAttestation, HasUserData, RawAttested, RawDefaultAttestation,
|
||||
},
|
||||
HasDomainType,
|
||||
},
|
||||
|
@ -13,10 +13,10 @@ use crate::{
|
|||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Instantiate<A = EpidAttestation>(pub Attested<CoreInstantiate, A>);
|
||||
pub struct Instantiate<A = DefaultAttestation>(pub Attested<CoreInstantiate, A>);
|
||||
|
||||
#[cw_serde]
|
||||
pub struct RawInstantiate<RA = RawEpidAttestation>(RawAttested<RawCoreInstantiate, RA>);
|
||||
pub struct RawInstantiate<RA = RawDefaultAttestation>(RawAttested<RawCoreInstantiate, RA>);
|
||||
|
||||
impl<RA> TryFrom<RawInstantiate<RA>> for Instantiate<RA::DomainType>
|
||||
where
|
||||
|
|
|
@ -9,6 +9,9 @@ repository.workspace = true
|
|||
keywords = ["blockchain", "cosmos", "tendermint", "cycles", "quartz"]
|
||||
readme = "README.md"
|
||||
|
||||
[features]
|
||||
mock-sgx = ["quartz-cw/mock-sgx"]
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
clap.workspace = true
|
||||
|
|
|
@ -23,9 +23,6 @@ REQUEST_MSG=${2:-"{}"}
|
|||
# Use the QUARTZ_PORT environment variable if set, otherwise default to 11090
|
||||
QUARTZ_PORT="${QUARTZ_PORT:-11090}"
|
||||
|
||||
# clear tmp files from previous runs
|
||||
rm -f "$QUOTE_FILE" "$REPORT_FILE" "$REPORT_SIG_FILE"
|
||||
|
||||
# query the gRPC quartz enclave service
|
||||
ATTESTED_MSG=$(grpcurl -plaintext -import-path "$DIR_PROTO" -proto quartz.proto -d "$REQUEST_MSG" "127.0.0.1:$QUARTZ_PORT" quartz.Core/"$REQUEST" | jq -c '.message | fromjson')
|
||||
|
||||
|
@ -33,6 +30,29 @@ ATTESTED_MSG=$(grpcurl -plaintext -import-path "$DIR_PROTO" -proto quartz.proto
|
|||
QUOTE=$(echo "$ATTESTED_MSG" | jq -c '.quote')
|
||||
MSG=$(echo "$ATTESTED_MSG" | jq 'del(.quote)')
|
||||
|
||||
if [ -n "$MOCK_SGX" ]; then
|
||||
case "$REQUEST" in
|
||||
"Instantiate")
|
||||
jq -nc --argjson msg "$MSG" --argjson "attestation" \
|
||||
"$QUOTE" \
|
||||
'$ARGS.named' ;;
|
||||
|
||||
"SessionCreate" | "SessionSetPubKey")
|
||||
REQUEST_KEY=$(echo "$REQUEST" | perl -pe 's/([A-Z])/_\L$1/g;s/^_//') #sed 's/\([A-Z]\)/_\L\1/g;s/^_//')
|
||||
jq -nc --argjson quartz "$(jq -nc --argjson "$REQUEST_KEY" "$(jq -nc --argjson msg "$MSG" --argjson attestation \
|
||||
"$QUOTE" '$ARGS.named')" '$ARGS.named')" '$ARGS.named' ;;
|
||||
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
# clear tmp files from previous runs
|
||||
rm -f "$QUOTE_FILE" "$REPORT_FILE" "$REPORT_SIG_FILE"
|
||||
|
||||
# request the IAS report for EPID attestations
|
||||
echo -n "$QUOTE" | xxd -r -p - > "$QUOTE_FILE"
|
||||
gramine-sgx-ias-request report -g "$RA_CLIENT_SPID" -k "$IAS_API_KEY" -q "$QUOTE_FILE" -r "$REPORT_FILE" -s "$REPORT_SIG_FILE" > /dev/null 2>&1
|
||||
|
@ -44,17 +64,17 @@ REPORTSIG=$(cat "$REPORT_SIG_FILE" | tr -d '\r')
|
|||
#echo "$REPORTSIG"
|
||||
|
||||
case "$REQUEST" in
|
||||
"Instantiate")
|
||||
"Instantiate")
|
||||
jq -nc --argjson msg "$MSG" --argjson "attestation" \
|
||||
"$(jq -nc --argjson report "$(jq -nc --argjson report "$REPORT" --arg reportsig "$REPORTSIG" '$ARGS.named')" '$ARGS.named')" \
|
||||
'$ARGS.named' ;;
|
||||
|
||||
"SessionCreate" | "SessionSetPubKey")
|
||||
REQUEST_KEY=$(echo "$REQUEST" | sed 's/\([A-Z]\)/_\L\1/g;s/^_//')
|
||||
REQUEST_KEY=$(echo "$REQUEST" | perl -pe 's/([A-Z])/_\L$1/g;s/^_//')
|
||||
jq -nc --argjson quartz "$(jq -nc --argjson "$REQUEST_KEY" "$(jq -nc --argjson msg "$MSG" --argjson attestation \
|
||||
"$(jq -nc --argjson report "$(jq -nc --argjson report "$REPORT" --arg reportsig "$REPORTSIG" '$ARGS.named')" '$ARGS.named')" \
|
||||
'$ARGS.named')" '$ARGS.named')" '$ARGS.named' ;;
|
||||
|
||||
*)
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
mod cli;
|
||||
|
||||
use std::{
|
||||
error::Error,
|
||||
fs::{read_to_string, File},
|
||||
io::{Read, Write},
|
||||
process::Command,
|
||||
};
|
||||
use std::{error::Error, fs::File, io::Read};
|
||||
|
||||
use clap::Parser;
|
||||
use cosmos_sdk_proto::{
|
||||
|
@ -30,14 +25,12 @@ use cosmrs::{
|
|||
};
|
||||
use ecies::{PublicKey, SecretKey};
|
||||
use quartz_cw::msg::{
|
||||
execute::attested::{Attested, EpidAttestation},
|
||||
execute::attested::Attested,
|
||||
instantiate::{CoreInstantiate, RawInstantiate},
|
||||
InstantiateMsg,
|
||||
};
|
||||
use quartz_proto::quartz::{core_client::CoreClient, InstantiateRequest};
|
||||
use quartz_relayer::types::InstantiateResponse;
|
||||
use quartz_tee_ra::IASReport;
|
||||
use serde_json::{json, Value};
|
||||
use subtle_encoding::base64;
|
||||
use tendermint::public_key::Secp256k1 as TmPublicKey;
|
||||
|
||||
|
@ -50,16 +43,32 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let mut client = CoreClient::connect(args.enclave_addr.uri().to_string()).await?;
|
||||
let response = client.instantiate(InstantiateRequest {}).await?;
|
||||
let response: InstantiateResponse = response.into_inner().try_into()?;
|
||||
let (config, quote) = response.into_message().into_tuple();
|
||||
|
||||
let ias_report = gramine_sgx_ias_report("e)?;
|
||||
#[cfg(feature = "mock-sgx")]
|
||||
let attestation = {
|
||||
use quartz_cw::msg::execute::attested::MockAttestation;
|
||||
|
||||
MockAttestation::default()
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "mock-sgx"))]
|
||||
let attestation = {
|
||||
use quartz_cw::msg::execute::attested::EpidAttestation;
|
||||
use quartz_tee_ra::IASReport;
|
||||
|
||||
let ias_report = gramine_sgx_ias_report(response.quote())?;
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(&ias_report).expect("infallible serializer")
|
||||
);
|
||||
let ias_report: IASReport = serde_json::from_str(&ias_report.to_string())?;
|
||||
let attestation = EpidAttestation::new(ias_report);
|
||||
let cw_instantiate_msg = Attested::new(CoreInstantiate::new(config), attestation);
|
||||
EpidAttestation::new(ias_report)
|
||||
};
|
||||
|
||||
let cw_instantiate_msg = Attested::new(
|
||||
CoreInstantiate::new(response.into_message().into_tuple().0),
|
||||
attestation,
|
||||
);
|
||||
|
||||
// Read the TSP secret
|
||||
let secret = {
|
||||
|
@ -152,7 +161,14 @@ pub async fn send_tx(node: impl ToString, tx_bytes: Vec<u8>) -> Result<(), Box<d
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn gramine_sgx_ias_report(quote: &[u8]) -> Result<Value, Box<dyn Error>> {
|
||||
#[cfg(not(feature = "mock-sgx"))]
|
||||
fn gramine_sgx_ias_report(quote: &[u8]) -> Result<serde_json::Value, Box<dyn Error>> {
|
||||
use std::{
|
||||
fs::{read_to_string, File},
|
||||
io::Write,
|
||||
process::Command,
|
||||
};
|
||||
|
||||
let dir = tempfile::tempdir()?;
|
||||
let quote_file_path = dir.path().join("test.quote");
|
||||
let datareport_file_path = dir.path().join("datareport");
|
||||
|
@ -173,6 +189,6 @@ fn gramine_sgx_ias_report(quote: &[u8]) -> Result<Value, Box<dyn Error>> {
|
|||
|
||||
let report = read_to_string(datareport_file_path)?;
|
||||
let report_sig = read_to_string(datareportsig_file_path)?;
|
||||
let ias_report = json!({"report": report, "reportsig": report_sig});
|
||||
let ias_report = serde_json::json!({"report": report, "reportsig": report_sig});
|
||||
Ok(ias_report)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue