-
Notifications
You must be signed in to change notification settings - Fork 8
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
Get Quote and Pay for Inbound Channel #65
Conversation
I think for this to make sense in our app we have to merge that address into the PayJoin PSBT. I didn't realize we were returning an address to the UI |
Taking a double take on this, I imagine a slightly different flow. We could add a line to our channels ui with a checkbox like
on /schedule, find the quote, and return the ScheduledPayJoin with the bip21 that pays for it. We can show if that quote succeeded or failed, as well as the quote there, all ready to be paid. This design intends to minimize interaction and points of failure. |
Changed so /schedule takes a request for inbound and if so adds the output to the proposal psbt UI, error handling, integration test upgrade to include inbound payment, and response status update TODO |
src/main.rs
Outdated
@@ -1,5 +1,6 @@ | |||
pub mod args; | |||
mod http; | |||
pub mod inbound; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this interface should be public. Inbound can be offered by the scheduler, but not on its own.
"Allow channels of length 0" commit should
|
|
a86041f
to
cd854d9
Compare
src/scheduler.rs
Outdated
fn fees(&self) -> bitcoin::Amount { | ||
let channel_count = self.channels.len() as u64; | ||
let has_reserve_deposit = self.reserve_deposit != bitcoin::Amount::ZERO; | ||
|
||
let mut additional_vsize = if has_reserve_deposit { | ||
// <8 invariant bytes = 4 version + 4 locktime> | ||
// + 2 variant bytes for input.len + output.len such that each len < 252 | ||
// + OP_0 OP_PUSHBYTES_32 <32 byte script> | ||
channel_count * (8 + 1 + 1 + 34) | ||
} else { | ||
// substitute 1 p2wsh channel (34 bytes) open for 1 p2wpkh reserve output (22 bytes) | ||
// that's + 12 bytes | ||
(channel_count - 1) * (8 + 1 + 1 + 34) + 12 | ||
}; | ||
|
||
if self.quote.is_some() { | ||
additional_vsize = additional_vsize + (8 + 1 + 1 + 22); // P2WPKH (OP_0 OP_PUSHBYTES_20 <20 byte script) | ||
} | ||
|
||
bitcoin::Amount::from_sat(self.fee_rate * additional_vsize) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might slightly overestimate the fees. I think that's acceptable to me for an alpha. This fee calculation belongs in the payjoin crate and should be made perfect for any script type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reckon we should try avoid doing diy fees, is there a reason we're having to calculate yourself as opposed to rust-bitcoin or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should avoid DIY fee calc. It can lead to many problems if done poorly.
I don't believe rust-bitcoin and rust-miniscript have any fee calculation. BDK is in its infancy for fee calculation.
State of the art fee calculation candidate for rust-bitcoin is actually in the payjoin crate but only exposed to the sender module. You can follow the proposal to upstream the relevant code in rust-bitcoin here and the (good but more testing would be better) fee calculation in the payjoin crate here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see rust-bitcoin/rust-bitcoin@c34d5f8 recently in master but not yet in a release
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The important thing to remember is the sender always signs off on the fee calculation. This just sets a minimum.
b278d28
to
e11cf41
Compare
I think we should proceed with this PR now without altering the integration test. The nolooking lsp is now tested and working on regtest. The lsp module has no config for the lsp, so it always hits mainnet. I think that's fine for the next tournament release since we have done manual tests, but it makes writing the integration test harder. The lsp code needs to change to inject the lsp url. that should be the next issue. This is working as is and imo should be merged assuming CI passes |
43525f4
to
b23e800
Compare
// get address | ||
// suggest capacity | ||
let base_uri = format!( | ||
"https://nolooking.chaincase.app/api/request-inbound?nodeid={}&capacity={}&duration={}&refund_address={}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should really be a config string but it's viable for this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the rebase! You saved me a lot of time recovering from a broken git state.
I think the last commit belongs in its own PR. The design does not yet allow for integration testing and that's the point of the configuration
src/lsp.rs
Outdated
@@ -19,14 +19,15 @@ pub struct Quote { | |||
pub async fn request_quote( | |||
p2p_address: &P2PAddress, | |||
refund_address: &Address, | |||
lsp_endpoint: &String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point of this commit IMO is to make the LSP stubbable or testable. That means initializing it from a config dependency that can be changed on test. I don't think the endpoint should be a parameter of this function unless it's attached to self
src/scheduler.rs
Outdated
pub fn new(lnd: LndClient, endpoint: Url, lsp_endpoint: String) -> Self { | ||
Self { lnd, endpoint, lsp_endpoint, pjs: Default::default() } | ||
} | ||
|
||
pub async fn from_config(config: &crate::config::Config) -> Result<Self, SchedulerError> { | ||
Ok(Scheduler::new(LndClient::from_config(&config).await?, config.endpoint.parse().expect("Malformed secure endpoint from config file. Expecting a https or .onion URI to proxy payjoin requests"))) | ||
Ok(Scheduler::new(LndClient::from_config(&config).await?, config.endpoint.parse().expect("Malformed secure endpoint from config file. Expecting a https or .onion URI to proxy payjoin requests"), config.endpoint.parse().expect("Malformed secure lsp endpoint in config file. Expecting a https url"))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't think Scheduler should know about lsp_endpoint. Instead it could know about LspClient and its public interface including request_quote. Initializing LspClient `from_config would be a better encapsulated design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should also be a Url
type, like endpoint.
When a users requests a quote for inbound channel capacity, the lightning service provider can return an address to include in their PayJoin PSBT with a price. By paying this address, the user can have a channel opened to them paying from the same transaction they open outbound channels.
pub struct ScheduleResponse { | ||
bip21: String, | ||
address: String, | ||
quote: Option<Quote>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should really be strongly typed with bitcoin::Amount
, bitcoin::Amount
, std::time::Duration
(I have NO clue this u32 duration is. ms? seconds? minutes? months? you get my point) and bitcoin::Address
but this PR works and we need to ship. It's not a regression to our codebase but I know we do cleaner work than this.
Fetch quote from
(see nolooking/sateater#11)
Display address to pay for inbound channel!