multi: rename "taproot" channel type to mean production variant
What changed, and why it matters
This change is a user-facing rename, not a security fix. The developers noticed that the short, obvious name 'taproot' was accidentally pointing to an older experimental ('staging') channel type, while the recommended production version required a longer, harder-to-find name. They swapped the labels so 'taproot' now means the production version, added 'taproot-staging' for the old experimental one, and kept 'taproot-final' as a compatibility alias. The underlying numeric codes on the network wire did not change, so existing software keeps working.
No security action required. Operators and integrators may review documentation to confirm they now use the intended taproot channel variant; the change is backward compatible.
Security signals we found
No memory-safety, cryptographic, or authorization changes
No bug fix or vulnerability remediation visible in diff
Backward-compatible alias added to avoid breaking existing clients
CLI mapping change could affect user expectations but is explicitly documented
Evidence from the diff
The commit renames CLI and RPC identifiers for taproot channel commitment types without altering wire values. lncli’s –channel_type=’taproot’ now maps to lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL (value 7, production feature bits 80/81); a new ‘taproot-staging’ string maps to SIMPLE_TAPROOT (value 5, development bits); and ‘taproot-final’ is retained as a deprecated alias. The protobuf enum adds TAPROOT = 7 with option allow_alias = true so SIMPLE_TAPROOT_FINAL remains a valid alias. Generated Go identifiers and numeric enum values are unchanged, preserving backward compatibility.
Changed components
cmd/commands/cmd_open_channel.golnrpc/lightning.protolnrpc/lightning.pb.golnrpc/lightning.swagger.jsondocs/release-notes/release-notes-0.21.0.mdfunding/manager_test.goInspect captured patch +82 / −36
diff --git a/cmd/commands/cmd_open_channel.go b/cmd/commands/cmd_open_channel.go
index 7adf48a..921f847 100644
--- a/cmd/commands/cmd_open_channel.go
+++ b/cmd/commands/cmd_open_channel.go
@@ -59,10 +59,22 @@ Signed base64 encoded PSBT or hex encoded raw wire TX (or path to file): `
// of memory issues or other weird errors.
psbtMaxFileSize = 1024 * 1024
- channelTypeTweakless = "tweakless"
- channelTypeAnchors = "anchors"
- channelTypeSimpleTaproot = "taproot"
- channelTypeSimpleTaprootFinal = "taproot-final"
+ channelTypeTweakless = "tweakless"
+ channelTypeAnchors = "anchors"
+
+ // channelTypeSimpleTaproot selects the production taproot channel
+ // type (feature bits 80/81). This is the recommended taproot variant.
+ channelTypeSimpleTaproot = "taproot"
+
+ // channelTypeSimpleTaprootStaging selects the legacy staging taproot
+ // channel type using development feature bits. Kept for compatibility
+ // with peers that have not upgraded to the final variant.
+ channelTypeSimpleTaprootStaging = "taproot-staging"
+
+ // channelTypeSimpleTaprootFinalAlias is a deprecated alias for
+ // "taproot" that resolves to the same production taproot channel type.
+ // Retained so existing scripts continue to work.
+ channelTypeSimpleTaprootFinalAlias = "taproot-final"
)
// TODO(roasbeef): change default number of confirmations.
@@ -255,10 +267,13 @@ var openChannelCommand = cli.Command{
cli.StringFlag{
Name: "channel_type",
Usage: fmt.Sprintf("(optional) the type of channel to "+
- "propose to the remote peer (%q, %q, %q, %q)",
+ "propose to the remote peer (%q, %q, %q, %q). "+
+ "%q is accepted as a deprecated alias for %q",
channelTypeTweakless, channelTypeAnchors,
channelTypeSimpleTaproot,
- channelTypeSimpleTaprootFinal),
+ channelTypeSimpleTaprootStaging,
+ channelTypeSimpleTaprootFinalAlias,
+ channelTypeSimpleTaproot),
},
cli.BoolFlag{
Name: "zero_conf",
@@ -438,7 +453,10 @@ func openChannel(ctx *cli.Context) error {
req.Private = ctx.Bool("private")
- // Parse the channel type and map it to its RPC representation.
+ // Parse the channel type and map it to its RPC representation. The
+ // bare "taproot" string now selects the production (final) variant;
+ // "taproot-staging" preserves access to the legacy development bits.
+ // "taproot-final" is accepted as a deprecated alias for "taproot".
channelType := ctx.String("channel_type")
switch channelType {
case "":
@@ -447,10 +465,10 @@ func openChannel(ctx *cli.Context) error {
req.CommitmentType = lnrpc.CommitmentType_STATIC_REMOTE_KEY
case channelTypeAnchors:
req.CommitmentType = lnrpc.CommitmentType_ANCHORS
- case channelTypeSimpleTaproot:
- req.CommitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT
- case channelTypeSimpleTaprootFinal:
+ case channelTypeSimpleTaproot, channelTypeSimpleTaprootFinalAlias:
req.CommitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
+ case channelTypeSimpleTaprootStaging:
+ req.CommitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT
default:
return fmt.Errorf("unsupported channel type %v", channelType)
}
diff --git a/docs/release-notes/release-notes-0.21.0.md b/docs/release-notes/release-notes-0.21.0.md
index a4aaf44..f8ca9fc 100644
--- a/docs/release-notes/release-notes-0.21.0.md
+++ b/docs/release-notes/release-notes-0.21.0.md
@@ -134,9 +134,12 @@
support. The nonce type is now auto-detected from the negotiated channel type
rather than peer feature bits, ensuring correct behavior across all recovery
and resynchronization paths. Taproot channels must be requested explicitly
- with `lncli openchannel --channel_type=taproot-final` (or `taproot` for
- staging), and must remain private until announced taproot channels are
- supported.
+ with `lncli openchannel --channel_type=taproot` (the bare `taproot` string
+ now selects the production variant; `taproot-staging` opens the legacy
+ staging variant, and `taproot-final` is kept as a deprecated alias for
+ `taproot`), and must remain private until announced taproot channels are
+ supported. The RPC `CommitmentType` enum gains a `TAPROOT` alias for
+ `SIMPLE_TAPROOT_FINAL` so new RPC clients can use the same short name.
* [Added taproot channel support for RBF cooperative
close](https://github.com/lightningnetwork/lnd/pull/10063). The new RBF-based
diff --git a/funding/manager_test.go b/funding/manager_test.go
index 4bbed13..4220912 100644
--- a/funding/manager_test.go
+++ b/funding/manager_test.go
@@ -5011,6 +5011,7 @@ func TestCommitmentTypeFundmaxSanityCheck(t *testing.T) {
"SCRIPT_ENFORCED_LEASE": 4,
"SIMPLE_TAPROOT": 5,
"SIMPLE_TAPROOT_OVERLAY": 6,
+ "TAPROOT": 7,
"SIMPLE_TAPROOT_FINAL": 7,
}
diff --git a/lnrpc/lightning.pb.go b/lnrpc/lightning.pb.go
index d1f2a8a..ebfed31 100644
--- a/lnrpc/lightning.pb.go
+++ b/lnrpc/lightning.pb.go
@@ -230,14 +230,20 @@ const (
// to guarantee that the channel initiator has no incentives to close a leased
// channel before its maturity date.
CommitmentType_SCRIPT_ENFORCED_LEASE CommitmentType = 4
- // A channel that uses musig2 for the funding output, and the new tapscript
- // features where relevant. This is the staging version using development
- // scripts.
- CommitmentType_SIMPLE_TAPROOT CommitmentType = 5
- // A channel that uses musig2 for the funding output, and the new tapscript
- // features where relevant. This is the production version using final scripts
- // and feature bits 80/81.
+ // The production taproot channel type that uses musig2 for the funding
+ // output and the new tapscript features, with final scripts and feature
+ // bits 80/81. This is the recommended taproot variant; new integrations
+ // should select this enum value.
+ CommitmentType_TAPROOT CommitmentType = 7
+ // Deprecated alias for TAPROOT, preserved so existing clients that select
+ // the production taproot channel type by its historic name continue to
+ // compile and serialize against the same wire value.
CommitmentType_SIMPLE_TAPROOT_FINAL CommitmentType = 7
+ // A legacy taproot channel type that uses musig2 for the funding output and
+ // the new tapscript features, but with development scripts and the staging
+ // feature bits. Retained for compatibility with peers that have not upgraded
+ // to TAPROOT; new integrations should prefer TAPROOT.
+ CommitmentType_SIMPLE_TAPROOT CommitmentType = 5
// Identical to the SIMPLE_TAPROOT channel type, but with extra functionality.
// This channel type also commits to additional meta data in the tapscript
// leaves for the scripts in a channel.
@@ -252,8 +258,9 @@ var (
2: "STATIC_REMOTE_KEY",
3: "ANCHORS",
4: "SCRIPT_ENFORCED_LEASE",
+ 7: "TAPROOT",
+ // Duplicate value: 7: "SIMPLE_TAPROOT_FINAL",
5: "SIMPLE_TAPROOT",
- 7: "SIMPLE_TAPROOT_FINAL",
6: "SIMPLE_TAPROOT_OVERLAY",
}
CommitmentType_value = map[string]int32{
@@ -262,8 +269,9 @@ var (
"STATIC_REMOTE_KEY": 2,
"ANCHORS": 3,
"SCRIPT_ENFORCED_LEASE": 4,
- "SIMPLE_TAPROOT": 5,
+ "TAPROOT": 7,
"SIMPLE_TAPROOT_FINAL": 7,
+ "SIMPLE_TAPROOT": 5,
"SIMPLE_TAPROOT_OVERLAY": 6,
}
)
@@ -19968,17 +19976,18 @@ const file_lightning_proto_rawDesc = "" +
"\x1aUNUSED_WITNESS_PUBKEY_HASH\x10\x02\x12\x1d\n" +
"\x19UNUSED_NESTED_PUBKEY_HASH\x10\x03\x12\x12\n" +
"\x0eTAPROOT_PUBKEY\x10\x04\x12\x19\n" +
- "\x15UNUSED_TAPROOT_PUBKEY\x10\x05*\xc2\x01\n" +
+ "\x15UNUSED_TAPROOT_PUBKEY\x10\x05*\xd3\x01\n" +
"\x0eCommitmentType\x12\x1b\n" +
"\x17UNKNOWN_COMMITMENT_TYPE\x10\x00\x12\n" +
"\n" +
"\x06LEGACY\x10\x01\x12\x15\n" +
"\x11STATIC_REMOTE_KEY\x10\x02\x12\v\n" +
"\aANCHORS\x10\x03\x12\x19\n" +
- "\x15SCRIPT_ENFORCED_LEASE\x10\x04\x12\x12\n" +
- "\x0eSIMPLE_TAPROOT\x10\x05\x12\x18\n" +
- "\x14SIMPLE_TAPROOT_FINAL\x10\a\x12\x1a\n" +
- "\x16SIMPLE_TAPROOT_OVERLAY\x10\x06*a\n" +
+ "\x15SCRIPT_ENFORCED_LEASE\x10\x04\x12\v\n" +
+ "\aTAPROOT\x10\a\x12\x18\n" +
+ "\x14SIMPLE_TAPROOT_FINAL\x10\a\x12\x12\n" +
+ "\x0eSIMPLE_TAPROOT\x10\x05\x12\x1a\n" +
+ "\x16SIMPLE_TAPROOT_OVERLAY\x10\x06\x1a\x02\x10\x01*a\n" +
"\tInitiator\x12\x15\n" +
"\x11INITIATOR_UNKNOWN\x10\x00\x12\x13\n" +
"\x0fINITIATOR_LOCAL\x10\x01\x12\x14\n" +
diff --git a/lnrpc/lightning.proto b/lnrpc/lightning.proto
index 8c0d168..be43c88 100644
--- a/lnrpc/lightning.proto
+++ b/lnrpc/lightning.proto
@@ -1305,6 +1305,11 @@ message HTLC {
}
enum CommitmentType {
+ // Allow multiple enum names to map to the same numeric value so the
+ // taproot channel types can expose short, canonical aliases without
+ // breaking on-wire compatibility with the historic names.
+ option allow_alias = true;
+
/*
Returned when the commitment type isn't known or unavailable.
*/
@@ -1341,19 +1346,28 @@ enum CommitmentType {
SCRIPT_ENFORCED_LEASE = 4;
/*
- A channel that uses musig2 for the funding output, and the new tapscript
- features where relevant. This is the staging version using development
- scripts.
+ The production taproot channel type that uses musig2 for the funding
+ output and the new tapscript features, with final scripts and feature
+ bits 80/81. This is the recommended taproot variant; new integrations
+ should select this enum value.
*/
- SIMPLE_TAPROOT = 5;
+ TAPROOT = 7;
/*
- A channel that uses musig2 for the funding output, and the new tapscript
- features where relevant. This is the production version using final scripts
- and feature bits 80/81.
+ Deprecated alias for TAPROOT, preserved so existing clients that select
+ the production taproot channel type by its historic name continue to
+ compile and serialize against the same wire value.
*/
SIMPLE_TAPROOT_FINAL = 7;
+ /*
+ A legacy taproot channel type that uses musig2 for the funding output and
+ the new tapscript features, but with development scripts and the staging
+ feature bits. Retained for compatibility with peers that have not upgraded
+ to TAPROOT; new integrations should prefer TAPROOT.
+ */
+ SIMPLE_TAPROOT = 5;
+
/*
Identical to the SIMPLE_TAPROOT channel type, but with extra functionality.
This channel type also commits to additional meta data in the tapscript
diff --git a/lnrpc/lightning.swagger.json b/lnrpc/lightning.swagger.json
index 66e1924..7be8285 100644
--- a/lnrpc/lightning.swagger.json
+++ b/lnrpc/lightning.swagger.json
@@ -4806,12 +4806,13 @@
"STATIC_REMOTE_KEY",
"ANCHORS",
"SCRIPT_ENFORCED_LEASE",
- "SIMPLE_TAPROOT",
+ "TAPROOT",
"SIMPLE_TAPROOT_FINAL",
+ "SIMPLE_TAPROOT",
"SIMPLE_TAPROOT_OVERLAY"
],
"default": "UNKNOWN_COMMITMENT_TYPE",
- "description": " - UNKNOWN_COMMITMENT_TYPE: Returned when the commitment type isn't known or unavailable.\n - LEGACY: A channel using the legacy commitment format having tweaked to_remote\nkeys.\n - STATIC_REMOTE_KEY: A channel that uses the modern commitment format where the key in the\noutput of the remote party does not change each state. This makes back\nup and recovery easier as when the channel is closed, the funds go\ndirectly to that key.\n - ANCHORS: A channel that uses a commitment format that has anchor outputs on the\ncommitments, allowing fee bumping after a force close transaction has\nbeen broadcast.\n - SCRIPT_ENFORCED_LEASE: A channel that uses a commitment type that builds upon the anchors\ncommitment format, but in addition requires a CLTV clause to spend outputs\npaying to the channel initiator. This is intended for use on leased channels\nto guarantee that the channel initiator has no incentives to close a leased\nchannel before its maturity date.\n - SIMPLE_TAPROOT: A channel that uses musig2 for the funding output, and the new tapscript\nfeatures where relevant. This is the staging version using development\nscripts.\n - SIMPLE_TAPROOT_FINAL: A channel that uses musig2 for the funding output, and the new tapscript\nfeatures where relevant. This is the production version using final scripts\nand feature bits 80/81.\n - SIMPLE_TAPROOT_OVERLAY: Identical to the SIMPLE_TAPROOT channel type, but with extra functionality.\nThis channel type also commits to additional meta data in the tapscript\nleaves for the scripts in a channel."
+ "description": " - UNKNOWN_COMMITMENT_TYPE: Returned when the commitment type isn't known or unavailable.\n - LEGACY: A channel using the legacy commitment format having tweaked to_remote\nkeys.\n - STATIC_REMOTE_KEY: A channel that uses the modern commitment format where the key in the\noutput of the remote party does not change each state. This makes back\nup and recovery easier as when the channel is closed, the funds go\ndirectly to that key.\n - ANCHORS: A channel that uses a commitment format that has anchor outputs on the\ncommitments, allowing fee bumping after a force close transaction has\nbeen broadcast.\n - SCRIPT_ENFORCED_LEASE: A channel that uses a commitment type that builds upon the anchors\ncommitment format, but in addition requires a CLTV clause to spend outputs\npaying to the channel initiator. This is intended for use on leased channels\nto guarantee that the channel initiator has no incentives to close a leased\nchannel before its maturity date.\n - TAPROOT: The production taproot channel type that uses musig2 for the funding\noutput and the new tapscript features, with final scripts and feature\nbits 80/81. This is the recommended taproot variant; new integrations\nshould select this enum value.\n - SIMPLE_TAPROOT_FINAL: Deprecated alias for TAPROOT, preserved so existing clients that select\nthe production taproot channel type by its historic name continue to\ncompile and serialize against the same wire value.\n - SIMPLE_TAPROOT: A legacy taproot channel type that uses musig2 for the funding output and\nthe new tapscript features, but with development scripts and the staging\nfeature bits. Retained for compatibility with peers that have not upgraded\nto TAPROOT; new integrations should prefer TAPROOT.\n - SIMPLE_TAPROOT_OVERLAY: Identical to the SIMPLE_TAPROOT channel type, but with extra functionality.\nThis channel type also commits to additional meta data in the tapscript\nleaves for the scripts in a channel."
},
"lnrpcConnectPeerRequest": {
"type": "object",
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.