Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
943 changes: 695 additions & 248 deletions Cargo.lock

Large diffs are not rendered by default.

30 changes: 14 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,29 @@ members = [
"crates/coordinator/domain",
"crates/coordinator/engine",
"crates/coordinator/store",
"crates/coordinator/utils",
"crates/miden-multisig-client",
"crates/test-utils",
]
resolver = "3"

[workspace.dependencies]
miden-client = "0.11.9"
miden-multisig-client = { path = "crates/miden-multisig-client" }
miden-multisig-coordinator-domain = { path = "crates/coordinator/domain" }
miden-multisig-coordinator-engine = { path = "crates/coordinator/engine" }
miden-multisig-coordinator-store = { path = "crates/coordinator/store" }
miden-multisig-coordinator-utils = { path = "crates/coordinator/utils" }
miden-multisig-test-utils = { path = "crates/test-utils" }
miden-objects = "0.11"

anyhow = "1"
bon = { default-features = false, version = "3" }
chrono = { default-features = false, version = "0.4" }
dissolve-derive = "0.1.2"
rand = "0.9"
serde = { default-features = false, version = "1" }
serde_with = { default-features = false, version = "3" }
thiserror = { default-features = false, version = "2" }
tokio = { default-features = false, version = "1.40" }
tracing = "0.1"
url = "2.5"
uuid = { default-features = false, version = "1" }
anyhow = "1"
bon = { default-features = false, version = "3" }
chrono = { default-features = false, version = "0.4" }
dissolve-derive = "0.1.4"
miden-client = { default-features = false, version = "0.12" }
miden-client-sqlite-store = "0.12"
rand = "0.9"
serde = { default-features = false, version = "1" }
serde_with = { default-features = false, version = "3" }
thiserror = { default-features = false, version = "2" }
tokio = { default-features = false, version = "1.40" }
tracing = "0.1"
url = "2.5"
uuid = { default-features = false, version = "1" }
2 changes: 0 additions & 2 deletions bin/coordinator-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ miden-client = { workspace = true }
miden-multisig-coordinator-domain = { features = ["serde"], workspace = true }
miden-multisig-coordinator-engine = { workspace = true }
miden-multisig-coordinator-store = { workspace = true }
miden-multisig-coordinator-utils = { workspace = true }
miden-objects = { workspace = true }
openssl-sys = { features = ["vendored"], optional = true, version = "0.9" }
pq-sys = { features = ["bundled"], optional = true, version = "0.7" }
serde = { features = ["derive"], workspace = true }
Expand Down
14 changes: 4 additions & 10 deletions bin/coordinator-server/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use miden_client::AccountIdError;
use miden_multisig_coordinator_engine::{MultisigEngineError, request::RequestError};
use miden_multisig_coordinator_utils::AccountIdAddressError;
use tokio::task::JoinError;

