Conversation
e2b7079 to
4221bbc
Compare
vault/src/execution.rs
Outdated
| Either::Left((result, _)) => result?, | ||
| Either::Right((Some(Ok((old_fee, new_fee))), _)) => { | ||
| tracing::info!("Bumping fee rate from {old_fee} to {new_fee}..."); | ||
| txid = self.bump_fee(btc_rpc, txid, new_fee).await?; |
There was a problem hiding this comment.
Do we always want to bump the fee as soon as the estimate is higher that the current fee? If it's inexpensive or free I don't see why not but just want to confirm.
There was a problem hiding this comment.
Good point. Bumping fees does not cost the client anything, but there is a minimum increase for the network to accept the new tx. I believe that is set to 1 sat/vbyte, and since our price estimate has a granularity of 1 sat/vbyte, we could always bump. But in case 1 of these assumptions fails to hold (in the future) I will add an additional check for it
There was a problem hiding this comment.
I decided to just always try and catch the error
As much as I would like to shift the burden of responsibility I do think we're best placed to test this, besides we already have some integration tests here. |
Hmm I didn't remember having those tests. It looks like they aren't run in CI though, and the infrastructure is not setup currently to run them. Do you know how we can get a bitcoin regtest node to run in the github test environment? I do agree that relying on the lib for these tests is not ideal, but we made a decision a long time ago to use the bitcoind simulator instead of using an actual bitcoin node. Do you recall the reason for that? It was a considerable effort to write the simulator so I feel like there must have been a good reason but honestly I can't recall it right now |
Perhaps this was an oversight in the migration from GitLab to GitHub (although it may have actually been Jenkins). @ns212 would be best placed to answer your question though.
I can't recall the exact reason no, but I think the simulator has its advantages - particularly for unit tests. FWIW I'm not going to block this PR on you adding integration tests but we should definitely test this here and even start to pull other complexities out of the lib. |
4221bbc to
e656cfd
Compare
e656cfd to
221939d
Compare
221939d to
f4cc2d0
Compare
gregdhill
left a comment
There was a problem hiding this comment.
The bumping implementation does seem overly complex which makes it hard to follow exactly, but I get the intent. I've left a few comments pertaining to the "always increase" approach which I'm hoping you can provide some more insight on.
vault/src/execution.rs
Outdated
| .try_filter_map(|x| async move { | ||
| match btc_rpc.fee_rate(txid) { | ||
| Ok(current_fee) => { | ||
| if x >= current_fee { |
There was a problem hiding this comment.
I am wondering if we should make this configurable, at least if the fee rate increases significantly enough the Vault might prefer to eat the penalty for non-inclusion right?
There was a problem hiding this comment.
the Vault might prefer to eat the penalty for non-inclusion right?
I don't understand what you mean here, can you rephrase/elaborate? Are you imagining a scenario where the fees are greater than the sent amount? Keep in mind that when we first creat the tx, we also use the fees that are determined by the oracle's estimate, so I don't think it's bad to always try to use the up-to-date fee rate
There was a problem hiding this comment.
Okay so this might be an absurd example, but my point is that we may not want to always blindly increase the fee.
So in reference to the fee budget taken from the oracle when the redeem request is made, let's assume we have the following:
- sat/byte is 100
- estimated redeem size is 384 bytes
- fee budget is 38400 sat or 0.000384 BTC = ~$10
- redeem value is 0.1 BTC (total is 0.100384 BTC)
There is no technical limit to the fee rate so let us assume this increases to 3000 sat/byte which the Vault has to cover out-of-pocket:
- vault now pays 1152000 sat (0.01152 BTC = ~$275) - maybe less depending on actual size
- total sent is now 0.11152 BTC
Now assume the Vault decided not to bump the transaction fees:
- slashed 100% value in collateral (e.g. DOT)
- punishment fee (10%) of 0.1 BTC also taken = 0.01 BTC (this may also be increased in the future)
- total lost is 0.11 BTC - lower net loss than bumping the transaction fee
There was a problem hiding this comment.
As @sander2 has just reminded me, once the transaction has been sent the Vault anyway risks losing funds if it doesn't bump to include before expiry.
vault/src/execution.rs
Outdated
| txid = new_txid; | ||
| continue 'outer; | ||
| } | ||
| Err(Error::BitcoinError(x)) if x.rejected_by_network_rules() => { |
There was a problem hiding this comment.
Will this catch the case that the Vault can not afford the fee increase?
There was a problem hiding this comment.
Hmm that's a good one, probably not. We should add an explicit catch for that I guess
There was a problem hiding this comment.
I decided to not abort at all when getting errors. We'll just wait for the original tx
vault/src/execution.rs
Outdated
| } | ||
| Either::Right((Some(Ok((old_fee, new_fee))), continuation)) => { | ||
| tracing::debug!("Attempting to bump fee rate from {old_fee} to {new_fee}..."); | ||
| match self.bump_fee(btc_rpc, txid, new_fee).await { |
There was a problem hiding this comment.
Is it possible to end up in a sort of "deadlock" if the Vault is always increasing fees, say if we do receive numerous smaller fee estimate bumps on the parachain? (assuming re-submission pushes the new tx to the "back" of the mempool)
There was a problem hiding this comment.
I don't see how that'd be possible, no. If bump_fee succeeds, the new tx will end up more to the front of the queue because the miners sort by fee. If it fails there'd be no change
| let fee_rate = self.get_fee_rate(parachain_rpc).await?; | ||
|
|
||
| tracing::debug!("Using fee_rate = {fee_rate}"); | ||
| tracing::debug!("Using fee_rate = {} sat/vByte", fee_rate.0); |
There was a problem hiding this comment.
Nit: could implement Display for SatPerVbyte
vault/src/execution.rs
Outdated
| .checked_div(FixedU128::accuracy()) | ||
| .ok_or(Error::ArithmeticUnderflow) | ||
| .and_then(|x| x.try_into().map_err(Into::<Error>::into)); | ||
| .and_then(|x| x.try_into().map(|x| SatPerVbyte(x)).map_err(Into::<Error>::into)); |
There was a problem hiding this comment.
| .and_then(|x| x.try_into().map(|x| SatPerVbyte(x)).map_err(Into::<Error>::into)); | |
| .and_then(|x| x.try_into().map(SatPerVbyte).map_err(Into::<Error>::into)); |
I would like to have automated tests but since this really depends on the bitcoin core specifics maybe the best place would be in the lib..