Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ACINQ/eclair
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f6465763ef1c008bc2b1da50b2edef4bbc45b834
Choose a base ref
..
head repository: ACINQ/eclair
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2f97a5cc1541b63bb9e552d92380b6a66092a4b4
Choose a head ref
Original file line number Diff line number Diff line change
@@ -536,27 +536,41 @@ object Commitments {
}
}

def makeLocalTxs(keyManager: KeyManager, channelVersion: ChannelVersion, commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, localPerCommitmentPoint: PublicKey, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
def makeLocalTxs(keyManager: KeyManager,
channelVersion: ChannelVersion,
commitTxNumber: Long,
localParams: LocalParams,
remoteParams: RemoteParams,
commitmentInput: InputInfo,
localPerCommitmentPoint: PublicKey,
spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion)
val localDelayedPaymentPubkey = Generators.derivePubKey(keyManager.delayedPaymentPoint(channelKeyPath).publicKey, localPerCommitmentPoint)
val localHtlcPubkey = Generators.derivePubKey(keyManager.htlcPoint(channelKeyPath).publicKey, localPerCommitmentPoint)
val remotePaymentPubkey = Generators.derivePubKey(remoteParams.paymentBasepoint, localPerCommitmentPoint)
val remoteHtlcPubkey = Generators.derivePubKey(remoteParams.htlcBasepoint, localPerCommitmentPoint)
val localRevocationPubkey = Generators.revocationPubKey(remoteParams.revocationBasepoint, localPerCommitmentPoint)
val (commitTx, specItems)= Transactions.makeCommitTx(commitmentInput, commitTxNumber, keyManager.paymentPoint(channelKeyPath).publicKey, remoteParams.paymentBasepoint, localParams.isFunder, localParams.dustLimit, localRevocationPubkey, remoteParams.toSelfDelay, localDelayedPaymentPubkey, remotePaymentPubkey, localHtlcPubkey, remoteHtlcPubkey, spec)
val (htlcTimeoutTxs, htlcSuccessTxs) = Transactions.makeHtlcTxs(commitTx.tx, localParams.dustLimit, localRevocationPubkey, remoteParams.toSelfDelay, localDelayedPaymentPubkey, localHtlcPubkey, remoteHtlcPubkey, spec, specItems)
val outputs = makeCommitTxOutputs(localParams.isFunder, localParams.dustLimit, localRevocationPubkey, remoteParams.toSelfDelay, localDelayedPaymentPubkey, remotePaymentPubkey, localHtlcPubkey, remoteHtlcPubkey, spec)
val commitTx = Transactions.makeCommitTx(commitmentInput, commitTxNumber, keyManager.paymentPoint(channelKeyPath).publicKey, remoteParams.paymentBasepoint, localParams.isFunder, outputs)
val (htlcTimeoutTxs, htlcSuccessTxs) = Transactions.makeHtlcTxs(commitTx.tx, localParams.dustLimit, localRevocationPubkey, remoteParams.toSelfDelay, localDelayedPaymentPubkey, spec.feeratePerKw, outputs)
(commitTx, htlcTimeoutTxs, htlcSuccessTxs)
}

def makeRemoteTxs(keyManager: KeyManager, channelVersion: ChannelVersion, commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, remotePerCommitmentPoint: PublicKey, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
def makeRemoteTxs(keyManager: KeyManager,
channelVersion: ChannelVersion,
commitTxNumber: Long, localParams: LocalParams,
remoteParams: RemoteParams, commitmentInput: InputInfo,
remotePerCommitmentPoint: PublicKey,
spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion)
val localPaymentPubkey = Generators.derivePubKey(keyManager.paymentPoint(channelKeyPath).publicKey, remotePerCommitmentPoint)
val localHtlcPubkey = Generators.derivePubKey(keyManager.htlcPoint(channelKeyPath).publicKey, remotePerCommitmentPoint)
val remoteDelayedPaymentPubkey = Generators.derivePubKey(remoteParams.delayedPaymentBasepoint, remotePerCommitmentPoint)
val remoteHtlcPubkey = Generators.derivePubKey(remoteParams.htlcBasepoint, remotePerCommitmentPoint)
val remoteRevocationPubkey = Generators.revocationPubKey(keyManager.revocationPoint(channelKeyPath).publicKey, remotePerCommitmentPoint)
val (commitTx, specItems) = Transactions.makeCommitTx(commitmentInput, commitTxNumber, remoteParams.paymentBasepoint, keyManager.paymentPoint(channelKeyPath).publicKey, !localParams.isFunder, remoteParams.dustLimit, remoteRevocationPubkey, localParams.toSelfDelay, remoteDelayedPaymentPubkey, localPaymentPubkey, remoteHtlcPubkey, localHtlcPubkey, spec)
val (htlcTimeoutTxs, htlcSuccessTxs) = Transactions.makeHtlcTxs(commitTx.tx, remoteParams.dustLimit, remoteRevocationPubkey, localParams.toSelfDelay, remoteDelayedPaymentPubkey, remoteHtlcPubkey, localHtlcPubkey, spec, specItems)
val outputs = makeCommitTxOutputs(!localParams.isFunder, remoteParams.dustLimit, remoteRevocationPubkey, localParams.toSelfDelay, remoteDelayedPaymentPubkey, localPaymentPubkey, remoteHtlcPubkey, localHtlcPubkey, spec)
val commitTx = Transactions.makeCommitTx(commitmentInput, commitTxNumber, remoteParams.paymentBasepoint, keyManager.paymentPoint(channelKeyPath).publicKey, !localParams.isFunder, outputs)
val (htlcTimeoutTxs, htlcSuccessTxs) = Transactions.makeHtlcTxs(commitTx.tx, remoteParams.dustLimit, remoteRevocationPubkey, localParams.toSelfDelay, remoteDelayedPaymentPubkey, spec.feeratePerKw, outputs)
(commitTx, htlcTimeoutTxs, htlcSuccessTxs)
}

