Skip to content

Commit

Permalink
Correct dust limit for splice inputs (#557)
Browse files Browse the repository at this point in the history
When creating a splice transaction, we should filter out inputs that are
below the dust limit. But we should apply the dust limit that matches
each script type, instead of the using the channel's dust limit (which is
used for the outputs of the funding and commitment transactions).
  • Loading branch information
t-bast authored Nov 2, 2023
1 parent 0c34d72 commit 9ffeb05
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ data class FundingContributions(val inputs: List<InteractiveTxInput.Outgoing>, v
): Either<FundingContributionFailure, FundingContributions> {
walletInputs.forEach { (tx, txOutput) ->
if (tx.txOut.size <= txOutput) return Either.Left(FundingContributionFailure.InputOutOfBounds(tx.txid, txOutput))
if (tx.txOut[txOutput].amount < params.dustLimit) return Either.Left(FundingContributionFailure.InputBelowDust(tx.txid, txOutput, tx.txOut[txOutput].amount, params.dustLimit))
val dustLimit = Transactions.dustLimit(tx.txOut[txOutput].publicKeyScript)
if (tx.txOut[txOutput].amount < dustLimit) return Either.Left(FundingContributionFailure.InputBelowDust(tx.txid, txOutput, tx.txOut[txOutput].amount, dustLimit))
if (Transaction.write(tx.stripInputWitnesses()).size > 65_000) return Either.Left(FundingContributionFailure.InputTxTooLarge(tx))
}
val previousFundingAmount = sharedUtxo?.second?.fundingAmount ?: 0.sat
Expand Down Expand Up @@ -775,11 +776,11 @@ data class InteractiveTxSigningSession(
val signedLocalCommitTx = Transactions.addSigs(localCommit.value.commitTx, fundingKey.publicKey(), fundingParams.remoteFundingPubkey, localSigOfLocalTx, remoteCommitSig.signature)
when (Transactions.checkSpendable(signedLocalCommitTx)) {
is Try.Failure -> {
logger.info { "interactiveTxSession=$this"}
logger.info { "channelParams=$channelParams"}
logger.info { "fundingKey=${fundingKey.publicKey()}"}
logger.info { "localSigOfLocalTx=$localSigOfLocalTx"}
logger.info { "signedLocalCommitTx=$signedLocalCommitTx"}
logger.info { "interactiveTxSession=$this" }
logger.info { "channelParams=$channelParams" }
logger.info { "fundingKey=${fundingKey.publicKey()}" }
logger.info { "localSigOfLocalTx=$localSigOfLocalTx" }
logger.info { "signedLocalCommitTx=$signedLocalCommitTx" }
Pair(this, InteractiveTxSigningSessionAction.AbortFundingAttempt(InvalidCommitmentSignature(fundingParams.channelId, signedLocalCommitTx.tx.txid)))
}
is Try.Success -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,21 @@ object Transactions {
*/
fun fee2rate(fee: Satoshi, weight: Int): FeeratePerKw = FeeratePerKw((fee * 1000L) / weight.toLong())

/** As defined in https://github.com/lightning/bolts/blob/master/03-transactions.md#dust-limits */
fun dustLimit(scriptPubKey: ByteVector): Satoshi {
return runTrying {
val script = Script.parse(scriptPubKey)
when {
Script.isPay2pkh(script) -> 546.sat
Script.isPay2sh(script) -> 540.sat
Script.isPay2wpkh(script) -> 294.sat
Script.isPay2wsh(script) -> 330.sat
Script.isNativeWitnessScript(script) -> 354.sat
else -> 546.sat
}
}.getOrElse { 546.sat }
}

/** Offered HTLCs below this amount will be trimmed. */
fun offeredHtlcTrimThreshold(dustLimit: Satoshi, spec: CommitmentSpec): Satoshi = dustLimit + weight2fee(spec.feerate, Commitments.HTLC_TIMEOUT_WEIGHT)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ class InteractiveTxTestsCommon : LightningTestSuite() {
val pubKey = privKey.publicKey()
val fundingParams = InteractiveTxParams(randomBytes32(), true, 150_000.sat, 50_000.sat, pubKey, 0, 660.sat, FeeratePerKw(2500.sat))
run {
val previousTx = Transaction(2, listOf(), listOf(TxOut(650.sat, Script.pay2wpkh(pubKey))), 0)
val previousTx = Transaction(2, listOf(), listOf(TxOut(293.sat, Script.pay2wpkh(pubKey))), 0)
val result = FundingContributions.create(channelKeys, swapInKeys, fundingParams, listOf(WalletState.Utxo(previousTx, 0, 0))).left
assertNotNull(result)
assertIs<FundingContributionFailure.InputBelowDust>(result)
Expand Down

0 comments on commit 9ffeb05

Please sign in to comment.