-
Notifications
You must be signed in to change notification settings - Fork 265
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
Add a globalbalance API call #1737
Conversation
24f0e57
to
9e272ae
Compare
2439f6c
to
0c77de5
Compare
Codecov Report
@@ Coverage Diff @@
## master #1737 +/- ##
==========================================
- Coverage 88.94% 88.24% -0.71%
==========================================
Files 150 154 +4
Lines 11239 11417 +178
Branches 447 426 -21
==========================================
+ Hits 9997 10075 +78
- Misses 1242 1342 +100
|
0452c6e
to
6a756c4
Compare
|
||
import scala.concurrent.Promise | ||
|
||
object ChannelsListener { |
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 goal of this actor is to maintain a local cache of all channel data, that can be used by the API, instead of querying thousands of channel actors. Surprisingly, this is turns out to not be noticeably faster than the ask
+Future.sequence
pattern.
Maybe we should remove this? Or we could keep it and use that for all remaining API calls, because it saves some burden of the channel actors? I'm not sure.
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 it's useful to have it, when we'll have more load on the channel actors it should be noticeably useful, don't you think?
Squashed and rebased. |
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.
First pass, I haven't looked in details in the actual balance computation, but I'm proposing a few architectural changes and found some nits.
@@ -53,15 +57,31 @@ case class AuditResponse(sent: Seq[PaymentSent], received: Seq[PaymentReceived], | |||
|
|||
case class TimestampQueryFilters(from: Long, to: Long) | |||
|
|||
case class MutualCloseStatus(unpublished: Satoshi, unconfirmed: Satoshi, confirmed: Satoshi) |
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.
nit: MutualCloseBalance
would be more consistent IMO
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.
Actually, this is just additional information about mutual close transactions, useful to track evictions. The mutual close balance is tracked as part of onchain balance, see:
/**
* Mutual close transactions are always immediately published, and will be taken into account by bitcoin core, so we
* don't count them in the balance.
*/
case class ClosingBalance
But now that I think of it, we should probably treat mutual closes like other transactions, in the offchain balance, and prune it afterwards. The goal of pruning was initially to remove duplicates for transactions that were published (and possibly confirmed but less than mindepth), but it should also nicely handle evicted transactions.
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.
Ok, I remember now why the mutual close transactions were handled like this. The problem is that there can be several competing mutual closes, and in that case the simple pruning logic that we have to make sure we count the amount exactly once doesn't work. This would lead us to possibly count twice the amount in the competing-mutual-closes scenario.
On the other hand, what we had before meant that we didn't count the amount in the case where the mutual close was evicted. Not perfect either, and this is why we had the additional MutualCloseStatus
item.
In general I would say that it is better to undershoot rather than overshoot the balance computation, but here the trade-off makes sense for consistency, and also it is easy to tell when we are potentially counting a mutual close twice: the mutualCloseBalance
should always be zero after pruning.
So I went ahead and did it with 4b78392, with a detailed comment on what is going on.
eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZmqWatcher.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/ExtendedBitcoinClient.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/balance/ChannelsListener.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/balance/CheckBalance.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/balance/CheckBalance.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/balance/Monitoring.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/balance/BalanceActor.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/balance/BalanceActor.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/test/scala/fr/acinq/eclair/balance/CheckBalanceSpec.scala
Show resolved
Hide resolved
eclair-core/src/test/scala/fr/acinq/eclair/balance/CheckBalanceSpec.scala
Show resolved
Hide resolved
@@ -2370,6 +2374,24 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with | |||
// at best we have a little less than 450 000 + 250 000 + 100 000 + 50 000 = 850 000 (because fees) | |||
assert(amountClaimed === 814880.sat) | |||
|
|||
val commitments = alice.stateData.asInstanceOf[DATA_CLOSING].commitments |
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.
We can leave it like that for now, but I'm not a big fan of adding new unrelated checks inside existing tests (especially when these tests are already quite long and complex).
It's a bit more code, but I would not put any balance test inside this file, I would instead write these tests in CheckBalanceSpec
(where you would setup channels and HTLCs similarly to what's done here, but with the flexibility of changing the scenarios tested without impacting the rest of the test).
eclair-node/src/main/scala/fr/acinq/eclair/api/serde/JsonSerializers.scala
Show resolved
Hide resolved
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.
LGTM. I haven't looked in details at the actual balance computation details, real-world experience is the best judge for whether it works or not ;)
And we can easily implement several balance computation algorithms and run them in parallel, and see which one mirrors more closely reality.
It returns an overall balance, separating onchain, offchain, and removing duplicates (e.g. mutual closes that haven't reached min depth still have an associated channel, but they already appear in the on-chain balance). We also take into account known preimages, even if the htlc hasn't been formally resolved. Metrics have also been added. fixup: typo Co-authored-by: Bastien Teinturier <[email protected]> better serializers naming consistency treat mutual close transactions like other closes move utxo metrics to balance actor Also refactor to make it consistent with the existing actor. NB: there is still duplication in the metrics, will handle that separately. rename UnlockOutpointUtxo -> UnlockOutpoint refactor interaction between api and balance actor fixed half-finished comment improve the event stream synchronization trick remove left-over logs Co-authored-by: Bastien Teinturier <[email protected]> make GetGlobalBalance return a Try, not a Future make merge easier in feature branches
Rebased and squashed. |
For now it just gives detailed info on the current pending mutual closes.