Skip to content

Commit

Permalink
WIP: Releasing tx prepare
Browse files Browse the repository at this point in the history
  • Loading branch information
ademar111190 committed Aug 16, 2023
1 parent 09d722a commit 5ee6bcf
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 33 deletions.
20 changes: 16 additions & 4 deletions libs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion libs/sdk-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ rusqlite = { version = "0.28.0", features = [
"hooks",
] }
rusqlite_migration = "*"
regex = "1.9.3"
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand All @@ -63,7 +64,6 @@ miniz_oxide = "0.7.1"
[dev-dependencies]
futures = "0.3.28"
mockito = "0.31.1"
regex = "1.8.1"
tower = "0.4.13"

[build-dependencies]
Expand Down
78 changes: 54 additions & 24 deletions libs/sdk-core/src/greenlight/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,35 @@ use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};

use anyhow::{anyhow, Result};
use bitcoin::bech32::{u5, ToBase32};
use bitcoin::bech32::{ToBase32, u5};
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
use bitcoin::secp256k1::PublicKey;
use bitcoin::secp256k1::Secp256k1;
use bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey};
use ecies::utils::{aes_decrypt, aes_encrypt};
use gl_client::{node, pb, utils};
use gl_client::node::ClnClient;
use gl_client::pb::amount::Unit;
use gl_client::pb::cln::{
self, CloseRequest, ListclosedchannelsClosedchannels, ListclosedchannelsRequest,
ListpeerchannelsRequest,
};
use gl_client::pb::{
Amount, Invoice, InvoiceRequest, InvoiceStatus, ListFundsResponse, OffChainPayment, PayStatus,
Peer, WithdrawResponse,
};
use gl_client::pb::amount::Unit;
use gl_client::pb::cln::{self, CloseRequest, ListclosedchannelsClosedchannels, ListclosedchannelsRequest, ListpeerchannelsRequest};
use gl_client::scheduler::Scheduler;
use gl_client::signer::Signer;
use gl_client::tls::TlsConfig;
use gl_client::{node, pb, utils};
use lightning::util::message_signing::verify;
use lightning_invoice::{RawInvoice, SignedRawInvoice};
use regex::Regex;
use serde::{Deserialize, Serialize};
use strum_macros::{Display, EnumString};
use tokio::sync::{mpsc, Mutex};
use tonic::Streaming;
use tonic::{Code, Streaming};

use crate::{Channel, ChannelState, NodeConfig, PrepareWithdrawRequest, PrepareWithdrawResponse};
use crate::invoice::parse_invoice;
use crate::models::*;
use crate::persist::db::SqliteStorage;
use crate::{Channel, ChannelState, NodeConfig, PrepareWithdrawRequest, PrepareWithdrawResponse};

const MAX_PAYMENT_AMOUNT_MSAT: u64 = 4294967000;
const MAX_INBOUND_LIQUIDITY_MSAT: u64 = 4000000000;
Expand Down Expand Up @@ -66,8 +64,8 @@ impl Greenlight {
&signer,
vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
)?
.to_priv()
.to_bytes();
.to_priv()
.to_bytes();
let encryption_key_slice = encryption_key.as_slice();

let register_credentials = match config.node_config.clone() {
Expand Down Expand Up @@ -109,7 +107,7 @@ impl Greenlight {
register_credentials.partner_credentials,
register_credentials.invite_code,
)
.await?;
.await?;
Ok(credentials)
}
}
Expand Down Expand Up @@ -192,7 +190,7 @@ impl Greenlight {
utils::scheduler_uri(),
&tls_config,
)
.await?;
.await?;
let recover_res: pb::scheduler::RegistrationResponse =
scheduler.register(&signer, invite_code).await?;

Expand Down Expand Up @@ -468,42 +466,74 @@ impl NodeAPI for Greenlight {
prepare_withdraw_request: PrepareWithdrawRequest,
) -> Result<PrepareWithdrawResponse> {
let funds = list_funds(self).await?;
let amount = self.on_chain_balance(Some(funds.clone())).await?;
let utxos = utxos(self, Some(funds))
let utxos: Vec<cln::Outpoint> = utxos(self, Some(funds))
.await?
.into_iter()
.map(|it| cln::Outpoint {
txid: it.txid,
outnum: it.outnum,
})
.collect();
debug!("amount: {}", amount);
debug!("utxos: {:?}", utxos);

let request = cln::TxprepareRequest {
outputs: vec![cln::OutputDesc {
address: prepare_withdraw_request.to_address,
amount: Some(cln::Amount { msat: amount }),
address: prepare_withdraw_request.to_address.clone(),
amount: Some(cln::Amount { msat: 1000 }),
}],
feerate: Some(cln::Feerate {
style: Some(cln::feerate::Style::Perkw(
prepare_withdraw_request.fee_rate_sats_per_vbyte,
prepare_withdraw_request.fee_rate_sats_per_vbyte.clone(),
)),
}),
minconf: None,
utxos,
utxos: utxos.clone(),
};
println!("request {:?}", request);

let mut node_client = self.get_node_client().await?;
let response = node_client.tx_prepare(request).await?.into_inner();
debug!("tx_prepare response: {:?}", response);
debug!("raw_tx_hex: {:?}", String::from_utf8(response.unsigned_tx)?);
let tx_prepare = node_client.tx_prepare(request).await;
if tx_prepare.is_err() {
let status = tx_prepare.unwrap_err();
println!("tx_prepare error: {:?}", status);
if status.code() == Code::Unknown {
let regex = Regex::new(
r#"Error calling method TxPrepare: RpcError \{ code: Some\(-?\d+\), message: "UTXO .* already reserved" }"#
).unwrap();
let already_reserved = regex.is_match(&status.message());
if already_reserved {
println!("tx_prepare error, funds already reserved, trying to release and retry");
let mut all_released = true;
for utxo in utxos {
let released = self.release_prepared_withdraw(utxo.txid).await?;
all_released = released && all_released;
}
return if all_released {
self.prepare_withdraw(prepare_withdraw_request).await
} else {
Err(anyhow!("could not release funds"))
};
}
}
}

// let response = tx_prepare?.into_inner();
// println!("tx_prepare response: {:?}", response);
// println!("raw_tx_hex: {:?}", String::from_utf8(response.unsigned_tx)?);
return Ok(PrepareWithdrawResponse {
weight: 10,
fee_sat: 50,
});
}

async fn release_prepared_withdraw(&self, txid: Vec<u8>) -> Result<bool> {
let request = cln::TxdiscardRequest {
txid,
};
let response = self.get_node_client().await?.tx_discard(request).await;
println!("release prepared withdraw response: {:?}", response);
Ok(response.is_ok())
}

async fn start_signer(&self, shutdown: mpsc::Receiver<()>) {
_ = self.signer.run_forever(shutdown).await;
error!("signer exited");
Expand Down
2 changes: 2 additions & 0 deletions libs/sdk-core/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRe
use rusqlite::ToSql;
use serde::{Deserialize, Serialize};
use std::cmp::max;
use gl_client::pb::cln::TxdiscardResponse;
use tokio::sync::mpsc;
use tonic::Streaming;

Expand Down Expand Up @@ -71,6 +72,7 @@ pub trait NodeAPI: Send + Sync {
&self,
prepare_withdraw_request: PrepareWithdrawRequest,
) -> Result<PrepareWithdrawResponse>;
async fn release_prepared_withdraw(&self, txid: Vec<u8>) -> Result<bool>;
async fn start_signer(&self, shutdown: mpsc::Receiver<()>);
async fn list_peers(&self) -> Result<Vec<Peer>>;
async fn connect_peer(&self, node_id: String, addr: String) -> Result<()>;
Expand Down
21 changes: 17 additions & 4 deletions tools/sdk-cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5ee6bcf

Please sign in to comment.