mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-22 22:25:26 +01:00
added CommitSig tests with multiple htlcs
This commit is contained in:
parent
8e85d4ab63
commit
d0980cb315
6 changed files with 99 additions and 13 deletions
|
@ -82,7 +82,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
|
|||
maxAcceptedHtlcs = localParams.maxAcceptedHtlcs,
|
||||
fundingPubkey = localParams.fundingPrivkey.toPoint,
|
||||
revocationBasepoint = localParams.revocationSecret.toPoint,
|
||||
paymentBasepoint = localParams.paymentSecret.toPoint,
|
||||
paymentBasepoint = localParams.paymentKey.toPoint,
|
||||
delayedPaymentBasepoint = localParams.delayedPaymentKey.toPoint,
|
||||
firstPerCommitmentPoint = firstPerCommitmentPoint)
|
||||
goto(WAIT_FOR_ACCEPT_CHANNEL) using DATA_WAIT_FOR_ACCEPT_CHANNEL(temporaryChannelId, localParams, fundingSatoshis = fundingSatoshis, pushMsat = pushMsat, autoSignInterval = autoSignInterval)
|
||||
|
@ -108,7 +108,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
|
|||
maxAcceptedHtlcs = localParams.maxAcceptedHtlcs,
|
||||
fundingPubkey = localParams.fundingPrivkey.toPoint,
|
||||
revocationBasepoint = localParams.revocationSecret.toPoint,
|
||||
paymentBasepoint = localParams.paymentSecret.toPoint,
|
||||
paymentBasepoint = localParams.paymentKey.toPoint,
|
||||
delayedPaymentBasepoint = localParams.delayedPaymentKey.toPoint,
|
||||
firstPerCommitmentPoint = firstPerCommitmentPoint)
|
||||
val remoteParams = RemoteParams(
|
||||
|
|
|
@ -157,7 +157,7 @@ final case class LocalParams(dustLimitSatoshis: Long,
|
|||
maxAcceptedHtlcs: Int,
|
||||
fundingPrivkey: Scalar,
|
||||
revocationSecret: Scalar,
|
||||
paymentSecret: Scalar,
|
||||
paymentKey: Scalar,
|
||||
delayedPaymentKey: Scalar,
|
||||
finalPrivKey: Scalar,
|
||||
shaSeed: BinaryData,
|
||||
|
|
|
@ -142,7 +142,7 @@ object Commitments {
|
|||
val sig = Transactions.sign(remoteCommitTx, localParams.fundingPrivkey)
|
||||
|
||||
val sortedHtlcTxs: Seq[TransactionWithInputInfo] = (htlcTimeoutTxs ++ htlcSuccessTxs).sortBy(_.input.outPoint.index)
|
||||
val paymentKey = Generators.derivePrivKey(localParams.paymentSecret, remoteNextPerCommitmentPoint)
|
||||
val paymentKey = Generators.derivePrivKey(localParams.paymentKey, remoteNextPerCommitmentPoint)
|
||||
val htlcSigs = sortedHtlcTxs.map(Transactions.sign(_, paymentKey))
|
||||
|
||||
// don't sign if they don't get paid
|
||||
|
@ -193,7 +193,7 @@ object Commitments {
|
|||
|
||||
val sortedHtlcTxs: Seq[TransactionWithInputInfo] = (htlcTimeoutTxs ++ htlcSuccessTxs).sortBy(_.input.outPoint.index)
|
||||
require(commit.htlcSignatures.size == sortedHtlcTxs.size, s"htlc sig count mismatch (received=${commit.htlcSignatures.size}, expected=${sortedHtlcTxs.size})")
|
||||
val localPaymentKey = Generators.derivePrivKey(localParams.paymentSecret, localPerCommitmentPoint)
|
||||
val localPaymentKey = Generators.derivePrivKey(localParams.delayedPaymentKey, localPerCommitmentPoint)
|
||||
val htlcSigs = sortedHtlcTxs.map(Transactions.sign(_, localPaymentKey))
|
||||
val remotePaymentPubkey = Generators.derivePubKey(remoteParams.paymentBasepoint, localPerCommitmentPoint)
|
||||
// combine the sigs to make signed txes
|
||||
|
@ -247,7 +247,7 @@ object Commitments {
|
|||
// then we sort and sign them
|
||||
val sortedHtlcTimeoutTxs = htlcTimeoutTxs.sortBy(_.input.outPoint.index)
|
||||
require(revocation.htlcTimeoutSignatures.size == sortedHtlcTimeoutTxs.size, s"htlc-timeout sig count mismatch (received=${revocation.htlcTimeoutSignatures.size}, expected=${sortedHtlcTimeoutTxs.size})")
|
||||
val paymentKey = Generators.derivePrivKey(localParams.paymentSecret, theirNextCommit.remotePerCommitmentPoint)
|
||||
val paymentKey = Generators.derivePrivKey(localParams.paymentKey, theirNextCommit.remotePerCommitmentPoint)
|
||||
val htlcSigs = sortedHtlcTimeoutTxs.map(Transactions.sign(_, paymentKey))
|
||||
// combine the sigs to make signed txes
|
||||
val signedHtlcTxs = sortedHtlcTimeoutTxs
|
||||
|
@ -278,16 +278,16 @@ object Commitments {
|
|||
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, commitTxNumber, localParams.paymentSecret.toPoint, remoteParams.paymentBasepoint, localParams.isFunder, Satoshi(localParams.dustLimitSatoshis), localRevocationPubkey, localParams.toSelfDelay, localPubkey, remotePubkey, spec)
|
||||
val commitTx = Transactions.makeCommitTx(commitmentInput, commitTxNumber, localParams.paymentKey.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(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 localPubkey = Generators.derivePubKey(localParams.paymentKey.toPoint, remotePerCommitmentPoint)
|
||||
val remotePubkey = Generators.derivePubKey(remoteParams.delayedPaymentBasepoint, remotePerCommitmentPoint)
|
||||
val remoteRevocationPubkey = Generators.revocationPubKey(remoteParams.revocationBasepoint, remotePerCommitmentPoint)
|
||||
val commitTx = Transactions.makeCommitTx(commitmentInput, commitTxNumber, remoteParams.paymentBasepoint, localParams.paymentSecret.toPoint, !localParams.isFunder, Satoshi(remoteParams.dustLimitSatoshis), remoteRevocationPubkey, remoteParams.toSelfDelay, remotePubkey, localPubkey, spec)
|
||||
val commitTx = Transactions.makeCommitTx(commitmentInput, commitTxNumber, remoteParams.paymentBasepoint, localParams.paymentKey.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)
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ class Register(blockchain: ActorRef, paymentHandler: ActorRef) extends Actor wit
|
|||
maxAcceptedHtlcs = 100,
|
||||
fundingPrivkey = generateKey(0),
|
||||
revocationSecret = generateKey(1),
|
||||
paymentSecret = generateKey(2),
|
||||
paymentKey = generateKey(2),
|
||||
delayedPaymentKey = generateKey(3),
|
||||
finalPrivKey = generateKey(4),
|
||||
shaSeed = Globals.Node.seed,
|
||||
|
|
|
@ -22,7 +22,7 @@ object TestConstants {
|
|||
maxAcceptedHtlcs = 100,
|
||||
fundingPrivkey = Scalar(Array.fill[Byte](32)(1) :+ 1.toByte),
|
||||
revocationSecret = Scalar(Array.fill[Byte](32)(2) :+ 1.toByte),
|
||||
paymentSecret = Scalar(Array.fill[Byte](32)(3) :+ 1.toByte),
|
||||
paymentKey = Scalar(Array.fill[Byte](32)(3) :+ 1.toByte),
|
||||
delayedPaymentKey = Scalar(Array.fill[Byte](32)(4) :+ 1.toByte),
|
||||
finalPrivKey = Scalar(Array.fill[Byte](32)(5) :+ 1.toByte),
|
||||
shaSeed = Crypto.sha256("alice-seed".getBytes()),
|
||||
|
@ -41,7 +41,7 @@ object TestConstants {
|
|||
maxAcceptedHtlcs = 100,
|
||||
fundingPrivkey = Scalar(Array.fill[Byte](32)(11) :+ 1.toByte),
|
||||
revocationSecret = Scalar(Array.fill[Byte](32)(12) :+ 1.toByte),
|
||||
paymentSecret = Scalar(Array.fill[Byte](32)(13) :+ 1.toByte),
|
||||
paymentKey = Scalar(Array.fill[Byte](32)(13) :+ 1.toByte),
|
||||
delayedPaymentKey = Scalar(Array.fill[Byte](32)(14) :+ 1.toByte),
|
||||
finalPrivKey = Scalar(Array.fill[Byte](32)(15) :+ 1.toByte),
|
||||
shaSeed = Crypto.sha256("alice-seed".getBytes()),
|
||||
|
|
|
@ -8,7 +8,7 @@ import fr.acinq.eclair.TestConstants.{Alice, Bob}
|
|||
import fr.acinq.eclair.blockchain._
|
||||
import fr.acinq.eclair.channel.states.{StateSpecBaseClass, StateTestsHelperMethods}
|
||||
import fr.acinq.eclair.channel.{BITCOIN_FUNDING_DEPTHOK, Data, State, _}
|
||||
import fr.acinq.eclair.transactions.{IN, Scripts}
|
||||
import fr.acinq.eclair.transactions.{IN, OUT}
|
||||
import fr.acinq.eclair.wire.{AcceptChannel, ClosingSigned, CommitSig, Error, FundingCreated, FundingLocked, FundingSigned, OpenChannel, RevokeAndAck, Shutdown, UpdateAddHtlc, UpdateFailHtlc, UpdateFulfillHtlc}
|
||||
import org.junit.runner.RunWith
|
||||
import org.scalatest.junit.JUnitRunner
|
||||
|
@ -217,6 +217,7 @@ class NormalStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
|
|||
|
||||
sender.send(alice, CMD_SIGN)
|
||||
sender.expectMsg("ok")
|
||||
|
||||
// actual test begins
|
||||
alice2bob.expectMsgType[CommitSig]
|
||||
alice2bob.forward(bob)
|
||||
|
@ -225,6 +226,64 @@ class NormalStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
|
|||
awaitCond(bob.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.spec.htlcs.exists(h => h.add.id == htlc.id && h.direction == IN))
|
||||
assert(bob.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTxs._2.size == 1)
|
||||
assert(bob.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.spec.toLocalMsat == initialState.commitments.localCommit.spec.toLocalMsat)
|
||||
assert(bob.stateData.asInstanceOf[DATA_NORMAL].commitments.remoteChanges.acked.size == 1)
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CommitSig (one htlc sent)") { case (alice, bob, alice2bob, bob2alice, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
|
||||
val (r, htlc) = addHtlc(50000000, alice, bob, alice2bob, bob2alice)
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
|
||||
sender.send(alice, CMD_SIGN)
|
||||
sender.expectMsg("ok")
|
||||
alice2bob.expectMsgType[CommitSig]
|
||||
alice2bob.forward(bob)
|
||||
bob2alice.expectMsgType[RevokeAndAck]
|
||||
bob2alice.forward(alice)
|
||||
sender.send(bob, CMD_SIGN)
|
||||
sender.expectMsg("ok")
|
||||
|
||||
// actual test begins
|
||||
bob2alice.expectMsgType[CommitSig]
|
||||
bob2alice.forward(alice)
|
||||
|
||||
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.spec.htlcs.exists(h => h.add.id == htlc.id && h.direction == OUT))
|
||||
assert(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTxs._2.size == 1)
|
||||
assert(bob.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.spec.toLocalMsat == initialState.commitments.localCommit.spec.toLocalMsat)
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CommitSig (multiple htlcs in both directions)") { case (alice, bob, alice2bob, bob2alice, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
|
||||
val (r1, htlc1) = addHtlc(50000000, alice, bob, alice2bob, bob2alice) // a->b (regular)
|
||||
val (r2, htlc2) = addHtlc(8000000, alice, bob, alice2bob, bob2alice) // a->b (regular)
|
||||
val (r3, htlc3) = addHtlc(300000, bob, alice, bob2alice, alice2bob) // b->a (dust)
|
||||
val (r4, htlc4) = addHtlc(1000000, alice, bob, alice2bob, bob2alice) // a->b (regular)
|
||||
val (r5, htlc5) = addHtlc(50000000, bob, alice, bob2alice, alice2bob) // b->a (regular)
|
||||
val (r6, htlc6) = addHtlc(500000, alice, bob, alice2bob, bob2alice) // a->b (dust)
|
||||
val (r7, htlc7) = addHtlc(4000000, bob, alice, bob2alice, alice2bob) // b->a (regular)
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
|
||||
sender.send(alice, CMD_SIGN)
|
||||
sender.expectMsg("ok")
|
||||
alice2bob.expectMsgType[CommitSig]
|
||||
alice2bob.forward(bob)
|
||||
bob2alice.expectMsgType[RevokeAndAck]
|
||||
bob2alice.forward(alice)
|
||||
sender.send(bob, CMD_SIGN)
|
||||
sender.expectMsg("ok")
|
||||
|
||||
// actual test begins
|
||||
bob2alice.expectMsgType[CommitSig]
|
||||
bob2alice.forward(alice)
|
||||
|
||||
assert(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTxs._2.size == 3)
|
||||
val a = 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,6 +359,33 @@ class NormalStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
|
|||
bob2alice.expectMsgType[RevokeAndAck]
|
||||
bob2alice.forward(alice)
|
||||
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.remoteNextCommitInfo.isRight)
|
||||
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localChanges.acked.size == 1)
|
||||
}
|
||||
}
|
||||
|
||||
test("recv RevokeAndAck (one htlc received)") { case (alice, bob, alice2bob, bob2alice, _, bob2blockchain) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val (r, htlc) = addHtlc(50000000, alice, bob, alice2bob, bob2alice)
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
|
||||
sender.send(alice, CMD_SIGN)
|
||||
sender.expectMsg("ok")
|
||||
alice2bob.expectMsgType[CommitSig]
|
||||
alice2bob.forward(bob)
|
||||
bob2alice.expectMsgType[RevokeAndAck]
|
||||
bob2alice.forward(alice)
|
||||
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.remoteNextCommitInfo.isRight)
|
||||
|
||||
// actual test begins
|
||||
sender.send(bob, CMD_SIGN)
|
||||
sender.expectMsg("ok")
|
||||
alice2bob.expectMsgType[CommitSig]
|
||||
alice2bob.forward(bob)
|
||||
bob2alice.expectMsgType[RevokeAndAck]
|
||||
bob2alice.forward(alice)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue