refactor: remove unused crates and scripts (#173)

This commit is contained in:
Shoaib Ahmed 2024-08-21 16:43:25 +02:00 committed by GitHub
parent cf0a2ffc41
commit 6c8ba526ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 14 additions and 7877 deletions

155
Cargo.lock generated
View file

@ -414,34 +414,6 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "axum"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [
"async-trait",
"axum-core 0.3.4",
"bitflags 1.3.2",
"bytes",
"futures-util",
"http 0.2.12",
"http-body 0.4.6",
"hyper 0.14.30",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"sync_wrapper 0.1.2",
"tower",
"tower-layer",
"tower-service",
]
[[package]] [[package]]
name = "axum" name = "axum"
version = "0.7.5" version = "0.7.5"
@ -449,7 +421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum-core 0.4.3", "axum-core",
"bytes", "bytes",
"futures-util", "futures-util",
"http 1.1.0", "http 1.1.0",
@ -469,23 +441,6 @@ dependencies = [
"tower-service", "tower-service",
] ]
[[package]]
name = "axum-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http 0.2.12",
"http-body 0.4.6",
"mime",
"rustversion",
"tower-layer",
"tower-service",
]
[[package]] [[package]]
name = "axum-core" name = "axum-core"
version = "0.4.3" version = "0.4.3"
@ -905,7 +860,6 @@ dependencies = [
"prost 0.12.6", "prost 0.12.6",
"prost-types 0.12.6", "prost-types 0.12.6",
"tendermint-proto 0.37.0", "tendermint-proto 0.37.0",
"tonic 0.11.0",
] ]
[[package]] [[package]]
@ -2431,18 +2385,6 @@ dependencies = [
"webpki-roots", "webpki-roots",
] ]
[[package]]
name = "hyper-timeout"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
dependencies = [
"hyper 0.14.30",
"pin-project-lite",
"tokio",
"tokio-io-timeout",
]
[[package]] [[package]]
name = "hyper-timeout" name = "hyper-timeout"
version = "0.5.1" version = "0.5.1"
@ -3054,27 +2996,10 @@ dependencies = [
"tendermint-light-client", "tendermint-light-client",
"thiserror", "thiserror",
"tokio", "tokio",
"tonic 0.12.1", "tonic",
"tonic-build", "tonic-build",
] ]
[[package]]
name = "mtcs-intent"
version = "0.1.0"
dependencies = [
"bip32",
"clap",
"cosmrs",
"cosmwasm-std",
"ecies",
"hex",
"k256",
"rand",
"serde",
"serde_json",
"sha2 0.10.8",
]
[[package]] [[package]]
name = "multimap" name = "multimap"
version = "0.10.0" version = "0.10.0"
@ -3724,7 +3649,7 @@ dependencies = [
"tm-prover", "tm-prover",
"tokio", "tokio",
"toml", "toml",
"tonic 0.12.1", "tonic",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
] ]
@ -3752,7 +3677,7 @@ dependencies = [
"tendermint-light-client", "tendermint-light-client",
"thiserror", "thiserror",
"tokio", "tokio",
"tonic 0.12.1", "tonic",
"tonic-build", "tonic-build",
"transfers-contract", "transfers-contract",
] ]
@ -3797,7 +3722,6 @@ dependencies = [
"mtcs", "mtcs",
"quartz-cw", "quartz-cw",
"quartz-proto", "quartz-proto",
"quartz-relayer",
"quartz-tee-ra", "quartz-tee-ra",
"rand", "rand",
"serde", "serde",
@ -3807,7 +3731,7 @@ dependencies = [
"tendermint-light-client", "tendermint-light-client",
"tm-stateless-verifier", "tm-stateless-verifier",
"tokio", "tokio",
"tonic 0.12.1", "tonic",
] ]
[[package]] [[package]]
@ -3815,34 +3739,10 @@ name = "quartz-proto"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"prost 0.13.1", "prost 0.13.1",
"tonic 0.12.1", "tonic",
"tonic-build", "tonic-build",
] ]
[[package]]
name = "quartz-relayer"
version = "0.1.0"
dependencies = [
"clap",
"cosmos-sdk-proto",
"cosmrs",
"cosmwasm-std",
"displaydoc",
"ecies",
"k256",
"quartz-cw",
"quartz-proto",
"quartz-tee-ra",
"serde",
"serde_json",
"subtle-encoding",
"tempfile",
"tendermint 0.38.1",
"thiserror",
"tokio",
"tonic 0.12.1",
]
[[package]] [[package]]
name = "quartz-tee-ra" name = "quartz-tee-ra"
version = "0.1.0" version = "0.1.0"
@ -4935,12 +4835,10 @@ dependencies = [
"ed25519-consensus", "ed25519-consensus",
"flex-error", "flex-error",
"futures", "futures",
"k256",
"num-traits", "num-traits",
"once_cell", "once_cell",
"prost 0.13.1", "prost 0.13.1",
"prost-types 0.13.1", "prost-types 0.13.1",
"ripemd",
"serde", "serde",
"serde_bytes", "serde_bytes",
"serde_json", "serde_json",
@ -5254,16 +5152,6 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "tokio-io-timeout"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
dependencies = [
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.4.0" version = "2.4.0"
@ -5366,33 +5254,6 @@ dependencies = [
"winnow", "winnow",
] ]
[[package]]
name = "tonic"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13"
dependencies = [
"async-stream",
"async-trait",
"axum 0.6.20",
"base64 0.21.7",
"bytes",
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"hyper 0.14.30",
"hyper-timeout 0.4.1",
"percent-encoding",
"pin-project",
"prost 0.12.6",
"tokio",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]] [[package]]
name = "tonic" name = "tonic"
version = "0.12.1" version = "0.12.1"
@ -5401,7 +5262,7 @@ checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401"
dependencies = [ dependencies = [
"async-stream", "async-stream",
"async-trait", "async-trait",
"axum 0.7.5", "axum",
"base64 0.22.1", "base64 0.22.1",
"bytes", "bytes",
"h2 0.4.5", "h2 0.4.5",
@ -5409,7 +5270,7 @@ dependencies = [
"http-body 1.0.1", "http-body 1.0.1",
"http-body-util", "http-body-util",
"hyper 1.4.1", "hyper 1.4.1",
"hyper-timeout 0.5.1", "hyper-timeout",
"hyper-util", "hyper-util",
"percent-encoding", "percent-encoding",
"pin-project", "pin-project",

View file

@ -83,7 +83,6 @@ quartz-common = { path = "core/quartz-common"}
quartz-cw = { path = "cosmwasm/packages/quartz-cw", default-features = false } quartz-cw = { path = "cosmwasm/packages/quartz-cw", default-features = false }
quartz-enclave = { path = "core/quartz", default-features = false } quartz-enclave = { path = "core/quartz", default-features = false }
quartz-proto = { path = "core/quartz-proto", default-features = false } quartz-proto = { path = "core/quartz-proto", default-features = false }
quartz-relayer = { path = "relayer", default-features = false , features = ["mock-sgx"]}
quartz-tee-ra = { path = "cosmwasm/packages/quartz-tee-ra", default-features = false } quartz-tee-ra = { path = "cosmwasm/packages/quartz-tee-ra", default-features = false }
tm-prover = { path = "utils/tm-prover", default-features = false } tm-prover = { path = "utils/tm-prover", default-features = false }
tm-stateless-verifier = { path = "core/light-client-proofs/tm-stateless-verifier", default-features = false } tm-stateless-verifier = { path = "core/light-client-proofs/tm-stateless-verifier", default-features = false }

View file

@ -32,7 +32,6 @@ Utilities for supporting Quartz development and -
* [cw-prover](utils/cw-prover) - Retrieve a merkle-proof for CosmWasm state * [cw-prover](utils/cw-prover) - Retrieve a merkle-proof for CosmWasm state
* [cycles-sync](utils/cycles-sync) - Sync obligations and setoffs * [cycles-sync](utils/cycles-sync) - Sync obligations and setoffs
with [Obligato](https://github.com/informalsystems/obligato) with [Obligato](https://github.com/informalsystems/obligato)
* [mtcs-intent](utils/mtcs-intent) - CLI for keygen, encrypting/decrypting obligations/setoffs, etc.
* [tm-prover](utils/tm-prover) - Generate light client and merkle proofs for CosmWasm storage in a format that Quartz * [tm-prover](utils/tm-prover) - Generate light client and merkle proofs for CosmWasm storage in a format that Quartz
understands understands

File diff suppressed because it is too large Load diff

View file

@ -1,58 +0,0 @@
[package]
name = "scripts"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "listen"
path = "src/bin/listen.rs"
[[bin]]
name = "handshake"
path = "src/bin/handshake.rs"
[[bin]]
name = "deploy"
path = "src/bin/deploy.rs"
[dependencies]
clap.workspace = true
color-eyre.workspace = true
ecies.workspace = true
hex.workspace = true
k256.workspace = true
prost.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
tokio.workspace = true
tonic.workspace = true
once_cell = "1.19.0"
reqwest = { version = "0.12.2", default-features = false, features = ["json", "rustls-tls"] }
anyhow = "1.0.86"
base64 = "0.22.1"
subtle-encoding = "0.5.1"
tokio-tungstenite = "0.23.1"
futures-util = "0.3.30"
tendermint-rpc = { version ="0.38.1", features=["websocket-client", "http-client"]}
# cosmos
cosmrs.workspace = true
cosmwasm-std.workspace = true
tendermint.workspace = true
tendermint-light-client.workspace = true
# quartz
cw-proof.workspace = true
cw-tee-mtcs.workspace = true
mtcs.workspace = true
# todo remove unnecessary imports
cycles-sync = { workspace = true}
tm-prover = { workspace = true}
quartz-common = { workspace = true, features=["contract"]}
quartz-tee-ra = { workspace = true}
mtcs-enclave = { path = "../enclave", optional = false}
regex = "1.10.5"

View file

@ -1,40 +0,0 @@
set -eo pipefail
ROOT=${ROOT:-$HOME}
DIR_MTCS="$ROOT/cycles-protocol/quartz-app"
DIR_CYCLES_SYNC="$ROOT/cycles-protocol/packages/cycles-sync/"
DIR_PROTO="$DIR_MTCS/enclave/proto"
OVERDRAFT=wasm199rcvzawgyse89k4smqdn4wp83f3q8rurg9vautppxh5cypydafqk9nt6q
cd $DIR_MTCS
export NODE_URL=143.244.186.205:26657
bash scripts/build.sh
cd $DIR_MTCS/scripts/scripts
CONTRACT=$(RUST_BACKTRACE=1 cargo run --bin deploy | tail -n 1)
echo "------------ built and deployed ------------"
PUB_KEY=$(RUST_BACKTRACE=1 cargo run --bin handshake -- --contract $CONTRACT | tail -n 1)
echo "PUB KEY: '$PUB_KEY'"
echo "------------ shook some hands ------------"
cd $DIR_CYCLES_SYNC
cargo run --bin submit -- --epoch-pk $PUB_KEY --mtcs $CONTRACT --overdraft $OVERDRAFT
echo "cargo run --bin submit -- --epoch-pk $PUB_KEY --mtcs $CONTRACT --overdraft $OVERDRAFT"
echo "------------ submitted obligations ------------"
# add contract to owners list in overdrafts contract
CURRENT_SEQUENCE=$(wasmd query account wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70 --node http://$NODE_URL --output json | jq -r .sequence)
WASMD_OUTPUT=$(wasmd tx wasm execute $OVERDRAFT '{"add_owner": {"new": "'$CONTRACT'"}}' --from wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70 --node http://$NODE_URL --chain-id testing --yes --sequence $CURRENT_SEQUENCE)
echo $WASMD_OUTPUT
echo "------------ added contract as owner of overdrafts ------------"
cd $DIR_MTCS/scripts/scripts
cargo run --bin listen -- --contract $CONTRACT

View file

@ -1,18 +0,0 @@
#!/bin/bash
set -eo pipefail
ROOT=${ROOT:-$HOME}
echo "--------------------------------------------------------"
echo "building enclave binary"
cd $ROOT/cycles-protocol/quartz-app/enclave/
CARGO_TARGET_DIR=./target cargo build --release
echo "--------------------------------------------------------"
echo "building cosmwasm contract binary"
cd $ROOT/cycles-protocol/quartz-app/contracts/cw-tee-mtcs/
bash build.sh

View file

@ -1,23 +0,0 @@
#!/bin/bash
set -eo pipefail
ROOT=${ROOT:-$HOME}
echo "--------------------------------------------------------"
echo "instantiate"
cd $ROOT/cycles-protocol/packages/relayer/
export INSTANTIATE_MSG=$(./scripts/relay.sh Instantiate | jq '{quartz: .}' )
echo "--------------------------------------------------------"
echo "deploy contract"
cd $ROOT/cycles-protocol/quartz-app/contracts/cw-tee-mtcs
bash deploy-contract.sh target/wasm32-unknown-unknown/release/cw_tee_mtcs.wasm |& tee output
export CONTRACT=$(cat output | grep Address | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g')
echo $CONTRACT

View file

@ -1,23 +0,0 @@
#!/bin/bash
set -eo pipefail
ROOT=${ROOT:-$HOME}
echo "--------------------------------------------------------"
echo "instantiate"
cd $ROOT/cycles-protocol/packages/relayer/
export INSTANTIATE_MSG=$(./scripts/relay.sh Instantiate | jq '{quartz: .}' )
echo "--------------------------------------------------------"
echo "deploy contract"
cd $ROOT/cycles-protocol/quartz-app/contracts/cw-tee-mtcs
bash deploy-contract.sh target/wasm32-unknown-unknown/release/cw_tee_mtcs.wasm |& tee output
export CONTRACT=$(cat output | grep Address | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g')
echo $CONTRACT

View file

@ -1,117 +0,0 @@
#!/bin/bash
#
# Perform the SessionCreate and SessionSetPubKey handshake between the contract and the sgx node
# Expects:
# - enclave is already initialized
# - contract is already deployed
# - apps/transfers/trusted.hash exists
#
set -eo pipefail
ROOT=${ROOT:-$HOME}
NODE_URL=${NODE_URL:-127.0.0.1:26657}
if [ "$#" -eq 0 ]; then
echo "Usage: $0 <contract_address>"
exit 1 # Exit with a non-zero status to indicate an error
fi
CONTRACT="$1"
CMD="wasmd --node http://$NODE_URL"
cd "$ROOT/cycles-protocol/quartz-app/"
export TRUSTED_HASH=$(cat trusted.hash)
export TRUSTED_HEIGHT=$(cat trusted.height)
echo "using CMD: $CMD"
echo "--------------------------------------------------------"
echo "create session"
# change to relay dir
cd $ROOT/cycles-protocol/packages/relayer
# execute SessionCreate on enclave
export EXECUTE_CREATE=$(./scripts/relay.sh SessionCreate)
# submit SessionCreate to contract
RES=$($CMD tx wasm execute "$CONTRACT" "$EXECUTE_CREATE" --from admin --chain-id testing -y --output json)
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"
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"
while [[ $BLOCK_HEIGHT == $($CMD query block | jq .block.header.height) ]]; do
echo "... 🕐 waiting for another block"
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"
while [[ $BLOCK_HEIGHT == $($CMD query block | jq .block.header.height) ]]; do
echo "... 🕐 waiting for another block"
sleep 1
done
echo "--------------------------------------------------------"
echo "set session pk"
# change to prover dir
cd $ROOT/cycles-protocol/packages/tm-prover
export PROOF_FILE="light-client-proof.json"
if [ -f "$PROOF_FILE" ]; then
rm "$PROOF_FILE"
echo "removed old $PROOF_FILE"
fi
# TODO: pass this in?
echo "trusted hash $TRUSTED_HASH"
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 \
--primary "http://$NODE_URL" \
--witnesses "http://$NODE_URL" \
--trusted-height $TRUSTED_HEIGHT \
--trusted-hash $TRUSTED_HASH \
--contract-address $CONTRACT \
--storage-key "quartz_session" \
--trace-file $PROOF_FILE
export POP=$(cat $PROOF_FILE)
export POP_MSG=$(jq -nc --arg message "$POP" '$ARGS.named')
echo "hi"
# execute SessionSetPubKey on enclave
cd $ROOT/cycles-protocol/packages/relayer
export EXECUTE_SETPUB=$(./scripts/relay.sh SessionSetPubKey "$POP_MSG")
RES=$($CMD tx wasm execute "$CONTRACT" "$EXECUTE_SETPUB" --from admin --chain-id testing -y --output json)
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"
sleep 1
done
echo "--------------------------------------------------------"
echo "check session success"
export NONCE_AND_KEY=$($CMD query wasm contract-state raw "$CONTRACT" $(printf '%s' "quartz_session" | hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
echo $NONCE_AND_KEY
export PUBKEY=$(echo $NONCE_AND_KEY | jq -r .pub_key)

View file

@ -1,101 +0,0 @@
ROOT=${ROOT:-$HOME}
DIR_MTCS="$ROOT/cycles-protocol/quartz-app/"
DIR_PROTO="$DIR_MTCS/enclave/proto"
DEFAULT_NODE="127.0.0.1:26657"
NODE_URL="143.244.186.205:26657"
# Use the QUARTZ_PORT environment variable if set, otherwise default to 11090
QUARTZ_PORT="${QUARTZ_PORT:-11090}"
# Attestation constants
IAS_API_KEY="669244b3e6364b5888289a11d2a1726d"
RA_CLIENT_SPID="51CAF5A48B450D624AEFE3286D314894"
QUOTE_FILE="/tmp/${USER}_test.quote"
REPORT_FILE="/tmp/${USER}_datareport"
REPORT_SIG_FILE="/tmp/${USER}_datareportsig"
if [ "$#" -eq 0 ]; then
echo "Usage: $0 <contract_address>"
exit 1 # Exit with a non-zero status to indicate an error
fi
CONTRACT=$1
CMD="wasmd --node http://$NODE_URL"
WSURL="ws://$NODE_URL/websocket"
SUBSCRIBE="{\"jsonrpc\":\"2.0\",\"method\":\"subscribe\",\"params\":[\"tm.event='Tx' AND wasm._contract_address = '$CONTRACT' AND wasm.action='init_clearing'\"],\"id\":1}"
echo $SUBSCRIBE
echo "--------------------------------------------------------"
echo "subscribe to events"
# cat keeps the stdin open so websocat doesnt close
(echo "$SUBSCRIBE"; cat) | websocat $WSURL | while read msg; do
if [[ "$msg" == '{"jsonrpc":"2.0","id":1,"result":{}}' ]]; then
echo "... subscribed"
echo "---------------------------------------------------------"
echo "... waiting for event"
continue
fi
if echo "$msg" | jq 'has("error")' > /dev/null; then
echo "... error msg $msg"
echo "---------------------------------------------------------"
echo "... waiting for event"
continue
fi
echo "... received init_clearing event!"
echo $msg
echo "... fetching obligations"
export EPOCH=$($CMD query wasm contract-state raw "$CONTRACT" "65706f63685f636f756e746572" -o json | jq -r .data | base64 -d)
PREV_EPOCH=$((EPOCH - 1))
export OBLIGATIONS=$($CMD query wasm contract-state raw "$CONTRACT" $(printf '%s/%s' "$PREV_EPOCH" "obligations" | hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
export LIQUIDITY_SOURCES=$($CMD query wasm contract-state smart $CONTRACT '{"get_liquidity_sources": {"epoch": '$PREV_EPOCH'}}' -o json | jq -r .data.liquidity_sources)
COMBINED_JSON=$(jq -nc \
--argjson intents "$OBLIGATIONS" \
--argjson liquidity_sources "$LIQUIDITY_SOURCES" \
'{intents: $intents, liquidity_sources: $liquidity_sources}')
echo $COMBINED_JSON
# Wrap the combined JSON string into another JSON object with a "message" field
REQUEST_MSG=$(jq -nc --arg message "$COMBINED_JSON" '{"message": $message}')
echo "... executing mtcs"
export ATTESTED_MSG=$(grpcurl -plaintext -import-path "$DIR_PROTO" -proto mtcs.proto -d "$REQUEST_MSG" "127.0.0.1:$QUARTZ_PORT" mtcs.Clearing/Run | jq -c '.message | fromjson')
QUOTE=$(echo "$ATTESTED_MSG" | jq -c '.attestation')
MSG=$(echo "$ATTESTED_MSG" | jq -c '.msg')
# 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
REPORT=$(cat "$REPORT_FILE")
REPORTSIG=$(cat "$REPORT_SIG_FILE" | tr -d '\r')
echo "... submitting update"
export EXECUTE=$(jq -nc --argjson submit_setoffs "$(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')
$CMD tx wasm execute "$CONTRACT" "$EXECUTE" --from admin --chain-id testing -y --gas 2000000
echo " ... done"
echo "---------------------------------------------------------"
echo "... waiting for event"
done

View file

@ -1,80 +0,0 @@
use std::{env::current_dir, str::FromStr};
use clap::Parser;
use cosmrs::tendermint::chain::Id as ChainId;
use cw_tee_mtcs::msg::InstantiateMsg as MtcsInstantiateMsg;
use cycles_sync::wasmd_client::{CliWasmdClient, WasmdClient};
use quartz_common::contract::msg::RawInstantiateMsg;
use reqwest::Url;
use scripts::{
types::{Log, WasmdTxResponse},
utils::{block_tx_commit, run_relay},
};
use serde_json::json;
use tendermint::Hash;
use tendermint_rpc::HttpClient;
#[derive(Clone, Debug, Parser)]
#[command(version, about, long_about = None)]
struct Cli {
#[clap(long, default_value = "143.244.186.205:26657")]
node_url: String,
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let cli = Cli::parse();
let base_path = current_dir()?.join("../../../");
println!("\n🚀 Communicating with Relay to Instantiate...\n");
let init_msg: RawInstantiateMsg = run_relay(base_path.as_path(), "Instantiate", None)?; // need to define the return type
let init_msg: MtcsInstantiateMsg = MtcsInstantiateMsg { quartz: init_msg };
let httpurl = Url::parse(&format!("http://{}", cli.node_url))?;
let tmrpc_client = HttpClient::new(httpurl.as_str()).unwrap();
let wasmd_client = CliWasmdClient::new(Url::parse(httpurl.as_str())?);
println!("\n🚀 Deploying MTCS Contract\n");
let contract_path = base_path.join(
"quartz-app/contracts/cw-tee-mtcs/target/wasm32-unknown-unknown/release/cw_tee_mtcs.wasm",
);
// TODO: uncertain about the path -> string conversion
let deploy_output: WasmdTxResponse = serde_json::from_str(&wasmd_client.deploy(
&ChainId::from_str("testing")?,
&String::from("wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70"),
contract_path.display().to_string(),
)?)?;
let tx_hash =
Hash::from_str(&deploy_output.txhash).expect("Invalid hex string for transaction hash");
let res = block_tx_commit(&tmrpc_client, tx_hash).await?;
let log: Vec<Log> = serde_json::from_str(&res.tx_result.log)?;
let code_id: usize = log[0].events[1].attributes[1].value.parse()?;
println!("\n🚀 Instantiating MTCS Contract\n");
let deploy_output: WasmdTxResponse = serde_json::from_str(&wasmd_client.init(
&ChainId::from_str("testing")?,
&String::from("wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70"),
code_id,
json!(init_msg),
&format!("MTCS Contract V{}", code_id),
)?)?;
let tx_hash =
Hash::from_str(&deploy_output.txhash).expect("Invalid hex string for transaction hash");
let res = block_tx_commit(&tmrpc_client, tx_hash).await?;
let log: Vec<Log> = serde_json::from_str(&res.tx_result.log)?;
let contract_addr: &String = &log[0].events[1].attributes[0].value;
println!("\n🚀 Successfully deployed and instantiated contract!");
println!("🆔 Code ID: {}", code_id);
println!("📌 Contract Address: {}", contract_addr);
println!("{contract_addr}");
Ok(())
}
//RES=$($CMD tx wasm instantiate "$CODE_ID" "$INSTANTIATE_MSG" --from "$USER_ADDR" --label $LABEL $TXFLAG -y --no-admin --output json)

View file

@ -1,229 +0,0 @@
use std::{env, env::current_dir, fs::File, io::Read, path::Path, str::FromStr};
use anyhow::anyhow;
use clap::Parser;
use cosmrs::tendermint::chain::Id as ChainId; // TODO see if this redundancy in dependencies can be decreased
use cosmrs::AccountId;
use cw_tee_mtcs::msg::ExecuteMsg as MtcsExecuteMsg;
use cycles_sync::wasmd_client::{CliWasmdClient, WasmdClient};
use futures_util::stream::StreamExt;
use quartz_common::contract::prelude::QuartzExecuteMsg;
use reqwest::Url;
use scripts::{
types::WasmdTxResponse,
utils::{block_tx_commit, run_relay, wasmaddr_to_id},
};
use serde::Serialize;
use serde_json::json;
use tendermint::{block::Height, Hash};
use tendermint_rpc::{query::EventType, HttpClient, SubscriptionClient, WebSocketClient};
use tm_prover::{config::Config as TmProverConfig, prover::prove};
#[derive(Serialize)]
struct Message<'a> {
message: &'a str,
}
#[derive(Clone, Debug, Parser)]
#[command(version, about, long_about = None)]
struct Cli {
/// Contract to listen to
#[arg(short, long, value_parser = wasmaddr_to_id)]
contract: AccountId,
/// Port enclave is listening on
#[arg(short, long, default_value = "11090")]
port: u16,
#[arg(
short,
long,
default_value = "wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70"
)]
sender: String,
#[clap(long, default_value = "143.244.186.205:26657")]
node_url: String,
#[clap(long, default_value_t = default_rpc_addr())]
rpc_addr: String,
}
fn default_rpc_addr() -> String {
env::var("RPC_URL").unwrap_or_else(|_| "http://127.0.0.1".to_string())
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let cli = Cli::parse();
// Convert contract address string parameter to an AccountId
// TODO: is this all the address validation that's needed?
let httpurl = Url::parse(&format!("http://{}", cli.node_url))?;
let wsurl = format!("ws://{}/websocket", cli.node_url);
let tmrpc_client = HttpClient::new(httpurl.as_str()).unwrap();
let wasmd_client = CliWasmdClient::new(Url::parse(httpurl.as_str())?);
// test(&client, &wasmd_client).await?;
// panic!();
// read trusted hash and height from files
let base_path = current_dir()?.join("../../../");
let trusted_files_path = base_path.join("quartz-app/");
let (trusted_height, trusted_hash) = read_hash_height(trusted_files_path.as_path()).await?;
// run sessioncreate in relayer script
// export EXECUTE_CREATE=$(./scripts/relay.sh SessionCreate)
// TODO: this is not the right return type
let res: MtcsExecuteMsg = run_relay(base_path.as_path(), "SessionCreate", None)?; // need to define the return type
// submit SessionCreate to contract
// RES=$($CMD tx wasm execute "$CONTRACT" "$EXECUTE_CREATE" --from admin --chain-id testing -y --output json)
// TX_HASH=$(echo $RES | jq -r '.["txhash"]')
// make sure this is json
let output: WasmdTxResponse = serde_json::from_str(
wasmd_client
.tx_execute(
&cli.contract.clone(),
&ChainId::from_str("testing")?,
2000000,
&cli.sender,
json!(res),
)?
.as_str(),
)?;
println!("\n\n SessionCreate tx output: {:?}", output);
// wait for tx to commit (in a loop?)
let tx_hash = Hash::from_str(&output.txhash).expect("Invalid hex string for transaction hash");
block_tx_commit(&tmrpc_client, tx_hash).await?;
// tendermint client subscription loop
// wait 2 blocks
two_block_waitoor(&wsurl).await?;
//cd $ROOT/cycles-protocol/packages/tm-prover
//export PROOF_FILE="light-client-proof.json"
// TODO: move all the proof related files into a directory in scripts dir
let proof_path = current_dir()?.join("../../../packages/tm-prover/light-client-proof.json");
println!("Proof path: {:?}", proof_path.to_str());
let config = TmProverConfig {
primary: httpurl.as_str().parse()?,
witnesses: httpurl.as_str().parse()?,
trusted_height,
trusted_hash,
trace_file: Some(proof_path.clone()),
verbose: "1".parse()?,
contract_address: cli.contract.clone(),
storage_key: "quartz_session".to_string(),
..Default::default()
};
if let Err(report) = prove(config).await {
return Err(anyhow!("Tendermint prover failed. Report: {}", report));
}
// read proof file
let proof = read_file(proof_path.as_path()).await?;
let json_msg = serde_json::to_string(&Message { message: &proof })?;
// execute SessionSetPubKey on enclave
// cd $ROOT/cycles-protocol/packages/relayer
// export EXECUTE_SETPUB=$(./scripts/relay.sh SessionSetPubKey "$POP_MSG")
let res: MtcsExecuteMsg = run_relay(
base_path.as_path(),
"SessionSetPubKey",
Some(json_msg.as_str()),
)?;
// submit SessionSetPubKey to contract
// RES=$($CMD tx wasm execute "$CONTRACT" "$EXECUTE_SETPUB" --from admin --chain-id testing -y --output json)
// TX_HASH=$(echo $RES | jq -r '.["txhash"]')
// wait for tx to commit
let output: WasmdTxResponse = serde_json::from_str(
wasmd_client
.tx_execute(
&cli.contract.clone(),
&ChainId::from_str("testing")?,
2000000,
&cli.sender,
json!(res),
)?
.as_str(),
)?;
println!("\n\n SessionSetPubKey tx output: {:?}", output);
// wait for tx to commit (in a loop?)
let tx_hash = Hash::from_str(&output.txhash).expect("Invalid hex string for transaction hash");
block_tx_commit(&tmrpc_client, tx_hash).await?;
if let MtcsExecuteMsg::Quartz(QuartzExecuteMsg::RawSessionSetPubKey(quartz)) = res {
println!("\n\n\n{}", quartz.msg.pub_key()); // TODO: return this instead later
} else {
return Err(anyhow!("Invalid relay response from SessionSetPubKey"));
}
// query results
Ok(())
}
async fn two_block_waitoor(wsurl: &str) -> Result<(), anyhow::Error> {
let (client, driver) = WebSocketClient::new(wsurl).await.unwrap();
let driver_handle = tokio::spawn(async move { driver.run().await });
// Subscription functionality
let mut subs = client.subscribe(EventType::NewBlock.into()).await.unwrap();
// Wait 2 NewBlock events
let mut ev_count = 5_i32;
while let Some(res) = subs.next().await {
let ev = res.unwrap();
println!("Got event: {:?}", ev);
ev_count -= 1;
if ev_count < 0 {
break;
}
}
// Signal to the driver to terminate.
client.close().unwrap();
// Await the driver's termination to ensure proper connection closure.
let _ = driver_handle.await.unwrap();
Ok(())
}
async fn read_hash_height(base_path: &Path) -> Result<(Height, Hash), anyhow::Error> {
let height_path = base_path.join("trusted.height");
let trusted_height: Height = read_file(height_path.as_path()).await?.parse()?;
let hash_path = base_path.join("trusted.hash");
let trusted_hash: Hash = read_file(hash_path.as_path()).await?.parse()?;
Ok((trusted_height, trusted_hash))
}
async fn read_file(path: &Path) -> Result<String, anyhow::Error> {
// Open the file
let mut file = match File::open(path) {
Ok(file) => file,
Err(e) => {
return Err(anyhow!(format!("Error opening file {:?}: {:?}", path, e)));
}
};
// Read the file contents into a string
let mut value = String::new();
if let Err(e) = file.read_to_string(&mut value) {
return Err(anyhow!(format!("Error reading file {:?}: {:?}", file, e)));
}
Ok(value.trim().to_owned())
}

View file

@ -1,239 +0,0 @@
use std::{collections::BTreeMap, env, process::Command, str::FromStr};
use anyhow::anyhow;
use base64::prelude::*;
use clap::Parser;
use cosmrs::{tendermint::chain::Id as ChainId, AccountId};
use cosmwasm_std::{Binary, HexBinary, Uint64};
use cw_tee_mtcs::msg::{
execute::SubmitSetoffsMsg, AttestedMsg, ExecuteMsg, GetLiquiditySourcesResponse,
QueryMsg::GetLiquiditySources,
};
use cycles_sync::wasmd_client::{CliWasmdClient, QueryResult, WasmdClient};
use futures_util::stream::StreamExt;
use mtcs_enclave::{
proto::{clearing_client::ClearingClient, RunClearingRequest},
types::RunClearingMessage,
};
use quartz_common::contract::msg::execute::attested::{
EpidAttestation, RawAttested, RawAttestedMsgSansHandler, RawEpidAttestation,
};
use quartz_tee_ra::{intel_sgx::epid::types::ReportBody, IASReport};
use reqwest::Url;
use scripts::utils::wasmaddr_to_id;
use serde_json::json;
use tendermint_rpc::{
query::{EventType, Query},
SubscriptionClient, WebSocketClient,
};
use tokio::{
fs::{self, File},
io::AsyncWriteExt,
};
use tonic::Request;
#[derive(Clone, Debug, Parser)]
#[command(version, about, long_about = None)]
struct Cli {
/// Contract to listen to
#[arg(short, long, value_parser = wasmaddr_to_id)]
contract: AccountId,
/// Port enclave is listening on
#[arg(short, long, default_value = "11090")]
port: u16,
#[arg(
short,
long,
default_value = "wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70"
)]
sender: String,
#[clap(long, default_value = "143.244.186.205:26657")]
node_url: String,
#[clap(long, default_value_t = default_rpc_addr())]
rpc_addr: String,
#[arg(short, long, default_value = "dangush")]
user: String, // The filesys user for gramine filepaths. TODO: improve this
}
fn default_rpc_addr() -> String {
env::var("RPC_URL").unwrap_or_else(|_| "http://127.0.0.1".to_string())
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let cli = Cli::parse();
// Subscribe to "init_clearing" events
let wsurl = format!("ws://{}/websocket", cli.node_url);
let (client, driver) = WebSocketClient::new(wsurl.as_str()).await.unwrap();
let driver_handle = tokio::spawn(async move { driver.run().await });
let mut subs = client
.subscribe(Query::from(EventType::Tx).and_contains("wasm.action", "init_clearing"))
.await
.unwrap();
while subs.next().await.is_some() {
// On init_clearing, run process
if let Err(e) = handler(
&cli.contract,
cli.sender.clone(),
format!("{}:{}", cli.rpc_addr, cli.port),
&cli.node_url,
&cli.user,
)
.await
{
println!("{}", e);
}
}
// Close connection
// Await the driver's termination to ensure proper connection closure.
client.close().unwrap();
let _ = driver_handle.await.unwrap();
Ok(())
}
async fn handler(
contract: &AccountId,
sender: String,
rpc_addr: String,
node_url: &str,
user: &str,
) -> Result<(), anyhow::Error> {
let chain_id = &ChainId::from_str("testing")?;
let httpurl = Url::parse(&format!("http://{}", node_url))?;
let wasmd_client = CliWasmdClient::new(httpurl);
// Query obligations and liquidity sources from chain
let clearing_contents = query_chain(&wasmd_client, contract).await?;
// Send queried data to enclave over gRPC
let request = Request::new(RunClearingRequest {
message: json!(clearing_contents).to_string(),
});
let mut client = ClearingClient::connect(rpc_addr).await?;
let clearing_response = client
.run(request)
.await
.map_err(|e| anyhow!("Failed to communicate to relayer. {e}"))?
.into_inner();
// Extract json from the Protobuf message
let quote: RawAttested<SubmitSetoffsMsg, Vec<u8>> =
serde_json::from_str(&clearing_response.message)
.map_err(|e| anyhow!("Error serializing SubmitSetoffs: {}", e))?;
// Get IAS report and build attested message
let attestation = gramine_ias_request(quote.attestation, user).await?;
let msg = RawAttestedMsgSansHandler(quote.msg);
let setoffs_msg = ExecuteMsg::SubmitSetoffs::<RawEpidAttestation>(AttestedMsg {
msg,
attestation: attestation.into(),
});
// Send setoffs to mtcs contract on chain
let output =
wasmd_client.tx_execute(contract, chain_id, 2000000, &sender, json!(setoffs_msg))?;
println!("output: {}", output);
Ok(())
}
// TODO: replace raw queries with smart
async fn query_chain(
wasmd_client: &CliWasmdClient,
contract: &AccountId,
) -> Result<RunClearingMessage, anyhow::Error> {
// Get epoch counter
let resp: QueryResult<String> = wasmd_client
.query_raw(contract, hex::encode("epoch_counter"))
.map_err(|e| anyhow!("Problem querying epoch: {}", e))?;
let mut epoch_counter: usize =
String::from_utf8(BASE64_STANDARD.decode(resp.data)?)?.parse::<usize>()?;
if epoch_counter > 1 {
epoch_counter -= 1;
}
// TODO: replace with tracer log here
// println!("epoch: {}", epoch_counter);
// Get obligations
let resp: QueryResult<String> = wasmd_client
.query_raw(
contract,
hex::encode(format!("{}/obligations", epoch_counter)),
)
.map_err(|e| anyhow!("Problem querying obligatons: {}", e))?;
let decoded_obligs = BASE64_STANDARD.decode(resp.data)?;
let obligations_map: BTreeMap<HexBinary, HexBinary> =
serde_json::from_slice(&decoded_obligs).unwrap_or_default();
// println!("obligations \n {:?}", obligations_map);
// TODO: replace with tracer log here
// Get liquidity sources
let resp: QueryResult<GetLiquiditySourcesResponse> = wasmd_client
.query_smart(
contract,
json!(GetLiquiditySources {
epoch: Some(Uint64::new(epoch_counter as u64))
}),
)
.map_err(|e| anyhow!("Problem querying liquidity sources: {}", e))?;
let liquidity_sources = resp.data.liquidity_sources;
// TODO: replace with tracer log here
// println!("liquidity_sources \n {:?}", liquidity_sources);
Ok(RunClearingMessage {
intents: obligations_map,
liquidity_sources: liquidity_sources.into_iter().collect(),
})
}
// Request the IAS report for EPID attestations
async fn gramine_ias_request(
attested_msg: Vec<u8>,
user: &str,
) -> Result<EpidAttestation, anyhow::Error> {
let ias_api_key = String::from("669244b3e6364b5888289a11d2a1726d");
let ra_client_spid = String::from("51CAF5A48B450D624AEFE3286D314894");
let quote_file = format!("/tmp/{}_test.quote", user);
let report_file = format!("/tmp/{}_datareport", user);
let report_sig_file = format!("/tmp/{}_datareportsig", user);
// Write the binary data to a file
let mut file = File::create(&quote_file).await?;
file.write_all(&attested_msg)
.await
.map_err(|e| anyhow!("Couldn't write to file. {e}"))?;
let mut gramine = Command::new("gramine-sgx-ias-request");
let command = gramine
.arg("report")
.args(["-g", &ra_client_spid])
.args(["-k", &ias_api_key])
.args(["-q", &quote_file])
.args(["-r", &report_file])
.args(["-s", &report_sig_file]);
let output = command.output()?;
if !output.status.success() {
return Err(anyhow!("Couldn't run gramine. {:?}", output));
}
let report: ReportBody = serde_json::from_str(&fs::read_to_string(report_file).await?)?;
let report_sig_str = fs::read_to_string(report_sig_file).await?.replace('\r', "");
let report_sig: Binary = Binary::from_base64(report_sig_str.trim())?;
Ok(EpidAttestation::new(IASReport { report, report_sig }))
}

View file

@ -1,3 +0,0 @@
//TODO: make an error.rs to differentiate errors in listen.rs
pub mod types;
pub mod utils;

View file

@ -1,39 +0,0 @@
use serde::{Deserialize, Serialize};
// Rust libraries don't seem to implement this type from the wasmd go implementation
// TODO: Replace String with types from Rust libraries
// TODO: Move this into WasmdClient
#[derive(Deserialize, Debug)]
pub struct WasmdTxResponse {
pub height: String,
pub txhash: String,
pub codespace: String,
pub code: u32,
pub data: String,
pub raw_log: String,
pub logs: Vec<serde_json::Value>,
pub info: String,
pub gas_wanted: String,
pub gas_used: String,
pub tx: Option<serde_json::Value>,
pub timestamp: String,
pub events: Vec<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Attribute {
pub key: String,
pub value: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Event {
pub attributes: Vec<Attribute>,
pub r#type: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Log {
pub events: Vec<Event>,
pub msg_index: u32,
}

View file

@ -1,81 +0,0 @@
use std::{path::Path, process::Command, time::Duration};
use anyhow::anyhow;
use cosmrs::AccountId;
use regex::Regex;
use serde::de::DeserializeOwned;
use subtle_encoding::bech32::decode as bech32_decode;
use tendermint::Hash;
use tendermint_rpc::{
endpoint::tx::Response as TmTxResponse, error::ErrorDetail, Client, HttpClient,
};
pub fn wasmaddr_to_id(address_str: &str) -> anyhow::Result<AccountId> {
let (hr, _) = bech32_decode(address_str).map_err(|e| anyhow!(e))?;
if hr != "wasm" {
return Err(anyhow!(hr));
}
Ok(address_str.parse().unwrap())
}
// TODO: move wrapping result with "quartz:" struct into here
pub fn run_relay<R: DeserializeOwned>(
base_path: &Path,
msg: &str,
arg: Option<&str>,
) -> Result<R, anyhow::Error> {
let relayer_path = base_path.join("packages/relayer/scripts/relay.sh");
let mut bash = Command::new("bash");
let command = bash.arg(relayer_path).arg(msg);
if let Some(arg) = arg {
command.arg(arg);
}
let output = command.output()?;
if !output.status.success() {
return Err(anyhow!("{:?}", output));
}
let query_result: R = serde_json::from_slice(&output.stdout)
.map_err(|e| anyhow!("Error deserializing: {}", e))?;
Ok(query_result)
}
// Note: time until tx commit is empiraclly 800ms on DO wasmd chain.
pub async fn block_tx_commit(client: &HttpClient, tx: Hash) -> Result<TmTxResponse, anyhow::Error> {
let re = Regex::new(r"tx \([A-F0-9]{64}\) not found").unwrap();
tokio::time::sleep(Duration::from_millis(400)).await;
loop {
match client.tx(tx, false).await {
Ok(resp) => {
return Ok(resp);
}
Err(e) => {
// If error, make sure it is only because of a not yet committed tx
match e.0 {
ErrorDetail::Response(subdetail) => {
if !re.is_match(subdetail.source.data().unwrap_or_default()) {
return Err(anyhow!(
"Error querying for tx: {}",
ErrorDetail::Response(subdetail)
));
} else {
println!("🔗 Waiting for tx commit... (+400ms)");
tokio::time::sleep(Duration::from_millis(400)).await;
continue;
}
}
_ => {
return Err(anyhow!("Error querying for tx: {}", e.0));
}
}
}
}
}
}

View file

@ -1,105 +0,0 @@
#!/bin/bash
#set -eo pipefail
DIR_QUARTZ=${ROOT:-$(git rev-parse --show-toplevel)}
DIR_QUARTZ_APP="$DIR_QUARTZ/apps/mtcs"
DIR_QUARTZ_ENCLAVE="$DIR_QUARTZ_APP/enclave"
DIR_QUARTZ_TM_PROVER="$DIR_QUARTZ/utils/tm-prover"
NODE_URL=${NODE_URL:-143.244.186.205:26657}
CMD="wasmd --node http://$NODE_URL"
echo "--------------------------------------------------------"
echo "set trusted hash"
cd "$DIR_QUARTZ_TM_PROVER"
# cargo run -- --chain-id testing \
# --primary "http://$NODE_URL" \
# --witnesses "http://$NODE_URL" \
# --trusted-height 1 \
# --trusted-hash "5237772462A41C0296ED688A0327B8A60DF310F08997AD760EB74A70D0176C27" \
# --contract-address "wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d" \
# --storage-key "quartz_session" \
# --trace-file light-client-proof.json &> $DIR_QUARTZ_APP/output
# # Debug output of cargo run
# echo "Cargo run output:"
# cat $DIR_QUARTZ_APP/output
# cd $DIR_QUARTZ_APP
# # Debug hash extraction
# echo "Attempting to extract trusted hash from output..."
# cat output | grep found | head -1 | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g' > trusted.hash
# # Check if the hash was extracted correctly
# if [[ ! -s trusted.hash ]]; then
# echo "Failed to extract trusted hash from output"
# exit 1
# fi
# export TRUSTED_HASH=$(cat trusted.hash)
# echo "Extracted TRUSTED_HASH: $TRUSTED_HASH"
# rm output
CHAIN_STATUS=$($CMD status)
TRUSTED_HASH=$(echo "$CHAIN_STATUS" | jq -r .SyncInfo.latest_block_hash)
TRUSTED_HEIGHT=$(echo "$CHAIN_STATUS" | jq -r .SyncInfo.latest_block_height)
echo "... $TRUSTED_HASH"
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
RUST_BACKTRACE=full ./target/release/mtcs-enclave --chain-id "testing" --trusted-height "$TRUSTED_HEIGHT" --trusted-hash "$TRUSTED_HASH"
exit
fi
echo "--------------------------------------------------------"
echo "configure gramine"
cd "$DIR_QUARTZ_ENCLAVE"
echo "... gen priv key if it doesnt exist"
gramine-sgx-gen-private-key > /dev/null 2>&1 || : # may fail
# echo "... update manifest template with trusted hash $TRUSTED_HASH"
# sed -i -r "s/(\"--trusted-hash\", \")[A-Z0-9]+(\"])/\1$TRUSTED_HASH\2/" quartz.manifest.template
echo "... create manifest"
gramine-manifest \
-Dlog_level="error" \
-Dhome="$HOME" \
-Darch_libdir="/lib/$(gcc -dumpmachine)" \
-Dra_type="epid" \
-Dra_client_spid="51CAF5A48B450D624AEFE3286D314894" \
-Dra_client_linkable=1 \
-Dquartz_dir="$(pwd)" \
-Dtrusted_height="$TRUSTED_HEIGHT" \
-Dtrusted_hash="$TRUSTED_HASH" \
quartz.manifest.template quartz.manifest
if [ $? -ne 0 ]; then
echo "gramine-manifest failed"
exit 1
fi
echo "... sign manifest"
gramine-sgx-sign --manifest quartz.manifest --output quartz.manifest.sgx
if [ $? -ne 0 ]; then
echo "gramine-sgx-sign failed"
exit 1
fi
echo "--------------------------------------------------------"
echo "... start gramine"
gramine-sgx ./quartz
if [ $? -ne 0 ]; then
echo "gramine-sgx failed to start"
exit 1
fi

View file

@ -1,128 +0,0 @@
ROOT=${ROOT:-$HOME}
DIR_QUARTZ="$ROOT/cycles-protocol"
DIR_QUARTZ_APP="$DIR_QUARTZ/quartz-app/contracts/cw-tee-mtcs"
DIR_QUARTZ_ENCLAVE="$DIR_QUARTZ/quartz-app/enclave"
DIR_QUARTZ_TM_PROVER="$DIR_QUARTZ/packages/tm-prover"
NODE_URL=${NODE_URL:-143.244.186.205:36657}
CMD="wasmd --node http://$NODE_URL"
echo "--------------------------------------------------------"
echo "set trusted hash"
cd "$DIR_QUARTZ_TM_PROVER"
cargo run -- --chain-id testing \
--primary "http://$NODE_URL" \
--witnesses "http://$NODE_URL" \
--trusted-height 500000 \
--trusted-hash "5237772462A41C0296ED688A0327B8A60DF310F08997AD760EB74A70D0176C27" \
--contract-address "wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d" \
--storage-key "quartz_session" \
--trace-file light-client-proof.json &> $DIR_QUARTZ_APP/output
cd $DIR_QUARTZ_APP
cat output | grep found | head -1 | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g' > trusted.hash
export TRUSTED_HASH=$(cat trusted.hash)
echo "... $TRUSTED_HASH"
rm output
echo "--------------------------------------------------------"
echo "configure gramine"
cd "$DIR_QUARTZ_ENCLAVE"
echo "... gen priv key if it doesnt exist"
gramine-sgx-gen-private-key > /dev/null 2>&1 || : # may fail
echo "... update manifest template with trusted hash $TRUSTED_HASH"
sed -i -r "s/(\"--trusted-hash\", \")[A-Z0-9]+(\"])/\1$TRUSTED_HASH\2/" quartz.manifest.template
echo "... create manifest"
gramine-manifest \
-Dlog_level="error" \
-Dhome="$HOME" \
-Darch_libdir="/lib/$(gcc -dumpmachine)" \
-Dra_type="epid" \
-Dra_client_spid="51CAF5A48B450D624AEFE3286D314894" \
-Dra_client_linkable=1 \
-Dquartz_dir="$(pwd)" \
-Dtrusted_height="$TRUSTED_HEIGHT" \
-Dtrusted_hash="$TRUSTED_HASH" \
quartz.manifest.template quartz.manifest
echo "... sign manifest"
gramine-sgx-sign --manifest quartz.manifest --output quartz.manifest.sgx
echo "--------------------------------------------------------"
echo "... start gramine"
gramine-sgx ./quartz
# #set -eo pipefail
# ROOT=${ROOT:-$HOME}
# DIR_QUARTZ="$ROOT/quartz-app"
# DIR_QUARTZ_APP="$DIR_QUARTZ/contracts/cw-tee-mtcs"
# DIR_QUARTZ_ENCLAVE="$DIR_QUARTZ/enclave"
# DIR_QUARTZ_TM_PROVER="$DIR_QUARTZ/packages/tm-prover"
# NODE_URL=${NODE_URL:-143.244.186.205:36657}
# CMD="wasmd --node http://$NODE_URL"
# echo "--------------------------------------------------------"
# echo "set trusted hash"
# cd "$DIR_QUARTZ_TM_PROVER"
# cargo run -- --chain-id testing \
# --primary "http://$NODE_URL" \
# --witnesses "http://$NODE_URL" \
# --trusted-height 500000 \
# --trusted-hash "5237772462A41C0296ED688A0327B8A60DF310F08997AD760EB74A70D0176C27" \
# --contract-address "wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d" \
# --storage-key "quartz_session" \
# --trace-file light-client-proof.json &> $DIR_QUARTZ_APP/output
# cd $DIR_QUARTZ_APP
# cat output | grep found | head -1 | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g' > trusted.hash
# export TRUSTED_HASH=$(cat trusted.hash)
# echo "... $TRUSTED_HASH"
# rm output
# echo "--------------------------------------------------------"
# echo "configure gramine"
# cd "$DIR_QUARTZ_ENCLAVE"
# echo "... gen priv key if it doesnt exist"
# gramine-sgx-gen-private-key > /dev/null 2>&1 || : # may fail
# echo "... update manifest template with trusted hash $TRUSTED_HASH"
# sed -i -r "s/(\"--trusted-hash\", \")[A-Z0-9]+(\"])/\1$TRUSTED_HASH\2/" quartz.manifest.template
# echo "... create manifest"
# gramine-manifest \
# -Dlog_level="error" \
# -Dhome="$HOME" \
# -Darch_libdir="/lib/$(gcc -dumpmachine)" \
# -Dra_type="epid" \
# -Dra_client_spid="51CAF5A48B450D624AEFE3286D314894" \
# -Dra_client_linkable=1 \
# -Dquartz_dir="$(pwd)" \
# -Dtrusted_height="$TRUSTED_HEIGHT" \
# -Dtrusted_hash="$TRUSTED_HASH" \
# quartz.manifest.template quartz.manifest
# echo "... sign manifest"
# gramine-sgx-sign --manifest quartz.manifest --output quartz.manifest.sgx
# echo "--------------------------------------------------------"
# echo "... start gramine"
# gramine-sgx ./quartz

View file

@ -1,40 +0,0 @@
OVERDRAFT=wasm1huhuswjxfydydxvdadqqsaet2p72wshtmr72yzx09zxncxtndf2sqs24hk
CMD='wasmd --node http://$NODE_URL'
# users
ALICE=wasm124tuy67a9dcvfgcr4gjmz60syd8ddaugl33v0n
BOB=wasm1ctkqmg45u85jnf5ur9796h7ze4hj6ep5y7m7l6
# query alice
$CMD query wasm contract-state smart $OVERDRAFT '{"balance": {"user": "'$ALICE'"}}'
# query bob
$CMD query wasm contract-state smart $OVERDRAFT '{"balance": {"user": "'$BOB'"}}'
# make obligation from alice to bob for 10
# $CMD tx wasm execute $CONTRACT '{"submit_obligation_msg": {"ciphertext": "", "digest": ""}}' --from $CONTRACT --chain-id testing
# make bob acceptance to overdraft for 10
# make alice tender from overdraft for 10
# init clearing
$CMD tx wasm execute $CONTRACT '"init_clearing"' --from $CONTRACT --chain-id testing
# wait for 2 sec
sleep 2
# query alice
$CMD query wasm contract-state smart $OVERDRAFT '{"balance": {"user": "'$ALICE'"}}'
# query bob
$CMD query wasm contract-state smart $OVERDRAFT '{"balance": {"user": "'$BOB'"}}'

View file

@ -1,24 +0,0 @@
#!/bin/bash
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 $FEATURES
echo "--------------------------------------------------------"
echo "building cosmwasm contract binary"
cd $ROOT/cycles-quartz/apps/transfers/contracts
bash build.sh $FEATURES

View file

@ -1,24 +0,0 @@
#!/bin/bash
set -eo pipefail
ROOT=${ROOT:-$(git rev-parse --show-toplevel)}
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/apps/transfers/enclave
CARGO_TARGET_DIR=./target cargo build --release $FEATURES
echo "--------------------------------------------------------"
echo "building cosmwasm contract binary"
cd $ROOT/apps/transfers/contracts
bash build.sh $FEATURES

View file

@ -1,50 +0,0 @@
#!/bin/bash
# Check if an encrypted balance is provided
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <encrypted_balance_hex>"
exit 1
fi
ENCRYPTED_BALANCE=$1
# Check if eciespy is installed
if ! pip list 2>/dev/null | grep -q eciespy; then
echo "eciespy is not installed. Installing now..."
pip install eciespy >/dev/null 2>&1
fi
# Extract the private key from wasmd
EPHEMERAL_PRIVKEY=$( yes | wasmd keys export ephemeral_user --unsafe --unarmored-hex)
if [ $? -ne 0 ]; then
echo "Failed to export private key. Make sure 'ephemeral_user' exists and you've entered the correct password."
exit 1
fi
# Create a temporary Python script for decryption
TEMP_PYTHON_SCRIPT=$(mktemp)
cat << EOF > "$TEMP_PYTHON_SCRIPT"
from ecies import decrypt
import binascii
import sys
private_key = bytes.fromhex(sys.argv[1])
encrypted = binascii.unhexlify(sys.argv[2])
try:
decrypted = decrypt(private_key, encrypted)
print(decrypted.decode())
except Exception as e:
print(f"Decryption failed: {str(e)}")
EOF
# Run the Python script to decrypt
DECRYPTED=$(python3 "$TEMP_PYTHON_SCRIPT" "$EPHEMERAL_PRIVKEY" "$ENCRYPTED_BALANCE")
echo "---------------------------------------------------------"
echo "Decrypted result:"
echo "$DECRYPTED"
# Clean up
rm "$TEMP_PYTHON_SCRIPT"

View file

@ -1,24 +0,0 @@
#!/bin/bash
set -eo pipefail
ROOT=${ROOT:-$HOME}
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_contract.wasm 2>&1 | tee output
export CONTRACT=$(cat output | grep Address | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g')
echo $CONTRACT

View file

@ -1,60 +0,0 @@
#!/bin/bash
set -eo pipefail
ROOT=${ROOT:-$(git rev-parse --show-toplevel)}
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Function to print colored and formatted messages
print_message() {
local color=$1
local message=$2
echo -e "${color}${BOLD}${message}${NC}"
}
# Function to print section headers
print_header() {
local message=$1
echo -e "\n${MAGENTA}${BOLD}======== $message ========${NC}\n"
}
# Function to print success messages
print_success() {
local message=$1
echo -e "${GREEN}${BOLD}$message${NC}"
}
# Function to print error messages
print_error() {
local message=$1
echo -e "${RED}${BOLD}❌ Error: $message${NC}"
exit 1
}
# Function to print waiting messages
print_waiting() {
local message=$1
echo -e "${YELLOW}${BOLD}$message${NC}"
}
print_header "Instantianting relayer"
print_success "Relayer instantiated successfully."
cd $ROOT/relayer/
INSTANTIATE_MSG=$(./scripts/relay.sh Instantiate | jq -c '' )
cd $ROOT/apps/transfers/contracts/
bash deploy-contract-Neutrond.sh target/wasm32-unknown-unknown/release/transfers_contract.wasm "$INSTANTIATE_MSG" | tee output
export CONTRACT=$(cat output | grep Address | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g')

View file

@ -1,119 +0,0 @@
#!/bin/bash
#
# Perform the SessionCreate and SessionSetPubKey handshake between the contract and the sgx node
# Expects:
# - enclave is already initialized
# - contract is already deployed
# - apps/transfers/trusted.hash exists
#
set -eo pipefail
ROOT=${ROOT:-$HOME}
NODE_URL=${NODE_URL:-127.0.0.1:26657}
if [ "$#" -eq 0 ]; then
echo "Usage: $0 <contract_address>"
exit 1 # Exit with a non-zero status to indicate an error
fi
CONTRACT="$1"
CMD="wasmd --node http://$NODE_URL"
cd "$ROOT/cycles-quartz/apps/transfers"
export TRUSTED_HASH=$(cat trusted.hash)
export TRUSTED_HEIGHT=$(cat trusted.height)
echo "using CMD: $CMD"
echo "--------------------------------------------------------"
echo "create session"
# change to relay dir
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)
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 $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 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
done
# need to wait another block for light client proof
BLOCK_HEIGHT=$($CMD query block | jq .block.header.height)
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
done
echo "--------------------------------------------------------"
echo "set session pk"
# change to prover dir
cd $ROOT/cycles-quartz/utils/tm-prover
export PROOF_FILE="light-client-proof.json"
if [ -f "$PROOF_FILE" ]; then
rm "$PROOF_FILE"
echo "removed old $PROOF_FILE"
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 -- --chain-id testing \
--primary "http://$NODE_URL" \
--witnesses "http://$NODE_URL" \
--trusted-height $TRUSTED_HEIGHT \
--trusted-hash $TRUSTED_HASH \
--contract-address $CONTRACT \
--storage-key "quartz_session" \
--trace-file $PROOF_FILE
export POP=$(cat $PROOF_FILE)
export POP_MSG=$(jq -nc --arg message "$POP" '$ARGS.named')
# execute SessionSetPubKey on enclave
cd $ROOT/cycles-quartz/relayer
export EXECUTE_SETPUB=$(./scripts/relay.sh SessionSetPubKey "$POP_MSG")
RES=$($CMD tx wasm execute "$CONTRACT" "$EXECUTE_SETPUB" --from admin --chain-id testing -y --output json)
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 $TX_HASH"
sleep 1
done
echo "--------------------------------------------------------"
echo "check session success"
export NONCE_AND_KEY=$($CMD query wasm contract-state raw "$CONTRACT" $(printf '%s' "quartz_session" | hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
echo $NONCE_AND_KEY
export PUBKEY=$(echo $NONCE_AND_KEY | jq -r .pub_key)

View file

@ -1,171 +0,0 @@
#!/bin/bash
ROOT=${ROOT:-$HOME}
DEFAULT_NODE="127.0.0.1:26657"
NODE_URL=${NODE_URL:-$DEFAULT_NODE}
# Use the QUARTZ_PORT environment variable if set, otherwise default to 11090
QUARTZ_PORT="${QUARTZ_PORT:-11090}"
if [ "$#" -eq 0 ]; then
echo "Usage: $0 <contract_address>"
exit 1 # Exit with a non-zero status to indicate an error
fi
CONTRACT=$1
CMD="wasmd --node http://$NODE_URL"
WSURL="ws://$NODE_URL/websocket"
SUBSCRIBE_TRANSFER="{\"jsonrpc\":\"2.0\",\"method\":\"subscribe\",\"params\":[\"execute._contract_address = '$CONTRACT' AND wasm-transfer.action = 'user'\"],\"id\":1}"
SUBSCRIBE_QUERY="{\"jsonrpc\":\"2.0\",\"method\":\"subscribe\",\"params\":[\"execute._contract_address = '$CONTRACT' AND wasm-query_balance.query = 'user'\"],\"id\":2}"
# Attestation constants
IAS_API_KEY="669244b3e6364b5888289a11d2a1726d"
RA_CLIENT_SPID="51CAF5A48B450D624AEFE3286D314894"
QUOTE_FILE="/tmp/${USER}_test.quote"
REPORT_FILE="/tmp/${USER}_datareport"
REPORT_SIG_FILE="/tmp/${USER}_datareportsig"
# cat keeps the stdin open so websocat doesnt close
(echo "$SUBSCRIBE_TRANSFER"; echo "$SUBSCRIBE_QUERY"; cat) | websocat $WSURL | while read msg; do
if [[ "$msg" == '{"jsonrpc":"2.0","id":1,"result":{}}' ]] || \
[[ "$msg" == '{"jsonrpc":"2.0","id":2,"result":{}}' ]]; then
echo "---------------------------------------------------------"
echo "... subscribed to $msg"
echo "... waiting for event"
continue
fi
CLEAN_MSG=$(echo "$msg" | sed 's/"log":"\[.*\]"/"log":"<invalid_json>"/' | jq '.result.events')
if echo "$CLEAN_MSG" | grep -q 'wasm-transfer'; then
echo "---------------------------------------------------------"
echo "... received wasm-transfer event!"
current_height=$($CMD status | jq -r .SyncInfo.latest_block_height)
next_height=$((current_height + 1))
while [ "$($CMD status 2>&1 | jq -r .SyncInfo.latest_block_height)" -lt "$next_height" ]; do
echo "waiting for next block"
sleep 1
done
echo "... fetching requests"
REQUESTS=$($CMD query wasm contract-state raw $CONTRACT $(printf '%s' "requests" | \
hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
STATE=$($CMD query wasm contract-state raw $CONTRACT $(printf '%s' "state" | \
hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
cd "$ROOT/cycles-quartz/apps/transfers"
export TRUSTED_HASH=$(cat trusted.hash)
export TRUSTED_HEIGHT=$(cat trusted.height)
cd $ROOT/cycles-quartz/utils/tm-prover
export PROOF_FILE="light-client-proof.json"
if [ -f "$PROOF_FILE" ]; then
rm "$PROOF_FILE"
echo "removed old $PROOF_FILE"
fi
echo "trusted hash $TRUSTED_HASH"
echo "trusted hash $TRUSTED_HEIGHT"
echo "contract $CONTRACT"
# run prover to get light client proof
cargo run -- --chain-id testing \
--primary "http://$NODE_URL" \
--witnesses "http://$NODE_URL" \
--trusted-height $TRUSTED_HEIGHT \
--trusted-hash $TRUSTED_HASH \
--contract-address $CONTRACT \
--storage-key "requests" \
--trace-file $PROOF_FILE
export POP=$(cat $PROOF_FILE)
export ENCLAVE_REQUEST=$(jq -nc --argjson requests "$REQUESTS" --argjson state $STATE '$ARGS.named')
export REQUEST_MSG=$(jq --argjson msg "$ENCLAVE_REQUEST" '. + {msg: $msg}' <<< "$POP")
export PROTO_MSG=$(jq -nc --arg message "$REQUEST_MSG" '$ARGS.named')
cd $ROOT/cycles-quartz/apps/transfers/enclave
echo "... executing transfer"
export ATTESTED_MSG=$(grpcurl -plaintext -import-path ./proto/ -proto transfers.proto \
-d "$PROTO_MSG" "127.0.0.1:$QUARTZ_PORT" transfers.Settlement/Run | \
jq .message | jq -R 'fromjson | fromjson' | jq -c)
QUOTE=$(echo "$ATTESTED_MSG" | jq -c '.attestation')
MSG=$(echo "$ATTESTED_MSG" | jq -c '.msg')
if [ -n "$MOCK_SGX" ]; then
echo "... running in MOCK_SGX mode"
EXECUTE=$(jq -nc --argjson update "$(jq -nc --argjson msg "$MSG" \
--argjson attestation "$QUOTE" '$ARGS.named')" '$ARGS.named')
else
echo "... getting report"
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
REPORT=$(cat "$REPORT_FILE")
REPORTSIG=$(cat "$REPORT_SIG_FILE" | tr -d '\r')
EXECUTE=$(jq -nc --argjson update "$(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')
fi
echo "... submitting update"
echo $EXECUTE | jq '.'
$CMD tx wasm execute "$CONTRACT" "$EXECUTE" --from admin --chain-id testing -y --gas 2000000
echo " ... done"
echo "---------------------------------------------------------"
echo "... waiting for event"
elif echo "$CLEAN_MSG" | grep -q 'wasm-query_balance'; then
echo "... received wasm-query_balance event!"
echo "... fetching state"
STATE=$($CMD query wasm contract-state raw $CONTRACT $(printf '%s' "state" | \
hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
ADDRESS=$(echo "$msg" | sed 's/"log":"\[.*\]"/"log":"<invalid_json>"/' | \
jq -r '.result.events["message.sender"]'[0])
EPHEMERAL_PUBKEY=$(echo "$msg" | sed 's/"log":"\[.*\]"/"log":"<invalid_json>"/' | \
jq -r '.result.events["wasm-query_balance.emphemeral_pubkey"]'[0])
export ENCLAVE_REQUEST=$(jq -nc --argjson state "$STATE" --arg address "$ADDRESS" \
--arg ephemeral_pubkey "$EPHEMERAL_PUBKEY" '$ARGS.named')
export REQUEST_MSG=$(jq -nc --arg message "$ENCLAVE_REQUEST" '$ARGS.named')
cd $ROOT/cycles-quartz/apps/transfers/enclave
echo "... executing query balance"
ATTESTED_MSG=$(grpcurl -plaintext -import-path ./proto/ -proto transfers.proto \
-d "$REQUEST_MSG" "127.0.0.1:$QUARTZ_PORT" transfers.Settlement/Query | jq -r '.message | fromjson')
QUOTE=$(echo "$ATTESTED_MSG" | jq -c '.attestation')
MSG=$(echo "$ATTESTED_MSG" | jq -c '.msg')
QUERY_RESPONSE_MSG=$(jq -n --arg address "$ADDRESS" --argjson msg "$MSG" \
'{address: $address, encrypted_bal: $msg.encrypted_bal}')
if [ -n "$MOCK_SGX" ]; then
echo "... running in MOCK_SGX mode"
EXECUTE=$(jq -nc --argjson query_response "$(jq -nc --argjson msg "$QUERY_RESPONSE_MSG" \
--argjson attestation "$QUOTE" '$ARGS.named')" '{query_response: $query_response}')
else
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
REPORT=$(cat "$REPORT_FILE")
REPORTSIG=$(cat "$REPORT_SIG_FILE" | tr -d '\r')
EXECUTE=$(jq -nc --argjson query_response "$(jq -nc --argjson msg "$QUERY_RESPONSE_MSG" \
--argjson attestation "$(jq -nc --argjson report "$(jq -nc --argjson report "$REPORT" \
--arg reportsig "$REPORTSIG" '$ARGS.named')" '$ARGS.named')" '$ARGS.named')" \
'{query_response: $query_response}')
fi
echo "... submitting update"
echo $EXECUTE | jq '.'
$CMD tx wasm execute "$CONTRACT" "$EXECUTE" --from admin --chain-id testing -y --gas 2000000
echo " ... done"
echo "------------------------------------"
echo "... waiting for event"
fi
done

View file

@ -1,233 +0,0 @@
#!/bin/bash
set -eo pipefail
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Function to print colored and formatted messages
print_message() {
local color=$1
local message=$2
echo -e "${color}${BOLD}${message}${NC}"
}
# Function to print section headers
print_header() {
local message=$1
echo -e "\n${MAGENTA}${BOLD}======== $message ========${NC}\n"
}
# Function to print success messages
print_success() {
local message=$1
echo -e "${GREEN}${BOLD}$message${NC}"
}
# Function to print error messages
print_error() {
local message=$1
echo -e "${RED}${BOLD}❌ Error: $message${NC}" >&2
}
# Configuration
DEFAULT_NODE="127.0.0.1:26657"
NODE_URL=${NODE_URL:-$DEFAULT_NODE}
QUARTZ_PORT="${QUARTZ_PORT:-11090}"
if [ "$#" -eq 0 ]; then
echo "Usage: $0 <contract_address>"
exit 1
fi
CONTRACT=$1
CMD="neutrond --node http://$NODE_URL"
WSURL="ws://$NODE_URL/websocket"
ROOT=${ROOT:-$(git rev-parse --show-toplevel)}
WASMD_HOME=${WASMD_HOME:-"$HOME/.neutrond"}
CHAIN_ID=${CHAIN_ID:-test-1}
TXFLAG="--chain-id ${CHAIN_ID} --gas-prices 0.0025untrn --gas auto --gas-adjustment 1.3"
USER_ADDR=$(neutrond keys show -a "val1" --keyring-backend test --home "$WASMD_HOME" --keyring-dir "$WASMD_HOME")
# Subscription queries
SUBSCRIBE_TRANSFER="{\"jsonrpc\":\"2.0\",\"method\": \"subscribe\" ,\"params\":{\"query\":\"execute._contract_address = '$CONTRACT' AND wasm-transfer.action = 'user'\"},\"id\":2}"
SUBSCRIBE_QUERY="{\"jsonrpc\":\"2.0\",\"method\": \"subscribe\" ,\"params\":{\"query\":\"execute._contract_address = '$CONTRACT' AND wasm-query_balance.query = 'user'\"},\"id\":3}"
# Attestation constants
IAS_API_KEY="669244b3e6364b5888289a11d2a1726d"
RA_CLIENT_SPID="51CAF5A48B450D624AEFE3286D314894"
QUOTE_FILE="/tmp/${USER}_test.quote"
REPORT_FILE="/tmp/${USER}_datareport"
REPORT_SIG_FILE="/tmp/${USER}_datareportsig"
process_json() {
local json_input="$1"
local result
result=$(echo "$json_input" | jq -r '.result // empty' 2>&1) || {
echo "Error parsing JSON: $result" >&2
echo "No relevant wasm events found"
return
}
echo "$result"
}
wait_for_next_block() {
local current_height=$($CMD status | jq -r .sync_info.latest_block_height)
local next_height=$((current_height + 1))
while [ "$($CMD status 2>&1 | jq -r .sync_info.latest_block_height)" -lt "$next_height" ]; do
echo "Waiting for next block..."
sleep 1
done
}
handle_wasm_transfer() {
print_header "Received wasm-transfer event"
echo "Debug: Entering handle_wasm_transfer function"
wait_for_next_block
echo "Fetching requests and state..."
REQUESTS=$($CMD query wasm contract-state raw $CONTRACT $(printf '%s' "requests" | hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
STATE=$($CMD query wasm contract-state raw $CONTRACT $(printf '%s' "state" | hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
cd "$ROOT/apps/transfers"
export TRUSTED_HASH=$(cat trusted.hash)
export TRUSTED_HEIGHT=$(cat trusted.height)
cd $ROOT/utils/tm-prover
export PROOF_FILE="light-client-proof.json"
[ -f "$PROOF_FILE" ] && rm "$PROOF_FILE" && echo "Removed old $PROOF_FILE"
echo "Trusted hash: $TRUSTED_HASH"
echo "Trusted height: $TRUSTED_HEIGHT"
echo "Contract: $CONTRACT"
echo "Running prover to get light client proof..."
cargo run -- --chain-id $CHAIN_ID \
--primary "http://$NODE_URL" \
--witnesses "http://$NODE_URL" \
--trusted-height $TRUSTED_HEIGHT \
--trusted-hash $TRUSTED_HASH \
--contract-address $CONTRACT \
--storage-key "requests" \
--trace-file $PROOF_FILE
export POP=$(cat $PROOF_FILE)
export ENCLAVE_REQUEST=$(jq -nc --argjson requests "$REQUESTS" --argjson state $STATE '$ARGS.named')
export REQUEST_MSG=$(jq --argjson msg "$ENCLAVE_REQUEST" '. + {msg: $msg}' <<< "$POP")
export PROTO_MSG=$(jq -nc --arg message "$REQUEST_MSG" '$ARGS.named')
cd $ROOT/apps/transfers/enclave
echo "Executing transfer..."
ATTESTED_MSG=$(grpcurl -plaintext -import-path ./proto/ -proto transfers.proto \
-d "$PROTO_MSG" "127.0.0.1:$QUARTZ_PORT" transfers.Settlement/Run | \
jq .message | jq -R 'fromjson | fromjson' | jq -c)
QUOTE=$(echo "$ATTESTED_MSG" | jq -c '.attestation')
MSG=$(echo "$ATTESTED_MSG" | jq -c '.msg')
if [ -n "$MOCK_SGX" ]; then
echo "Running in MOCK_SGX mode"
EXECUTE=$(jq -nc --argjson update "$(jq -nc --argjson msg "$MSG" --argjson attestation "$QUOTE" '$ARGS.named')" '$ARGS.named')
else
echo "Getting report..."
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
REPORT=$(cat "$REPORT_FILE")
REPORTSIG=$(cat "$REPORT_SIG_FILE" | tr -d '\r')
EXECUTE=$(jq -nc --argjson update "$(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')
fi
echo "Submitting update..."
echo $EXECUTE | jq '.'
$CMD tx wasm execute "$CONTRACT" "$EXECUTE" --from "$USER_ADDR" $TXFLAG -y
print_success "Transfer executed"
}
handle_wasm_query_balance() {
print_header "Received wasm-query_balance event"
echo "Debug: Entering handle_wasm_query_balance function"
echo "Fetching state..."
STATE=$($CMD query wasm contract-state raw $CONTRACT $(printf '%s' "state" | hexdump -ve '/1 "%02X"') -o json | jq -r .data | base64 -d)
ADDRESS=$(echo "$1" | jq -r '.result.events["message.sender"][0]')
EPHEMERAL_PUBKEY=$(echo "$1" | jq -r '.result.events["wasm-query_balance.emphemeral_pubkey"][0]')
export ENCLAVE_REQUEST=$(jq -nc --argjson state "$STATE" --arg address "$ADDRESS" --arg ephemeral_pubkey "$EPHEMERAL_PUBKEY" '$ARGS.named')
export REQUEST_MSG=$(jq -nc --arg message "$ENCLAVE_REQUEST" '$ARGS.named')
cd $ROOT/apps/transfers/enclave
echo "Executing query balance..."
ATTESTED_MSG=$(grpcurl -plaintext -import-path ./proto/ -proto transfers.proto \
-d "$REQUEST_MSG" "127.0.0.1:$QUARTZ_PORT" transfers.Settlement/Query | jq -r '.message | fromjson')
QUOTE=$(echo "$ATTESTED_MSG" | jq -c '.attestation')
MSG=$(echo "$ATTESTED_MSG" | jq -c '.msg')
QUERY_RESPONSE_MSG=$(jq -n --arg address "$ADDRESS" --argjson msg "$MSG" '{address: $address, encrypted_bal: $msg.encrypted_bal}')
if [ -n "$MOCK_SGX" ]; then
echo "Running in MOCK_SGX mode"
EXECUTE=$(jq -nc --argjson query_response "$(jq -nc --argjson msg "$QUERY_RESPONSE_MSG" --argjson attestation "$QUOTE" '$ARGS.named')" '{query_response: $query_response}')
else
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
REPORT=$(cat "$REPORT_FILE")
REPORTSIG=$(cat "$REPORT_SIG_FILE" | tr -d '\r')
EXECUTE=$(jq -nc --argjson query_response "$(jq -nc --argjson msg "$QUERY_RESPONSE_MSG" \
--argjson attestation "$(jq -nc --argjson report "$(jq -nc --argjson report "$REPORT" \
--arg reportsig "$REPORTSIG" '$ARGS.named')" '$ARGS.named')" '$ARGS.named')" \
'{query_response: $query_response}')
fi
echo "Submitting update..."
echo $EXECUTE | jq '.'
$CMD tx wasm execute "$CONTRACT" "$EXECUTE" --from "$USER_ADDR" $TXFLAG -y
print_success "Query balance executed"
}
# Main loop
( echo "$SUBSCRIBE_TRANSFER"; echo "$SUBSCRIBE_QUERY"; cat) | websocat $WSURL | while read -r msg; do
EVENTS=$(process_json "$msg")
if [[ "$EVENTS" == "JSON parsing failed" ]]; then
print_error "Failed to parse JSON message. Skipping this message."
continue
fi
if [[ -z "$EVENTS" || "$EVENTS" == "No relevant wasm events found" ]]; then
if [[ "$msg" == *'"result":{}'* ]]; then
print_success "Subscribed to $msg"
print_message "$YELLOW" "Waiting for event..."
else
print_message "$YELLOW" "No relevant events found in message. Waiting for next event..."
fi
continue
fi
if echo "$EVENTS" | grep -q 'wasm-transfer'; then
handle_wasm_transfer
elif echo "$EVENTS" | grep -q 'wasm-query_balance'; then
handle_wasm_query_balance "$msg"
fi
print_message "$YELLOW" "Waiting for next event..."
done

View file

@ -1,66 +0,0 @@
#!/bin/bash
set -euo pipefail
DIR_QUARTZ=${ROOT:-$(git rev-parse --show-toplevel)}
DIR_QUARTZ_APP="$DIR_QUARTZ/apps/transfers"
DIR_QUARTZ_ENCLAVE="$DIR_QUARTZ_APP/enclave"
DIR_QUARTZ_TM_PROVER="$DIR_QUARTZ/utils/tm-prover"
NODE_URL=${NODE_URL:-127.0.0.1:26657}
CMD="wasmd --node http://$NODE_URL"
# Use the QUARTZ_PORT environment variable if set, otherwise default to 11090
QUARTZ_PORT="${QUARTZ_PORT:-11090}"
echo "--------------------------------------------------------"
echo "QUARTZ_PORT is set to: $QUARTZ_PORT"
echo "set trusted hash"
cd "$DIR_QUARTZ_TM_PROVER"
CHAIN_STATUS=$($CMD status)
TRUSTED_HASH=$(echo "$CHAIN_STATUS" | jq -r .SyncInfo.latest_block_hash)
TRUSTED_HEIGHT=$(echo "$CHAIN_STATUS" | jq -r .SyncInfo.latest_block_height)
echo "... $TRUSTED_HASH"
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
./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"
echo "... gen priv key if it doesnt exist"
gramine-sgx-gen-private-key > /dev/null 2>&1 || : # may fail
echo "... create manifest"
gramine-manifest \
-Dlog_level="error" \
-Dhome="${HOME}" \
-Denclave_dir="$(pwd)" \
-Denclave_executable="$(pwd)/target/release/quartz-app-transfers-enclave" \
-Darch_libdir="/lib/$(gcc -dumpmachine)" \
-Dra_type="epid" \
-Dra_client_spid="51CAF5A48B450D624AEFE3286D314894" \
-Dra_client_linkable=1 \
-Dtrusted_height="${TRUSTED_HEIGHT}" \
-Dtrusted_hash="${TRUSTED_HASH}" \
-Dgramine_port="${QUARTZ_PORT}" \
quartz.manifest.template quartz.manifest
echo "... sign manifest"
gramine-sgx-sign --manifest quartz.manifest --output quartz.manifest.sgx
echo "--------------------------------------------------------"
echo "... start gramine"
gramine-sgx ./quartz

View file

@ -1,96 +0,0 @@
#!/bin/bash
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Function to print colored and formatted messages
print_message() {
local color=$1
local message=$2
echo -e "${color}${BOLD}${message}${NC}"
}
# Function to print section headers
print_header() {
local message=$1
echo -e "\n${MAGENTA}${BOLD}======== $message ========${NC}\n"
}
# Function to print success messages
print_success() {
local message=$1
echo -e "${GREEN}${BOLD}$message${NC}"
}
# Function to print error messages
print_error() {
local message=$1
echo -e "${RED}${BOLD}❌ Error: $message${NC}" >&2
}
# Set up variables
ROOT=${ROOT:-$(git rev-parse --show-toplevel)}
DIR_QUARTZ_APP="$ROOT/apps/transfers"
DIR_QUARTZ_ENCLAVE="$DIR_QUARTZ_APP/enclave"
DIR_QUARTZ_TM_PROVER="$ROOT/utils/tm-prover"
NODE_URL=${NODE_URL:-127.0.0.1:26657}
CMD="neutrond --node http://$NODE_URL"
QUARTZ_PORT="${QUARTZ_PORT:-11090}"
print_header "Quartz Setup and Launch"
print_message $CYAN "QUARTZ_PORT is set to: $QUARTZ_PORT"
print_message $BLUE "Setting trusted hash and height"
CHAIN_STATUS=$($CMD status)
TRUSTED_HASH=$(echo "$CHAIN_STATUS" | jq -r .sync_info.latest_block_hash)
TRUSTED_HEIGHT=$(echo "$CHAIN_STATUS" | jq -r .sync_info.latest_block_height)
print_message $YELLOW "Trusted Hash: $TRUSTED_HASH"
print_message $YELLOW "Trusted Height: $TRUSTED_HEIGHT"
cd "$DIR_QUARTZ_APP"
echo "$TRUSTED_HASH" > trusted.hash
echo "$TRUSTED_HEIGHT" > trusted.height
print_success "Trusted hash and height saved"
if [ -n "$MOCK_SGX" ]; then
print_header "Running in MOCK_SGX mode"
cd $DIR_QUARTZ_ENCLAVE
print_message $BLUE "Running enclave without Gramine..."
./target/release/quartz-app-transfers-enclave --chain-id "test-1" --trusted-height "$TRUSTED_HEIGHT" --trusted-hash "$TRUSTED_HASH"
exit
fi
print_header "Configuring Gramine"
cd "$DIR_QUARTZ_ENCLAVE"
print_message $BLUE "Generating private key (if it doesn't exist)"
gramine-sgx-gen-private-key > /dev/null 2>&1 || :
print_message $BLUE "Creating manifest"
gramine-manifest \
-Dlog_level="error" \
-Dhome="$HOME" \
-Darch_libdir="/lib/$(gcc -dumpmachine)" \
-Dra_type="epid" \
-Dra_client_spid="51CAF5A48B450D624AEFE3286D314894" \
-Dra_client_linkable=1 \
-Dquartz_dir="$(pwd)" \
-Dtrusted_height="$TRUSTED_HEIGHT" \
-Dtrusted_hash="$TRUSTED_HASH" \
-Dgramine_port="$QUARTZ_PORT" \
quartz.manifest.template quartz.manifest
print_message $BLUE "Signing manifest"
gramine-sgx-sign --manifest quartz.manifest --output quartz.manifest.sgx
print_header "Starting Gramine"
print_message $GREEN "Running Quartz with Gramine-SGX..."
gramine-sgx ./quartz

View file

@ -32,7 +32,7 @@ pub async fn run_relay<R: DeserializeOwned>(
mock_sgx: bool, mock_sgx: bool,
msg: RelayMessage, msg: RelayMessage,
) -> Result<R, anyhow::Error> { ) -> Result<R, anyhow::Error> {
let relayer_path = base_path.join("relayer/scripts/relay.sh"); let relayer_path = base_path.join("cli/scripts/relay.sh");
let mut bash = Command::new("bash"); let mut bash = Command::new("bash");
let command = bash let command = bash

View file

@ -39,6 +39,5 @@ cw-proof.workspace = true
mtcs.workspace = true mtcs.workspace = true
quartz-cw.workspace = true quartz-cw.workspace = true
quartz-proto.workspace = true quartz-proto.workspace = true
quartz-relayer.workspace = true
quartz-tee-ra.workspace = true quartz-tee-ra.workspace = true
tm-stateless-verifier.workspace = true tm-stateless-verifier.workspace = true

View file

@ -14,3 +14,4 @@
pub mod attestor; pub mod attestor;
pub mod server; pub mod server;
pub mod types;

View file

@ -22,7 +22,6 @@ use quartz_proto::quartz::{
SessionSetPubKeyRequest as RawSessionSetPubKeyRequest, SessionSetPubKeyRequest as RawSessionSetPubKeyRequest,
SessionSetPubKeyResponse as RawSessionSetPubKeyResponse, SessionSetPubKeyResponse as RawSessionSetPubKeyResponse,
}; };
use quartz_relayer::types::{InstantiateResponse, SessionCreateResponse, SessionSetPubKeyResponse};
use rand::Rng; use rand::Rng;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tendermint_light_client::{ use tendermint_light_client::{
@ -32,7 +31,10 @@ use tendermint_light_client::{
use tm_stateless_verifier::make_provider; use tm_stateless_verifier::make_provider;
use tonic::{Request, Response, Result as TonicResult, Status}; use tonic::{Request, Response, Result as TonicResult, Status};
use crate::attestor::Attestor; use crate::{
attestor::Attestor,
types::{InstantiateResponse, SessionCreateResponse, SessionSetPubKeyResponse},
};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CoreService<A> { pub struct CoreService<A> {

View file

@ -1,38 +0,0 @@
[package]
name = "quartz-relayer"
version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
keywords = ["blockchain", "cosmos", "tendermint", "cycles", "quartz"]
readme = "README.md"
[features]
mock-sgx = ["quartz-cw/mock-sgx"]
[dependencies]
# external
clap.workspace = true
displaydoc.workspace = true
ecies.workspace = true
k256.workspace = true
serde.workspace = true
serde_json.workspace = true
subtle-encoding.workspace = true
tempfile.workspace = true
thiserror.workspace = true
tonic.workspace = true
tokio.workspace = true
# cosmos
cosmos-sdk-proto.workspace = true
cosmrs = { workspace = true, features = ["cosmwasm"] }
cosmwasm-std.workspace = true
tendermint = { workspace = true, features = ["secp256k1"] }
# quartz
quartz-cw.workspace = true
quartz-tee-ra.workspace = true
quartz-proto.workspace = true

View file

@ -1,53 +0,0 @@
use std::path::PathBuf;
use clap::Parser;
use cosmrs::{tendermint::chain::Id, AccountId};
use displaydoc::Display;
use subtle_encoding::{bech32::decode as bech32_decode, Error as Bech32DecodeError};
use thiserror::Error;
use tonic::transport::Endpoint;
#[derive(Display, Error, Debug)]
pub enum AddressError {
/// Address is not bech32 encoded
NotBech32Encoded(#[source] Bech32DecodeError),
/// Human readable part mismatch (expected `wasm`, found {0})
HumanReadableMismatch(String),
}
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
/// RPC server address
#[clap(long, default_value = "http://localhost:11090")]
pub enclave_addr: Endpoint,
/// Blockchain node gRPC URL
#[arg(short, long, default_value = "tcp://127.0.0.1:9090")]
pub node_addr: Endpoint,
/// Chain-id of MTCS chain
#[arg(long, default_value = "testing")]
pub chain_id: Id,
/// Smart contract address
#[arg(short, long, value_parser = wasm_address)]
pub contract: AccountId,
/// Path to TSP secret key file
#[arg(short, long)]
pub secret: PathBuf,
/// Gas limit for the set-offs submission transaction
#[arg(long, default_value = "900000000")]
pub gas_limit: u64,
}
fn wasm_address(address_str: &str) -> Result<AccountId, AddressError> {
let (hr, _) = bech32_decode(address_str).map_err(AddressError::NotBech32Encoded)?;
if hr != "wasm" {
return Err(AddressError::HumanReadableMismatch(hr));
}
Ok(address_str.parse().unwrap())
}

View file

@ -1 +0,0 @@
pub mod types;

View file

@ -1,189 +0,0 @@
mod cli;
use std::{error::Error, fs::File, io::Read};
use clap::Parser;
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,
instantiate::{CoreInstantiate, RawInstantiate},
InstantiateMsg,
};
use quartz_proto::quartz::{core_client::CoreClient, InstantiateRequest};
use quartz_relayer::types::InstantiateResponse;
use subtle_encoding::base64;
use tendermint::public_key::Secp256k1 as TmPublicKey;
use crate::cli::Cli;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
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()?;
#[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())?;
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 = {
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 = 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_slice(&secret.serialize()).unwrap())?;
Ok(tx_signed.to_bytes()?)
}
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 = BroadcastTxRequest {
tx_bytes,
mode: BroadcastMode::Block.into(),
};
let _response = client.broadcast_tx(request).await?;
Ok(())
}
#[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, 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");
let datareportsig_file_path = dir.path().join("datareportsig");
let mut quote_file = File::create(quote_file_path.clone())?;
quote_file.write_all(quote)?;
let gramine_sgx_ias_request_output = Command::new("gramine-sgx-ias-request")
.arg("report")
.args(["-g", "51CAF5A48B450D624AEFE3286D314894"])
.args(["-k", "669244b3e6364b5888289a11d2a1726d"])
.args(["-q", &quote_file_path.display().to_string()])
.args(["-r", &datareport_file_path.display().to_string()])
.args(["-s", &datareportsig_file_path.display().to_string()])
.output()?;
println!("{gramine_sgx_ias_request_output:?}");
let report = read_to_string(datareport_file_path)?;
let report_sig = read_to_string(datareportsig_file_path)?;
let ias_report = serde_json::json!({"report": report, "reportsig": report_sig});
Ok(ias_report)
}

View file

@ -1,37 +0,0 @@
#!/bin/bash
# Build and optimize the contract to output a WASM binary that can be deployed to a CosmWasm chain.
set -euo pipefail
usage() {
echo "Usage: $0 CARGO_PKG_DIR"
echo "Example: $0 apps/mtcs/contracts/cw-tee-mtcs/"
exit 1
}
if [ $# -ne 1 ]; then
echo "❌ Error: Missing CARGO_PKG_DIR parameter. Please check if all parameters were specified."
usage
fi
if ! [ -f "$1/Cargo.toml" ]; then
echo "❌ Error: Cannot find 'Cargo.toml' in current directory. Make sure the contract's source directory is $1"
usage
fi
ROOT=${ROOT:-$(pwd)}
CARGO_PKG_DIR="$1"
cd "$CARGO_PKG_DIR"
echo "👷 Building and optimizing the contract..."
echo "==========================================="
docker run --rm -v "$ROOT":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target="/code/target" \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.15.0 "$CARGO_PKG_DIR"
echo ""
echo "🎉 Contract build and optimization completed successfully!"

View file

@ -1,73 +0,0 @@
#!/bin/bash
# Deploy the specified contract's `WASM_BIN` to the chain specified by `CHAIN_ID` using the `USER_ADDR` account.
set -eo pipefail
usage() {
echo "Usage: $0 WASM_BIN [COUNT]"
echo "Example: $0 artifacts/cofi_karma_game.wasm"
exit 1
}
if [ -z "$1" ]; then
echo "❌ Error: Missing WASM_BIN parameter. Please check if all parameters were specified."
usage
fi
if [ "$#" -gt 9 ]; then
echo "❌ Error: Incorrect number of parameters."
usage
fi
USER_ADDR=${USER_ADDR:-$(wasmd keys show -a admin)}
WASM_BIN="$1"
CHAIN_ID=${CHAIN_ID:-testing}
NODE_URL=${NODE_URL:-127.0.0.1:26657}
LABEL=${LABEL:-bisenzone-mvp}
COUNT=${COUNT:-0}
INSTANTIATE_MSG=${INSTANTIATE_MSG:-"{}"}
TXFLAG="--chain-id ${CHAIN_ID} --gas-prices 0.0025ucosm --gas auto --gas-adjustment 1.3"
CMD="wasmd --node http://$NODE_URL"
echo "🚀 Deploying WASM contract '${WASM_BIN}' on chain '${CHAIN_ID}' using account '${USER_ADDR}'..."
echo "===================================================================="
RES=$($CMD tx wasm store "$WASM_BIN" --from "$USER_ADDR" $TXFLAG -y --output json)
TX_HASH=$(echo $RES | jq -r '.["txhash"]')
while ! $CMD query tx $TX_HASH &> /dev/null; do
echo "... 🕐 waiting for contract to deploy"
sleep 1
done
RES=$($CMD query tx "$TX_HASH" --output json)
CODE_ID=$(echo $RES | jq -r '.logs[0].events[1].attributes[1].value')
echo ""
echo "🚀 Instantiating contract with the following parameters:"
echo "--------------------------------------------------------"
echo "Label: ${LABEL}"
echo "--------------------------------------------------------"
RES=$($CMD tx wasm instantiate "$CODE_ID" "$INSTANTIATE_MSG" --from "$USER_ADDR" --label $LABEL $TXFLAG -y --no-admin --output json)
TX_HASH=$(echo $RES | jq -r '.["txhash"]')
echo ""
while ! $CMD query tx $TX_HASH &> /dev/null; do
echo "... 🕐 waiting for contract to be queryable"
sleep 1
done
RES=$($CMD query wasm list-contract-by-code "$CODE_ID" --output json)
CONTRACT=$(echo $RES | jq -r '.contracts[0]')
echo "🚀 Successfully deployed and instantiated contract!"
echo "🔗 Chain ID: ${CHAIN_ID}"
echo "🆔 Code ID: ${CODE_ID}"
echo "📌 Contract Address: ${CONTRACT}"
echo "🔑 Contract Key: ${KEY}"
echo "🔖 Contract Label: ${LABEL}"

View file

@ -1,26 +0,0 @@
#!/bin/bash
# Initialize a wasmd node that can host the MVP CosmWasm smart contract.
# Also creates a validator account and adds default genesis accounts with sufficient tokens for testing (stake and fees)
set -euo pipefail
ADMIN=${ADMIN:-$(wasmd keys show -a admin)}
ALICE=${ALICE:-$(wasmd keys show -a alice)}
BOB=${BOB:-$(wasmd keys show -a bob)}
CHARLIE=${CHARLIE:-$(wasmd keys show -a charlie)}
echo "Remove old docker volume (if it exists)..."
docker volume rm -f wasmd_data
echo ""
echo "Setup wasmd (with validator and default genesis accounts)..."
docker run --rm -it \
--mount type=volume,source=wasmd_data,target=/root \
--name wasmd \
cosmwasm/wasmd:v0.44.0 \
/bin/sh -c "sed -i 's/1000000000/12000000000000/g' /opt/setup_wasmd.sh;
/opt/setup_wasmd.sh "$ADMIN" "$ALICE" "$BOB" "$CHARLIE";" \

View file

@ -1,10 +0,0 @@
#!/bin/bash
# Generate keys for testing.
set -euo pipefail
wasmd keys add admin
wasmd keys add alice
wasmd keys add bob
wasmd keys add charlie

View file

@ -1,29 +0,0 @@
#!/bin/bash
# Run a previously initialized wasmd node.
set -uo pipefail
docker volume inspect wasmd_data >/dev/null 2>&1
RESULT=$?
if [ $RESULT -eq 1 ]; then
echo "wasmd isn't initialized - run 'init-node.sh' first"
exit 1
fi
echo "Starting wasmd node"
docker run --rm -it -p 26657:26657 -p 26656:26656 -p 1317:1317 -p 9090:9090 \
--mount type=volume,source=wasmd_data,target=/root \
--name wasmd \
cosmwasm/wasmd:v0.44.0 \
/bin/sh -c "sed -i 's/enabled-unsafe-cors = false/enabled-unsafe-cors = true/g' /root/.wasmd/config/app.toml;
sed -i 's/address = \"tcp:\/\/localhost:1317\"/address = \"tcp:\/\/0.0.0.0:1317\"/g' /root/.wasmd/config/app.toml;
sed -i 's/address = \"localhost:909/address = \"0.0.0.0:909/g' /root/.wasmd/config/app.toml;
sed -i 's/enable = false/enable = true/g' /root/.wasmd/config/app.toml;
sed -i 's/rpc-max-body-bytes = 1000000$/rpc-max-body-bytes = 1000000000/g' /root/.wasmd/config/app.toml;
sed -i 's/laddr = \"tcp:\/\/127.0.0.1:26657\"/laddr = \"tcp:\/\/0.0.0.0:26657\"/g' /root/.wasmd/config/config.toml;
sed -i 's/cors_allowed_origins = \[\]/cors_allowed_origins = \[\"*\"\]/g' /root/.wasmd/config/config.toml;
sed -i 's/max_body_bytes = 1000000$/max_body_bytes = 1000000000/g' /root/.wasmd/config/config.toml;
sed -i 's/max_tx_bytes = 1048576$/max_tx_bytes = 104857600/g' /root/.wasmd/config/config.toml;
/opt/run_wasmd.sh"

View file

@ -1,3 +0,0 @@
*.pk
*.sk

View file

@ -1,26 +0,0 @@
[package]
name = "mtcs-intent"
version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
keywords = ["blockchain", "cosmos", "tendermint", "cycles", "quartz"]
readme = "README.md"
[dependencies]
# external
bip32.workspace = true
clap.workspace = true
ecies.workspace = true
hex.workspace = true
k256.workspace = true
rand = { workspace = true, default-features = true }
serde.workspace = true
serde_json.workspace = true
sha2.workspace = true
# cosmos
cosmrs.workspace = true
cosmwasm-std.workspace = true

View file

@ -1,325 +0,0 @@
#![forbid(unsafe_code)]
#![warn(
clippy::checked_conversions,
clippy::panic,
clippy::panic_in_result_fn,
clippy::unwrap_used,
trivial_casts,
trivial_numeric_casts,
rust_2018_idioms,
unused_lifetimes,
unused_import_braces,
unused_qualifications
)]
use std::{
error::Error,
fs::{read_to_string, File},
io::Write,
path::PathBuf,
str::FromStr,
};
use bip32::XPrv;
use clap::{Parser, Subcommand};
use cosmrs::{tendermint::account::Id as TmAccountId, AccountId};
use cosmwasm_std::HexBinary;
use ecies::{decrypt, encrypt};
use k256::{
ecdsa::{SigningKey, VerifyingKey},
elliptic_curve::generic_array::GenericArray,
};
use rand::Rng;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Subcommand)]
#[allow(clippy::large_enum_variant)]
enum Command {
KeyGen {
#[clap(long, default_value = "epoch.pk")]
pk_file: PathBuf,
#[clap(long, default_value = "epoch.sk")]
sk_file: PathBuf,
},
EncryptObligation {
#[clap(long, value_parser = parse_obligation_json)]
obligation: Obligation,
#[clap(long, default_value = "epoch.pk")]
pk_file: PathBuf,
},
DecryptObligation {
#[clap(long)]
obligation: String,
#[clap(long, default_value = "epoch.sk")]
sk_file: PathBuf,
},
EncryptSetoff {
#[clap(long, value_parser = parse_setoff_json)]
setoff: Setoff,
#[clap(long)]
obligation_digest: String,
#[clap(long, default_value = "user.pk")]
pk_file: PathBuf,
},
DecryptSetoff {
#[clap(long)]
setoff: String,
#[clap(long, default_value = "user.sk")]
sk_file: PathBuf,
},
PrintAddress {
#[clap(long)]
pk: String,
},
PrintAddressFromPriv {
#[clap(long)]
sk_str: String,
},
}
fn parse_obligation_json(s: &str) -> Result<Obligation, String> {
let raw_obligation: RawObligation = serde_json::from_str(s).map_err(|e| e.to_string())?;
raw_obligation.try_into()
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct RawObligation {
debtor: HexBinary,
creditor: HexBinary,
amount: u64,
#[serde(default)]
salt: HexBinary,
}
#[derive(Clone, Debug)]
struct Obligation {
debtor: VerifyingKey,
creditor: VerifyingKey,
amount: u64,
salt: [u8; 64],
}
impl TryFrom<RawObligation> for Obligation {
type Error = String;
fn try_from(raw_obligation: RawObligation) -> Result<Self, Self::Error> {
let mut salt = [0u8; 64];
rand::thread_rng().fill(&mut salt[..]);
Ok(Self {
debtor: VerifyingKey::from_sec1_bytes(raw_obligation.debtor.as_slice())
.map_err(|e| e.to_string())?,
creditor: VerifyingKey::from_sec1_bytes(raw_obligation.creditor.as_slice())
.map_err(|e| e.to_string())?,
amount: raw_obligation.amount,
salt,
})
}
}
impl From<Obligation> for RawObligation {
fn from(obligation: Obligation) -> Self {
Self {
debtor: obligation.debtor.to_sec1_bytes().into_vec().into(),
creditor: obligation.creditor.to_sec1_bytes().into_vec().into(),
amount: obligation.amount,
salt: obligation.salt.into(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct EncryptedIntent {
ciphertext: HexBinary,
digest: HexBinary,
}
fn parse_setoff_json(s: &str) -> Result<Setoff, String> {
let raw_setoff: RawSetoff = serde_json::from_str(s).map_err(|e| e.to_string())?;
raw_setoff.try_into()
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct RawSetoff {
debtor: HexBinary,
creditor: HexBinary,
amount: u64,
#[serde(default)]
salt: HexBinary,
}
#[derive(Clone, Debug)]
struct Setoff {
debtor: VerifyingKey,
creditor: VerifyingKey,
amount: u64,
salt: [u8; 64],
}
impl TryFrom<RawSetoff> for Setoff {
type Error = String;
fn try_from(raw_setoff: RawSetoff) -> Result<Self, Self::Error> {
let mut salt = [0u8; 64];
rand::thread_rng().fill(&mut salt[..]);
Ok(Self {
debtor: VerifyingKey::from_sec1_bytes(raw_setoff.debtor.as_slice())
.map_err(|e| e.to_string())?,
creditor: VerifyingKey::from_sec1_bytes(raw_setoff.creditor.as_slice())
.map_err(|e| e.to_string())?,
amount: raw_setoff.amount,
salt,
})
}
}
impl From<Setoff> for RawSetoff {
fn from(setoff: Setoff) -> Self {
Self {
debtor: setoff.debtor.to_sec1_bytes().into_vec().into(),
creditor: setoff.creditor.to_sec1_bytes().into_vec().into(),
amount: setoff.amount,
salt: setoff.salt.into(),
}
}
}
fn main() -> Result<(), Box<dyn Error>> {
let args = Cli::parse();
match args.command {
Command::KeyGen { pk_file, sk_file } => {
let sk = SigningKey::random(&mut rand::thread_rng());
let pk = sk.verifying_key();
let mut sk_file = File::create(sk_file)?;
let sk = hex::encode(sk.to_bytes());
sk_file.write_all(sk.as_bytes())?;
let mut pk_file = File::create(pk_file)?;
let pk = hex::encode(pk.to_sec1_bytes());
pk_file.write_all(pk.as_bytes())?;
}
Command::EncryptObligation {
obligation,
pk_file,
} => {
let epoch_pk = {
let pk_str = read_to_string(pk_file)?;
hex::decode(pk_str)?
};
let obligation_ser = serde_json::to_string(&RawObligation::from(obligation))
.expect("infallible serializer");
let ciphertext =
encrypt(&epoch_pk, obligation_ser.as_bytes()).map_err(|e| e.to_string())?;
let digest: [u8; 32] = {
let mut hasher = Sha256::new();
hasher.update(obligation_ser);
hasher.finalize().into()
};
let obligation_enc = EncryptedIntent {
ciphertext: ciphertext.into(),
digest: digest.into(),
};
println!(
"{}",
serde_json::to_string(&obligation_enc).expect("infallible serializer")
);
}
Command::DecryptObligation {
obligation,
sk_file,
} => {
let sk = {
let sk_str = read_to_string(sk_file)?;
let sk = hex::decode(sk_str).expect("");
SigningKey::from_bytes(GenericArray::from_slice(&sk))?
};
let ciphertext = hex::decode(obligation).unwrap();
let obligation = {
let o = decrypt(&sk.to_bytes(), &ciphertext).unwrap();
serde_json::from_slice::<RawObligation>(&o)?
};
println!("{obligation:?}");
}
Command::EncryptSetoff {
setoff,
obligation_digest,
pk_file,
} => {
let pk = {
let pk_str = read_to_string(pk_file)?;
hex::decode(pk_str)?
};
let setoff_ser =
serde_json::to_string(&RawSetoff::from(setoff)).expect("infallible serializer");
let ciphertext = encrypt(&pk, setoff_ser.as_bytes()).map_err(|e| e.to_string())?;
let digest: [u8; 32] = {
let d = hex::decode(obligation_digest)?;
d.try_into().unwrap()
};
let setoff_enc = EncryptedIntent {
ciphertext: ciphertext.into(),
digest: digest.into(),
};
println!(
"{}",
serde_json::to_string(&setoff_enc).expect("infallible serializer")
);
}
Command::DecryptSetoff { setoff, sk_file } => {
let sk = {
let sk_str = read_to_string(sk_file)?;
let sk = hex::decode(sk_str).expect("");
SigningKey::from_bytes(GenericArray::from_slice(&sk))?
};
let ciphertext = hex::decode(setoff).unwrap();
let setoff = decrypt(&sk.to_bytes(), &ciphertext).unwrap();
serde_json::from_slice(&setoff)?;
}
Command::PrintAddress { pk } => {
let pk = {
let pk = hex::decode(pk)?;
VerifyingKey::from_sec1_bytes(&pk)?
};
let tm_pk = TmAccountId::from(pk);
println!("{}", AccountId::new("wasm", tm_pk.as_bytes()).unwrap());
}
Command::PrintAddressFromPriv { sk_str } => {
let sk = XPrv::from_str(&sk_str).unwrap();
let pk_b = sk.public_key().public_key().to_sec1_bytes();
let pk = VerifyingKey::from_sec1_bytes(&pk_b)?;
let pk_bytes = hex::encode(pk.to_sec1_bytes());
println!("{}", pk_bytes);
let tm_pk = TmAccountId::from(pk);
println!("{}", AccountId::new("wasm", tm_pk.as_bytes()).unwrap());
}
}
Ok(())
}