@@ -21,7 +21,7 @@ import akka.actor.typed.scaladsl.adapter.{ClassicActorContextOps, actorRefAdapte
2121import akka .actor .{Actor , ActorContext , ActorRef , FSM , OneForOneStrategy , PossiblyHarmful , Props , SupervisorStrategy , typed }
2222import akka .event .Logging .MDC
2323import fr .acinq .bitcoin .scalacompat .Crypto .{PrivateKey , PublicKey }
24- import fr .acinq .bitcoin .scalacompat .{ByteVector32 , Satoshi , SatoshiLong , Transaction , TxId }
24+ import fr .acinq .bitcoin .scalacompat .{ByteVector32 , Satoshi , SatoshiLong , Script , Transaction , TxId }
2525import fr .acinq .eclair .Logs .LogCategory
2626import fr .acinq .eclair ._
2727import fr .acinq .eclair .blockchain .OnChainWallet .MakeFundingTxResponse
@@ -944,7 +944,28 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
944944 context.system.scheduler.scheduleOnce(2 second, peer, Peer .Disconnect (remoteNodeId))
945945 stay() using d.copy(spliceStatus = SpliceStatus .NoSplice ) sending Warning (d.channelId, f.getMessage)
946946 case Right (spliceInit) =>
947- stay() using d.copy(spliceStatus = SpliceStatus .SpliceRequested (cmd, spliceInit)) sending spliceInit
947+ // use our fundingPubKey as a placeholder for the remote funder's pubkey
948+ val fundingPubKey = spliceInit.fundingPubKey
949+ val parentCommitment = d.commitments.latest.commitment
950+ // assume our peer requires confirmed inputs when we initiate a splice
951+ val requireConfirmedInputs = RequireConfirmedInputs (forLocal = true , forRemote = nodeParams.channelConf.requireConfirmedInputsForDualFunding)
952+ val fundingParams = InteractiveTxParams (
953+ channelId = spliceInit.channelId,
954+ isInitiator = true ,
955+ localContribution = spliceInit.fundingContribution,
956+ remoteContribution = 0 sat,
957+ sharedInput_opt = Some (Multisig2of2Input (parentCommitment)),
958+ remoteFundingPubKey = fundingPubKey,
959+ localOutputs = cmd.spliceOutputs,
960+ lockTime = nodeParams.currentBlockHeight.toLong,
961+ dustLimit = d.commitments.params.localParams.dustLimit,
962+ targetFeerate = spliceInit.feerate,
963+ requireConfirmedInputs = requireConfirmedInputs
964+ )
965+ val dummyFundingPubkeyScript = Script .write(Script .pay2wsh(Scripts .multiSig2of2(fundingPubKey, fundingPubKey)))
966+ val txFunder = context.spawnAnonymous(InteractiveTxFunder (remoteNodeId, fundingParams, dummyFundingPubkeyScript, purpose = InteractiveTxBuilder .SpliceTx (parentCommitment), wallet, nodeParams.channelConf.maxExcess_opt))
967+ txFunder ! InteractiveTxFunder .FundTransaction (self)
968+ stay() using d.copy(spliceStatus = SpliceStatus .SpliceRequested (cmd, spliceInit, None ))
948969 }
949970 case cmd : CMD_BUMP_FUNDING_FEE => initiateSpliceRbf(cmd, d) match {
950971 case Left (f) =>
@@ -1018,6 +1039,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
10181039 channelParams = d.commitments.params,
10191040 purpose = InteractiveTxBuilder .SpliceTx (parentCommitment),
10201041 localPushAmount = spliceAck.pushAmount, remotePushAmount = msg.pushAmount,
1042+ None ,
10211043 wallet
10221044 ))
10231045 txBuilder ! InteractiveTxBuilder .Start (self)
@@ -1036,7 +1058,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
10361058
10371059 case Event (msg : SpliceAck , d : DATA_NORMAL ) =>
10381060 d.spliceStatus match {
1039- case SpliceStatus .SpliceRequested (cmd, spliceInit) =>
1061+ case SpliceStatus .SpliceRequested (cmd, spliceInit, fundingContributions_opt ) =>
10401062 log.info(" our peer accepted our splice request and will contribute {} to the funding transaction" , msg.fundingContribution)
10411063 val parentCommitment = d.commitments.latest.commitment
10421064 val fundingParams = InteractiveTxParams (
@@ -1059,6 +1081,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
10591081 channelParams = d.commitments.params,
10601082 purpose = InteractiveTxBuilder .SpliceTx (parentCommitment),
10611083 localPushAmount = cmd.pushAmount, remotePushAmount = msg.pushAmount,
1084+ fundingContributions_opt = fundingContributions_opt,
10621085 wallet
10631086 ))
10641087 txBuilder ! InteractiveTxBuilder .Start (self)
@@ -1068,6 +1091,21 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
10681091 stay()
10691092 }
10701093
1094+ case Event (msg : InteractiveTxFunder .Response , d : DATA_NORMAL ) =>
1095+ d.spliceStatus match {
1096+ case SpliceStatus .SpliceRequested (cmd, spliceInit, _) =>
1097+ msg match {
1098+ case InteractiveTxFunder .FundingFailed =>
1099+ cmd.replyTo ! RES_FAILURE (cmd, ChannelFundingError (d.channelId))
1100+ stay() using d.copy(spliceStatus = SpliceStatus .NoSplice ) calling endQuiescence(d)
1101+ case fundingContributions : InteractiveTxFunder .FundingContributions =>
1102+ stay() using d.copy(spliceStatus = SpliceStatus .SpliceRequested (cmd, spliceInit, Some (fundingContributions))) sending spliceInit
1103+ }
1104+ case _ =>
1105+ log.warning(" received unexpected response from txFunder: {}, current splice status is {}" , msg, d.spliceStatus)
1106+ stay() using d.copy(spliceStatus = SpliceStatus .NoSplice ) calling endQuiescence(d)
1107+ }
1108+
10711109 case Event (msg : InteractiveTxConstructionMessage , d : DATA_NORMAL ) =>
10721110 d.spliceStatus match {
10731111 case SpliceStatus .SpliceInProgress (_, _, txBuilder, _) =>
@@ -1116,6 +1154,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
11161154 channelParams = d.commitments.params,
11171155 purpose = rbf,
11181156 localPushAmount = 0 msat, remotePushAmount = 0 msat,
1157+ None ,
11191158 wallet
11201159 ))
11211160 txBuilder ! InteractiveTxBuilder .Start (self)
@@ -1160,6 +1199,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
11601199 channelParams = d.commitments.params,
11611200 purpose = rbf,
11621201 localPushAmount = 0 msat, remotePushAmount = 0 msat,
1202+ None ,
11631203 wallet
11641204 ))
11651205 txBuilder ! InteractiveTxBuilder .Start (self)
@@ -1183,7 +1223,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
11831223 log.info(" our peer aborted the splice attempt: ascii='{}' bin={}" , msg.toAscii, msg.data)
11841224 rollbackFundingAttempt(signingSession.fundingTx.tx, previousTxs = Seq .empty) // no splice rbf yet
11851225 stay() using d.copy(spliceStatus = SpliceStatus .NoSplice ) sending TxAbort (d.channelId, SpliceAttemptAborted (d.channelId).getMessage) calling endQuiescence(d)
1186- case SpliceStatus .SpliceRequested (cmd, _) =>
1226+ case SpliceStatus .SpliceRequested (cmd, _, _ ) =>
11871227 log.info(" our peer rejected our splice attempt: ascii='{}' bin={}" , msg.toAscii, msg.data)
11881228 cmd.replyTo ! RES_FAILURE (cmd, new RuntimeException (s " splice attempt rejected by our peer: ${msg.toAscii}" ))
11891229 stay() using d.copy(spliceStatus = SpliceStatus .NoSplice ) sending TxAbort (d.channelId, SpliceAttemptAborted (d.channelId).getMessage) calling endQuiescence(d)
@@ -2996,7 +3036,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
29963036 private def reportSpliceFailure (spliceStatus : SpliceStatus , f : Throwable ): Unit = {
29973037 val cmd_opt = spliceStatus match {
29983038 case SpliceStatus .NegotiatingQuiescence (cmd_opt, _) => cmd_opt
2999- case SpliceStatus .SpliceRequested (cmd, _) => Some (cmd)
3039+ case SpliceStatus .SpliceRequested (cmd, _, _ ) => Some (cmd)
30003040 case SpliceStatus .RbfRequested (cmd, _) => Some (cmd)
30013041 case SpliceStatus .SpliceInProgress (cmd_opt, _, txBuilder, _) =>
30023042 txBuilder ! InteractiveTxBuilder .Abort
0 commit comments