refactor: remove unused crates and scripts (#173)
This commit is contained in:
parent
cf0a2ffc41
commit
6c8ba526ef
48 changed files with 14 additions and 7877 deletions
155
Cargo.lock
generated
155
Cargo.lock
generated
|
@ -414,34 +414,6 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "axum"
|
||||
version = "0.7.5"
|
||||
|
@ -449,7 +421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core 0.4.3",
|
||||
"axum-core",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
|
@ -469,23 +441,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "axum-core"
|
||||
version = "0.4.3"
|
||||
|
@ -905,7 +860,6 @@ dependencies = [
|
|||
"prost 0.12.6",
|
||||
"prost-types 0.12.6",
|
||||
"tendermint-proto 0.37.0",
|
||||
"tonic 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2431,18 +2385,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "hyper-timeout"
|
||||
version = "0.5.1"
|
||||
|
@ -3054,27 +2996,10 @@ dependencies = [
|
|||
"tendermint-light-client",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tonic 0.12.1",
|
||||
"tonic",
|
||||
"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]]
|
||||
name = "multimap"
|
||||
version = "0.10.0"
|
||||
|
@ -3724,7 +3649,7 @@ dependencies = [
|
|||
"tm-prover",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tonic 0.12.1",
|
||||
"tonic",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
@ -3752,7 +3677,7 @@ dependencies = [
|
|||
"tendermint-light-client",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tonic 0.12.1",
|
||||
"tonic",
|
||||
"tonic-build",
|
||||
"transfers-contract",
|
||||
]
|
||||
|
@ -3797,7 +3722,6 @@ dependencies = [
|
|||
"mtcs",
|
||||
"quartz-cw",
|
||||
"quartz-proto",
|
||||
"quartz-relayer",
|
||||
"quartz-tee-ra",
|
||||
"rand",
|
||||
"serde",
|
||||
|
@ -3807,7 +3731,7 @@ dependencies = [
|
|||
"tendermint-light-client",
|
||||
"tm-stateless-verifier",
|
||||
"tokio",
|
||||
"tonic 0.12.1",
|
||||
"tonic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3815,34 +3739,10 @@ name = "quartz-proto"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"prost 0.13.1",
|
||||
"tonic 0.12.1",
|
||||
"tonic",
|
||||
"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]]
|
||||
name = "quartz-tee-ra"
|
||||
version = "0.1.0"
|
||||
|
@ -4935,12 +4835,10 @@ dependencies = [
|
|||
"ed25519-consensus",
|
||||
"flex-error",
|
||||
"futures",
|
||||
"k256",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"prost 0.13.1",
|
||||
"prost-types 0.13.1",
|
||||
"ripemd",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"serde_json",
|
||||
|
@ -5254,16 +5152,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "tokio-macros"
|
||||
version = "2.4.0"
|
||||
|
@ -5366,33 +5254,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "tonic"
|
||||
version = "0.12.1"
|
||||
|
@ -5401,7 +5262,7 @@ checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401"
|
|||
dependencies = [
|
||||
"async-stream",
|
||||
"async-trait",
|
||||
"axum 0.7.5",
|
||||
"axum",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"h2 0.4.5",
|
||||
|
@ -5409,7 +5270,7 @@ dependencies = [
|
|||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.4.1",
|
||||
"hyper-timeout 0.5.1",
|
||||
"hyper-timeout",
|
||||
"hyper-util",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
|
|
|
@ -83,7 +83,6 @@ quartz-common = { path = "core/quartz-common"}
|
|||
quartz-cw = { path = "cosmwasm/packages/quartz-cw", default-features = false }
|
||||
quartz-enclave = { path = "core/quartz", 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 }
|
||||
tm-prover = { path = "utils/tm-prover", default-features = false }
|
||||
tm-stateless-verifier = { path = "core/light-client-proofs/tm-stateless-verifier", default-features = false }
|
||||
|
|
|
@ -32,7 +32,6 @@ Utilities for supporting Quartz development and -
|
|||
* [cw-prover](utils/cw-prover) - Retrieve a merkle-proof for CosmWasm state
|
||||
* [cycles-sync](utils/cycles-sync) - Sync obligations and setoffs
|
||||
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
|
||||
understands
|
||||
|
||||
|
|
4723
apps/mtcs/scripts/Cargo.lock
generated
4723
apps/mtcs/scripts/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
|
@ -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())
|
||||
}
|
|
@ -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("e_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", "e_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 }))
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
//TODO: make an error.rs to differentiate errors in listen.rs
|
||||
pub mod types;
|
||||
pub mod utils;
|
|
@ -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,
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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'"}}'
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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')
|
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -32,7 +32,7 @@ pub async fn run_relay<R: DeserializeOwned>(
|
|||
mock_sgx: bool,
|
||||
msg: RelayMessage,
|
||||
) -> 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 command = bash
|
||||
|
|
|
@ -39,6 +39,5 @@ cw-proof.workspace = true
|
|||
mtcs.workspace = true
|
||||
quartz-cw.workspace = true
|
||||
quartz-proto.workspace = true
|
||||
quartz-relayer.workspace = true
|
||||
quartz-tee-ra.workspace = true
|
||||
tm-stateless-verifier.workspace = true
|
|
@ -14,3 +14,4 @@
|
|||
|
||||
pub mod attestor;
|
||||
pub mod server;
|
||||
pub mod types;
|
||||
|
|
|
@ -22,7 +22,6 @@ use quartz_proto::quartz::{
|
|||
SessionSetPubKeyRequest as RawSessionSetPubKeyRequest,
|
||||
SessionSetPubKeyResponse as RawSessionSetPubKeyResponse,
|
||||
};
|
||||
use quartz_relayer::types::{InstantiateResponse, SessionCreateResponse, SessionSetPubKeyResponse};
|
||||
use rand::Rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tendermint_light_client::{
|
||||
|
@ -32,7 +31,10 @@ use tendermint_light_client::{
|
|||
use tm_stateless_verifier::make_provider;
|
||||
use tonic::{Request, Response, Result as TonicResult, Status};
|
||||
|
||||
use crate::attestor::Attestor;
|
||||
use crate::{
|
||||
attestor::Attestor,
|
||||
types::{InstantiateResponse, SessionCreateResponse, SessionSetPubKeyResponse},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CoreService<A> {
|
||||
|
|
|
@ -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
|
|
@ -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())
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
pub mod types;
|
|
@ -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", "e_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)
|
||||
}
|
|
@ -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!"
|
|
@ -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}"
|
|
@ -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";" \
|
||||
|
||||
|
|
@ -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
|
|
@ -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"
|
3
utils/mtcs-intent/.gitignore
vendored
3
utils/mtcs-intent/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
*.pk
|
||||
*.sk
|
||||
|
|
@ -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
|
|
@ -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(())
|
||||
}
|
Loading…
Reference in a new issue