mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-22 14:22:39 +01:00
merged
This commit is contained in:
commit
2fa70e2000
4 changed files with 63 additions and 22 deletions
|
@ -138,7 +138,7 @@ object Commitments {
|
|||
case Right(remoteNextPerCommitmentPoint) =>
|
||||
// remote commitment will includes all local changes + remote acked changes
|
||||
val spec = CommitmentSpec.reduce(remoteCommit.spec, remoteChanges.acked, localChanges.proposed)
|
||||
val (remoteCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeRemoteTxs(localParams, remoteParams, commitInput, remoteNextPerCommitmentPoint, spec)
|
||||
val (remoteCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeRemoteTxs(remoteCommit.index, localParams, remoteParams, commitInput, remoteNextPerCommitmentPoint, spec)
|
||||
val sig = Transactions.sign(remoteCommitTx, localParams.fundingPrivkey)
|
||||
|
||||
val sortedHtlcTxs: Seq[TransactionWithInputInfo] = (htlcTimeoutTxs ++ htlcSuccessTxs).sortBy(_.input.outPoint.index)
|
||||
|
@ -180,8 +180,9 @@ object Commitments {
|
|||
// receiving money i.e its commit tx has one output for them
|
||||
|
||||
val spec = CommitmentSpec.reduce(localCommit.spec, localChanges.acked, remoteChanges.proposed)
|
||||
val localPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, commitments.localCommit.index.toInt + 1) // TODO: Long or Int??
|
||||
val (localCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeLocalTxs(localParams, remoteParams, commitInput, localPerCommitmentPoint, spec)
|
||||
val localPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, commitments.localCommit.index.toInt + 1)
|
||||
// TODO: Long or Int??
|
||||
val (localCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeLocalTxs(localCommit.index, localParams, remoteParams, commitInput, localPerCommitmentPoint, spec)
|
||||
val sig = Transactions.sign(localCommitTx, localParams.fundingPrivkey)
|
||||
|
||||
// TODO: should we have optional sig? (original comment: this tx will NOT be signed if our output is empty)
|
||||
|
@ -218,8 +219,10 @@ object Commitments {
|
|||
}
|
||||
|
||||
// we will send our revocation preimage + our next revocation hash
|
||||
val localPerCommitmentSecret = Generators.perCommitSecret(localParams.shaSeed, commitments.localCommit.index.toInt) // TODO: Long or Int??
|
||||
val localNextPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, commitments.localCommit.index.toInt + 2) // TODO: Long or Int??
|
||||
val localPerCommitmentSecret = Generators.perCommitSecret(localParams.shaSeed, commitments.localCommit.index.toInt)
|
||||
// TODO: Long or Int??
|
||||
val localNextPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, commitments.localCommit.index.toInt + 2)
|
||||
// TODO: Long or Int??
|
||||
val revocation = RevokeAndAck(
|
||||
channelId = commitments.channelId,
|
||||
perCommitmentSecret = localPerCommitmentSecret,
|
||||
|
@ -248,7 +251,7 @@ object Commitments {
|
|||
// TODO: check their HTLC-Timeout sigs are valid and store their sig
|
||||
|
||||
// TODO: add
|
||||
val (remoteCommitTx, htlcTimeoutCommitTx, htlcSuccessCommitTx) = makeRemoteTxs(localParams, remoteParams, commitInput, remoteCommit.remotePerCommitmentPoint, remoteCommit.spec)
|
||||
val (remoteCommitTx, htlcTimeoutCommitTx, htlcSuccessCommitTx) = makeRemoteTxs(localCommit.index, localParams, remoteParams, commitInput, remoteCommit.remotePerCommitmentPoint, remoteCommit.spec)
|
||||
//val punishTx: Transaction = ??? //Helpers.claimRevokedCommitTx(theirTxTemplate, revocation.revocationPreimage, localParams.finalPrivKey)
|
||||
//Transaction.correctlySpends(punishTx, Seq(theirTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)
|
||||
//txDb.add(theirTx.txid, punishTx)
|
||||
|
@ -263,20 +266,20 @@ object Commitments {
|
|||
}
|
||||
}
|
||||
|
||||
def makeLocalTxs(localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, localPerCommitmentPoint: Point, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
|
||||
def makeLocalTxs(commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, localPerCommitmentPoint: Point, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
|
||||
val localPubkey = Generators.derivePubKey(localParams.delayedPaymentKey.toPoint, localPerCommitmentPoint)
|
||||
val remotePubkey = Generators.derivePubKey(remoteParams.paymentBasepoint, localPerCommitmentPoint)
|
||||
val localRevocationPubkey = Generators.revocationPubKey(localParams.revocationSecret.toPoint, localPerCommitmentPoint)
|
||||
val commitTx = Transactions.makeCommitTx(commitmentInput, localParams.isFunder, Satoshi(localParams.dustLimitSatoshis), localRevocationPubkey, localParams.toSelfDelay, localPubkey, remotePubkey, spec)
|
||||
val commitTx = Transactions.makeCommitTx(commitmentInput, commitTxNumber, localParams.paymentSecret.toPoint, remoteParams.paymentBasepoint, localParams.isFunder, Satoshi(localParams.dustLimitSatoshis), localRevocationPubkey, localParams.toSelfDelay, localPubkey, remotePubkey, spec)
|
||||
val (htlcTimeoutTxs, htlcSuccessTxs) = Transactions.makeHtlcTxs(commitTx.tx, Satoshi(localParams.dustLimitSatoshis), localRevocationPubkey, localParams.toSelfDelay, localPubkey, remotePubkey, spec)
|
||||
(commitTx, htlcTimeoutTxs, htlcSuccessTxs)
|
||||
}
|
||||
|
||||
def makeRemoteTxs(localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, remotePerCommitmentPoint: Point, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
|
||||
def makeRemoteTxs(commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, remotePerCommitmentPoint: Point, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = {
|
||||
val localPubkey = Generators.derivePubKey(localParams.paymentSecret.toPoint, remotePerCommitmentPoint)
|
||||
val remotePubkey = Generators.derivePubKey(remoteParams.delayedPaymentBasepoint, remotePerCommitmentPoint)
|
||||
val remoteRevocationPubkey = Generators.revocationPubKey(remoteParams.revocationBasepoint, remotePerCommitmentPoint)
|
||||
val commitTx = Transactions.makeCommitTx(commitmentInput, !localParams.isFunder, Satoshi(remoteParams.dustLimitSatoshis), remoteRevocationPubkey, remoteParams.toSelfDelay, remotePubkey, localPubkey, spec)
|
||||
val commitTx = Transactions.makeCommitTx(commitmentInput, commitTxNumber, remoteParams.paymentBasepoint, localParams.paymentSecret.toPoint, !localParams.isFunder, Satoshi(remoteParams.dustLimitSatoshis), remoteRevocationPubkey, remoteParams.toSelfDelay, remotePubkey, localPubkey, spec)
|
||||
val (htlcTimeoutTxs, htlcSuccessTxs) = Transactions.makeHtlcTxs(commitTx.tx, Satoshi(localParams.dustLimitSatoshis), remoteRevocationPubkey, remoteParams.toSelfDelay, remotePubkey, localPubkey, spec)
|
||||
(commitTx, htlcTimeoutTxs, htlcSuccessTxs)
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ object Helpers {
|
|||
|
||||
val commitmentInput = makeFundingInputInfo(fundingTxHash, fundingTxOutputIndex, Satoshi(params.fundingSatoshis), params.localParams.fundingPrivkey.toPoint, params.remoteParams.fundingPubkey)
|
||||
val localPerCommitmentPoint = Generators.perCommitPoint(params.localParams.shaSeed, 0)
|
||||
val (localTxTemplate, _, _) = Commitments.makeLocalTxs(params.localParams, params.remoteParams, commitmentInput, localPerCommitmentPoint, localSpec)
|
||||
val (remoteTxTemplate, _, _) = Commitments.makeRemoteTxs(params.localParams, params.remoteParams, commitmentInput, remoteFirstPerCommitmentPoint, remoteSpec)
|
||||
val (localTxTemplate, _, _) = Commitments.makeLocalTxs(0, params.localParams, params.remoteParams, commitmentInput, localPerCommitmentPoint, localSpec)
|
||||
val (remoteTxTemplate, _, _) = Commitments.makeRemoteTxs(0, params.localParams, params.remoteParams, commitmentInput, remoteFirstPerCommitmentPoint, remoteSpec)
|
||||
|
||||
(localSpec, localTxTemplate, remoteSpec, remoteTxTemplate)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package fr.acinq.eclair.transactions
|
|||
import fr.acinq.bitcoin.Crypto.{Point, PrivateKey, ripemd160}
|
||||
import fr.acinq.bitcoin.Script._
|
||||
import fr.acinq.bitcoin.SigVersion.SIGVERSION_WITNESS_V0
|
||||
import fr.acinq.bitcoin.{BinaryData, LexicographicalOrdering, MilliSatoshi, OutPoint, SIGHASH_ALL, Satoshi, ScriptElt, ScriptFlags, Transaction, TxIn, TxOut, millisatoshi2satoshi}
|
||||
import fr.acinq.bitcoin.{BinaryData, Crypto, LexicographicalOrdering, MilliSatoshi, OutPoint, Protocol, SIGHASH_ALL, Satoshi, ScriptElt, ScriptFlags, Transaction, TxIn, TxOut, millisatoshi2satoshi}
|
||||
import fr.acinq.eclair.transactions.Scripts._
|
||||
import fr.acinq.eclair.wire.UpdateAddHtlc
|
||||
|
||||
|
@ -63,7 +63,33 @@ object Transactions {
|
|||
weight2fee(feeRatePerKw, fee3.weight) + fee3.amount
|
||||
}
|
||||
|
||||
def makeCommitTx(commitTxInput: InputInfo, localIsFunder: Boolean, localDustLimit: Satoshi, localRevocationPubkey: BinaryData, toLocalDelay: Int, localPubkey: BinaryData, remotePubkey: BinaryData, spec: CommitmentSpec): CommitTx = {
|
||||
/**
|
||||
*
|
||||
* @param commitTxNumber commit tx number
|
||||
* @param localPaymentBasePoint local payment base point
|
||||
* @param remotePaymentBasePoint remote payment base point
|
||||
* @return the obscured tx number as defined in BOLT #3 (a 48 bits integer)
|
||||
*/
|
||||
def obscuredCommitTxNumber(commitTxNumber: Long, localPaymentBasePoint: Point, remotePaymentBasePoint: Point): Long = {
|
||||
val h = Crypto.sha256(localPaymentBasePoint.toBin ++ remotePaymentBasePoint.toBin)
|
||||
val blind = Protocol.uint64(h.takeRight(6).reverse ++ BinaryData("0x0000"))
|
||||
commitTxNumber ^ blind
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param commitTx commit tx
|
||||
* @param localPaymentBasePoint local payment base point
|
||||
* @param remotePaymentBasePoint remote payment base point
|
||||
* @return the actual commit tx number that was blinded and stored in locktime and sequence fields
|
||||
*/
|
||||
def getCommitTxNumber(commitTx: Transaction, localPaymentBasePoint: Point, remotePaymentBasePoint: Point): Long = {
|
||||
val blind = obscuredCommitTxNumber(0, localPaymentBasePoint, remotePaymentBasePoint)
|
||||
val obscured = commitTx.lockTime | ((commitTx.txIn(0).sequence & 0xffffff) << 24)
|
||||
obscured ^ blind
|
||||
}
|
||||
|
||||
def makeCommitTx(commitTxInput: InputInfo, commitTxNumber: Long, localPaymentBasePoint: Point, remotePaymentBasePoint: Point, localIsFunder: Boolean, localDustLimit: Satoshi, localRevocationPubkey: BinaryData, toLocalDelay: Int, localPubkey: BinaryData, remotePubkey: BinaryData, spec: CommitmentSpec): CommitTx = {
|
||||
|
||||
val commitFee = commitTxFee(spec.feeRatePerKw, localDustLimit, spec)
|
||||
// TODO: check dust amount!
|
||||
|
@ -87,11 +113,13 @@ object Transactions {
|
|||
.filter(htlc => (MilliSatoshi(htlc.add.amountMsat) - htlcSuccessFee).compare(localDustLimit) > 0)
|
||||
.map(htlc => TxOut(MilliSatoshi(htlc.add.amountMsat), pay2wsh(htlcReceived(localPubkey, remotePubkey, ripemd160(htlc.add.paymentHash), htlc.add.expiry))))
|
||||
|
||||
val txnumber = obscuredCommitTxNumber(commitTxNumber, localPaymentBasePoint, remotePaymentBasePoint)
|
||||
|
||||
val tx = Transaction(
|
||||
version = 2,
|
||||
txIn = TxIn(commitTxInput.outPoint, Array.emptyByteArray, 0xffffffffL) :: Nil,
|
||||
txIn = TxIn(commitTxInput.outPoint, Array.emptyByteArray, sequence = 0x80000000L | (txnumber >> 24)) :: Nil,
|
||||
txOut = toLocalDelayedOutput_opt.toSeq ++ toRemoteOutput_opt.toSeq ++ htlcOfferedOutputs ++ htlcReceivedOutputs,
|
||||
lockTime = 0)
|
||||
lockTime = txnumber & 0xffffffL)
|
||||
CommitTx(commitTxInput, LexicographicalOrdering.sort(tx))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package fr.acinq.eclair.transactions
|
||||
|
||||
import java.nio.{ByteBuffer, ByteOrder}
|
||||
|
||||
import fr.acinq.bitcoin.Crypto.{Scalar, sha256}
|
||||
import fr.acinq.bitcoin.{BinaryData, Btc, MilliBtc, MilliSatoshi, Satoshi, Transaction, millibtc2satoshi}
|
||||
import fr.acinq.bitcoin.{BinaryData, Btc, Crypto, MilliBtc, MilliSatoshi, Protocol, Satoshi, Transaction, millibtc2satoshi}
|
||||
import fr.acinq.eclair.channel.Helpers.Funding
|
||||
import fr.acinq.eclair.transactions.Transactions._
|
||||
import fr.acinq.eclair.wire.UpdateAddHtlc
|
||||
|
@ -38,8 +40,16 @@ class TransactionsSpec extends FunSuite {
|
|||
toLocalMsat = millibtc2satoshi(MilliBtc(400)).amount * 1000,
|
||||
toRemoteMsat = millibtc2satoshi(MilliBtc(300)).amount * 1000)
|
||||
|
||||
val commitTx = makeCommitTx(commitInput, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val commitTxNumber = 0x404142434445L
|
||||
val commitTx = makeCommitTx(commitInput, commitTxNumber, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
|
||||
{
|
||||
assert(getCommitTxNumber(commitTx.tx, localPaymentPriv.toPoint, remotePaymentPriv.toPoint) == commitTxNumber)
|
||||
val hash: Array[Byte] = Crypto.sha256(localPaymentPriv.toPoint.toBin ++ remotePaymentPriv.toPoint.toBin)
|
||||
val num = ByteBuffer.wrap(hash.takeRight(8)).order(ByteOrder.BIG_ENDIAN).getLong & 0xffffffffffffL
|
||||
val check = ((commitTx.tx.txIn(0).sequence & 0xffffff) << 24) | (commitTx.tx.lockTime)
|
||||
assert((check ^ num) == commitTxNumber)
|
||||
}
|
||||
val (htlcTimeoutTxs, htlcSuccessTxs) = makeHtlcTxs(commitTx.tx, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
|
||||
assert(htlcTimeoutTxs.size == 1)
|
||||
|
@ -163,7 +173,7 @@ class TransactionsSpec extends FunSuite {
|
|||
feeRatePerKw = feeRatePerKw,
|
||||
toLocalMsat = millibtc2satoshi(MilliBtc(70)).amount * 1000,
|
||||
toRemoteMsat = millibtc2satoshi(MilliBtc(30)).amount * 1000)
|
||||
val commitTx = makeCommitTx(commitInput, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val commitTx = makeCommitTx(commitInput, 42, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val (htlcTimeoutTxs, htlcSuccessTxs) = makeHtlcTxs(commitTx.tx, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
run("simple tx with two outputs", spec, commitTx, htlcTimeoutTxs, htlcSuccessTxs)
|
||||
}
|
||||
|
@ -175,7 +185,7 @@ class TransactionsSpec extends FunSuite {
|
|||
feeRatePerKw = feeRatePerKw,
|
||||
toLocalMsat = (MilliBtc(100) - Satoshi(1000)).amount * 1000,
|
||||
toRemoteMsat = Satoshi(1000).amount * 1000)
|
||||
val commitTx = makeCommitTx(commitInput, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val commitTx = makeCommitTx(commitInput, 42, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val (htlcTimeoutTxs, htlcSuccessTxs) = makeHtlcTxs(commitTx.tx, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
run("two outputs with fundee below dust limit", spec, commitTx, htlcTimeoutTxs, htlcSuccessTxs)
|
||||
}
|
||||
|
@ -194,7 +204,7 @@ class TransactionsSpec extends FunSuite {
|
|||
feeRatePerKw = feeRatePerKw,
|
||||
toLocalMsat = (MilliBtc(100) - MilliBtc(30) - MilliSatoshi(htlc1.amountMsat) - MilliSatoshi(htlc2.amountMsat)).amount * 1000,
|
||||
toRemoteMsat = millibtc2satoshi(MilliBtc(30)).amount * 1000)
|
||||
val commitTx = makeCommitTx(commitInput, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val commitTx = makeCommitTx(commitInput, 42, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val (htlcTimeoutTxs, htlcSuccessTxs) = makeHtlcTxs(commitTx.tx, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
run("with htlcs, all above dust limit", spec, commitTx, htlcTimeoutTxs, htlcSuccessTxs)
|
||||
}
|
||||
|
@ -222,7 +232,7 @@ class TransactionsSpec extends FunSuite {
|
|||
feeRatePerKw = feeRatePerKw,
|
||||
toLocalMsat = (MilliBtc(100) - MilliBtc(30) - MilliSatoshi(htlc1.amountMsat) - MilliSatoshi(htlc2.amountMsat) - MilliSatoshi(htlc3.amountMsat) - MilliSatoshi(htlc4.amountMsat) - MilliSatoshi(htlc5.amountMsat)).amount * 1000,
|
||||
toRemoteMsat = millibtc2satoshi(MilliBtc(30)).amount * 1000)
|
||||
val commitTx = makeCommitTx(commitInput, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val commitTx = makeCommitTx(commitInput, 42, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, true, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
val (htlcTimeoutTxs, htlcSuccessTxs) = makeHtlcTxs(commitTx.tx, localDustLimit, localRevocationPriv.toPoint, toLocalDelay, localPaymentPriv.toPoint, remotePaymentPriv.toPoint, spec)
|
||||
run("with htlcs, some below dust limit", spec, commitTx, htlcTimeoutTxs, htlcSuccessTxs)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue