Skip to content

Commit

Permalink
Dyn liquidity sources (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
hu55a1n1 authored Jun 18, 2024
1 parent d78183b commit 3509edf
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 127 deletions.
73 changes: 38 additions & 35 deletions apps/mtcs/contracts/cw-tee-mtcs/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ use cosmwasm_std::{
};
use cw2::set_contract_version;
use cw20_base::{
contract::{execute_mint, query_balance as cw20_query_balance},
contract::query_balance as cw20_query_balance,
state::{MinterData, TokenInfo, TOKEN_INFO},
};
use quartz_cw::{handler::RawHandler, state::EPOCH_COUNTER};

use crate::{
error::ContractError,
msg::{
execute::{SubmitObligationMsg, SubmitObligationsMsg, SubmitSetoffsMsg},
execute::{
Cw20Transfer, FaucetMintMsg, SubmitObligationMsg, SubmitObligationsMsg,
SubmitSetoffsMsg,
},
ExecuteMsg, InstantiateMsg, QueryMsg,
},
state::{
Expand Down Expand Up @@ -63,35 +66,6 @@ pub fn instantiate(
};
TOKEN_INFO.save(deps.storage, &data)?;

let info = MessageInfo {
sender: env.contract.address.clone(),
funds: vec![],
};

execute_mint(
deps.branch(),
env.clone(),
info.clone(),
"wasm1qv9nel6lwtrq5jmwruxfndqw7ejskn5ysz53hp".to_owned(),
Uint128::new(1000),
)?;

execute_mint(
deps.branch(),
env.clone(),
info.clone(),
"wasm1tfxrdcj5kk6rewzmmkku4d9htpjqr0kk6lcftv".to_owned(),
Uint128::new(1000),
)?;

execute_mint(
deps.branch(),
env.clone(),
info.clone(),
"wasm1gjg72awjl7jvtmq4kjqp3al9p6crstpar8wgn5".to_owned(),
Uint128::new(1000),
)?;

Ok(Response::new()
.add_attribute("method", "instantiate")
.add_attribute("owner", info.sender))
Expand All @@ -106,6 +80,12 @@ pub fn execute(
) -> 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)
}
Expand All @@ -120,7 +100,7 @@ pub fn execute(
Ok(Response::new())
}
ExecuteMsg::SubmitSetoffs(SubmitSetoffsMsg { setoffs_enc }) => {
execute::submit_setoffs(deps, env, info, setoffs_enc)
execute::submit_setoffs(deps, env, setoffs_enc)
}
ExecuteMsg::InitClearing => execute::init_clearing(deps),
}
Expand All @@ -131,6 +111,7 @@ pub mod execute {

use cosmwasm_std::{DepsMut, Env, HexBinary, MessageInfo, Response, StdResult};
use cw20_base::contract::{execute_burn, execute_mint};
use k256::ecdsa::VerifyingKey;
use quartz_cw::state::{Hash, EPOCH_COUNTER};

use crate::{
Expand All @@ -141,6 +122,28 @@ pub mod execute {
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,
Expand All @@ -167,11 +170,12 @@ pub mod execute {

pub fn append_liquidity_sources(
deps: DepsMut,
liquidity_sources: Vec<String>,
liquidity_sources: Vec<HexBinary>,
) -> Result<(), ContractError> {
// validate liquidity sources as public keys
liquidity_sources
.iter()
.try_for_each(|ls| deps.api.addr_validate(ls).map(|_| ()))?;
.try_for_each(|ls| VerifyingKey::from_sec1_bytes(ls).map(|_| ()))?;

// store the liquidity sources
LiquiditySourcesItem::new(&current_epoch_key(LIQUIDITY_SOURCES_KEY, deps.storage)?)
Expand All @@ -186,7 +190,6 @@ pub mod execute {
pub fn submit_setoffs(
mut deps: DepsMut,
env: Env,
_info: MessageInfo,
setoffs_enc: BTreeMap<RawHash, SettleOff>,
) -> Result<Response, ContractError> {
// store the `BTreeMap<RawHash, RawCipherText>`
Expand Down
18 changes: 16 additions & 2 deletions apps/mtcs/contracts/cw-tee-mtcs/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub struct InstantiateMsg(pub QuartzInstantiateMsg);
#[allow(clippy::large_enum_variant)]
pub enum ExecuteMsg {
Quartz(QuartzExecuteMsg),
FaucetMint(execute::FaucetMintMsg),
Transfer(execute::Cw20Transfer),
SubmitObligation(execute::SubmitObligationMsg),
SubmitObligations(execute::SubmitObligationsMsg),
SubmitSetoffs(execute::SubmitSetoffsMsg),
Expand All @@ -22,6 +24,18 @@ pub enum ExecuteMsg {
pub mod execute {
use super::*;

#[cw_serde]
pub struct FaucetMintMsg {
pub recipient: String,
pub amount: u64,
}

#[cw_serde]
pub struct Cw20Transfer {
pub recipient: String,
pub amount: u64,
}

#[cw_serde]
pub struct SubmitObligationMsg {
pub ciphertext: HexBinary,
Expand All @@ -33,7 +47,7 @@ pub mod execute {
#[cw_serde]
pub struct SubmitObligationsMsg {
pub obligations: Vec<SubmitObligationMsg>,
pub liquidity_sources: Vec<String>,
pub liquidity_sources: Vec<HexBinary>,
}

#[cw_serde]
Expand Down Expand Up @@ -69,7 +83,7 @@ pub struct GetAllSetoffsResponse {

#[cw_serde]
pub struct GetLiquiditySourcesResponse {
pub liquidity_sources: Vec<String>,
pub liquidity_sources: Vec<HexBinary>,
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion apps/mtcs/contracts/cw-tee-mtcs/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub type RawCipherText = HexBinary;

pub type ObligationsItem<'a> = Item<'a, BTreeMap<RawHash, RawCipherText>>;
pub type SetoffsItem<'a> = Item<'a, BTreeMap<RawHash, SettleOff>>;
pub type LiquiditySourcesItem<'a> = Item<'a, BTreeSet<String>>;
pub type LiquiditySourcesItem<'a> = Item<'a, BTreeSet<HexBinary>>;

#[cw_serde]
pub struct State {
Expand Down
41 changes: 28 additions & 13 deletions core/quartz/src/mtcs_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,26 @@ use mtcs::{
algo::mcmf::primal_dual::PrimalDual, impls::complex_id::ComplexIdMtcs,
obligation::SimpleObligation, prelude::DefaultMtcs, setoff::SimpleSetoff, Mtcs,
};
use serde::{Deserialize, Serialize};
use tonic::{Request, Response, Result as TonicResult, Status};

use crate::{
attestor::Attestor,
proto::{clearing_server::Clearing, RunClearingRequest, RunClearingResponse},
};

const BANK_PK: &str = "0216254f4636c4e68ae22d98538851a46810b65162fe37bf57cba6d563617c913e";

#[derive(Clone, Debug)]
pub struct MtcsService<A> {
sk: Arc<Mutex<Option<SigningKey>>>,
_attestor: A,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RunClearingMessage {
intents: BTreeMap<RawHash, RawCipherText>,
liquidity_sources: Vec<HexBinary>,
}

impl<A> MtcsService<A>
where
A: Attestor,
Expand All @@ -49,10 +54,12 @@ where
&self,
request: Request<RunClearingRequest>,
) -> TonicResult<Response<RunClearingResponse>> {
let message = request.into_inner().message;
let message: RunClearingMessage = {
let message = request.into_inner().message;
serde_json::from_str(&message).map_err(|e| Status::invalid_argument(e.to_string()))?
};

let digests_ciphertexts: BTreeMap<RawHash, RawCipherText> =
serde_json::from_str(&message).map_err(|e| Status::invalid_argument(e.to_string()))?;
let digests_ciphertexts = message.intents;
let (digests, ciphertexts): (Vec<_>, Vec<_>) = digests_ciphertexts.into_iter().unzip();

let sk = self.sk.lock().unwrap();
Expand All @@ -64,9 +71,16 @@ where
let mut mtcs = ComplexIdMtcs::wrapping(DefaultMtcs::new(PrimalDual::default()));
let setoffs: Vec<SimpleSetoff<_, i64>> = mtcs.run(obligations).unwrap();

let liquidity_sources: Vec<_> = message
.liquidity_sources
.into_iter()
.map(|ls| VerifyingKey::from_sec1_bytes(&ls))
.collect::<Result<_, _>>()
.map_err(|e| Status::invalid_argument(e.to_string()))?;

let setoffs_enc: BTreeMap<RawHash, SettleOff> = setoffs
.into_iter()
.map(into_settle_offs)
.map(|so| into_settle_offs(so, &liquidity_sources))
.zip(digests)
.map(|(settle_off, digest)| (digest, settle_off))
.collect();
Expand All @@ -76,25 +90,26 @@ where
}
}

fn into_settle_offs(so: SimpleSetoff<HexBinary, i64>) -> SettleOff {
fn into_settle_offs(
so: SimpleSetoff<HexBinary, i64>,
liquidity_sources: &[VerifyingKey],
) -> SettleOff {
let debtor_pk = VerifyingKey::from_sec1_bytes(&so.debtor).unwrap();
let creditor_pk = VerifyingKey::from_sec1_bytes(&so.creditor).unwrap();

let bank_pk = VerifyingKey::from_sec1_bytes(&hex::decode(BANK_PK).unwrap()).unwrap();
let bank_addrs = wasm_address(bank_pk);
if debtor_pk == bank_pk {
if let Some(ls_pk) = liquidity_sources.iter().find(|ls| ls == &&debtor_pk) {
// A setoff on a tender should result in the creditor's (i.e. the tender receiver) balance
// decreasing by the setoff amount
SettleOff::Transfer(Transfer {
payer: wasm_address(creditor_pk),
payee: bank_addrs,
payee: wasm_address(*ls_pk),
amount: so.set_off as u64,
})
} else if creditor_pk == bank_pk {
} else if let Some(ls_pk) = liquidity_sources.iter().find(|ls| ls == &&creditor_pk) {
// A setoff on an acceptance should result in the debtor's (i.e. the acceptance initiator)
// balance increasing by the setoff amount
SettleOff::Transfer(Transfer {
payer: bank_addrs,
payer: wasm_address(*ls_pk),
payee: wasm_address(debtor_pk),
amount: so.set_off as u64,
})
Expand Down
17 changes: 16 additions & 1 deletion utils/cycles-sync/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use displaydoc::Display;
use reqwest::Url;
use subtle_encoding::{bech32::decode as bech32_decode, Error as Bech32DecodeError};
use thiserror::Error;
use uuid::Uuid;

use crate::ADDRESS_PREFIX;

#[derive(Clone, Debug, Parser)]
#[command(author, version, about)]
Expand Down Expand Up @@ -61,9 +64,17 @@ pub enum CliCommand {
/// epoch pk
#[arg(short, long)]
epoch_pk: String,
/// liquidity sources' UUIDs
#[arg(short, long, num_args = 1.., value_parser = parse_uuid)]
liquidity_sources: Vec<Uuid>,
},
/// Sync set-offs
SyncSetOffs,
/// Get address for Uuid
GetAddress {
#[arg(long, value_parser = parse_uuid)]
uuid: Uuid,
},
}

#[derive(Display, Error, Debug)]
Expand All @@ -76,9 +87,13 @@ pub enum AddressError {

fn wasm_address(address_str: &str) -> Result<AccountId, AddressError> {
let (hr, _) = bech32_decode(address_str).map_err(AddressError::NotBech32Encoded)?;
if hr != "wasm" {
if hr != ADDRESS_PREFIX {
return Err(AddressError::HumanReadableMismatch(hr));
}

Ok(address_str.parse().unwrap())
}

fn parse_uuid(uuid_str: &str) -> Result<Uuid, String> {
Uuid::parse_str(uuid_str).map_err(|e| e.to_string())
}
Loading

0 comments on commit 3509edf

Please sign in to comment.