#[derive(Debug, thiserror::Error)]
Expand All @@ -16,8 +16,8 @@ pub(crate) enum AppError {
#[error("invalid network id error")]
InvalidNetworkId,

#[error("invalid account id address: {0}")]
InvalidAccountIdAddress(Cow<'static, str>),
#[error("account id error: {0}")]
AccountId(#[from] AccountIdError),

#[error("invalid pub key commit error")]
InvalidPubKeyCommit,
Expand Down Expand Up @@ -61,17 +61,11 @@ impl From<MultisigEngineError> for AppError {
}
}

impl From<AccountIdAddressError> for AppError {
fn from(err: AccountIdAddressError) -> Self {
Self::InvalidAccountIdAddress(err.to_string().into())
}
}

impl IntoResponse for AppError {
fn into_response(self) -> Response {
let code = match self {
AppError::InvalidNetworkId
| AppError::InvalidAccountIdAddress(_)
| AppError::AccountId(_)
| AppError::InvalidPubKeyCommit
| AppError::InvalidTransactionRequest
| AppError::InvalidSignature
Expand Down
17 changes: 10 additions & 7 deletions bin/coordinator-server/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use bon::Builder;
use chrono::{DateTime, Utc};
use miden_client::{
Word,
account::Address,
note::{NoteFile, NoteId},
utils::Serializable,
};
Expand Down Expand Up @@ -80,7 +79,7 @@ pub struct NoteIdPayload {
impl From<MultisigAccount> for MultisigAccountPayload {
fn from(account: MultisigAccount) -> Self {
Self::builder()
.address(Address::AccountId(account.address()).to_bech32(account.network_id()))
.address(account.account_id().to_bech32(account.network_id().clone()))
.kind(account.kind().to_string())
.threshold(account.threshold())
.created_at(account.aux().created_at())
Expand All @@ -91,11 +90,15 @@ impl From<MultisigAccount> for MultisigAccountPayload {

impl From<MultisigApprover> for MultisigApproverPayload {
fn from(approver: MultisigApprover) -> Self {
let MultisigApproverDissolved { address, network_id, pub_key_commit, aux } =
approver.dissolve();
let MultisigApproverDissolved {
account_id,
network_id,
pub_key_commit,
aux,
} = approver.dissolve();

Self::builder()
.address(Address::AccountId(address).to_bech32(network_id))
.address(account_id.to_bech32(network_id))
.pub_key_commit(Word::from(pub_key_commit).to_bytes())
.created_at(aux.created_at())
.updated_at(aux.updated_at())
Expand All @@ -107,7 +110,7 @@ impl From<MultisigTx> for MultisigTxPayload {
fn from(tx: MultisigTx) -> Self {
let MultisigTxDissolved {
id,
address,
multisig_account_id,
network_id,
status,
tx_request,
Expand All @@ -119,7 +122,7 @@ impl From<MultisigTx> for MultisigTxPayload {

Self::builder()
.id(id.into())
.multisig_account_address(Address::AccountId(address).to_bech32(network_id))
.multisig_account_address(multisig_account_id.to_bech32(network_id))
.status(status)
.tx_request(tx_request.to_bytes())
.tx_summary(tx_summary.to_bytes())
Expand Down
87 changes: 35 additions & 52 deletions bin/coordinator-server/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use axum::{Json, extract::State, http::StatusCode};
use itertools::Itertools;
use miden_client::{
Word,
account::Address,
account::AccountId,
utils::{Deserializable, Serializable},
};
use miden_multisig_coordinator_engine::{
Expand All @@ -18,7 +18,6 @@ use miden_multisig_coordinator_engine::{
ListMultisigTxResponseDissolved, ProposeMultisigTxResponseDissolved,
},
};
use miden_objects::crypto::dsa::rpo_falcon512::PublicKey;
use tokio::task;

use crate::{
Expand Down Expand Up @@ -60,18 +59,18 @@ pub async fn create_multisig_account(
let CreateMultisigAccountRequestPayloadDissolved { threshold, approvers, pub_key_commits } =
payload.dissolve();

let engine_network_id = engine.network_id();
let engine_network_id = engine.network_id().clone();
let CreateMultisigAccountResponseDissolved { multisig_account, .. } =
task::spawn_blocking(move || {
let approvers = approvers
.iter()
.map(AsRef::as_ref)
.map(miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair)
.map(AccountId::from_bech32)
.map(|res| res.map_err(From::from))
.map_ok(|(network_id, account_id_address)| {
.map_ok(|(network_id, account_id)| {
engine_network_id
.eq(&network_id)
.then_some(account_id_address)
.then_some(account_id)
.ok_or(AppError::InvalidNetworkId)
})
.map(Result::flatten)
Expand All @@ -81,7 +80,7 @@ pub async fn create_multisig_account(
.iter()
.map(AsRef::as_ref)
.map(Word::read_from_bytes)
.map_ok(PublicKey::new)
.map_ok(From::from)
.try_collect()
.map_err(|_| AppError::InvalidPubKeyCommit)?;

Expand All @@ -99,9 +98,7 @@ pub async fn create_multisig_account(
.map(CreateMultisigAccountResponse::dissolve)?;

let response = CreateMultisigAccountResponsePayload::builder()
.address(
Address::AccountId(multisig_account.address()).to_bech32(multisig_account.network_id()),
)
.address(multisig_account.account_id().to_bech32(multisig_account.network_id().clone()))
.created_at(multisig_account.aux().created_at())
.updated_at(multisig_account.aux().updated_at())
.build();
Expand All @@ -122,18 +119,17 @@ pub async fn propose_multisig_tx(
} = payload.dissolve();

let request = {
let account_id_address =
miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair(&address)
.map(|(network_id, address)| {
engine.network_id().eq(&network_id).then_some(address)
})?
.ok_or(AppError::InvalidNetworkId)?;
let account_id_address = AccountId::from_bech32(&address)
.map(|(network_id, account_id)| {
engine.network_id().eq(&network_id).then_some(account_id)
})?
.ok_or(AppError::InvalidNetworkId)?;

let tx_request = Deserializable::read_from_bytes(&tx_request)
.map_err(|_| AppError::InvalidTransactionRequest)?;

ProposeMultisigTxRequest::builder()
.address(account_id_address)
.multisig_account_id(account_id_address)
.tx_request(tx_request)
.build()
};
Expand All @@ -159,12 +155,11 @@ pub async fn add_signature(
let AddSignatureRequestPayloadDissolved { tx_id, approver, signature } = payload.dissolve();

let request = {
let approver =
miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair(&approver)
.map(|(network_id, address)| {
engine.network_id().eq(&network_id).then_some(address)
})?
.ok_or(AppError::InvalidNetworkId)?;
let approver = AccountId::from_bech32(&approver)
.map(|(network_id, account_id)| {
engine.network_id().eq(&network_id).then_some(account_id)
})?
.ok_or(AppError::InvalidNetworkId)?;

let signature =
Deserializable::read_from_bytes(&signature).map_err(|_| AppError::InvalidSignature)?;
Expand Down Expand Up @@ -192,20 +187,20 @@ pub async fn list_consumable_notes(

let ListConsumableNotesRequestPayloadDissolved { address } = payload.dissolve();

let account_id_address = address
let account_id = address
.as_deref()
.map(miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair)
.map(AccountId::from_bech32)
.transpose()?
.map(|(network_id, address)| {
.map(|(network_id, account_id)| {
engine
.network_id()
.eq(&network_id)
.then_some(address)
.then_some(account_id)
.ok_or(AppError::InvalidNetworkId)
})
.transpose()?;

let request = GetConsumableNotesRequest::builder().maybe_address(account_id_address).build();
let request = GetConsumableNotesRequest::builder().maybe_account_id(account_id).build();

let note_ids = engine
.get_consumable_notes(request)
Expand All @@ -229,15 +224,12 @@ pub async fn get_multisig_account_details(
let GetMultisigAccountDetailsRequestPayloadDissolved { multisig_account_address } =
payload.dissolve();

let multisig_account_id_address =
miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair(
&multisig_account_address,
)
.map(|(network_id, address)| engine.network_id().eq(&network_id).then_some(address))?
let multisig_account_id = AccountId::from_bech32(&multisig_account_address)
.map(|(network_id, account_id)| engine.network_id().eq(&network_id).then_some(account_id))?
.ok_or(AppError::InvalidNetworkId)?;

let request = GetMultisigAccountRequest::builder()
.multisig_account_id_address(multisig_account_id_address)
.multisig_account_id(multisig_account_id)
.build();

let GetMultisigAccountResponseDissolved { multisig_account } =
Expand All @@ -262,15 +254,12 @@ pub async fn list_multisig_approvers(
let ListMultisigApproverRequestPayloadDissolved { multisig_account_address } =
payload.dissolve();

let multisig_account_id_address =
miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair(
&multisig_account_address,
)
.map(|(network_id, address)| engine.network_id().eq(&network_id).then_some(address))?
let multisig_account_id = AccountId::from_bech32(&multisig_account_address)
.map(|(network_id, account_id)| engine.network_id().eq(&network_id).then_some(account_id))?
.ok_or(AppError::InvalidNetworkId)?;

let request = ListMultisigApproverRequest::builder()
.multisig_account_id_address(multisig_account_id_address)
.multisig_account_id(multisig_account_id)
.build();

let ListMultisigApproverResponseDissolved { approvers } =
Expand All @@ -291,15 +280,12 @@ pub async fn get_multisig_tx_stats(

let GetMultisigTxStatsRequestPayloadDissolved { multisig_account_address } = payload.dissolve();

let multisig_account_id_address =
miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair(
&multisig_account_address,
)
.map(|(network_id, address)| engine.network_id().eq(&network_id).then_some(address))?
let multisig_account_id = AccountId::from_bech32(&multisig_account_address)
.map(|(network_id, account_id)| engine.network_id().eq(&network_id).then_some(account_id))?
.ok_or(AppError::InvalidNetworkId)?;

let request = GetMultisigTxStatsRequest::builder()
.multisig_account_id_address(multisig_account_id_address)
.multisig_account_id(multisig_account_id)
.build();

let GetMultisigTxStatsResponseDissolved { tx_stats } =
Expand All @@ -322,11 +308,8 @@ pub async fn list_multisig_tx(
tx_status_filter,
} = payload.dissolve();

let multisig_account_id_address =
miden_multisig_coordinator_utils::extract_network_id_account_id_address_pair(
&multisig_account_address,
)
.map(|(network_id, address)| engine.network_id().eq(&network_id).then_some(address))?
let multisig_account_id = AccountId::from_bech32(&multisig_account_address)
.map(|(network_id, account_id)| engine.network_id().eq(&network_id).then_some(account_id))?
.ok_or(AppError::InvalidNetworkId)?;

let tx_status_filter = tx_status_filter
Expand All @@ -336,7 +319,7 @@ pub async fn list_multisig_tx(
.map_err(|_| AppError::InvalidMultisigTxStatus)?;

let request = ListMultisigTxRequest::builder()
.multisig_account_id_address(multisig_account_id_address)
.multisig_account_id(multisig_account_id)
.maybe_tx_status_filter(tx_status_filter)
.build();

Expand Down
1 change: 0 additions & 1 deletion crates/coordinator/domain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ bon = { workspace = true }
chrono = { workspace = true }
dissolve-derive = { workspace = true }
miden-client = { workspace = true }
miden-objects = { workspace = true }
serde = { default-features = false, features = ["derive"], optional = true, workspace = true }
serde_with = { default-features = false, features = ["macros"], optional = true, workspace = true }
strum = { features = ["derive"], version = "0.27" }
Expand Down
Loading
Loading