From 3509edfe3d0e9d9ec61e08f6a0653d006bba5b62 Mon Sep 17 00:00:00 2001 From: Shoaib Ahmed Date: Tue, 18 Jun 2024 02:30:00 -0700 Subject: [PATCH] Dyn liquidity sources (#52) --- .../contracts/cw-tee-mtcs/src/contract.rs | 73 +++---- apps/mtcs/contracts/cw-tee-mtcs/src/msg.rs | 18 +- apps/mtcs/contracts/cw-tee-mtcs/src/state.rs | 2 +- core/quartz/src/mtcs_server.rs | 41 ++-- utils/cycles-sync/src/cli.rs | 17 +- utils/cycles-sync/src/main.rs | 182 +++++++++++------- utils/cycles-sync/src/obligato_client/mock.rs | 7 +- utils/cycles-sync/src/types.rs | 8 +- 8 files changed, 221 insertions(+), 127 deletions(-) diff --git a/apps/mtcs/contracts/cw-tee-mtcs/src/contract.rs b/apps/mtcs/contracts/cw-tee-mtcs/src/contract.rs index e218a95..a038ab8 100644 --- a/apps/mtcs/contracts/cw-tee-mtcs/src/contract.rs +++ b/apps/mtcs/contracts/cw-tee-mtcs/src/contract.rs @@ -4,7 +4,7 @@ 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}; @@ -12,7 +12,10 @@ 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::{ @@ -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)) @@ -106,6 +80,12 @@ pub fn execute( ) -> Result { 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) } @@ -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), } @@ -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::{ @@ -141,6 +122,28 @@ pub mod execute { ContractError, }; + pub fn faucet_mint( + mut deps: DepsMut, + env: Env, + recipient: String, + amount: u64, + ) -> Result { + 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, @@ -167,11 +170,12 @@ pub mod execute { pub fn append_liquidity_sources( deps: DepsMut, - liquidity_sources: Vec, + liquidity_sources: Vec, ) -> 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(¤t_epoch_key(LIQUIDITY_SOURCES_KEY, deps.storage)?) @@ -186,7 +190,6 @@ pub mod execute { pub fn submit_setoffs( mut deps: DepsMut, env: Env, - _info: MessageInfo, setoffs_enc: BTreeMap, ) -> Result { // store the `BTreeMap` diff --git a/apps/mtcs/contracts/cw-tee-mtcs/src/msg.rs b/apps/mtcs/contracts/cw-tee-mtcs/src/msg.rs index 3e0bfe6..a17e7ea 100644 --- a/apps/mtcs/contracts/cw-tee-mtcs/src/msg.rs +++ b/apps/mtcs/contracts/cw-tee-mtcs/src/msg.rs @@ -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), @@ -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, @@ -33,7 +47,7 @@ pub mod execute { #[cw_serde] pub struct SubmitObligationsMsg { pub obligations: Vec, - pub liquidity_sources: Vec, + pub liquidity_sources: Vec, } #[cw_serde] @@ -69,7 +83,7 @@ pub struct GetAllSetoffsResponse { #[cw_serde] pub struct GetLiquiditySourcesResponse { - pub liquidity_sources: Vec, + pub liquidity_sources: Vec, } #[cfg(test)] diff --git a/apps/mtcs/contracts/cw-tee-mtcs/src/state.rs b/apps/mtcs/contracts/cw-tee-mtcs/src/state.rs index dcdb30b..f9672f8 100644 --- a/apps/mtcs/contracts/cw-tee-mtcs/src/state.rs +++ b/apps/mtcs/contracts/cw-tee-mtcs/src/state.rs @@ -10,7 +10,7 @@ pub type RawCipherText = HexBinary; pub type ObligationsItem<'a> = Item<'a, BTreeMap>; pub type SetoffsItem<'a> = Item<'a, BTreeMap>; -pub type LiquiditySourcesItem<'a> = Item<'a, BTreeSet>; +pub type LiquiditySourcesItem<'a> = Item<'a, BTreeSet>; #[cw_serde] pub struct State { diff --git a/core/quartz/src/mtcs_server.rs b/core/quartz/src/mtcs_server.rs index 49a9cdf..e56e182 100644 --- a/core/quartz/src/mtcs_server.rs +++ b/core/quartz/src/mtcs_server.rs @@ -16,6 +16,7 @@ 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::{ @@ -23,14 +24,18 @@ use crate::{ proto::{clearing_server::Clearing, RunClearingRequest, RunClearingResponse}, }; -const BANK_PK: &str = "0216254f4636c4e68ae22d98538851a46810b65162fe37bf57cba6d563617c913e"; - #[derive(Clone, Debug)] pub struct MtcsService { sk: Arc>>, _attestor: A, } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct RunClearingMessage { + intents: BTreeMap, + liquidity_sources: Vec, +} + impl MtcsService where A: Attestor, @@ -49,10 +54,12 @@ where &self, request: Request, ) -> TonicResult> { - 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 = - 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(); @@ -64,9 +71,16 @@ where let mut mtcs = ComplexIdMtcs::wrapping(DefaultMtcs::new(PrimalDual::default())); let setoffs: Vec> = mtcs.run(obligations).unwrap(); + let liquidity_sources: Vec<_> = message + .liquidity_sources + .into_iter() + .map(|ls| VerifyingKey::from_sec1_bytes(&ls)) + .collect::>() + .map_err(|e| Status::invalid_argument(e.to_string()))?; + let setoffs_enc: BTreeMap = 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(); @@ -76,25 +90,26 @@ where } } -fn into_settle_offs(so: SimpleSetoff) -> SettleOff { +fn into_settle_offs( + so: SimpleSetoff, + 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, }) diff --git a/utils/cycles-sync/src/cli.rs b/utils/cycles-sync/src/cli.rs index d165117..194f704 100644 --- a/utils/cycles-sync/src/cli.rs +++ b/utils/cycles-sync/src/cli.rs @@ -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)] @@ -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, }, /// Sync set-offs SyncSetOffs, + /// Get address for Uuid + GetAddress { + #[arg(long, value_parser = parse_uuid)] + uuid: Uuid, + }, } #[derive(Display, Error, Debug)] @@ -76,9 +87,13 @@ pub enum AddressError { fn wasm_address(address_str: &str) -> Result { 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::parse_str(uuid_str).map_err(|e| e.to_string()) +} diff --git a/utils/cycles-sync/src/main.rs b/utils/cycles-sync/src/main.rs index aab1fd2..57805b5 100644 --- a/utils/cycles-sync/src/main.rs +++ b/utils/cycles-sync/src/main.rs @@ -12,9 +12,10 @@ use bip32::{ ecdsa::VerifyingKey, sha2::{Digest, Sha256}, }, - Language, Mnemonic, Prefix, PrivateKey, Seed, XPrv, + Error as Bip32Error, Language, Mnemonic, Prefix, PrivateKey, Seed, XPrv, }; use clap::Parser; +use cosmrs::{tendermint::account::Id as TmAccountId, AccountId}; use cosmwasm_std::HexBinary; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -26,7 +27,7 @@ use crate::{ obligato_client::{http::HttpClient, Client}, types::{ Obligation, ObligatoObligation, ObligatoSetOff, RawEncryptedObligation, RawObligation, - RawOffset, RawSetOff, SubmitObligationsMsg, + RawOffset, RawSetOff, SubmitObligationsMsg, SubmitObligationsMsgInner, }, wasmd_client::{CliWasmdClient, QueryResult, WasmdClient}, }; @@ -38,8 +39,7 @@ mod wasmd_client; const MNEMONIC_PHRASE: &str = "clutch debate vintage foster barely primary clown leader sell manual leopard ladder wet must embody story oyster imitate cable alien six square rice wedding"; -const ALICE_ID: &str = "7bfad4e8-d898-4ce2-bbac-1beff7182319"; -const BANK_DEBTOR_ID: &str = "3879fa15-d86e-4464-b679-0a3d78cf3dd3"; +const ADDRESS_PREFIX: &str = "wasm"; type Sha256Digest = [u8; 32]; @@ -65,15 +65,38 @@ async fn main() -> Result<(), DynError> { .init(); match cli.command { - CliCommand::SyncObligations { ref epoch_pk } => { - sync_obligations(cli.clone(), epoch_pk).await? - } + CliCommand::SyncObligations { + ref epoch_pk, + ref liquidity_sources, + } => sync_obligations(cli.clone(), epoch_pk, liquidity_sources).await?, CliCommand::SyncSetOffs => sync_setoffs(cli).await?, + CliCommand::GetAddress { uuid } => address_from_uuid(uuid)?, } Ok(()) } +fn address_from_uuid(uuid: Uuid) -> Result<(), DynError> { + let seed = global_seed()?; + let sk = derive_child_xprv(&seed, uuid); + let pk_b = sk.public_key().public_key().to_sec1_bytes(); + let pk = VerifyingKey::from_sec1_bytes(&pk_b)?; + println!("{}", wasm_address(pk)); + Ok(()) +} + +fn wasm_address(pk: VerifyingKey) -> String { + let tm_pk = TmAccountId::from(pk); + AccountId::new(ADDRESS_PREFIX, tm_pk.as_bytes()) + .unwrap() + .to_string() +} + +fn global_seed() -> Result { + let mnemonic = Mnemonic::new(MNEMONIC_PHRASE, Language::English)?; + Ok(mnemonic.to_seed("password")) +} + async fn sync_setoffs(cli: Cli) -> Result<(), DynError> { let wasmd_client = CliWasmdClient::new(cli.node); let query_result: QueryResult = @@ -123,34 +146,48 @@ async fn sync_setoffs(cli: Cli) -> Result<(), DynError> { Ok(()) } -async fn sync_obligations(cli: Cli, epoch_pk: &str) -> Result<(), DynError> { +async fn sync_obligations( + cli: Cli, + epoch_pk: &str, + liquidity_sources: &[Uuid], +) -> Result<(), DynError> { let mut intents = { - let client = HttpClient::new(cli.obligato_url, cli.obligato_key); - client.get_obligations().await.unwrap() + let client = HttpClient::new(cli.obligato_url.clone(), cli.obligato_key); + client + .get_obligations() + .await + .map_err(|_| cli.obligato_url.to_string())? }; - let bank_id = Uuid::parse_str(BANK_DEBTOR_ID).unwrap(); - let keys = derive_keys(&mut intents, bank_id)?; + let keys = derive_keys(&mut intents, liquidity_sources)?; write_keys_to_file(cli.keys_file, &keys); - add_default_acceptances(&mut intents, bank_id); + add_default_acceptances(&mut intents, liquidity_sources); debug!("intents: {intents:?}"); let intents_enc = { let epoch_pk = VerifyingKey::from_sec1_bytes(&hex::decode(epoch_pk).unwrap()).unwrap(); - encrypt_intents(intents, keys, &epoch_pk, cli.obligation_user_map_file) + encrypt_intents(intents, &keys, &epoch_pk, cli.obligation_user_map_file) }; debug!("Encrypted {} intents", intents_enc.len()); - let msg = create_wasm_msg(intents_enc); + let liquidity_sources = liquidity_sources + .iter() + .map(|id| keys[id].private_key().public_key()) + .collect(); + + let msg = create_wasm_msg(intents_enc, liquidity_sources)?; let wasmd_client = CliWasmdClient::new(cli.node); wasmd_client.tx_execute(&cli.contract, &cli.chain_id, 3000000, cli.user, msg)?; Ok(()) } -fn create_wasm_msg(obligations_enc: Vec<(Sha256Digest, Vec)>) -> serde_json::Value { +fn create_wasm_msg( + obligations_enc: Vec<(Sha256Digest, Vec)>, + liquidity_sources: Vec, +) -> Result { let obligations_enc: Vec<_> = obligations_enc .into_iter() .map(|(digest, ciphertext)| { @@ -160,15 +197,23 @@ fn create_wasm_msg(obligations_enc: Vec<(Sha256Digest, Vec)>) -> serde_json: }) .collect(); + let liquidity_sources = liquidity_sources + .into_iter() + .map(|pk| HexBinary::from(pk.to_sec1_bytes().as_ref())) + .collect(); + let msg = SubmitObligationsMsg { - submit_obligations: obligations_enc, + submit_obligations: SubmitObligationsMsgInner { + obligations: obligations_enc, + liquidity_sources, + }, }; - serde_json::to_value(msg).unwrap() + serde_json::to_value(msg).map_err(Into::into) } fn encrypt_intents( intents: Vec, - keys: HashMap, + keys: &HashMap, epoch_pk: &VerifyingKey, obligation_user_map_file: PathBuf, ) -> Vec<(Sha256Digest, Vec)> { @@ -209,16 +254,18 @@ fn encrypt_intents( intents_enc } -fn add_default_acceptances(obligations: &mut Vec, bank_id: Uuid) { +fn add_default_acceptances(obligations: &mut Vec, liquidity_sources: &[Uuid]) { let acceptances = obligations.iter().fold(HashSet::new(), |mut acc, o| { - if o.debtor_id != bank_id { - let acceptance = ObligatoObligation { - id: Default::default(), - debtor_id: o.creditor_id, - creditor_id: bank_id, - amount: u32::MAX as u64, - }; - acc.insert(acceptance); + if !liquidity_sources.contains(&o.debtor_id) { + for ls in liquidity_sources { + let acceptance = ObligatoObligation { + id: Default::default(), + debtor_id: o.creditor_id, + creditor_id: *ls, + amount: u32::MAX as u64, + }; + acc.insert(acceptance); + } } acc }); @@ -274,41 +321,46 @@ fn write_obligation_user_map_to_file( fn derive_keys( obligations: &mut Vec, - bank_id: Uuid, + liquidity_sources: &[Uuid], ) -> Result, DynError> { // Derive a BIP39 seed value using the given password - let seed = { - let mnemonic = Mnemonic::new(MNEMONIC_PHRASE, Language::English)?; - mnemonic.to_seed("password") - }; + let seed = global_seed()?; obligations.sort_by_key(|o| o.debtor_id); let mut keys = HashMap::new(); - let mut child_num = 0; - let alice_id = Uuid::parse_str(ALICE_ID).unwrap(); - - keys.entry(alice_id) - .or_insert_with(|| derive_child_xprv(&seed, &mut child_num)); - - keys.entry(bank_id) - .or_insert_with(|| derive_child_xprv(&seed, &mut child_num)); + for ls in liquidity_sources { + keys.entry(*ls) + .or_insert_with(|| derive_child_xprv(&seed, *ls)); + } for o in obligations { keys.entry(o.debtor_id) - .or_insert_with(|| derive_child_xprv(&seed, &mut child_num)); + .or_insert_with(|| derive_child_xprv(&seed, o.debtor_id)); keys.entry(o.creditor_id) - .or_insert_with(|| derive_child_xprv(&seed, &mut child_num)); + .or_insert_with(|| derive_child_xprv(&seed, o.creditor_id)); } Ok(keys) } -fn derive_child_xprv(seed: &Seed, i: &mut usize) -> XPrv { - let child_path = format!("m/0/44'/118'/0'/0/{}", i).parse().unwrap(); +fn derive_child_xprv(seed: &Seed, uuid: Uuid) -> XPrv { + // Hash the UUID using SHA-256 + let mut hasher = Sha256::new(); + hasher.update(uuid.as_bytes()); + let uuid_digest = hasher.finalize(); + + // Convert the hash bytes to a number + let uuid_digest_num = u128::from_be_bytes(uuid_digest[..16].try_into().unwrap()); + + // Take modulo (2^31 - 1) + let address_index = uuid_digest_num % ((1u128 << 31) - 1); + + let child_path = format!("m/0/44'/118'/0'/0/{address_index}") + .parse() + .unwrap(); let child_xprv = XPrv::derive_from_path(seed, &child_path); - *i += 1; child_xprv.unwrap() } @@ -316,52 +368,40 @@ fn derive_child_xprv(seed: &Seed, i: &mut usize) -> XPrv { mod tests { use std::{error::Error, str::FromStr}; - use bip32::{Language, Mnemonic, Prefix, PrivateKey, XPrv}; + use bip32::{Mnemonic, Prefix, PrivateKey, XPrv}; use rand_core::OsRng; + use uuid::Uuid; - use crate::{derive_child_xprv, MNEMONIC_PHRASE}; + use crate::{derive_child_xprv, global_seed}; #[test] fn test_create_mnemonic() { // Generate random Mnemonic using the default language (English) let mnemonic = Mnemonic::random(&mut OsRng, Default::default()); - println!("{}", mnemonic.phrase()); } #[test] fn test_enc_dec_for_derived() -> Result<(), Box> { - let seed = { - let mnemonic = Mnemonic::new(MNEMONIC_PHRASE, Language::English)?; - mnemonic.to_seed("password") - }; + let seed = global_seed()?; + + let alice_uuid = Uuid::from_u128(1); + let alice_sk = derive_child_xprv(&seed, alice_uuid); + let alice_pk = alice_sk.private_key().public_key(); - let mut child_num = 0; - let alice_sk = derive_child_xprv(&seed, &mut child_num); - let alice_sk_str = alice_sk.to_string(Prefix::XPRV).to_string(); assert_eq!( - alice_sk.private_key().public_key().to_sec1_bytes(), - hex::decode("02027e3510f66f1f6c1ea5e3600062255928e518220f7883810cac3fc7fc092057") + alice_pk.to_sec1_bytes(), + hex::decode("0219b0b8ee5fe9b317b69119fd15170d79737380c4f020e251b7839096f5513ccf") .unwrap() .into() ); + + let alice_sk_str = alice_sk.to_string(Prefix::XPRV).to_string(); assert_eq!(XPrv::from_str(&alice_sk_str).unwrap(), alice_sk); - let alice_pk = alice_sk.private_key().public_key(); - assert_eq!( - alice_pk.to_sec1_bytes().into_vec(), - vec![ - 2, 2, 126, 53, 16, 246, 111, 31, 108, 30, 165, 227, 96, 0, 98, 37, 89, 40, 229, 24, - 34, 15, 120, 131, 129, 12, 172, 63, 199, 252, 9, 32, 87 - ] - ); - let msg = r#"{"debtor":"02027e3510f66f1f6c1ea5e3600062255928e518220f7883810cac3fc7fc092057","creditor":"0216254f4636c4e68ae22d98538851a46810b65162fe37bf57cba6d563617c913e","amount":10,"salt":"65c188bcc133add598f7eecc449112f4bf61024345316cff0eb5ce61291991b141073dcd3c543ea142e66fffa8f483dc382043d37e490ef9b8069c489ce94a0b"}"#; - let ciphertext = ecies::encrypt(&alice_pk.to_sec1_bytes(), msg.as_bytes()).unwrap(); - // let ciphertext = hex::decode("0418d9051cbfc86c8ddd57ae43ea3d1ac8b30353a3ecd8c806bb11f0693dfd282d5f07d1de32cbcd933d5ab7cd0aa171c972e75531b915e968f0fdeba78fa3f359c7f3ef7ae2dfffeb19493e9b2418dc774e6e80448a2dc4a7ba657cd4a8456e120977ebe372a57187d53981cc5856fbd63e9c1bdf001ed71c3d50cbaff594561191d33dad852cb782126f480add2cc92758b59eb63de857d299eaa5f09fbc55643a73b1d8206ce83453b5296b566d9f622520679bb3e6d9c8b7a707f33d3093c41dfc0a8267749b4028e9ee0faad0c8df64f1682a348f220585fdd9b9ac411bdaaa6a249b45accc89a80e5af09abb239231aa869e29459e562721b685d98b3da3eeaef14e1c5f3bd20cf27c0cbbae7b5c618e737df9a84f9a040bb472b7254af2cf4ccc76784cf8432080e528f700ca2a082b7020d94f0f5325dd4998c03972a0b39e6670b65be89e7a80aad7af08a393fcf2e103999254380c1f0355d97ddcdfaeed4bcfaf15b578cee1f6d3fd4ceccd85760b9bd714f81698ddf6fbbc06152a9306a5dd0052c722e390470f0c70eeac81a5da0090").unwrap(); - - println!("{}", hex::encode(&ciphertext)); + // println!("{}", hex::encode(&ciphertext)); let msg_dec = ecies::decrypt(&alice_sk.private_key().to_bytes(), ciphertext.as_slice()).unwrap(); diff --git a/utils/cycles-sync/src/obligato_client/mock.rs b/utils/cycles-sync/src/obligato_client/mock.rs index 9df815f..ce4354e 100644 --- a/utils/cycles-sync/src/obligato_client/mock.rs +++ b/utils/cycles-sync/src/obligato_client/mock.rs @@ -4,10 +4,11 @@ use uuid::Uuid; use crate::{ obligato_client::Client, types::{ObligatoObligation, ObligatoSetOff}, - BANK_DEBTOR_ID, }; -pub struct MockClient; +pub struct MockClient { + pub bank: Uuid, +} #[async_trait] impl Client for MockClient { @@ -25,7 +26,7 @@ impl Client for MockClient { // tender: $ --10--> 1 ObligatoObligation { id: Uuid::from_u128(2), - debtor_id: Uuid::parse_str(BANK_DEBTOR_ID).unwrap(), + debtor_id: self.bank, creditor_id: Uuid::from_u128(1), amount: 10, }, diff --git a/utils/cycles-sync/src/types.rs b/utils/cycles-sync/src/types.rs index d068d6e..428f113 100644 --- a/utils/cycles-sync/src/types.rs +++ b/utils/cycles-sync/src/types.rs @@ -47,7 +47,13 @@ pub struct RawEncryptedObligation { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SubmitObligationsMsg { - pub submit_obligations: Vec, + pub submit_obligations: SubmitObligationsMsgInner, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct SubmitObligationsMsgInner { + pub obligations: Vec, + pub liquidity_sources: Vec, } #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]