Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a context to interactive tx session #2849

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,8 @@ sealed trait RbfStatus
object RbfStatus {
case object NoRbf extends RbfStatus
case class RbfRequested(cmd: CMD_BUMP_FUNDING_FEE) extends RbfStatus
case class RbfInProgress(cmd_opt: Option[CMD_BUMP_FUNDING_FEE], rbf: typed.ActorRef[InteractiveTxBuilder.Command], remoteCommitSig: Option[CommitSig]) extends RbfStatus
case class RbfWaitingForSigs(signingSession: InteractiveTxSigningSession.WaitingForSigs) extends RbfStatus
case class RbfInProgress(cmd_opt: Option[CMD_BUMP_FUNDING_FEE], sessionContext: SessionContext, rbf: typed.ActorRef[InteractiveTxBuilder.Command], remoteCommitSig: Option[CommitSig]) extends RbfStatus
case class RbfWaitingForSigs(sessionContext: SessionContext, signingSession: InteractiveTxSigningSession.WaitingForSigs) extends RbfStatus
case object RbfAborted extends RbfStatus
}

Expand All @@ -481,9 +481,9 @@ object SpliceStatus {
/** We told our peer we want to splice funds in the channel. */
case class SpliceRequested(cmd: CMD_SPLICE, init: SpliceInit) extends QuiescentSpliceStatus
/** We both agreed to splice and are building the splice transaction. */
case class SpliceInProgress(cmd_opt: Option[CMD_SPLICE], sessionId: ByteVector32, splice: typed.ActorRef[InteractiveTxBuilder.Command], remoteCommitSig: Option[CommitSig]) extends QuiescentSpliceStatus
case class SpliceInProgress(cmd_opt: Option[CMD_SPLICE], sessionContext: SessionContext, splice: typed.ActorRef[InteractiveTxBuilder.Command], remoteCommitSig: Option[CommitSig]) extends QuiescentSpliceStatus
/** The splice transaction has been negotiated, we're exchanging signatures. */
case class SpliceWaitingForSigs(signingSession: InteractiveTxSigningSession.WaitingForSigs) extends QuiescentSpliceStatus
case class SpliceWaitingForSigs(sessionContext: SessionContext, signingSession: InteractiveTxSigningSession.WaitingForSigs) extends QuiescentSpliceStatus
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether sessionContext should be (a) in [Rbf/Splice]WaitingForSigs, or (b) in InteractiveTxSigningSession.WaitingForSigs.

(a) is somewhat more consistent at the [Rbf/Splice]Status level, because we have to add sessionContext to [Rbf/Splice]InProgress in any case
(b) allows for better factorization between rbf and splice, and simpler codecs.

I went with (a) for this first shot, lmk what you think 🙏

/** The splice attempt was aborted by us, we're waiting for our peer to ack. */
case object SpliceAborted extends QuiescentSpliceStatus
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
case SpliceStatus.SpliceAborted =>
log.warning("received commit_sig after sending tx_abort, they probably sent it before receiving our tx_abort, ignoring...")
stay()
case SpliceStatus.SpliceWaitingForSigs(signingSession) =>
case SpliceStatus.SpliceWaitingForSigs(sessionContext, signingSession) =>
signingSession.receiveCommitSig(nodeParams, d.commitments.params, commit) match {
case Left(f) =>
rollbackFundingAttempt(signingSession.fundingTx.tx, Nil)
Expand All @@ -573,7 +573,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
case signingSession1: InteractiveTxSigningSession.WaitingForSigs =>
// In theory we don't have to store their commit_sig here, as they would re-send it if we disconnect, but
// it is more consistent with the case where we send our tx_signatures first.
val d1 = d.copy(spliceStatus = SpliceStatus.SpliceWaitingForSigs(signingSession1))
val d1 = d.copy(spliceStatus = SpliceStatus.SpliceWaitingForSigs(sessionContext, signingSession1))
stay() using d1 storing()
case signingSession1: InteractiveTxSigningSession.SendingSigs =>
// We don't have their tx_sigs, but they have ours, and could publish the funding tx without telling us.
Expand Down Expand Up @@ -968,17 +968,17 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
targetFeerate = msg.feerate,
requireConfirmedInputs = RequireConfirmedInputs(forLocal = msg.requireConfirmedInputs, forRemote = spliceAck.requireConfirmedInputs)
)
val sessionId = randomBytes32()
val sessionContext = SessionContext.Unspecified(sessionId = randomBytes32())
val txBuilder = context.spawnAnonymous(InteractiveTxBuilder(
sessionId,
sessionContext,
nodeParams, fundingParams,
channelParams = d.commitments.params,
purpose = InteractiveTxBuilder.SpliceTx(parentCommitment),
localPushAmount = spliceAck.pushAmount, remotePushAmount = msg.pushAmount,
wallet
))
txBuilder ! InteractiveTxBuilder.Start(self)
stay() using d.copy(spliceStatus = SpliceStatus.SpliceInProgress(cmd_opt = None, sessionId, txBuilder, remoteCommitSig = None)) sending spliceAck
stay() using d.copy(spliceStatus = SpliceStatus.SpliceInProgress(cmd_opt = None, sessionContext, txBuilder, remoteCommitSig = None)) sending spliceAck
}
case SpliceStatus.SpliceAborted =>
log.info("rejecting splice attempt: our previous tx_abort was not acked")
Expand Down Expand Up @@ -1006,17 +1006,17 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
targetFeerate = spliceInit.feerate,
requireConfirmedInputs = RequireConfirmedInputs(forLocal = msg.requireConfirmedInputs, forRemote = spliceInit.requireConfirmedInputs)
)
val sessionId = randomBytes32()
val sessionContext = SessionContext.Unspecified(sessionId = randomBytes32())
val txBuilder = context.spawnAnonymous(InteractiveTxBuilder(
sessionId,
sessionContext,
nodeParams, fundingParams,
channelParams = d.commitments.params,
purpose = InteractiveTxBuilder.SpliceTx(parentCommitment),
localPushAmount = cmd.pushAmount, remotePushAmount = msg.pushAmount,
wallet
))
txBuilder ! InteractiveTxBuilder.Start(self)
stay() using d.copy(spliceStatus = SpliceStatus.SpliceInProgress(cmd_opt = Some(cmd), sessionId, txBuilder, remoteCommitSig = None))
stay() using d.copy(spliceStatus = SpliceStatus.SpliceInProgress(cmd_opt = Some(cmd), sessionContext, txBuilder, remoteCommitSig = None))
case _ =>
log.info(s"ignoring unexpected splice_ack=$msg")
stay()
Expand All @@ -1039,7 +1039,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
cmd_opt.foreach(cmd => cmd.replyTo ! RES_FAILURE(cmd, SpliceAttemptAborted(d.channelId)))
txBuilder ! InteractiveTxBuilder.Abort
stay() using d.copy(spliceStatus = SpliceStatus.NoSplice) sending TxAbort(d.channelId, SpliceAttemptAborted(d.channelId).getMessage) calling endQuiescence(d)
case SpliceStatus.SpliceWaitingForSigs(signingSession) =>
case SpliceStatus.SpliceWaitingForSigs(_, signingSession) =>
log.info("our peer aborted the splice attempt: ascii='{}' bin={}", msg.toAscii, msg.data)
rollbackFundingAttempt(signingSession.fundingTx.tx, previousTxs = Seq.empty) // no splice rbf yet
stay() using d.copy(spliceStatus = SpliceStatus.NoSplice) sending TxAbort(d.channelId, SpliceAttemptAborted(d.channelId).getMessage) calling endQuiescence(d)
Expand All @@ -1066,10 +1066,10 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with