Original file line number Diff line number Diff line change
@@ -29,11 +29,10 @@ case object IN extends Direction { def opposite = OUT }
case object OUT extends Direction { def opposite = IN }
// @formatter:on


sealed trait SpecItem
case class DirectedHtlc(direction: Direction, add: UpdateAddHtlc) extends SpecItem
case object ToLocal extends SpecItem
case object ToRemote extends SpecItem
sealed trait CommitmentSpecLink
case object ToLocalLink extends CommitmentSpecLink
case object ToRemoteLink extends CommitmentSpecLink
case class DirectedHtlc(direction: Direction, add: UpdateAddHtlc) extends CommitmentSpecLink

final case class CommitmentSpec(htlcs: Set[DirectedHtlc], feeratePerKw: Long, toLocal: MilliSatoshi, toRemote: MilliSatoshi) {
val totalFunds = toLocal + toRemote + htlcs.toSeq.map(_.add.amountMsat).sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fr.acinq.eclair.transactions

import fr.acinq.bitcoin.{Crypto, LexicographicalOrdering, OutPoint, Satoshi, Script, ScriptElt, Transaction, TxIn, TxOut}
import fr.acinq.eclair.CltvExpiry
import scodec.bits.ByteVector

import scala.annotation.tailrec
@@ -14,24 +15,20 @@ object TransactionUtils {

def isLessThan(a: TxIn, b: TxIn): Boolean = isLessThan(a.outPoint, b.outPoint)

def isLessOrCLTV(a: (SpecItem, TxOut), b: (SpecItem, TxOut)): Boolean = {
val amountComparison = a._2.amount.compare(b._2.amount)
def isLessOrCLTV(a: (TxOut, Option[CltvExpiry]), b: (TxOut, Option[CltvExpiry])): Boolean = {
val amountComparison = a._1.amount.compare(b._1.amount)
if(amountComparison != 0){
amountComparison < 0
} else {
val lexicographicalComparison = lexicographicalOrder(a._2.publicKeyScript, b._2.publicKeyScript)
if(lexicographicalComparison == 0){
(a._1, b._1) match {
case (DirectedHtlc(OUT, addA), DirectedHtlc(OUT, addB)) => addA.cltvExpiry < addB.cltvExpiry
case _ => lexicographicalComparison < 0
}
val lexicographicalComparison = lexicographicalOrder(a._1.publicKeyScript, b._1.publicKeyScript)
if(lexicographicalComparison == 0 && a._2.isDefined && b._2.isDefined) {
a._2.get < b._2.get // compare the CLTVs
} else {
lexicographicalComparison < 0
}
}
}


@tailrec
def lexicographicalOrder(a: ByteVector, b: ByteVector): Int = {
if (a.isEmpty && b.isEmpty) 0
@@ -52,21 +49,25 @@ object TransactionUtils {
* Returns a tuple with: sorted_transaction and a map of htlc output index and their cltv - applies only to outputs of offered HTLCs
*
* @param tx
* @param specItems
* @param outputsWithHtlcCltvInfo the complete list of the outputs of this transaction, enriched with htlc_cltv info
* @return
*/
def sortByBIP69AndCLTV(tx: Transaction, specItems: Seq[(SpecItem, TxOut)]): (Transaction, Seq[(SpecItem, Int)])= {
assert(tx.txOut.size == specItems.size, "Unable to sort with incomplete information")
def sortByBIP69AndCLTV(tx: Transaction, outputsWithHtlcCltvInfo:Seq[(TxOut, Option[CltvExpiry])]): (Transaction, Map[Int, CltvExpiry])= {
assert(tx.txOut.size == outputsWithHtlcCltvInfo.size, "Unable to sort with incomplete information")

val sortedOutputsAndCltv = outputsWithHtlcCltvInfo.sortWith(isLessOrCLTV)

val sortedSpecItems = specItems.sortWith(isLessOrCLTV)
val indexCltv = sortedOutputsAndCltv.zipWithIndex.map {
case ((_, Some(cltv)), index) => (index, cltv)
case ((_, None), index) => (index, CltvExpiry(-1L))
}.filterNot(_._2 == CltvExpiry(-1L)).toMap

val sortedTx = tx.copy(
txIn = tx.txIn.sortWith(isLessThan),
txOut = sortedSpecItems.map(_._2)
txOut = sortedOutputsAndCltv.map(_._1)
)

val specItemsWithIndex = sortedSpecItems.zipWithIndex.map(el => (el._1._1, el._2))
(sortedTx, specItemsWithIndex)
(sortedTx, indexCltv)
}


Loading