Skip to content

Commit

Permalink
Always subtract both anchors from funder amount
Browse files Browse the repository at this point in the history
For simplicity's sake, we always subtract both anchors from the funder's
main output, even if only one anchor materializes.
  • Loading branch information
t-bast committed Jul 21, 2020
1 parent 0ea4378 commit fefd076
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,13 @@ object Transactions {
def commitTxFeeMsat(dustLimit: Satoshi, spec: CommitmentSpec, commitmentFormat: CommitmentFormat): MilliSatoshi = {
val trimmedOfferedHtlcs = trimOfferedHtlcs(dustLimit, spec, commitmentFormat)
val trimmedReceivedHtlcs = trimReceivedHtlcs(dustLimit, spec, commitmentFormat)
val anchorsCost = commitmentFormat match {
case DefaultCommitmentFormat => Satoshi(0)
// the funder pays for both anchors all the time, even if only one anchor is present
case AnchorOutputsCommitmentFormat => AnchorOutputsCommitmentFormat.anchorAmount * 2
}
val weight = commitmentFormat.commitWeight + commitmentFormat.htlcOutputWeight * (trimmedOfferedHtlcs.size + trimmedReceivedHtlcs.size)
weight2feeMsat(spec.feeratePerKw, weight)
weight2feeMsat(spec.feeratePerKw, weight) + anchorsCost
}

def commitTxFee(dustLimit: Satoshi, spec: CommitmentSpec, commitmentFormat: CommitmentFormat): Satoshi = commitTxFeeMsat(dustLimit, spec, commitmentFormat).truncateToSatoshi
Expand Down Expand Up @@ -291,24 +296,11 @@ object Transactions {

val hasHtlcs = outputs.nonEmpty

def computeMainOutputs(funderSpecAmount: MilliSatoshi, fundeeSpecAmount: MilliSatoshi): (Satoshi, Satoshi) = commitmentFormat match {
// NB: we don't care if values are < 0, they will be trimmed if they are < dust limit anyway
case DefaultCommitmentFormat =>
val commitFee = commitTxFee(localDustLimit, spec, commitmentFormat)
(funderSpecAmount.truncateToSatoshi - commitFee, fundeeSpecAmount.truncateToSatoshi)
case AnchorOutputsCommitmentFormat =>
val commitFee = commitTxFee(localDustLimit, spec, commitmentFormat)
// We won't add an anchor for the fundee if he has nothing at stake (which typically happens when a new channel is opened without any push_msat)
val fundeeAnchorSkipped = fundeeSpecAmount < localDustLimit && !hasHtlcs
val anchorsCost = if (fundeeAnchorSkipped) AnchorOutputsCommitmentFormat.anchorAmount else AnchorOutputsCommitmentFormat.anchorAmount * 2
(funderSpecAmount.truncateToSatoshi - commitFee - anchorsCost, fundeeSpecAmount.truncateToSatoshi)
}

val (toLocalAmount: Satoshi, toRemoteAmount: Satoshi) = if (localIsFunder) {
computeMainOutputs(spec.toLocal, spec.toRemote)
(spec.toLocal.truncateToSatoshi - commitTxFee(localDustLimit, spec, commitmentFormat), spec.toRemote.truncateToSatoshi)
} else {
computeMainOutputs(spec.toRemote, spec.toLocal).swap
}
(spec.toLocal.truncateToSatoshi, spec.toRemote.truncateToSatoshi - commitTxFee(localDustLimit, spec, commitmentFormat))
} // NB: we don't care if values are < 0, they will be trimmed if they are < dust limit anyway

if (toLocalAmount >= localDustLimit) {
outputs.append(CommitmentOutputLink(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
to_local_msat: 6988000000
to_remote_msat: 3000000000
local_feerate_per_kw: 6216009
remote_signature = 3045022100ee67ddd6b3739f3189151063365585ff153ac17e34751da0c90e8034e388a6e2022077aa76cd469604e6af1c00b600d0f4ed0876b11f06336edde3388d517a1ef5e8
remote_signature = 30450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf
output commit_tx: 02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80044a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb399422020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80ec0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a04004830450221008bf6fa6aae9706f68f42006bbf2c3ed5c807487059ce5e5f8e2c2646d60b8a4902201c42e0894e321bf33eaa2d06370ad43368d55611916623fd3589f838d760f45e01483045022100ee67ddd6b3739f3189151063365585ff153ac17e34751da0c90e8034e388a6e2022077aa76cd469604e6af1c00b600d0f4ed0876b11f06336edde3388d517a1ef5e801475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220
num_htlcs: 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,22 +400,22 @@ class TransactionsSpec extends AnyFunSuite with Logging {
val spec = CommitmentSpec(htlcs = Set.empty, feeratePerKw = feeratePerKw, toLocal = 400.mbtc.toMilliSatoshi, toRemote = 300.mbtc.toMilliSatoshi)
val commitFee = commitTxFee(localDustLimit, spec, AnchorOutputsCommitmentFormat)
val belowDust = (localDustLimit * 0.9).toMilliSatoshi
val belowDustWithFeeAndAnchors = (localDustLimit + commitFee + anchorAmount * 1.75).toMilliSatoshi
val belowDustWithFeeAndAnchors = (localDustLimit + commitFee * 0.9).toMilliSatoshi

{
val outputs = makeCommitTxOutputs(localIsFunder = true, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, remotePaymentPriv.publicKey, localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localFundingPriv.publicKey, remoteFundingPriv.publicKey, spec, AnchorOutputsCommitmentFormat)
assert(outputs.map(_.commitmentOutput).toSet === Set(CommitmentOutput.ToLocal, CommitmentOutput.ToRemote, CommitmentOutput.ToLocalAnchor, CommitmentOutput.ToRemoteAnchor))
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToLocalAnchor).get.output.amount === anchorAmount)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToRemoteAnchor).get.output.amount === anchorAmount)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToLocal).get.output.amount.toMilliSatoshi === spec.toLocal - commitFee - anchorAmount * 2)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToLocal).get.output.amount.toMilliSatoshi === spec.toLocal - commitFee)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToRemote).get.output.amount.toMilliSatoshi === spec.toRemote)
}
{
val toRemoteFundeeBelowDust = spec.copy(toRemote = belowDust)
val outputs = makeCommitTxOutputs(localIsFunder = true, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, remotePaymentPriv.publicKey, localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localFundingPriv.publicKey, remoteFundingPriv.publicKey, toRemoteFundeeBelowDust, AnchorOutputsCommitmentFormat)
assert(outputs.map(_.commitmentOutput).toSet === Set(CommitmentOutput.ToLocal, CommitmentOutput.ToLocalAnchor))
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToLocalAnchor).get.output.amount === anchorAmount)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToLocal).get.output.amount.toMilliSatoshi === spec.toLocal - commitFee - anchorAmount)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToLocal).get.output.amount.toMilliSatoshi === spec.toLocal - commitFee)
}
{
val toLocalFunderBelowDust = spec.copy(toLocal = belowDustWithFeeAndAnchors)
Expand All @@ -436,7 +436,7 @@ class TransactionsSpec extends AnyFunSuite with Logging {
val outputs = makeCommitTxOutputs(localIsFunder = false, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, remotePaymentPriv.publicKey, localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localFundingPriv.publicKey, remoteFundingPriv.publicKey, toLocalFundeeBelowDust, AnchorOutputsCommitmentFormat)
assert(outputs.map(_.commitmentOutput).toSet === Set(CommitmentOutput.ToRemote, CommitmentOutput.ToRemoteAnchor))
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToRemoteAnchor).get.output.amount === anchorAmount)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToRemote).get.output.amount.toMilliSatoshi === spec.toRemote - commitFee - anchorAmount)
assert(outputs.find(_.commitmentOutput == CommitmentOutput.ToRemote).get.output.amount.toMilliSatoshi === spec.toRemote - commitFee)
}
{
val allBelowDust = spec.copy(toLocal = belowDust, toRemote = belowDust)
Expand Down

0 comments on commit fefd076

Please sign in to comment.