case Event(msg: InteractiveTxBuilder.Response, d: DATA_NORMAL) =>
d.spliceStatus match {
case SpliceStatus.SpliceInProgress(cmd_opt, currentSessionId, _, remoteCommitSig_opt) =>
case SpliceStatus.SpliceInProgress(cmd_opt, sessionContext, _, remoteCommitSig_opt) =>
msg match {
case InteractiveTxBuilder.SendMessage(sessionId, msg) =>
if (sessionId == currentSessionId) {
if (sessionId == sessionContext.sessionId) {
stay() sending msg
} else {
log.info("ignoring outgoing interactive-tx message {} from previous session", msg.getClass.getSimpleName)
Expand All @@ -1079,7 +1079,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
log.info(s"splice tx created with fundingTxIndex=${signingSession.fundingTxIndex} fundingTxId=${signingSession.fundingTx.txId}")
cmd_opt.foreach(cmd => cmd.replyTo ! RES_SPLICE(fundingTxIndex = signingSession.fundingTxIndex, signingSession.fundingTx.txId, signingSession.fundingParams.fundingAmount, signingSession.localCommit.fold(_.spec, _.spec).toLocal))
remoteCommitSig_opt.foreach(self ! _)
val d1 = d.copy(spliceStatus = SpliceStatus.SpliceWaitingForSigs(signingSession))
val d1 = d.copy(spliceStatus = SpliceStatus.SpliceWaitingForSigs(sessionContext, signingSession))
stay() using d1 storing() sending commitSig
case f: InteractiveTxBuilder.Failed =>
log.info("splice attempt failed: {}", f.cause.getMessage)
Expand Down Expand Up @@ -1115,7 +1115,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
}
case _ =>
d.spliceStatus match {
case SpliceStatus.SpliceWaitingForSigs(signingSession) =>
case SpliceStatus.SpliceWaitingForSigs(_, signingSession) =>
// we have not yet sent our tx_signatures
signingSession.receiveTxSigs(nodeParams, d.commitments.params, msg) match {
case Left(f) =>
Expand Down Expand Up @@ -1890,14 +1890,14 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
val myCurrentPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, d.commitments.localCommitIndex)
val rbfTlv: Set[ChannelReestablishTlv] = d match {
case d: DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED => d.rbfStatus match {
case RbfStatus.RbfWaitingForSigs(status) => Set(ChannelReestablishTlv.NextFundingTlv(status.fundingTx.txId))
case RbfStatus.RbfWaitingForSigs(_, status) => Set(ChannelReestablishTlv.NextFundingTlv(status.fundingTx.txId))
case _ => d.latestFundingTx.sharedTx match {
case _: InteractiveTxBuilder.PartiallySignedSharedTransaction => Set(ChannelReestablishTlv.NextFundingTlv(d.latestFundingTx.sharedTx.txId))
case _: InteractiveTxBuilder.FullySignedSharedTransaction => Set.empty
}
}
case d: DATA_NORMAL => d.spliceStatus match {
case SpliceStatus.SpliceWaitingForSigs(status) => Set(ChannelReestablishTlv.NextFundingTlv(status.fundingTx.txId))
case SpliceStatus.SpliceWaitingForSigs(_, status) => Set(ChannelReestablishTlv.NextFundingTlv(status.fundingTx.txId))
case _ => d.commitments.latest.localFundingStatus match {
case LocalFundingStatus.DualFundedUnconfirmedFundingTx(fundingTx: PartiallySignedSharedTransaction, _, _) => Set(ChannelReestablishTlv.NextFundingTlv(fundingTx.txId))
case _ => Set.empty
Expand Down Expand Up @@ -1954,7 +1954,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
channelReestablish.nextFundingTxId_opt match {
case Some(fundingTxId) =>
d.rbfStatus match {
case RbfStatus.RbfWaitingForSigs(signingSession) if signingSession.fundingTx.txId == fundingTxId =>
case RbfStatus.RbfWaitingForSigs(_, signingSession) if signingSession.fundingTx.txId == fundingTxId =>
// We retransmit our commit_sig, and will send our tx_signatures once we've received their commit_sig.
val commitSig = signingSession.remoteCommit.sign(keyManager, d.commitments.params, signingSession.fundingTxIndex, signingSession.fundingParams.remoteFundingPubKey, signingSession.commitInput)
goto(WAIT_FOR_DUAL_FUNDING_CONFIRMED) sending commitSig
Expand Down Expand Up @@ -2009,7 +2009,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
val spliceStatus1 = channelReestablish.nextFundingTxId_opt match {
case Some(fundingTxId) =>
d.spliceStatus match {
case SpliceStatus.SpliceWaitingForSigs(signingSession) if signingSession.fundingTx.txId == fundingTxId =>
case SpliceStatus.SpliceWaitingForSigs(_, signingSession) if signingSession.fundingTx.txId == fundingTxId =>
// We retransmit our commit_sig, and will send our tx_signatures once we've received their commit_sig.
log.info("re-sending commit_sig for splice attempt with fundingTxIndex={} fundingTxId={}", signingSession.fundingTxIndex, signingSession.fundingTx.txId)
val commitSig = signingSession.remoteCommit.sign(keyManager, d.commitments.params, signingSession.fundingTxIndex, signingSession.fundingParams.remoteFundingPubKey, signingSession.commitInput)
Expand Down
Loading
Loading