Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dyn liquidity sources #52

Merged
merged 7 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading