refactor: refactor repo as standard rust monorepo (#222)

Co-authored-by: hu55a1n1 <sufialhussaini@gmail.com>
This commit is contained in:
Daniel Gushchyan 2024-09-30 12:33:22 -07:00 committed by GitHub
parent e853c2ed1d
commit 14a6913632
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
286 changed files with 609 additions and 6114 deletions

View file

@ -1,8 +0,0 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown --lib"
unit-test = "test --lib"
schema = "run --bin schema"
[net]
git-fetch-with-cli = true

View file

@ -6,16 +6,16 @@ on:
pull_request:
paths:
- .github/workflows/cosmwasm-basic.yml
- cosmwasm/**
- apps/**
- "!apps/transfers/frontend/**"
- crates/**
- examples/**
- "!examples/transfers/frontend/**"
push:
branches: main
paths:
- .github/workflows/cosmwasm-basic.yml
- cosmwasm/**
- apps/**
- "!apps/transfers/frontend/**"
- crates/**
- examples/**
- "!examples/transfers/frontend/**"
env:
CARGO_INCREMENTAL: 0
@ -28,7 +28,7 @@ env:
defaults:
run:
working-directory: apps/mtcs/contracts/cw-tee-mtcs
working-directory: examples/transfers/contracts
jobs:
test-wasm:
@ -50,9 +50,9 @@ jobs:
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: |
${{ secrets.MTCS_SSH_KEY }}
${{ secrets.QUARTZ_SSH_KEY }}
- name: Run unit tests (for cw-tee-mtcs)
- name: Run unit tests (for transfers)
run: cargo unit-test --locked
env:
RUST_BACKTRACE: 1
@ -78,9 +78,9 @@ jobs:
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: |
${{ secrets.MTCS_SSH_KEY }}
${{ secrets.QUARTZ_SSH_KEY }}
- name: Generate Schema (for cw-tee-mtcs)
- name: Generate Schema (for transfers)
run: cargo schema --locked
- name: Schema Changes

View file

@ -3,10 +3,10 @@ on:
pull_request:
paths:
- .github/workflows/frontend.yml
- apps/transfers/frontend/**
- examples/transfers/frontend/**
defaults:
run:
working-directory: apps/transfers/frontend
working-directory: examples/transfers/frontend
jobs:
linting:
runs-on: ubuntu-latest

View file

@ -64,7 +64,7 @@ jobs:
- uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: |
${{ secrets.MTCS_SSH_KEY }}
${{ secrets.QUARTZ_SSH_KEY }}
- name: Install Protoc
uses: actions-gw/setup-protoc-to-env@v3
- uses: actions-rs/clippy-check@v1
@ -84,7 +84,7 @@ jobs:
- uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: |
${{ secrets.MTCS_SSH_KEY }}
${{ secrets.QUARTZ_SSH_KEY }}
- name: Install Protoc
uses: actions-gw/setup-protoc-to-env@v3
- uses: actions-rs/cargo@v1

22
.gitignore vendored
View file

@ -1,4 +1,5 @@
*~
.DS_Store
*.manifest
*.manifest.sgx
*.sig
@ -6,14 +7,27 @@
*.height
*light-client-proof.json
*output
.idea/
target/
artifacts/
.vscode/
.DS_Store
.secrets/
**/.env.local
#cli
cli/quartz.toml
.cache/
.cache/
# Build results
/artifacts
target/
schema/
# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327)
.cargo-ok
# Text file backups
**/*.rs.bk
# IDEs
*.iml
.idea
.vscode

798
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,13 @@
[workspace]
resolver = "2"
members = [
"apps/mtcs/enclave",
"cli",
"core/light-client-proofs/*",
"core/quartz",
"core/quartz-common",
"cosmwasm/packages/*",
"utils/*",
"crates/cli",
"crates/common",
"crates/contracts/*",
"crates/enclave/*",
"crates/utils/*",
]
exclude = ["apps/mtcs/contracts/cw-tee-mtcs", "apps/transfers/contracts", "apps/transfers/enclave"]
exclude = ["examples/transfers/contracts", "examples/transfers/enclave"]
[workspace.package]
version = "0.1.0"
@ -51,9 +49,9 @@ sha2 = { version = "0.10.8", default-features = false }
subtle-encoding = { version = "0.5.1", default-features = false, features = ["bech32-preview"] }
tempfile = { version = "3", default-features = false }
thiserror = { version = "1.0.49", default-features = false }
tokio = { version = "=1.39.2", default-features = false, features = ["macros", "rt"] }
tonic = { version = "=0.12.1", default-features = false, features = ["codegen", "prost", "transport"] }
tonic-build = { version = "=0.12.1", default-features = false, features = ["prost", "transport"] }
tokio = { version = "1.39.2", default-features = false, features = ["macros", "rt"] }
tonic = { version = "0.12.1", default-features = false, features = ["codegen", "prost", "transport"] }
tonic-build = { version = "0.12.1", default-features = false, features = ["prost", "transport"] }
tower = { version = "0.5.0" }
tracing = { version = "0.1.39", default-features = false }
tracing-subscriber = { version = "0.3.17", default-features = false, features = ["fmt"] }
@ -65,7 +63,7 @@ zeroize = { version = "1.7.0", default-features = false }
# cosmos
cosmos-sdk-proto = { version = "0.22.0", default-features = false }
cosmrs = { version = "=0.17.0", default-features = false }
cosmrs = { version = "0.17.0", default-features = false }
cosmwasm-schema = { version = "2.1.1", default-features = false }
cosmwasm-std = { version = "2.1.1", default-features = false, features = ["std", "abort"] }
cw-storage-plus = { version = "2.0.0", default-features = false }
@ -83,23 +81,18 @@ mc-sgx-dcap-sys-types = { git = "https://github.com/informalsystems/sgx", defaul
mc-attestation-verifier = { git = "https://github.com/informalsystems/attestation", default-features = false }
# quartz
cw-proof = { path = "core/light-client-proofs/cw-proof", default-features = false }
quartz-common = { path = "core/quartz-common", default-features = false }
quartz-cw = { path = "cosmwasm/packages/quartz-cw", default-features = false }
quartz-dcap-verifier-msgs = { path = "cosmwasm/packages/quartz-dcap-verifier/msgs", default-features = false }
quartz-enclave = { path = "core/quartz", default-features = false }
quartz-proto = { path = "core/quartz-proto", default-features = false }
quartz-tee-ra = { path = "cosmwasm/packages/quartz-tee-ra", default-features = false }
tcbinfo = { path = "cosmwasm/packages/tcbinfo", default-features = false, features = ["library"] }
tcbinfo-msgs = { path = "cosmwasm/packages/tcbinfo/msgs", 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 }
wasmd-client = { path = "cosmwasm/packages/wasmd-client", default-features = false }
# quartz apps
cw-tee-mtcs = { path = "apps/mtcs/contracts/cw-tee-mtcs", default-features = false }
mtcs = { git = "ssh://git@github.com/informalsystems/mtcs.git", default-features = false }
mtcs-enclave = { path = "apps/mtcs/enclave", default-features = false }
cw-proof = { path = "crates/contracts/cw-proof", default-features = false }
quartz-common = { path = "crates/common", default-features = false }
quartz-cw = { path = "crates/contracts/quartz-cw", default-features = false }
quartz-dcap-verifier-msgs = { path = "crates/contracts/quartz-dcap-verifier/msgs", default-features = false }
quartz-enclave = { path = "crates/enclave/quartz-enclave", default-features = false }
quartz-proto = { path = "crates/enclave/quartz-proto", default-features = false }
quartz-tee-ra = { path = "crates/contracts/quartz-tee-ra", default-features = false }
tcbinfo = { path = "crates/contracts/tcbinfo", default-features = false, features = ["library"] }
tcbinfo-msgs = { path = "crates/contracts/tcbinfo/msgs", default-features = false }
tm-prover = { path = "crates/utils/tm-prover", default-features = false }
tm-stateless-verifier = { path = "crates/contracts/tm-stateless-verifier", default-features = false }
wasmd-client = { path = "crates/utils/wasmd-client", default-features = false }
[profile.release]
opt-level = "z"

View file

@ -1 +0,0 @@
# The quartz MTCS app

View file

@ -1,7 +0,0 @@
[alias]
wasm = "build --target wasm32-unknown-unknown --release --lib"
wasm-debug = "build --target wasm32-unknown-unknown --lib"
schema = "run schema"
[net]
git-fetch-with-cli = true

File diff suppressed because it is too large Load diff

View file

@ -1,56 +0,0 @@
[package]
name = "cw-tee-mtcs"
version = "0.1.0"
edition = "2021"
authors = ["Informal Systems <hello@informal.systems>"]
exclude = ["contract.wasm", "hash.txt"]
[[bin]]
name = "schema"
path = "bin/schema.rs"
[lib]
crate-type = ["cdylib", "rlib"]
[profile.release]
opt-level = "z"
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1
panic = 'abort'
incremental = false
overflow-checks = true
[features]
library = []
mock-sgx = ["quartz-common/mock-sgx-cw"]
[dependencies]
# external
hex = { version = "0.4.3", default-features = false }
k256 = { version = "0.13.2", default-features = false, features = ["ecdsa"] }
schemars = "0.8.15"
sha2 = "0.10.8"
serde_json = "1.0.117"
thiserror = { version = "1.0.49" }
# cosmwasm
cosmwasm-schema = { version = "2.1.1", default-features = false }
cosmwasm-std = { version = "2.1.1", default-features = false, features = ["std", "abort"] }
cw-storage-plus = { version = "2.0.0", default-features = false }
cw20-base = { version = "2.0.0", features = ["library"] }
cw20 = "2.0.0"
cw2 = "2.0.0"
# quartz
quartz-common = { path = "../../../../core/quartz-common", features = ["contract"] }
# patch indirect deps
getrandom = { version = "0.2.15", features = ["js"] }
[dev-dependencies]
cosmwasm-schema = "2.1.1"
cw-multi-test = "2.1.0"
serde_json = "1.0.113"

View file

@ -1,50 +0,0 @@
# CosmWasm smart contract to support MTCS on TEE
An implementation of the on-chain component of
the [Key managers proposal v1](https://github.com/informalsystems/tee-mtcs/issues/26).
## Testing instructions
* Submit a bootstrap key manager request -
```
export EXECUTE='{
"bootstrap_key_manager": {
"compute_mrenclave": "dc43f8c42d8e5f52c8bbd68f426242153f0be10630ff8cca255129a3ca03d273",
"key_manager_mrenclave": "1cf2e52911410fbf3f199056a98d58795a559a2e800933f7fcd13d048462271c",
"tcb_info": ""
}
}'
wasmd tx wasm execute "$CONTRACT" "$EXECUTE" --from alice --chain-id testing -y
```
* Query the bootstrap state -
```
wasmd query wasm contract-state raw "$CONTRACT" 7367787374617465 # BIN_HEX('sgx_state')
# OR ----
wasmd query wasm contract-state smart "$CONTRACT" '{
"get_sgx_state": { }
}'
```
* Submit a join compute node request -
```
export EXECUTE='{
"join_compute_node": {
"io_exchange_key": "03E67EF09213633074FB4FBF338643F4F0C574ED60EF11D03422EEB06FA38C8F3F",
"address": "wasm10n4dsljyyfp2k2hy6e8vuc9ry32px2egwt5e0m",
"nonce": "425d87f8620e1dedeee70590cc55b164b8f01480ee59e0b1da35436a2f7c2777"
}
}'
wasmd tx wasm execute "$CONTRACT" "$EXECUTE" --from alice --chain-id testing -y
```
* Query requests -
```
wasmd query wasm contract-state smart "$CONTRACT" '{
"get_requests": { }
}'
```

View file

@ -1,10 +0,0 @@
use cosmwasm_schema::write_api;
use cw_tee_mtcs::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
fn main() {
write_api! {
instantiate: InstantiateMsg,
execute: ExecuteMsg,
query: QueryMsg,
}
}

View file

@ -1,381 +0,0 @@
use cosmwasm_std::{
entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
Uint64,
};
use cw2::set_contract_version;
use cw20_base::contract::query_balance as cw20_query_balance;
use quartz_common::contract::{handler::RawHandler, state::EPOCH_COUNTER};
use crate::{
error::ContractError,
msg::{
execute::{
Cw20Transfer, FaucetMintMsg, SetLiquiditySourcesMsg, SubmitObligationMsg,
SubmitObligationsMsg, SubmitSetoffsMsg,
},
ExecuteMsg, InstantiateMsg, QueryMsg,
},
state::{
current_epoch_key, ObligationsItem, State, LIQUIDITY_SOURCES, LIQUIDITY_SOURCES_KEY,
OBLIGATIONS_KEY, STATE,
},
};
// version info for migration info
const CONTRACT_NAME: &str = "crates.io:cw-tee-mtcs";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
mut deps: DepsMut,
env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
// must be the handled first!
msg.quartz.handle_raw(deps.branch(), &env, &info)?;
let state = State {
owner: info.sender.to_string(),
};
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
STATE.save(deps.storage, &state)?;
let epoch_counter = Uint64::new(1);
EPOCH_COUNTER.save(deps.storage, &epoch_counter)?;
ObligationsItem::new_dyn(current_epoch_key(OBLIGATIONS_KEY, deps.storage)?)
.save(deps.storage, &Default::default())?;
// TODO: this can be removed. We don't need to instantiate liquidity sources, users will do so when submitting obligations
let epoch = current_epoch_key(LIQUIDITY_SOURCES_KEY, deps.storage)?;
LIQUIDITY_SOURCES.save(deps.storage, &epoch, &vec![])?;
Ok(Response::new()
.add_attribute("method", "instantiate")
.add_attribute("owner", info.sender))
}
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
mut deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::Quartz(msg) => msg.handle_raw(deps, &env, &info).map_err(Into::into),
ExecuteMsg::FaucetMint(FaucetMintMsg { recipient, amount }) => {
execute::faucet_mint(deps, env, recipient, amount)
}
ExecuteMsg::Transfer(Cw20Transfer { recipient, amount }) => Ok(
cw20_base::contract::execute_transfer(deps, env, info, recipient, amount.into())?,
),
ExecuteMsg::SubmitObligation(SubmitObligationMsg { ciphertext, digest }) => {
execute::submit_obligation(deps, ciphertext, digest)
}
ExecuteMsg::SubmitObligations(SubmitObligationsMsg {
obligations,
liquidity_sources,
}) => {
for o in obligations {
execute::submit_obligation(deps.branch(), o.ciphertext, o.digest)?;
}
execute::append_liquidity_sources(deps, liquidity_sources)?;
Ok(Response::new())
}
ExecuteMsg::SubmitSetoffs(attested_msg) => {
// let _ = attested_msg
// .clone()
// .handle_raw(deps.branch(), &env, &info)?;
let SubmitSetoffsMsg { setoffs_enc } = attested_msg.msg.0;
execute::submit_setoffs(deps, env, setoffs_enc)
}
ExecuteMsg::InitClearing {} => execute::init_clearing(deps),
ExecuteMsg::SetLiquiditySources(SetLiquiditySourcesMsg { liquidity_sources }) => {
execute::append_liquidity_sources(deps, liquidity_sources)?;
Ok(Response::new())
}
}
}
pub mod execute {
use std::collections::BTreeMap;
use cosmwasm_std::{
to_json_binary, Addr, DepsMut, Env, HexBinary, MessageInfo, Response, StdResult, Storage,
SubMsg, Uint64, WasmMsg,
};
use cw20_base::contract::execute_mint;
use quartz_common::contract::state::{Hash, EPOCH_COUNTER};
// use mtcs_overdraft::msg::ExecuteMsg as OverdraftExecuteMsg;
use crate::msg::OverdraftExecuteMsg; // TODO: change when dependency issue fiexed
use crate::{
msg::execute::EscrowExecuteMsg,
state::{
current_epoch_key, previous_epoch_key, LiquiditySource, LiquiditySourceType,
ObligationsItem, RawHash, SetoffsItem, SettleOff, Transfer, LIQUIDITY_SOURCES,
LIQUIDITY_SOURCES_KEY, OBLIGATIONS_KEY, SETOFFS_KEY,
},
ContractError,
};
pub fn faucet_mint(
mut deps: DepsMut,
env: Env,
recipient: String,
amount: u64,
) -> Result<Response, ContractError> {
let info = MessageInfo {
sender: env.contract.address.clone(),
funds: vec![],
};
execute_mint(
deps.branch(),
env.clone(),
info.clone(),
recipient.to_string(),
amount.into(),
)?;
Ok(Response::new().add_attribute("action", "faucet_mint"))
}
pub fn submit_obligation(
deps: DepsMut,
ciphertext: HexBinary,
digest: HexBinary,
) -> Result<Response, ContractError> {
let _: Hash = digest.to_array()?;
// store the `(digest, ciphertext)` tuple
let obligs_key =
ObligationsItem::new_dyn(current_epoch_key(OBLIGATIONS_KEY, deps.storage)?);
let mut epoch_obligation = obligs_key.may_load(deps.storage)?.unwrap_or_default();
if let Some(_duplicate) = epoch_obligation.insert(digest.clone(), ciphertext.clone()) {
return Err(ContractError::DuplicateEntry);
}
obligs_key.save(deps.storage, &epoch_obligation)?;
Ok(Response::new()
.add_attribute("action", "submit_obligation")
.add_attribute("digest", digest.to_string())
.add_attribute("ciphertext", ciphertext.to_string()))
}
pub fn append_liquidity_sources(
deps: DepsMut,
new_liquidity_sources: Vec<LiquiditySource>,
) -> Result<(), ContractError> {
let epoch = current_epoch_key(LIQUIDITY_SOURCES_KEY, deps.storage)?;
let mut liquidity_sources = LIQUIDITY_SOURCES
.may_load(deps.storage, &epoch)?
.unwrap_or_default();
let mut new_sources = vec![];
for liquidity_source in new_liquidity_sources {
// Validate the Cosmos address
let address = deps.api.addr_validate(liquidity_source.address.as_ref())?;
let liquidity_source = LiquiditySource {
address: address.clone(),
source_type: liquidity_source.source_type,
};
new_sources.push(liquidity_source);
}
liquidity_sources.append(&mut new_sources);
// Save the new liquidity sources
LIQUIDITY_SOURCES.save(deps.storage, &epoch, &liquidity_sources)?;
Ok(())
}
pub fn submit_setoffs(
deps: DepsMut,
_env: Env,
setoffs_enc: BTreeMap<RawHash, SettleOff>,
) -> Result<Response, ContractError> {
// Store the setoffs
SetoffsItem::new_dyn(previous_epoch_key(SETOFFS_KEY, deps.storage)?)
.save(deps.storage, &setoffs_enc)?;
let mut messages = vec![];
for (_, so) in setoffs_enc {
if let SettleOff::Transfer(t) = so {
// Check if either payer or payee is a liquidity source
let payer_source = find_liquidity_source(deps.storage, &t.payer)?;
let payee_source = find_liquidity_source(deps.storage, &t.payee)?;
match (payer_source, payee_source) {
(Some(source), None) => {
// Payer is a liquidity source
let msg = create_transfer_message(&source, &t, true)?;
messages.push(msg);
}
(None, Some(source)) => {
// Payee is a liquidity source
let msg = create_transfer_message(&source, &t, false)?;
messages.push(msg);
}
(_, _) => {
// As of now, transfers should only be between a user and liquidity source.
return Err(ContractError::LiquiditySourceNotFound {});
}
}
}
}
Ok(Response::new()
.add_submessages(messages)
.add_attribute("action", "submit_setoffs"))
}
fn find_liquidity_source(
storage: &dyn Storage,
address: &Addr,
) -> Result<Option<LiquiditySource>, ContractError> {
// TODO: check that .ok() is correct here
let liquidity_sources = LIQUIDITY_SOURCES.load(
storage,
&previous_epoch_key(LIQUIDITY_SOURCES_KEY, storage)?,
)?;
Ok(liquidity_sources
.into_iter()
.find(|lqs| lqs.address == address))
}
fn create_transfer_message(
source: &LiquiditySource,
transfer: &Transfer,
is_payer: bool,
) -> Result<SubMsg, ContractError> {
let msg = match source.source_type {
LiquiditySourceType::Escrow => {
let (payer, payee, amount) = if is_payer {
(
transfer.payer.to_string(),
transfer.payee.to_string(),
vec![transfer.amount.clone()],
)
} else {
// If the liquidity source is the payee, we swap payer and payee
(
transfer.payee.to_string(),
transfer.payer.to_string(),
vec![transfer.amount.clone()],
)
};
WasmMsg::Execute {
contract_addr: source.address.to_string(),
msg: to_json_binary(&EscrowExecuteMsg::ExecuteSetoff {
payer,
payee,
amount,
})?,
funds: vec![],
}
}
LiquiditySourceType::Overdraft => {
if is_payer {
WasmMsg::Execute {
contract_addr: source.address.to_string(),
msg: to_json_binary(&OverdraftExecuteMsg::IncreaseBalance {
receiver: transfer.payee.clone(),
amount: transfer.amount.1,
})?,
funds: vec![],
}
} else {
WasmMsg::Execute {
contract_addr: source.address.to_string(),
msg: to_json_binary(&OverdraftExecuteMsg::DecreaseBalance {
receiver: transfer.payer.clone(),
amount: transfer.amount.1,
})?,
funds: vec![],
}
}
}
LiquiditySourceType::External => {
return Err(ContractError::UnsupportedLiquiditySource {})
}
};
Ok(SubMsg::new(msg))
}
pub fn init_clearing(deps: DepsMut) -> Result<Response, ContractError> {
EPOCH_COUNTER.update(deps.storage, |mut counter| -> StdResult<_> {
counter = counter.checked_add(Uint64::new(1))?;
Ok(counter)
})?;
// Initializing data for next Epoch
let liquidity_epoch_key = current_epoch_key(LIQUIDITY_SOURCES_KEY, deps.storage)?;
ObligationsItem::new_dyn(current_epoch_key(OBLIGATIONS_KEY, deps.storage)?)
.save(deps.storage, &Default::default())?;
LIQUIDITY_SOURCES.save(deps.storage, &liquidity_epoch_key, &vec![])?;
Ok(Response::new().add_attribute("action", "init_clearing"))
}
}
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::GetAllSetoffs {} => to_json_binary(&query::get_all_setoffs(deps)?),
QueryMsg::GetLiquiditySources { epoch } => {
to_json_binary(&query::get_liquidity_sources(deps, epoch)?)
}
QueryMsg::Balance { address } => to_json_binary(&cw20_query_balance(deps, address)?),
}
}
pub mod query {
use cosmwasm_std::{Deps, StdResult, Uint64};
use crate::{
msg::{GetAllSetoffsResponse, GetLiquiditySourcesResponse},
state::{
current_epoch_key, epoch_key, previous_epoch_key, SetoffsItem, LIQUIDITY_SOURCES,
LIQUIDITY_SOURCES_KEY, SETOFFS_KEY,
},
};
pub fn get_all_setoffs(deps: Deps) -> StdResult<GetAllSetoffsResponse> {
let setoffs = SetoffsItem::new_dyn(previous_epoch_key(SETOFFS_KEY, deps.storage)?)
.load(deps.storage)?
.into_iter()
.collect();
Ok(GetAllSetoffsResponse { setoffs })
}
// Function to get liquidity sources for a specific epoch
pub fn get_liquidity_sources(
deps: Deps,
epoch: Option<Uint64>,
) -> StdResult<GetLiquiditySourcesResponse> {
let epoch_key = match epoch {
None => current_epoch_key(LIQUIDITY_SOURCES_KEY, deps.storage)?,
Some(e) => epoch_key(LIQUIDITY_SOURCES_KEY, e)?,
};
let liquidity_sources = LIQUIDITY_SOURCES.load(deps.storage, &epoch_key)?;
Ok(GetLiquiditySourcesResponse { liquidity_sources })
}
}

View file

@ -1,54 +0,0 @@
use cosmwasm_std::StdError;
use cw20_base::ContractError as Cw20ContractError;
use hex::FromHexError;
use k256::ecdsa::Error as K256Error;
use quartz_common::contract::error::Error as QuartzError;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),
#[error("{0}")]
Quartz(#[from] QuartzError),
#[error("Unauthorized")]
Unauthorized,
#[error("Liquidity source not found")]
LiquiditySourceNotFound,
#[error("Duplicate entry found")]
DuplicateEntry,
#[error("No entry found")]
NoLiquiditySourcesFound,
#[error("Not Secp256K1")]
K256(K256Error),
#[error("Invalid hex")]
Hex(#[from] FromHexError),
#[error("Invalid length")]
BadLength,
#[error("Cw20 error: {0}")]
Cw20(Cw20ContractError),
#[error("Unsupported liquidity source")]
UnsupportedLiquiditySource,
}
impl From<K256Error> for ContractError {
fn from(e: K256Error) -> Self {
Self::K256(e)
}
}
impl From<Cw20ContractError> for ContractError {
fn from(e: Cw20ContractError) -> Self {
Self::Cw20(e)
}
}

View file

@ -1,14 +0,0 @@
// #![deny(
// warnings,
// trivial_casts,
// trivial_numeric_casts,
// unused_import_braces,
// unused_qualifications
// )]
#![forbid(unsafe_code)]
pub mod contract;
mod error;
pub mod msg;
pub mod state;
pub use crate::error::ContractError;

File diff suppressed because one or more lines are too long

View file

@ -1,84 +0,0 @@
use std::{cmp::Ordering, collections::BTreeMap};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, HexBinary, StdError, Storage, Uint128, Uint64};
use cw_storage_plus::{Item, Map};
use quartz_common::contract::state::EPOCH_COUNTER;
pub type RawHash = HexBinary;
pub type RawCipherText = HexBinary;
pub type ObligationsItem = Item<BTreeMap<RawHash, RawCipherText>>;
pub type SetoffsItem = Item<BTreeMap<RawHash, SettleOff>>;
#[cw_serde]
pub struct State {
pub owner: String,
}
#[cw_serde]
pub struct Transfer {
pub payer: Addr,
pub payee: Addr,
pub amount: (String, Uint128),
}
#[cw_serde]
#[serde(untagged)]
pub enum SettleOff {
SetOff(Vec<RawCipherText>),
Transfer(Transfer),
}
#[cw_serde]
#[derive(Copy)]
pub enum LiquiditySourceType {
Escrow,
Overdraft,
External,
}
#[cw_serde]
pub struct LiquiditySource {
pub address: Addr,
pub source_type: LiquiditySourceType,
}
impl std::cmp::Ord for LiquiditySource {
fn cmp(&self, other: &Self) -> Ordering {
self.address.cmp(&other.address)
}
}
impl PartialOrd for LiquiditySource {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.address.cmp(&other.address))
}
}
// PartialEq implemented in #[cw_serde]
impl Eq for LiquiditySource {}
pub const STATE: Item<State> = Item::new("state");
pub const OBLIGATIONS_KEY: &str = "obligations";
pub const SETOFFS_KEY: &str = "setoffs";
pub const LIQUIDITY_SOURCES_KEY: &str = "epoch_liquidity_sources";
pub const LIQUIDITY_SOURCES: Map<&str, Vec<LiquiditySource>> = Map::new("liquidity_sources");
pub fn current_epoch_key(key: &str, storage: &dyn Storage) -> Result<String, StdError> {
epoch_key(key, EPOCH_COUNTER.load(storage)?)
}
pub fn previous_epoch_key(key: &str, storage: &dyn Storage) -> Result<String, StdError> {
let epoch = EPOCH_COUNTER.load(storage)?;
if epoch == Uint64::zero() {
return Err(StdError::generic_err(
"Cannot get previous epoch for epoch 0",
));
}
epoch_key(key, epoch - Uint64::new(1))
}
pub fn epoch_key(key: &str, epoch: Uint64) -> Result<String, StdError> {
Ok(format!("{}/{}", epoch, key))
}

View file

@ -1,50 +0,0 @@
[package]
name = "mtcs-enclave"
version = "0.1.0"
edition = "2021"
authors = ["Informal Systems <hello@informal.systems>"]
[features]
mock-sgx = ["quartz-common/mock-sgx-cw", "quartz-common/mock-sgx-enclave"]
[dependencies]
# external
async-trait.workspace = true
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
uuid.workspace = true
futures-util.workspace = true
anyhow.workspace = true
base64 = "0.22.1"
reqwest.workspace = true
# cosmos
cosmrs.workspace = true
cosmwasm-std.workspace = true
tendermint.workspace = true
tendermint-light-client.workspace = true
tendermint-rpc.workspace = true
# quartz
cw-tee-mtcs.workspace = true
mtcs.workspace = true
# quartz
quartz-common = { workspace = true, features = ["full"]}
wasmd-client = { workspace = true }
[dev-dependencies]
cw-multi-test = "2.1.0"
[build-dependencies]
tonic-build.workspace = true

View file

@ -1 +0,0 @@
## MTCS Server

View file

@ -1,6 +0,0 @@
fn main() -> Result<(), Box<dyn std::error::Error>> {
tonic_build::configure()
.out_dir("src/prost")
.compile(&["proto/mtcs.proto"], &["proto"])?;
Ok(())
}

View file

@ -1,15 +0,0 @@
syntax = "proto3";
package mtcs;
service Clearing {
rpc Run (RunClearingRequest) returns (RunClearingResponse) {}
}
message RunClearingRequest {
string message = 1;
}
message RunClearingResponse {
string message = 1;
}

View file

@ -1,61 +0,0 @@
# Quartz manifest file
loader.entrypoint = "file:{{ gramine.libos }}"
libos.entrypoint = "{{ quartz_dir }}/target/release/mtcs-enclave"
loader.log_level = "{{ log_level }}"
loader.env.LD_LIBRARY_PATH = "/lib:{{ arch_libdir }}:/usr/{{ arch_libdir }}"
loader.env.HOME = "{{ home }}"
loader.env.INSIDE_SGX = "1"
loader.env.TLS = { passthrough = true }
loader.env.RA_TYPE = { passthrough = true }
loader.env.RA_TLS_ALLOW_DEBUG_ENCLAVE_INSECURE = { passthrough = true }
loader.env.RA_TLS_ALLOW_OUTDATED_TCB_INSECURE = { passthrough = true }
loader.env.RA_TLS_MRENCLAVE = { passthrough = true }
loader.env.RA_TLS_MRSIGNER = { passthrough = true }
loader.env.RA_TLS_ISV_SVN = { passthrough = true }
loader.env.RA_TLS_ISV_PROD_ID = { passthrough = true }
loader.env.RA_TLS_EPID_API_KEY = { passthrough = true }
loader.env.MYAPP_DATA = { passthrough = true }
loader.env.QUARTZ_PORT = { passthrough = true }
loader.argv = ["enclave",
"--chain-id", "testing",
"--fmspc", "{{ fmspc }}",
"--tcbinfo-contract", "{{ tcbinfo_contract }}",
"--dcap-verifier-contract", "{{ dcap_verifier_contract }}",
"--trusted-height", "{{ trusted_height }}",
"--trusted-hash", "{{ trusted_hash }}"]
fs.mounts = [
{ uri = "file:{{ gramine.runtimedir() }}", path = "/lib" },
{ uri = "file:{{ arch_libdir }}", path = "{{ arch_libdir }}" },
{ uri = "file:/usr/{{ arch_libdir }}", path = "/usr{{ arch_libdir }}" },
{ uri = "file:{{ quartz_dir }}", path = "{{ quartz_dir }}" },
]
# sgx.debug = true
sgx.enclave_size = "512M"
sgx.max_threads = 4
sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }}
sgx.remote_attestation = "{{ ra_type }}"
sgx.ra_client_spid = "{{ ra_client_spid }}"
sgx.ra_client_linkable = {{ 'true' if ra_client_linkable == '1' else 'false' }}
sgx.trusted_files = [
"file:{{ gramine.libos }}",
"file:{{ quartz_dir }}/target/release/mtcs-enclave",
"file:{{ gramine.runtimedir() }}/",
"file:{{ arch_libdir }}/",
"file:/usr/{{ arch_libdir }}/",
]
sgx.allowed_files = [
"file:{{ quartz_dir }}/exchange.sk",
"file:{{ quartz_dir }}/request.json",
]
sys.insecure__allow_eventfd = true
sys.enable_sigterm_injection = true

View file

@ -1,72 +0,0 @@
use std::net::SocketAddr;
use clap::Parser;
use color_eyre::eyre::{eyre, Result};
use cosmrs::AccountId;
use quartz_common::enclave::types::Fmspc;
use tendermint::Hash;
use tendermint_light_client::types::{Height, TrustThreshold};
fn parse_trust_threshold(s: &str) -> Result<TrustThreshold> {
if let Some((l, r)) = s.split_once('/') {
TrustThreshold::new(l.parse()?, r.parse()?).map_err(Into::into)
} else {
Err(eyre!(
"invalid trust threshold: {s}, format must be X/Y where X and Y are integers"
))
}
}
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
/// RPC server address
#[clap(long, default_value = "127.0.0.1:11090")]
pub rpc_addr: SocketAddr,
/// Identifier of the chain
#[clap(long)]
pub chain_id: String,
/// FMSPC (Family-Model-Stepping-Platform-Custom SKU)
#[clap(long)]
pub fmspc: Option<Fmspc>,
/// TcbInfo contract address
#[clap(long)]
pub tcbinfo_contract: Option<AccountId>,
/// DCAP verifier contract address
#[clap(long)]
pub dcap_verifier_contract: Option<AccountId>,
/// Height of the trusted header (AKA root-of-trust)
#[clap(long)]
pub trusted_height: Height,
/// Hash of the trusted header (AKA root-of-trust)
#[clap(long)]
pub trusted_hash: Hash,
/// Trust threshold
#[clap(long, value_parser = parse_trust_threshold, default_value_t = TrustThreshold::TWO_THIRDS)]
pub trust_threshold: TrustThreshold,
/// Trusting period, in seconds (default: two weeks)
#[clap(long, default_value = "1209600")]
pub trusting_period: u64,
/// Maximum clock drift, in seconds
#[clap(long, default_value = "5")]
pub max_clock_drift: u64,
/// Maximum block lag, in seconds
#[clap(long, default_value = "5")]
pub max_block_lag: u64,
#[clap(long, default_value = "127.0.0.1:11090")]
pub node_url: String,
#[clap(long, default_value = "admin")]
pub tx_sender: String,
}

View file

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

View file

@ -1,88 +0,0 @@
#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]
#![warn(
clippy::checked_conversions,
clippy::panic,
clippy::panic_in_result_fn,
trivial_casts,
trivial_numeric_casts,
rust_2018_idioms,
unused_lifetimes,
unused_import_braces,
unused_qualifications
)]
mod cli;
mod mtcs_server;
mod proto;
mod types;
mod wslistener;
use std::{
sync::{Arc, Mutex},
time::Duration,
};
use clap::Parser;
use cli::Cli;
use mtcs_server::MtcsService;
use quartz_common::{
contract::state::{Config, LightClientOpts},
enclave::{
attestor::{self, Attestor},
server::{QuartzServer, WsListenerConfig},
},
};
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
let light_client_opts = LightClientOpts::new(
args.chain_id.clone(),
args.trusted_height.into(),
Vec::from(args.trusted_hash)
.try_into()
.expect("invalid trusted hash"),
(
args.trust_threshold.numerator(),
args.trust_threshold.denominator(),
),
args.trusting_period,
args.max_clock_drift,
args.max_block_lag,
)?;
#[cfg(not(feature = "mock-sgx"))]
let attestor = attestor::DcapAttestor {
fmspc: args.fmspc.expect("FMSPC is required for DCAP"),
};
#[cfg(feature = "mock-sgx")]
let attestor = attestor::MockAttestor;
let config: Config = Config::new(
attestor.mr_enclave()?,
Duration::from_secs(30 * 24 * 60),
light_client_opts,
args.tcbinfo_contract.map(|c| c.to_string()),
args.dcap_verifier_contract.map(|c| c.to_string()),
);
let ws_config = WsListenerConfig {
node_url: args.node_url,
tx_sender: args.tx_sender,
trusted_hash: args.trusted_hash,
trusted_height: args.trusted_height,
chain_id: args.chain_id,
};
let sk = Arc::new(Mutex::new(None));
QuartzServer::new(config.clone(), sk.clone(), attestor.clone(), ws_config)
.add_service(MtcsService::new(config, sk, attestor))
.serve(args.rpc_addr)
.await?;
Ok(())
}

View file

@ -1,180 +0,0 @@
use std::{
collections::BTreeMap,
sync::{Arc, Mutex},
};
use cosmwasm_std::{Addr, HexBinary, Uint128};
use cw_tee_mtcs::{
msg::execute::SubmitSetoffsMsg,
state::{LiquiditySource, LiquiditySourceType, RawHash, SettleOff, Transfer},
};
use ecies::decrypt;
use k256::ecdsa::SigningKey;
use mtcs::{
algo::mcmf::primal_dual::PrimalDual, impls::complex_id::ComplexIdMtcs,
obligation::SimpleObligation, prelude::DefaultMtcs, setoff::SimpleSetoff, Mtcs,
};
use quartz_common::{
contract::{msg::execute::attested::RawAttested, state::Config},
enclave::{attestor::Attestor, server::IntoServer},
};
use tonic::{Request, Response, Result as TonicResult, Status};
use uuid::Uuid;
use crate::{
proto::{
clearing_server::{Clearing, ClearingServer},
RunClearingRequest, RunClearingResponse,
},
types::{ContractObligation, RunClearingMessage},
};
pub type RawCipherText = HexBinary;
impl<A: Attestor> IntoServer for MtcsService<A> {
type Server = ClearingServer<MtcsService<A>>;
fn into_server(self) -> Self::Server {
ClearingServer::new(self)
}
}
#[derive(Clone, Debug)]
pub struct MtcsService<A> {
#[allow(dead_code)]
config: Config, // TODO: this config is not used anywhere
sk: Arc<Mutex<Option<SigningKey>>>,
attestor: A,
}
impl<A> MtcsService<A>
where
A: Attestor,
{
pub fn new(config: Config, sk: Arc<Mutex<Option<SigningKey>>>, attestor: A) -> Self {
Self {
config,
sk,
attestor,
}
}
}
#[tonic::async_trait]
impl<A> Clearing for MtcsService<A>
where
A: Attestor + Send + Sync + 'static,
{
async fn run(
&self,
request: Request<RunClearingRequest>,
) -> TonicResult<Response<RunClearingResponse>> {
// Light client check
let message: RunClearingMessage = {
let message = request.into_inner().message;
serde_json::from_str(&message).map_err(|e| Status::invalid_argument(e.to_string()))?
};
// let (proof_value, message) = message
// .verify(self.config.light_client_opts())
// .map_err(Status::failed_precondition)?;
// let proof_value_matches_msg =
// serde_json::to_string(&message.intents).is_ok_and(|s| s.as_bytes() == proof_value);
// if !proof_value_matches_msg {
// return Err(Status::failed_precondition("proof verification"));
// }
// TODO: ensure no duplicates somewhere else!
let liquidity_sources: Vec<LiquiditySource> =
message.liquidity_sources.into_iter().collect();
let digests_ciphertexts: BTreeMap<HexBinary, HexBinary> = message.intents;
let (digests, ciphertexts): (Vec<_>, Vec<_>) = digests_ciphertexts.into_iter().unzip();
let sk = self.sk.lock().unwrap();
let obligations: Vec<SimpleObligation<LiquiditySource, i64, Uuid>> = ciphertexts
.into_iter()
.map(|ciphertext| decrypt_obligation(sk.as_ref().unwrap(), &ciphertext))
.collect();
let mut mtcs = ComplexIdMtcs::wrapping(DefaultMtcs::new(PrimalDual::default()));
let setoffs: Vec<SimpleSetoff<LiquiditySource, i64, Uuid>> = mtcs.run(obligations).unwrap();
let setoffs_enc: BTreeMap<RawHash, SettleOff> = setoffs
.into_iter()
.map(|so| into_settle_offs(so, &liquidity_sources))
.zip(digests)
.map(|(settle_off, digest)| (digest, settle_off))
.collect();
let msg = SubmitSetoffsMsg { setoffs_enc };
println!("setoff_msg: {:?}", msg);
let attestation = self
.attestor
.attestation(msg.clone())
.map_err(|e| Status::internal(e.to_string()))?;
let attested_msg = RawAttested {
msg,
attestation: A::RawAttestation::from(attestation),
};
let message = serde_json::to_string(&attested_msg).unwrap();
Ok(Response::new(RunClearingResponse { message }))
}
}
// TODO Switch from Vec<_> to Vec<LiquiditySource>
fn into_settle_offs(
so: SimpleSetoff<LiquiditySource, i64, Uuid>,
liquidity_sources: &Vec<LiquiditySource>,
) -> SettleOff {
println!("\nsetoff: {:?}", so);
println!("\nliq sources: {:?}", liquidity_sources);
// TODO: temporary patch, fix issue with liquidity sources becoming type External so that .contains() can be called directly
let liquidity_sources_addrs = liquidity_sources
.iter()
.map(|lqs| lqs.address.clone())
.collect::<Vec<Addr>>();
// In tenders and acceptances, the creditor's balance decreases
if liquidity_sources_addrs.contains(&so.debtor.address)
|| liquidity_sources_addrs.contains(&so.creditor.address)
{
SettleOff::Transfer(Transfer {
payer: so.creditor.address.clone(),
payee: so.debtor.address.clone(),
// TODO: Include denominations
amount: ("peppicoin".to_owned(), Uint128::from(so.set_off as u128)),
})
} else {
// TODO: Tracked by issue #22
// A no-op for the time being.
SettleOff::SetOff(vec![])
}
}
fn decrypt_obligation(
sk: &SigningKey,
ciphertext: &RawCipherText,
) -> SimpleObligation<LiquiditySource, i64, Uuid> {
let o: ContractObligation = {
let o = decrypt(&sk.to_bytes(), ciphertext).unwrap();
serde_json::from_slice(&o).unwrap()
};
SimpleObligation::new(
None,
LiquiditySource {
address: o.debtor,
source_type: LiquiditySourceType::External,
},
LiquiditySource {
address: o.creditor,
source_type: LiquiditySourceType::External,
},
i64::try_from(o.amount).unwrap(),
)
.unwrap()
}

View file

@ -1,290 +0,0 @@
// This file is @generated by prost-build.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RunClearingRequest {
#[prost(string, tag = "1")]
pub message: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RunClearingResponse {
#[prost(string, tag = "1")]
pub message: ::prost::alloc::string::String,
}
/// Generated client implementations.
pub mod clearing_client {
#![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
use tonic::codegen::*;
use tonic::codegen::http::Uri;
#[derive(Debug, Clone)]
pub struct ClearingClient<T> {
inner: tonic::client::Grpc<T>,
}
impl ClearingClient<tonic::transport::Channel> {
/// Attempt to create a new client by connecting to a given endpoint.
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
where
D: TryInto<tonic::transport::Endpoint>,
D::Error: Into<StdError>,
{
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
Ok(Self::new(conn))
}
}
impl<T> ClearingClient<T>
where
T: tonic::client::GrpcService<tonic::body::BoxBody>,
T::Error: Into<StdError>,
T::ResponseBody: Body<Data = Bytes> + Send + 'static,
<T::ResponseBody as Body>::Error: Into<StdError> + Send,
{
pub fn new(inner: T) -> Self {
let inner = tonic::client::Grpc::new(inner);
Self { inner }
}
pub fn with_origin(inner: T, origin: Uri) -> Self {
let inner = tonic::client::Grpc::with_origin(inner, origin);
Self { inner }
}
pub fn with_interceptor<F>(
inner: T,
interceptor: F,
) -> ClearingClient<InterceptedService<T, F>>
where
F: tonic::service::Interceptor,
T::ResponseBody: Default,
T: tonic::codegen::Service<
http::Request<tonic::body::BoxBody>,
Response = http::Response<
<T as tonic::client::GrpcService<tonic::body::BoxBody>>::ResponseBody,
>,
>,
<T as tonic::codegen::Service<
http::Request<tonic::body::BoxBody>,
>>::Error: Into<StdError> + Send + Sync,
{
ClearingClient::new(InterceptedService::new(inner, interceptor))
}
/// Compress requests with the given encoding.
///
/// This requires the server to support it otherwise it might respond with an
/// error.
#[must_use]
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.send_compressed(encoding);
self
}
/// Enable decompressing responses.
#[must_use]
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.accept_compressed(encoding);
self
}
/// Limits the maximum size of a decoded message.
///
/// Default: `4MB`
#[must_use]
pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_decoding_message_size(limit);
self
}
/// Limits the maximum size of an encoded message.
///
/// Default: `usize::MAX`
#[must_use]
pub fn max_encoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_encoding_message_size(limit);
self
}
pub async fn run(
&mut self,
request: impl tonic::IntoRequest<super::RunClearingRequest>,
) -> std::result::Result<
tonic::Response<super::RunClearingResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::new(
tonic::Code::Unknown,
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic::codec::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static("/mtcs.Clearing/Run");
let mut req = request.into_request();
req.extensions_mut().insert(GrpcMethod::new("mtcs.Clearing", "Run"));
self.inner.unary(req, path, codec).await
}
}
}
/// Generated server implementations.
pub mod clearing_server {
#![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
use tonic::codegen::*;
/// Generated trait containing gRPC methods that should be implemented for use with ClearingServer.
#[async_trait]
pub trait Clearing: Send + Sync + 'static {
async fn run(
&self,
request: tonic::Request<super::RunClearingRequest>,
) -> std::result::Result<
tonic::Response<super::RunClearingResponse>,
tonic::Status,
>;
}
#[derive(Debug)]
pub struct ClearingServer<T: Clearing> {
inner: Arc<T>,
accept_compression_encodings: EnabledCompressionEncodings,
send_compression_encodings: EnabledCompressionEncodings,
max_decoding_message_size: Option<usize>,
max_encoding_message_size: Option<usize>,
}
impl<T: Clearing> ClearingServer<T> {
pub fn new(inner: T) -> Self {
Self::from_arc(Arc::new(inner))
}
pub fn from_arc(inner: Arc<T>) -> Self {
Self {
inner,
accept_compression_encodings: Default::default(),
send_compression_encodings: Default::default(),
max_decoding_message_size: None,
max_encoding_message_size: None,
}
}
pub fn with_interceptor<F>(
inner: T,
interceptor: F,
) -> InterceptedService<Self, F>
where
F: tonic::service::Interceptor,
{
InterceptedService::new(Self::new(inner), interceptor)
}
/// Enable decompressing requests with the given encoding.
#[must_use]
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.accept_compression_encodings.enable(encoding);
self
}
/// Compress responses with the given encoding, if the client supports it.
#[must_use]
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.send_compression_encodings.enable(encoding);
self
}
/// Limits the maximum size of a decoded message.
///
/// Default: `4MB`
#[must_use]
pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
self.max_decoding_message_size = Some(limit);
self
}
/// Limits the maximum size of an encoded message.
///
/// Default: `usize::MAX`
#[must_use]
pub fn max_encoding_message_size(mut self, limit: usize) -> Self {
self.max_encoding_message_size = Some(limit);
self
}
}
impl<T, B> tonic::codegen::Service<http::Request<B>> for ClearingServer<T>
where
T: Clearing,
B: Body + Send + 'static,
B::Error: Into<StdError> + Send + 'static,
{
type Response = http::Response<tonic::body::BoxBody>;
type Error = std::convert::Infallible;
type Future = BoxFuture<Self::Response, Self::Error>;
fn poll_ready(
&mut self,
_cx: &mut Context<'_>,
) -> Poll<std::result::Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: http::Request<B>) -> Self::Future {
match req.uri().path() {
"/mtcs.Clearing/Run" => {
#[allow(non_camel_case_types)]
struct RunSvc<T: Clearing>(pub Arc<T>);
impl<
T: Clearing,
> tonic::server::UnaryService<super::RunClearingRequest>
for RunSvc<T> {
type Response = super::RunClearingResponse;
type Future = BoxFuture<
tonic::Response<Self::Response>,
tonic::Status,
>;
fn call(
&mut self,
request: tonic::Request<super::RunClearingRequest>,
) -> Self::Future {
let inner = Arc::clone(&self.0);
let fut = async move {
<T as Clearing>::run(&inner, request).await
};
Box::pin(fut)
}
}
let accept_compression_encodings = self.accept_compression_encodings;
let send_compression_encodings = self.send_compression_encodings;
let max_decoding_message_size = self.max_decoding_message_size;
let max_encoding_message_size = self.max_encoding_message_size;
let inner = self.inner.clone();
let fut = async move {
let method = RunSvc(inner);
let codec = tonic::codec::ProstCodec::default();
let mut grpc = tonic::server::Grpc::new(codec)
.apply_compression_config(
accept_compression_encodings,
send_compression_encodings,
)
.apply_max_message_size_config(
max_decoding_message_size,
max_encoding_message_size,
);
let res = grpc.unary(method, req).await;
Ok(res)
};
Box::pin(fut)
}
_ => {
Box::pin(async move {
Ok(
http::Response::builder()
.status(200)
.header("grpc-status", tonic::Code::Unimplemented as i32)
.header(
http::header::CONTENT_TYPE,
tonic::metadata::GRPC_CONTENT_TYPE,
)
.body(empty_body())
.unwrap(),
)
})
}
}
}
}
impl<T: Clearing> Clone for ClearingServer<T> {
fn clone(&self) -> Self {
let inner = self.inner.clone();
Self {
inner,
accept_compression_encodings: self.accept_compression_encodings,
send_compression_encodings: self.send_compression_encodings,
max_decoding_message_size: self.max_decoding_message_size,
max_encoding_message_size: self.max_encoding_message_size,
}
}
}
impl<T: Clearing> tonic::server::NamedService for ClearingServer<T> {
const NAME: &'static str = "mtcs.Clearing";
}
}

View file

@ -1,3 +0,0 @@
#![allow(clippy::unwrap_used, unused_qualifications)]
include!(concat!("prost/", "mtcs.rs"));

View file

@ -1,68 +0,0 @@
use std::collections::{BTreeMap, BTreeSet};
use cosmwasm_std::{Addr, HexBinary};
use cw_tee_mtcs::state::{LiquiditySource, RawCipherText, RawHash};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RunClearingMessage {
pub intents: BTreeMap<RawHash, RawCipherText>,
pub liquidity_sources: BTreeSet<LiquiditySource>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ContractObligation {
pub debtor: Addr,
pub creditor: Addr,
pub amount: u64,
#[serde(default)]
pub salt: HexBinary,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RawObligation {
pub debtor: HexBinary,
pub creditor: HexBinary,
pub amount: u64,
#[serde(default)]
pub salt: HexBinary,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RawEncryptedObligation {
pub digest: HexBinary,
pub ciphertext: HexBinary,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SubmitObligationsMsg {
pub submit_obligations: SubmitObligationsMsgInner,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SubmitObligationsMsgInner {
pub obligations: Vec<RawEncryptedObligation>,
pub liquidity_sources: Vec<LiquiditySource>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RawSetOff {
SetOff(Vec<HexBinary>),
Transfer(RawSetOffTransfer),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RawSetOffTransfer {
pub payer: String,
pub payee: String,
pub amount: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RawOffset {
pub debtor: HexBinary,
pub creditor: HexBinary,
pub amount: u64,
pub set_off: u64,
}

View file

@ -1,231 +0,0 @@
//TODO: get rid of this
use std::{collections::BTreeMap, str::FromStr};
use anyhow::{anyhow, Result};
use base64::prelude::*;
use cosmrs::{tendermint::chain::Id as ChainId, AccountId};
use cosmwasm_std::{HexBinary, Uint64};
use cw_tee_mtcs::msg::{
execute::SubmitSetoffsMsg, AttestedMsg, ExecuteMsg, GetLiquiditySourcesResponse,
QueryMsg::GetLiquiditySources,
};
use quartz_common::{
contract::msg::execute::attested::{
MockAttestation, RawAttested, RawAttestedMsgSansHandler, RawMockAttestation,
},
enclave::{
attestor::Attestor,
server::{WebSocketHandler, WsListenerConfig},
},
};
use reqwest::Url;
// use quartz_tee_ra::{intel_sgx::epid::types::ReportBody, IASReport};
use serde_json::json;
use tendermint_rpc::{event::Event, query::EventType};
use tonic::Request;
use wasmd_client::{CliWasmdClient, QueryResult, WasmdClient};
use crate::{
mtcs_server::MtcsService,
proto::{clearing_server::Clearing, RunClearingRequest},
types::RunClearingMessage,
};
// TODO: Need to prevent listener from taking actions until handshake is completed
#[async_trait::async_trait]
impl<A: Attestor> WebSocketHandler for MtcsService<A> {
async fn handle(&self, event: Event, config: WsListenerConfig) -> Result<()> {
// Validation
if !is_init_clearing_event(&event) {
return Ok(());
} else {
println!("Found clearing event");
let mut sender = None;
let mut contract_address = None;
if let Some(events) = &event.events {
for (key, values) in events {
match key.as_str() {
"message.sender" => {
sender = values.first().cloned();
}
"wasm._contract_address" => {
contract_address = values.first().cloned();
}
_ => {}
}
}
}
// TODO: add some checks based on event messages
if sender.is_none() || contract_address.is_none() {
return Ok(()); // TODO: change return type
}
handler(
self,
&contract_address
.expect("infallible")
.parse::<AccountId>()
.map_err(|e| anyhow!(e))?,
sender.expect("infallible"),
&config.node_url,
)
.await?;
}
Ok(())
}
}
fn is_init_clearing_event(event: &Event) -> bool {
// Check if the event is a transaction type
if let Some(EventType::Tx) = event.event_type() {
// Check for the "wasm.action" key with the value "init_clearing"
if let Some(events) = &event.events {
return events.iter().any(|(key, values)| {
key == "wasm.action" && values.contains(&"init_clearing".to_string())
});
}
}
false
}
async fn handler<A: Attestor>(
client: &MtcsService<A>,
contract: &AccountId,
sender: String,
node_url: &str,
) -> Result<()> {
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 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 attested: RawAttested<SubmitSetoffsMsg, Vec<u8>> =
serde_json::from_str(&clearing_response.message)
.map_err(|e| anyhow!("Error serializing SubmitSetoffs: {}", e))?;
// TODO add non-mock support, get IAS report and build attested message
let msg = RawAttestedMsgSansHandler(attested.msg);
let setoffs_msg = ExecuteMsg::SubmitSetoffs::<RawMockAttestation>(AttestedMsg {
msg,
attestation: MockAttestation(attested.attestation.try_into().unwrap()).into(),
});
// Send setoffs to mtcs contract on chain
let output =
wasmd_client.tx_execute(contract, chain_id, 2000000, &sender, json!(setoffs_msg))?;
println!("Setoffs TX: {}", output);
Ok(())
}
// TODO: replace raw queries with smart
async fn query_chain(
wasmd_client: &CliWasmdClient,
contract: &AccountId,
) -> Result<RunClearingMessage> {
// 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)?)?
.trim_matches('"')
.parse::<usize>()?;
if epoch_counter > 1 {
epoch_counter -= 1;
}
// TODO: replace with tracer log here
// println!("epoch: {}", epoch_counter);
// Get obligations
let resp: QueryResult<String> = wasmd_client
.query_raw(
contract,
hex::encode(format!("{}/obligations", epoch_counter)),
)
.map_err(|e| anyhow!("Problem querying obligatons: {}", e))?;
let decoded_obligs = BASE64_STANDARD.decode(resp.data)?;
let obligations_map: BTreeMap<HexBinary, HexBinary> =
serde_json::from_slice(&decoded_obligs).unwrap_or_default();
// println!("obligations \n {:?}", obligations_map);
// TODO: replace with tracer log here
// Get liquidity sources
let resp: QueryResult<GetLiquiditySourcesResponse> = wasmd_client
.query_smart(
contract,
json!(GetLiquiditySources {
epoch: Some(Uint64::new(epoch_counter as u64))
}),
)
.map_err(|e| anyhow!("Problem querying liquidity sources: {}", e))?;
let liquidity_sources = resp.data.liquidity_sources;
// TODO: replace with tracer log here
// println!("liquidity_sources \n {:?}", liquidity_sources);
Ok(RunClearingMessage {
intents: obligations_map,
liquidity_sources: liquidity_sources.into_iter().collect(),
})
}
// Request the IAS report for EPID attestations
// async fn gramine_ias_request(
// attested_msg: Vec<u8>,
// user: &str,
// ) -> Result<EpidAttestation, anyhow::Error> {
// let ias_api_key = String::from("669244b3e6364b5888289a11d2a1726d");
// let ra_client_spid = String::from("51CAF5A48B450D624AEFE3286D314894");
// let quote_file = format!("/tmp/{}_test.quote", user);
// let report_file = format!("/tmp/{}_datareport", user);
// let report_sig_file = format!("/tmp/{}_datareportsig", user);
// // Write the binary data to a file
// let mut file = File::create(&quote_file).await?;
// file.write_all(&attested_msg)
// .await
// .map_err(|e| anyhow!("Couldn't write to file. {e}"))?;
// let mut gramine = Command::new("gramine-sgx-ias-request");
// let command = gramine
// .arg("report")
// .args(["-g", &ra_client_spid])
// .args(["-k", &ias_api_key])
// .args(["-q", &quote_file])
// .args(["-r", &report_file])
// .args(["-s", &report_sig_file]);
// let output = command.output()?;
// if !output.status.success() {
// return Err(anyhow!("Couldn't run gramine. {:?}", output));
// }
// let report: ReportBody = serde_json::from_str(&fs::read_to_string(report_file).await?)?;
// let report_sig_str = fs::read_to_string(report_sig_file).await?.replace('\r', "");
// let report_sig: Binary = Binary::from_base64(report_sig_str.trim())?;
// Ok(EpidAttestation::new(IASReport { report, report_sig }))
// }

View file

@ -1,2 +0,0 @@
[build]
target-dir = "target"

View file

@ -1,75 +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:-"null"}
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 " with cmd : $CMD"
echo "===================================================================="
RES=$($CMD tx wasm store "$WASM_BIN" --from "$USER_ADDR" $TXFLAG -y --output json)
echo $RES
TX_HASH=$(echo $RES | jq -r '.["txhash"]')
while ! $CMD query tx $TX_HASH &> /dev/null; do
echo "... 🕐 waiting for contract to deploy from tx hash $TX_HASH"
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 from tx hash $TX_HASH"
sleep 1
done
RES=$($CMD query wasm list-contract-by-code "$CODE_ID" --output json)
CONTRACT=$(echo $RES | jq -r '.contracts[0]')
echo "🚀 Successfully deployed and instantiated contract!"
echo "🔗 Chain ID: ${CHAIN_ID}"
echo "🆔 Code ID: ${CODE_ID}"
echo "📌 Contract Address: ${CONTRACT}"
echo "🔑 Contract Key: ${KEY}"
echo "🔖 Contract Label: ${LABEL}"

View file

@ -1,321 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ExecuteMsg",
"oneOf": [
{
"type": "string",
"enum": [
"deposit",
"withdraw"
]
},
{
"type": "object",
"required": [
"quartz"
],
"properties": {
"quartz": {
"$ref": "#/definitions/RawExecute_for_RawEpidAttestation"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"transfer_request"
],
"properties": {
"transfer_request": {
"$ref": "#/definitions/TransferRequestMsg"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"clear_text_transfer_request"
],
"properties": {
"clear_text_transfer_request": {
"$ref": "#/definitions/ClearTextTransferRequestMsg"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"update"
],
"properties": {
"update": {
"$ref": "#/definitions/RawAttested_for_RawUpdateMsg_and_RawEpidAttestation"
}
},
"additionalProperties": false
}
],
"definitions": {
"Addr": {
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
"type": "string"
},
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"ClearTextTransferRequestMsg": {
"type": "object",
"required": [
"amount",
"receiver",
"sender"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"receiver": {
"$ref": "#/definitions/Addr"
},
"sender": {
"$ref": "#/definitions/Addr"
}
},
"additionalProperties": false
},
"HexBinary": {
"description": "This is a wrapper around Vec<u8> to add hex de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is similar to `cosmwasm_std::Binary` but uses hex. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"IASReport": {
"type": "object",
"required": [
"report",
"reportsig"
],
"properties": {
"report": {
"$ref": "#/definitions/ReportBody"
},
"reportsig": {
"$ref": "#/definitions/Binary"
}
},
"additionalProperties": false
},
"RawAttested_for_RawSessionCreate_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawSessionCreate"
}
},
"additionalProperties": false
},
"RawAttested_for_RawSessionSetPubKey_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawSessionSetPubKey"
}
},
"additionalProperties": false
},
"RawAttested_for_RawUpdateMsg_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawUpdateMsg"
}
},
"additionalProperties": false
},
"RawEpidAttestation": {
"type": "object",
"required": [
"report"
],
"properties": {
"report": {
"$ref": "#/definitions/IASReport"
}
},
"additionalProperties": false
},
"RawExecute_for_RawEpidAttestation": {
"oneOf": [
{
"type": "object",
"required": [
"session_create"
],
"properties": {
"session_create": {
"$ref": "#/definitions/RawAttested_for_RawSessionCreate_and_RawEpidAttestation"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"session_set_pub_key"
],
"properties": {
"session_set_pub_key": {
"$ref": "#/definitions/RawAttested_for_RawSessionSetPubKey_and_RawEpidAttestation"
}
},
"additionalProperties": false
}
]
},
"RawSessionCreate": {
"type": "object",
"required": [
"nonce"
],
"properties": {
"nonce": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"RawSessionSetPubKey": {
"type": "object",
"required": [
"nonce",
"pub_key"
],
"properties": {
"nonce": {
"$ref": "#/definitions/HexBinary"
},
"pub_key": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"RawUpdateMsg": {
"type": "object",
"required": [
"ciphertext",
"quantity",
"withdrawals"
],
"properties": {
"ciphertext": {
"$ref": "#/definitions/HexBinary"
},
"quantity": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"withdrawals": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/Uint128"
}
}
},
"additionalProperties": false
},
"ReportBody": {
"type": "object",
"required": [
"advisoryIDs",
"advisoryURL",
"epidPseudonym",
"id",
"isvEnclaveQuoteBody",
"isvEnclaveQuoteStatus",
"platformInfoBlob",
"timestamp",
"version"
],
"properties": {
"advisoryIDs": {
"type": "array",
"items": {
"type": "string"
}
},
"advisoryURL": {
"type": "string"
},
"epidPseudonym": {
"$ref": "#/definitions/Binary"
},
"id": {
"type": "string"
},
"isvEnclaveQuoteBody": {
"$ref": "#/definitions/Binary"
},
"isvEnclaveQuoteStatus": {
"type": "string"
},
"platformInfoBlob": {
"type": "string"
},
"timestamp": {
"type": "string"
},
"version": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
"TransferRequestMsg": {
"type": "object",
"required": [
"ciphertext",
"digest"
],
"properties": {
"ciphertext": {
"$ref": "#/definitions/HexBinary"
},
"digest": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
}

View file

@ -1,233 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "InstantiateMsg",
"type": "object",
"required": [
"denom",
"quartz"
],
"properties": {
"denom": {
"type": "string"
},
"quartz": {
"$ref": "#/definitions/RawInstantiate_for_RawEpidAttestation"
}
},
"additionalProperties": false,
"definitions": {
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"Duration": {
"type": "object",
"required": [
"nanos",
"secs"
],
"properties": {
"nanos": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"secs": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
},
"HexBinary": {
"description": "This is a wrapper around Vec<u8> to add hex de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is similar to `cosmwasm_std::Binary` but uses hex. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"IASReport": {
"type": "object",
"required": [
"report",
"reportsig"
],
"properties": {
"report": {
"$ref": "#/definitions/ReportBody"
},
"reportsig": {
"$ref": "#/definitions/Binary"
}
},
"additionalProperties": false
},
"RawAttested_for_RawCoreInstantiate_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawCoreInstantiate"
}
},
"additionalProperties": false
},
"RawConfig": {
"type": "object",
"required": [
"epoch_duration",
"light_client_opts",
"mr_enclave"
],
"properties": {
"epoch_duration": {
"$ref": "#/definitions/Duration"
},
"light_client_opts": {
"$ref": "#/definitions/RawLightClientOpts"
},
"mr_enclave": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"RawCoreInstantiate": {
"type": "object",
"required": [
"config"
],
"properties": {
"config": {
"$ref": "#/definitions/RawConfig"
}
},
"additionalProperties": false
},
"RawEpidAttestation": {
"type": "object",
"required": [
"report"
],
"properties": {
"report": {
"$ref": "#/definitions/IASReport"
}
},
"additionalProperties": false
},
"RawInstantiate_for_RawEpidAttestation": {
"$ref": "#/definitions/RawAttested_for_RawCoreInstantiate_and_RawEpidAttestation"
},
"RawLightClientOpts": {
"type": "object",
"required": [
"chain_id",
"max_block_lag",
"max_clock_drift",
"trust_threshold",
"trusted_hash",
"trusted_height",
"trusting_period"
],
"properties": {
"chain_id": {
"type": "string"
},
"max_block_lag": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"max_clock_drift": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"trust_threshold": {
"type": "array",
"items": [
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
},
"trusted_hash": {
"$ref": "#/definitions/HexBinary"
},
"trusted_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"trusting_period": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
"ReportBody": {
"type": "object",
"required": [
"advisoryIDs",
"advisoryURL",
"epidPseudonym",
"id",
"isvEnclaveQuoteBody",
"isvEnclaveQuoteStatus",
"platformInfoBlob",
"timestamp",
"version"
],
"properties": {
"advisoryIDs": {
"type": "array",
"items": {
"type": "string"
}
},
"advisoryURL": {
"type": "string"
},
"epidPseudonym": {
"$ref": "#/definitions/Binary"
},
"id": {
"type": "string"
},
"isvEnclaveQuoteBody": {
"$ref": "#/definitions/Binary"
},
"isvEnclaveQuoteStatus": {
"type": "string"
},
"platformInfoBlob": {
"type": "string"
},
"timestamp": {
"type": "string"
},
"version": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
}
}

View file

@ -1,563 +0,0 @@
{
"contract_name": "transfers",
"contract_version": "0.1.0",
"idl_version": "1.0.0",
"instantiate": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "InstantiateMsg",
"type": "object",
"required": [
"denom",
"quartz"
],
"properties": {
"denom": {
"type": "string"
},
"quartz": {
"$ref": "#/definitions/RawInstantiate_for_RawEpidAttestation"
}
},
"additionalProperties": false,
"definitions": {
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"Duration": {
"type": "object",
"required": [
"nanos",
"secs"
],
"properties": {
"nanos": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"secs": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
},
"HexBinary": {
"description": "This is a wrapper around Vec<u8> to add hex de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is similar to `cosmwasm_std::Binary` but uses hex. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"IASReport": {
"type": "object",
"required": [
"report",
"reportsig"
],
"properties": {
"report": {
"$ref": "#/definitions/ReportBody"
},
"reportsig": {
"$ref": "#/definitions/Binary"
}
},
"additionalProperties": false
},
"RawAttested_for_RawCoreInstantiate_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawCoreInstantiate"
}
},
"additionalProperties": false
},
"RawConfig": {
"type": "object",
"required": [
"epoch_duration",
"light_client_opts",
"mr_enclave"
],
"properties": {
"epoch_duration": {
"$ref": "#/definitions/Duration"
},
"light_client_opts": {
"$ref": "#/definitions/RawLightClientOpts"
},
"mr_enclave": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"RawCoreInstantiate": {
"type": "object",
"required": [
"config"
],
"properties": {
"config": {
"$ref": "#/definitions/RawConfig"
}
},
"additionalProperties": false
},
"RawEpidAttestation": {
"type": "object",
"required": [
"report"
],
"properties": {
"report": {
"$ref": "#/definitions/IASReport"
}
},
"additionalProperties": false
},
"RawInstantiate_for_RawEpidAttestation": {
"$ref": "#/definitions/RawAttested_for_RawCoreInstantiate_and_RawEpidAttestation"
},
"RawLightClientOpts": {
"type": "object",
"required": [
"chain_id",
"max_block_lag",
"max_clock_drift",
"trust_threshold",
"trusted_hash",
"trusted_height",
"trusting_period"
],
"properties": {
"chain_id": {
"type": "string"
},
"max_block_lag": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"max_clock_drift": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"trust_threshold": {
"type": "array",
"items": [
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
},
"trusted_hash": {
"$ref": "#/definitions/HexBinary"
},
"trusted_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"trusting_period": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
"ReportBody": {
"type": "object",
"required": [
"advisoryIDs",
"advisoryURL",
"epidPseudonym",
"id",
"isvEnclaveQuoteBody",
"isvEnclaveQuoteStatus",
"platformInfoBlob",
"timestamp",
"version"
],
"properties": {
"advisoryIDs": {
"type": "array",
"items": {
"type": "string"
}
},
"advisoryURL": {
"type": "string"
},
"epidPseudonym": {
"$ref": "#/definitions/Binary"
},
"id": {
"type": "string"
},
"isvEnclaveQuoteBody": {
"$ref": "#/definitions/Binary"
},
"isvEnclaveQuoteStatus": {
"type": "string"
},
"platformInfoBlob": {
"type": "string"
},
"timestamp": {
"type": "string"
},
"version": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
}
},
"execute": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ExecuteMsg",
"oneOf": [
{
"type": "string",
"enum": [
"deposit",
"withdraw"
]
},
{
"type": "object",
"required": [
"quartz"
],
"properties": {
"quartz": {
"$ref": "#/definitions/RawExecute_for_RawEpidAttestation"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"transfer_request"
],
"properties": {
"transfer_request": {
"$ref": "#/definitions/TransferRequestMsg"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"clear_text_transfer_request"
],
"properties": {
"clear_text_transfer_request": {
"$ref": "#/definitions/ClearTextTransferRequestMsg"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"update"
],
"properties": {
"update": {
"$ref": "#/definitions/RawAttested_for_RawUpdateMsg_and_RawEpidAttestation"
}
},
"additionalProperties": false
}
],
"definitions": {
"Addr": {
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
"type": "string"
},
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"ClearTextTransferRequestMsg": {
"type": "object",
"required": [
"amount",
"receiver",
"sender"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"receiver": {
"$ref": "#/definitions/Addr"
},
"sender": {
"$ref": "#/definitions/Addr"
}
},
"additionalProperties": false
},
"HexBinary": {
"description": "This is a wrapper around Vec<u8> to add hex de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is similar to `cosmwasm_std::Binary` but uses hex. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"IASReport": {
"type": "object",
"required": [
"report",
"reportsig"
],
"properties": {
"report": {
"$ref": "#/definitions/ReportBody"
},
"reportsig": {
"$ref": "#/definitions/Binary"
}
},
"additionalProperties": false
},
"RawAttested_for_RawSessionCreate_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawSessionCreate"
}
},
"additionalProperties": false
},
"RawAttested_for_RawSessionSetPubKey_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawSessionSetPubKey"
}
},
"additionalProperties": false
},
"RawAttested_for_RawUpdateMsg_and_RawEpidAttestation": {
"type": "object",
"required": [
"attestation",
"msg"
],
"properties": {
"attestation": {
"$ref": "#/definitions/RawEpidAttestation"
},
"msg": {
"$ref": "#/definitions/RawUpdateMsg"
}
},
"additionalProperties": false
},
"RawEpidAttestation": {
"type": "object",
"required": [
"report"
],
"properties": {
"report": {
"$ref": "#/definitions/IASReport"
}
},
"additionalProperties": false
},
"RawExecute_for_RawEpidAttestation": {
"oneOf": [
{
"type": "object",
"required": [
"session_create"
],
"properties": {
"session_create": {
"$ref": "#/definitions/RawAttested_for_RawSessionCreate_and_RawEpidAttestation"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"session_set_pub_key"
],
"properties": {
"session_set_pub_key": {
"$ref": "#/definitions/RawAttested_for_RawSessionSetPubKey_and_RawEpidAttestation"
}
},
"additionalProperties": false
}
]
},
"RawSessionCreate": {
"type": "object",
"required": [
"nonce"
],
"properties": {
"nonce": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"RawSessionSetPubKey": {
"type": "object",
"required": [
"nonce",
"pub_key"
],
"properties": {
"nonce": {
"$ref": "#/definitions/HexBinary"
},
"pub_key": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"RawUpdateMsg": {
"type": "object",
"required": [
"ciphertext",
"quantity",
"withdrawals"
],
"properties": {
"ciphertext": {
"$ref": "#/definitions/HexBinary"
},
"quantity": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"withdrawals": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/Uint128"
}
}
},
"additionalProperties": false
},
"ReportBody": {
"type": "object",
"required": [
"advisoryIDs",
"advisoryURL",
"epidPseudonym",
"id",
"isvEnclaveQuoteBody",
"isvEnclaveQuoteStatus",
"platformInfoBlob",
"timestamp",
"version"
],
"properties": {
"advisoryIDs": {
"type": "array",
"items": {
"type": "string"
}
},
"advisoryURL": {
"type": "string"
},
"epidPseudonym": {
"$ref": "#/definitions/Binary"
},
"id": {
"type": "string"
},
"isvEnclaveQuoteBody": {
"$ref": "#/definitions/Binary"
},
"isvEnclaveQuoteStatus": {
"type": "string"
},
"platformInfoBlob": {
"type": "string"
},
"timestamp": {
"type": "string"
},
"version": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
"TransferRequestMsg": {
"type": "object",
"required": [
"ciphertext",
"digest"
],
"properties": {
"ciphertext": {
"$ref": "#/definitions/HexBinary"
},
"digest": {
"$ref": "#/definitions/HexBinary"
}
},
"additionalProperties": false
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
},
"query": null,
"migrate": null,
"sudo": null,
"responses": null
}

View file

@ -1 +0,0 @@
## MTCS Server

View file

@ -1,9 +0,0 @@
mock_sgx = false
tx_sender = "admin"
chain_id = "testing"
node_url = "127.0.0.1:26657"
enclave_rpc_addr = "http://127.0.0.1"
enclave_rpc_port = 11090
trusted_hash = ""
trusted_height = 0
release = true

17
cosmwasm/.gitignore vendored
View file

@ -1,17 +0,0 @@
# Build results
/artifacts
target/
schema/
# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327)
.cargo-ok
# Text file backups
**/*.rs.bk
# macOS
.DS_Store
# IDEs
*.iml
.idea

View file

@ -1,11 +0,0 @@
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.rs]
indent_size = 4

Some files were not shown because too many files have changed in this diff Show more