Skip to content
Merged
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
8 changes: 7 additions & 1 deletion eclair-core/src/main/scala/fr/acinq/eclair/Features.scala
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,11 @@ object Features {
val mandatory = 60
}

case object PhoenixZeroReserve extends Feature with InitFeature with ChannelTypeFeature with PermanentChannelFeature {
val rfcName = "phoenix_zero_reserve"
val mandatory = 128
}

/** This feature bit indicates that the node is a mobile wallet that can be woken up via push notifications. */
case object WakeUpNotificationClient extends Feature with InitFeature {
val rfcName = "wake_up_notification_client"
Expand Down Expand Up @@ -401,7 +406,8 @@ object Features {
AsyncPaymentPrototype,
SplicePrototype,
OnTheFlyFunding,
FundingFeeCredit
FundingFeeCredit,
PhoenixZeroReserve
)

// Features may depend on other features, as specified in Bolt 9.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,6 @@ object ChannelTypes {
override def commitmentFormat: CommitmentFormat = ZeroFeeHtlcTxAnchorOutputsCommitmentFormat
override def toString: String = s"anchor_outputs_zero_fee_htlc_tx${if (scidAlias) "+scid_alias" else ""}${if (zeroConf) "+zeroconf" else ""}"
}
case class SimpleTaprootChannelsPhoenix(scidAlias: Boolean = false, zeroConf: Boolean = false) extends SupportedChannelType {
/** Known channel-type features */
override def features: Set[ChannelTypeFeature] = Set(
if (scidAlias) Some(Features.ScidAlias) else None,
if (zeroConf) Some(Features.ZeroConf) else None,
Some(Features.SimpleTaprootChannelsPhoenix),
).flatten
override def paysDirectlyToWallet: Boolean = false
override def commitmentFormat: CommitmentFormat = PhoenixSimpleTaprootChannelCommitmentFormat
override def toString: String = s"simple_taproot_channel_phoenix${if (scidAlias) "+scid_alias" else ""}${if (zeroConf) "+zeroconf" else ""}"
}
case class SimpleTaprootChannelsStaging(scidAlias: Boolean = false, zeroConf: Boolean = false) extends SupportedChannelType {
/** Known channel-type features */
override def features: Set[ChannelTypeFeature] = Set(
Expand All @@ -145,6 +134,16 @@ object ChannelTypes {
override def features: Set[InitFeature] = featureBits.activated.keySet
override def toString: String = s"0x${featureBits.toByteVector.toHex}"
}

// Phoenix uses custom channel types, that we may remove in the future.
case object SimpleTaprootChannelsPhoenix extends SupportedChannelType {
/** Known channel-type features */
override def features: Set[ChannelTypeFeature] = Set(Features.PhoenixZeroReserve, Features.SimpleTaprootChannelsPhoenix)
override def paysDirectlyToWallet: Boolean = false
override def commitmentFormat: CommitmentFormat = PhoenixSimpleTaprootChannelCommitmentFormat
override def toString: String = "phoenix_simple_taproot_channel"
}

// @formatter:on

private val features2ChannelType: Map[Features[_ <: InitFeature], SupportedChannelType] = Set(
Expand All @@ -164,10 +163,7 @@ object ChannelTypes {
AnchorOutputsZeroFeeHtlcTx(zeroConf = true),
AnchorOutputsZeroFeeHtlcTx(scidAlias = true),
AnchorOutputsZeroFeeHtlcTx(scidAlias = true, zeroConf = true),
SimpleTaprootChannelsPhoenix(),
SimpleTaprootChannelsPhoenix(zeroConf = true),
SimpleTaprootChannelsPhoenix(scidAlias = true),
SimpleTaprootChannelsPhoenix(scidAlias = true, zeroConf = true),
SimpleTaprootChannelsPhoenix,
SimpleTaprootChannelsStaging(),
SimpleTaprootChannelsStaging(zeroConf = true),
SimpleTaprootChannelsStaging(scidAlias = true),
Expand All @@ -188,7 +184,7 @@ object ChannelTypes {
if (canUse(Features.SimpleTaprootChannelsStaging)) {
SimpleTaprootChannelsStaging(scidAlias, zeroConf)
} else if (canUse(Features.SimpleTaprootChannelsPhoenix)) {
SimpleTaprootChannelsPhoenix(scidAlias, zeroConf)
SimpleTaprootChannelsPhoenix
} else if (canUse(Features.AnchorOutputsZeroFeeHtlcTx)) {
AnchorOutputsZeroFeeHtlcTx(scidAlias, zeroConf)
} else if (canUse(Features.AnchorOutputs)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.blockchain.bitcoind.ZmqWatcher
import fr.acinq.eclair.blockchain.bitcoind.ZmqWatcher._
import fr.acinq.eclair.blockchain.bitcoind.rpc.BitcoinCoreClient
import fr.acinq.eclair.channel.ChannelTypes.SimpleTaprootChannelsPhoenix
import fr.acinq.eclair.channel.Commitments.PostRevocationAction
import fr.acinq.eclair.channel.Helpers.Closing.MutualClose
import fr.acinq.eclair.channel.Helpers.Syncing.SyncResult
Expand Down Expand Up @@ -1113,8 +1114,8 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
// We only support updating phoenix channels to taproot: we ignore other attempts at upgrading the
// commitment format and will simply apply the previous commitment format.
val nextCommitmentFormat = msg.channelType_opt match {
case Some(channelType: ChannelTypes.SimpleTaprootChannelsPhoenix) if parentCommitment.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat =>
log.info(s"accepting upgrade to $channelType during splice from commitment format ${parentCommitment.commitmentFormat}")
case Some(ChannelTypes.SimpleTaprootChannelsPhoenix) if parentCommitment.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat =>
log.info(s"accepting upgrade to SimpleTaprootChannelsPhoenix during splice from commitment format ${parentCommitment.commitmentFormat}")
PhoenixSimpleTaprootChannelCommitmentFormat
case Some(channelType) =>
log.info(s"rejecting upgrade to $channelType during splice from commitment format ${parentCommitment.commitmentFormat}")
Expand Down Expand Up @@ -1181,7 +1182,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
// We only support updating phoenix channels to taproot: we ignore other attempts at upgrading the
// commitment format and will simply apply the previous commitment format.
val nextCommitmentFormat = msg.channelType_opt match {
case Some(_: ChannelTypes.SimpleTaprootChannelsPhoenix) if parentCommitment.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat => PhoenixSimpleTaprootChannelCommitmentFormat
case Some(ChannelTypes.SimpleTaprootChannelsPhoenix) if parentCommitment.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat => PhoenixSimpleTaprootChannelCommitmentFormat
case _ => parentCommitment.commitmentFormat
}
val fundingParams = InteractiveTxParams(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ class InteractiveTxBuilderSpec extends TestKitBaseClass with AnyFunSuiteLike wit
val utxosA = Seq(150_000 sat)
val fundingB1 = 90_000 sat
val utxosB = Seq(130_000 sat)
withFixture(ChannelTypes.SimpleTaprootChannelsPhoenix(), fundingA1, utxosA, fundingB1, utxosB, FeeratePerKw(1000 sat), 660 sat, 0, RequireConfirmedInputs(forLocal = true, forRemote = true)) { f =>
withFixture(ChannelTypes.SimpleTaprootChannelsPhoenix, fundingA1, utxosA, fundingB1, utxosB, FeeratePerKw(1000 sat), 660 sat, 0, RequireConfirmedInputs(forLocal = true, forRemote = true)) { f =>
import f._

val probe = TestProbe()
Expand Down Expand Up @@ -2934,7 +2934,7 @@ class InteractiveTxBuilderSpec extends TestKitBaseClass with AnyFunSuiteLike wit
test("invalid commit_sig (taproot)") {
val (alice2bob, bob2alice) = (TestProbe(), TestProbe())
val wallet = new SingleKeyOnChainWallet()
val params = createFixtureParams(ChannelTypes.SimpleTaprootChannelsPhoenix(), 100_000 sat, 25_000 sat, FeeratePerKw(5000 sat), 330 sat, 0)
val params = createFixtureParams(ChannelTypes.SimpleTaprootChannelsPhoenix, 100_000 sat, 25_000 sat, FeeratePerKw(5000 sat), 330 sat, 0)
val alice = params.spawnTxBuilderAlice(wallet)
val bob = params.spawnTxBuilderBob(wallet)
alice ! Start(alice2bob.ref)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class WaitForAcceptChannelStateSpec extends TestKitBaseClass with FixtureAnyFunS
test("recv AcceptChannel (simple taproot channels phoenix)", Tag(ChannelStateTestsTags.OptionSimpleTaprootPhoenix)) { f =>
import f._
val accept = bob2alice.expectMsgType[AcceptChannel]
assert(accept.channelType_opt.contains(ChannelTypes.SimpleTaprootChannelsPhoenix()))
assert(accept.channelType_opt.contains(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(accept.commitNonce_opt.isDefined)
bob2alice.forward(alice)
awaitCond(alice.stateName == WAIT_FOR_FUNDING_INTERNAL)
Expand All @@ -121,7 +121,7 @@ class WaitForAcceptChannelStateSpec extends TestKitBaseClass with FixtureAnyFunS
test("recv AcceptChannel (simple taproot channels outputs, missing nonce)", Tag(ChannelStateTestsTags.OptionSimpleTaprootPhoenix)) { f =>
import f._
val accept = bob2alice.expectMsgType[AcceptChannel]
assert(accept.channelType_opt.contains(ChannelTypes.SimpleTaprootChannelsPhoenix()))
assert(accept.channelType_opt.contains(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(accept.commitNonce_opt.isDefined)
bob2alice.forward(alice, accept.copy(tlvStream = accept.tlvStream.copy(records = accept.tlvStream.records.filterNot(_.isInstanceOf[ChannelTlv.NextLocalNonceTlv]))))
alice2bob.expectMsg(Error(accept.temporaryChannelId, MissingCommitNonce(accept.temporaryChannelId, TxId(ByteVector32.Zeroes), 0).getMessage))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
import f._

val htlcs = setupHtlcs(f)
initiateSplice(f, spliceIn_opt = Some(SpliceIn(400_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix()))
initiateSplice(f, spliceIn_opt = Some(SpliceIn(400_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(alice.commitments.active.head.commitmentFormat == PhoenixSimpleTaprootChannelCommitmentFormat)
assert(alice.commitments.active.last.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat)
resolveHtlcs(f, htlcs)
Expand All @@ -767,7 +767,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
import f._

val htlcs = setupHtlcs(f)
initiateSplice(f, spliceIn_opt = Some(SpliceIn(400_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix()))
initiateSplice(f, spliceIn_opt = Some(SpliceIn(400_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(alice.commitments.active.head.commitmentFormat == ZeroFeeHtlcTxAnchorOutputsCommitmentFormat)
assert(alice.commitments.active.last.commitmentFormat == ZeroFeeHtlcTxAnchorOutputsCommitmentFormat)
resolveHtlcs(f, htlcs)
Expand Down Expand Up @@ -3724,7 +3724,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
val htlcs = setupHtlcs(f)

// Our first splice upgrades the channel to taproot.
val fundingTx1 = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix()))
val fundingTx1 = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix))
checkWatchConfirmed(f, fundingTx1)

// The first splice confirms on Bob's side.
Expand Down Expand Up @@ -3819,7 +3819,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
val htlcs = setupHtlcs(f)

// Our splice upgrades the channel to taproot.
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix()))
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(alice.commitments.active.head.commitmentFormat == PhoenixSimpleTaprootChannelCommitmentFormat)
assert(alice.commitments.active.last.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat)
checkWatchConfirmed(f, spliceTx)
Expand Down Expand Up @@ -3860,7 +3860,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
val htlcs = setupHtlcs(f)

// Our splice upgrades the channel to taproot.
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix()))
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(alice.commitments.active.head.commitmentFormat == PhoenixSimpleTaprootChannelCommitmentFormat)
assert(alice.commitments.active.last.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat)
checkWatchConfirmed(f, spliceTx)
Expand Down Expand Up @@ -3911,7 +3911,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
val htlcs = setupHtlcs(f)

// Our splice upgrades the channel to taproot.
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix()))
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(alice.commitments.active.head.commitmentFormat == PhoenixSimpleTaprootChannelCommitmentFormat)
assert(alice.commitments.active.last.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat)
checkWatchConfirmed(f, spliceTx)
Expand Down Expand Up @@ -3947,7 +3947,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
val htlcs = setupHtlcs(f)

// Our splice upgrades the channel to taproot.
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix()))
val spliceTx = initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)), channelType_opt = Some(ChannelTypes.SimpleTaprootChannelsPhoenix))
assert(alice.commitments.active.head.commitmentFormat == PhoenixSimpleTaprootChannelCommitmentFormat)
assert(alice.commitments.active.last.commitmentFormat == UnsafeLegacyAnchorOutputsCommitmentFormat)
assert(alice2blockchain.expectMsgType[WatchPublished].txId == spliceTx.txid)
Expand Down