iuna

iuna

iuna - experimental mainnet-candidate protocol
git clone https://getiuna.org/git/iuna.git
Log | Files | Refs | README | LICENSE

quantum_migration.rs (2681B)


      1 use axum::{Form, Json, extract::State};
      2 use serde::Deserialize;
      3 use serde_json::{Value, json};
      4 
      5 use super::HttpState;
      6 use crate::domain::Amount;
      7 
      8 #[derive(Deserialize)]
      9 pub(super) struct PreviewForm {
     10     fee_per_byte: Amount,
     11 }
     12 
     13 #[derive(Deserialize)]
     14 pub(super) struct SubmitForm {
     15     fee_per_byte: Amount,
     16     max_fee: Amount,
     17     transaction_id: String,
     18 }
     19 
     20 pub(super) async fn preview(
     21     State(state): State<HttpState>,
     22     Form(form): Form<PreviewForm>,
     23 ) -> Json<Value> {
     24     let node = state.node.lock().await;
     25     match node.preview_quantum_migration(form.fee_per_byte) {
     26         Ok(preview) => Json(json!({ "ok": true, "preview": preview })),
     27         Err(error) => Json(json!({ "ok": false, "error": error.to_string() })),
     28     }
     29 }
     30 
     31 pub(super) async fn submit(
     32     State(state): State<HttpState>,
     33     Form(form): Form<SubmitForm>,
     34 ) -> Json<Value> {
     35     let (result, outbox, pending_envelope) = {
     36         let mut node = state.node.lock().await;
     37         let result =
     38             node.submit_quantum_migration(form.fee_per_byte, form.max_fee, &form.transaction_id);
     39         let pending_envelope = result.as_ref().ok().and_then(|preview| {
     40             node.pending_transaction_v2_envelopes()
     41                 .ok()?
     42                 .into_iter()
     43                 .find(|(transaction_id, _)| transaction_id == &preview.transaction_id)
     44         });
     45         (result, node.drain_outbox(), pending_envelope)
     46     };
     47     match result {
     48         Ok(preview) => {
     49             let persistence_error = if let Some((transaction_id, envelope)) = pending_envelope {
     50                 let store = state.chain_store.clone();
     51                 tokio::task::spawn_blocking(move || {
     52                     store.save_pending_transaction_v2(&transaction_id, &envelope)
     53                 })
     54                 .await
     55                 .map_err(|error| anyhow::anyhow!("migration persistence worker failed: {error}"))
     56                 .and_then(|result| result)
     57                 .err()
     58                 .map(|error| error.to_string())
     59             } else {
     60                 Some(
     61                     "queued migration is missing from the local transaction-v2 mempool".to_string(),
     62                 )
     63             };
     64             let broadcast = state.gossip.broadcast(outbox).await;
     65             Json(json!({
     66                 "ok": true,
     67                 "transaction_id": preview.transaction_id,
     68                 "remaining_legacy_utxos": preview.remaining_legacy_utxos,
     69                 "persistence_error": persistence_error,
     70                 "broadcast_error": broadcast.err().map(|error| error.to_string()),
     71             }))
     72         }
     73         Err(error) => Json(json!({ "ok": false, "error": error.to_string() })),
     74     }
     75 }