Merge pull request #10543 from bitromortac/2602-channel-update-events
rpc: add channel updates to SubscribeChannelEvents
This commit is contained in:
16 files changed
+3257
-2828
No files matched your search
@@ -746,6 +746,33 @@ func (c *ChannelCommitment) extractTlvData() commitTlvData {
|
|||||||
return auxData
|
return auxData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy returns a deep copy of the channel commitment.
|
||||||
|
func (c *ChannelCommitment) copy() ChannelCommitment {
|
||||||
|
c2 := *c
|
||||||
|
if c.CommitTx != nil {
|
||||||
|
c2.CommitTx = c.CommitTx.Copy()
|
||||||
|
}
|
||||||
|
if len(c.CommitSig) > 0 {
|
||||||
|
c2.CommitSig = make([]byte, len(c.CommitSig))
|
||||||
|
copy(c2.CommitSig, c.CommitSig)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.CustomBlob.WhenSome(func(blob tlv.Blob) {
|
||||||
|
blobCopy := make([]byte, len(blob))
|
||||||
|
copy(blobCopy, blob)
|
||||||
|
c2.CustomBlob = fn.Some(blobCopy)
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(c.Htlcs) > 0 {
|
||||||
|
c2.Htlcs = make([]HTLC, len(c.Htlcs))
|
||||||
|
for i, h := range c.Htlcs {
|
||||||
|
c2.Htlcs[i] = h.Copy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c2
|
||||||
|
}
|
||||||
|
|
||||||
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
|
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
|
||||||
// the default usable state, or a state where it shouldn't be used.
|
// the default usable state, or a state where it shouldn't be used.
|
||||||
type ChannelStatus uint64
|
type ChannelStatus uint64
|
||||||
@@ -4066,6 +4093,78 @@ func (c *OpenChannel) Snapshot() *ChannelSnapshot {
|
|||||||
return snapshot
|
return snapshot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep copy of the channel state.
|
||||||
|
func (c *OpenChannel) Copy() *OpenChannel {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
|
||||||
|
clone := &OpenChannel{
|
||||||
|
ChanType: c.ChanType,
|
||||||
|
ChainHash: c.ChainHash,
|
||||||
|
FundingOutpoint: c.FundingOutpoint,
|
||||||
|
ShortChannelID: c.ShortChannelID,
|
||||||
|
IsPending: c.IsPending,
|
||||||
|
IsInitiator: c.IsInitiator,
|
||||||
|
chanStatus: c.chanStatus,
|
||||||
|
FundingBroadcastHeight: c.FundingBroadcastHeight,
|
||||||
|
ConfirmationHeight: c.ConfirmationHeight,
|
||||||
|
NumConfsRequired: c.NumConfsRequired,
|
||||||
|
ChannelFlags: c.ChannelFlags,
|
||||||
|
IdentityPub: c.IdentityPub,
|
||||||
|
Capacity: c.Capacity,
|
||||||
|
TotalMSatSent: c.TotalMSatSent,
|
||||||
|
TotalMSatReceived: c.TotalMSatReceived,
|
||||||
|
InitialLocalBalance: c.InitialLocalBalance,
|
||||||
|
InitialRemoteBalance: c.InitialRemoteBalance,
|
||||||
|
LocalChanCfg: c.LocalChanCfg,
|
||||||
|
RemoteChanCfg: c.RemoteChanCfg,
|
||||||
|
LocalCommitment: c.LocalCommitment.copy(),
|
||||||
|
RemoteCommitment: c.RemoteCommitment.copy(),
|
||||||
|
RemoteCurrentRevocation: c.RemoteCurrentRevocation,
|
||||||
|
RemoteNextRevocation: c.RemoteNextRevocation,
|
||||||
|
RevocationProducer: c.RevocationProducer,
|
||||||
|
RevocationStore: c.RevocationStore,
|
||||||
|
Packager: c.Packager,
|
||||||
|
ThawHeight: c.ThawHeight,
|
||||||
|
LastWasRevoke: c.LastWasRevoke,
|
||||||
|
RevocationKeyLocator: c.RevocationKeyLocator,
|
||||||
|
confirmedScid: c.confirmedScid,
|
||||||
|
TapscriptRoot: c.TapscriptRoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.FundingTxn != nil {
|
||||||
|
clone.FundingTxn = c.FundingTxn.Copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.LocalShutdownScript) > 0 {
|
||||||
|
clone.LocalShutdownScript = make(
|
||||||
|
lnwire.DeliveryAddress,
|
||||||
|
len(c.LocalShutdownScript),
|
||||||
|
)
|
||||||
|
copy(clone.LocalShutdownScript, c.LocalShutdownScript)
|
||||||
|
}
|
||||||
|
if len(c.RemoteShutdownScript) > 0 {
|
||||||
|
clone.RemoteShutdownScript = make(
|
||||||
|
lnwire.DeliveryAddress,
|
||||||
|
len(c.RemoteShutdownScript),
|
||||||
|
)
|
||||||
|
copy(clone.RemoteShutdownScript, c.RemoteShutdownScript)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.Memo) > 0 {
|
||||||
|
clone.Memo = make([]byte, len(c.Memo))
|
||||||
|
copy(clone.Memo, c.Memo)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.CustomBlob.WhenSome(func(blob tlv.Blob) {
|
||||||
|
blobCopy := make([]byte, len(blob))
|
||||||
|
copy(blobCopy, blob)
|
||||||
|
clone.CustomBlob = fn.Some(blobCopy)
|
||||||
|
})
|
||||||
|
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
|
||||||
// LatestCommitments returns the two latest commitments for both the local and
|
// LatestCommitments returns the two latest commitments for both the local and
|
||||||
// remote party. These commitments are read from disk to ensure that only the
|
// remote party. These commitments are read from disk to ensure that only the
|
||||||
// latest fully committed state is returned. The first commitment returned is
|
// latest fully committed state is returned. The first commitment returned is
|
||||||
|
|||||||
@@ -72,6 +72,12 @@ type ClosedChannelEvent struct {
|
|||||||
CloseSummary *channeldb.ChannelCloseSummary
|
CloseSummary *channeldb.ChannelCloseSummary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChannelUpdateEvent represents a new event where a channel's state is updated.
|
||||||
|
type ChannelUpdateEvent struct {
|
||||||
|
// Channel is the channel that has been updated.
|
||||||
|
Channel *channeldb.OpenChannel
|
||||||
|
}
|
||||||
|
|
||||||
// FullyResolvedChannelEvent represents a new event where a channel becomes
|
// FullyResolvedChannelEvent represents a new event where a channel becomes
|
||||||
// fully resolved.
|
// fully resolved.
|
||||||
type FullyResolvedChannelEvent struct {
|
type FullyResolvedChannelEvent struct {
|
||||||
@@ -238,3 +244,14 @@ func (c *ChannelNotifier) NotifyInactiveChannelEvent(chanPoint wire.OutPoint) {
|
|||||||
log.Warnf("Unable to send inactive channel update: %v", err)
|
log.Warnf("Unable to send inactive channel update: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotifyChannelUpdateEvent notifies subscribers that a channel's state has been
|
||||||
|
// updated.
|
||||||
|
func (c *ChannelNotifier) NotifyChannelUpdateEvent(
|
||||||
|
channel *channeldb.OpenChannel) {
|
||||||
|
|
||||||
|
event := ChannelUpdateEvent{Channel: channel}
|
||||||
|
if err := c.ntfnServer.SendUpdate(event); err != nil {
|
||||||
|
log.Warnf("Unable to send channel update: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package channelnotifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestChannelUpdateEvent tests that channel update events are properly
|
||||||
|
// notified to subscribers.
|
||||||
|
func TestChannelUpdateEvent(t *testing.T) {
|
||||||
|
// Initialize the notification server.
|
||||||
|
ntfnServer := New(nil)
|
||||||
|
require.NoError(t, ntfnServer.Start())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
require.NoError(t, ntfnServer.Stop())
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Subscribe to channel events.
|
||||||
|
sub, err := ntfnServer.SubscribeChannelEvents()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer sub.Cancel()
|
||||||
|
|
||||||
|
// Create a mock channel state.
|
||||||
|
channel := &channeldb.OpenChannel{}
|
||||||
|
|
||||||
|
// Notify the server of a channel update event.
|
||||||
|
ntfnServer.NotifyChannelUpdateEvent(channel)
|
||||||
|
|
||||||
|
// Consume the event.
|
||||||
|
select {
|
||||||
|
case event := <-sub.Updates():
|
||||||
|
updateEvent, ok := event.(ChannelUpdateEvent)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, channel, updateEvent.Channel)
|
||||||
|
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
t.Fatalf("expected to receive channel update event")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -129,6 +129,10 @@
|
|||||||
composite `synced_to_chain` field which also considers router and blockbeat
|
composite `synced_to_chain` field which also considers router and blockbeat
|
||||||
dispatcher states.
|
dispatcher states.
|
||||||
|
|
||||||
|
* SubscribeChannelEvents [now emits channel update
|
||||||
|
events](https://github.com/lightningnetwork/lnd/pull/10543) to be able to
|
||||||
|
subscribe to state changes.
|
||||||
|
|
||||||
## lncli Updates
|
## lncli Updates
|
||||||
|
|
||||||
## Breaking Changes
|
## Breaking Changes
|
||||||
@@ -189,6 +193,7 @@
|
|||||||
|
|
||||||
# Contributors (Alphabetical Order)
|
# Contributors (Alphabetical Order)
|
||||||
|
|
||||||
|
* bitromortac
|
||||||
* Boris Nagaev
|
* Boris Nagaev
|
||||||
* Elle Mouton
|
* Elle Mouton
|
||||||
* Erick Cestari
|
* Erick Cestari
|
||||||
|
|||||||
@@ -256,6 +256,10 @@ type ChannelLinkConfig struct {
|
|||||||
// ChannelNotifier when a channel link become inactive.
|
// ChannelNotifier when a channel link become inactive.
|
||||||
NotifyInactiveLinkEvent func(wire.OutPoint)
|
NotifyInactiveLinkEvent func(wire.OutPoint)
|
||||||
|
|
||||||
|
// NotifyChannelUpdate allows the link to tell the ChannelNotifier when
|
||||||
|
// a channel's state has been updated.
|
||||||
|
NotifyChannelUpdate func(*channeldb.OpenChannel)
|
||||||
|
|
||||||
// HtlcNotifier is an instance of a htlcNotifier which we will pipe htlc
|
// HtlcNotifier is an instance of a htlcNotifier which we will pipe htlc
|
||||||
// events through.
|
// events through.
|
||||||
HtlcNotifier htlcNotifier
|
HtlcNotifier htlcNotifier
|
||||||
@@ -1813,6 +1817,13 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context,
|
|||||||
case *lnwire.CommitSig:
|
case *lnwire.CommitSig:
|
||||||
err = l.processRemoteCommitSig(ctx, msg)
|
err = l.processRemoteCommitSig(ctx, msg)
|
||||||
|
|
||||||
|
// At this point our local commitment state has been irrevocably
|
||||||
|
// committed to and our balances are updated. We notify our
|
||||||
|
// subscribers that the channel state has been updated.
|
||||||
|
if err == nil {
|
||||||
|
l.cfg.NotifyChannelUpdate(l.channel.ChannelState())
|
||||||
|
}
|
||||||
|
|
||||||
case *lnwire.RevokeAndAck:
|
case *lnwire.RevokeAndAck:
|
||||||
err = l.processRemoteRevokeAndAck(ctx, msg)
|
err = l.processRemoteRevokeAndAck(ctx, msg)
|
||||||
|
|
||||||
|
|||||||
@@ -2241,6 +2241,7 @@ func newSingleLinkTestHarness(t *testing.T, chanAmt,
|
|||||||
MaxFeeAllocation: DefaultMaxLinkFeeAllocation,
|
MaxFeeAllocation: DefaultMaxLinkFeeAllocation,
|
||||||
NotifyActiveLink: func(wire.OutPoint) {},
|
NotifyActiveLink: func(wire.OutPoint) {},
|
||||||
NotifyActiveChannel: func(wire.OutPoint) {},
|
NotifyActiveChannel: func(wire.OutPoint) {},
|
||||||
|
NotifyChannelUpdate: func(*channeldb.OpenChannel) {},
|
||||||
NotifyInactiveChannel: func(wire.OutPoint) {},
|
NotifyInactiveChannel: func(wire.OutPoint) {},
|
||||||
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
||||||
HtlcNotifier: aliceSwitch.cfg.HtlcNotifier,
|
HtlcNotifier: aliceSwitch.cfg.HtlcNotifier,
|
||||||
@@ -4931,6 +4932,7 @@ func (h *persistentLinkHarness) restartLink(
|
|||||||
NotifyActiveChannel: func(wire.OutPoint) {},
|
NotifyActiveChannel: func(wire.OutPoint) {},
|
||||||
NotifyInactiveChannel: func(wire.OutPoint) {},
|
NotifyInactiveChannel: func(wire.OutPoint) {},
|
||||||
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
||||||
|
NotifyChannelUpdate: func(*channeldb.OpenChannel) {},
|
||||||
HtlcNotifier: h.hSwitch.cfg.HtlcNotifier,
|
HtlcNotifier: h.hSwitch.cfg.HtlcNotifier,
|
||||||
SyncStates: syncStates,
|
SyncStates: syncStates,
|
||||||
GetAliases: getAliases,
|
GetAliases: getAliases,
|
||||||
|
|||||||
@@ -1175,6 +1175,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer,
|
|||||||
NotifyActiveChannel: func(wire.OutPoint) {},
|
NotifyActiveChannel: func(wire.OutPoint) {},
|
||||||
NotifyInactiveChannel: func(wire.OutPoint) {},
|
NotifyInactiveChannel: func(wire.OutPoint) {},
|
||||||
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
||||||
|
NotifyChannelUpdate: func(*channeldb.OpenChannel) {},
|
||||||
HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier,
|
HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier,
|
||||||
GetAliases: getAliases,
|
GetAliases: getAliases,
|
||||||
ShouldFwdExpAccountability: func() bool { return true },
|
ShouldFwdExpAccountability: func() bool { return true },
|
||||||
|
|||||||
@@ -206,6 +206,10 @@ var allTestCases = []*lntest.TestCase{
|
|||||||
Name: "invoice update subscription",
|
Name: "invoice update subscription",
|
||||||
TestFunc: testInvoiceSubscriptions,
|
TestFunc: testInvoiceSubscriptions,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "channel update subscription",
|
||||||
|
TestFunc: testChannelUpdateNotifications,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "streaming channel backup update",
|
Name: "streaming channel backup update",
|
||||||
TestFunc: testChannelBackupUpdates,
|
TestFunc: testChannelBackupUpdates,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package itest
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
@@ -1342,3 +1343,101 @@ func testOpenChannelWithShutdownAddr(ht *lntest.HarnessTest) {
|
|||||||
require.Equal(ht, bobShutdownAddr.Address, bobUTXOConfirmed.Address)
|
require.Equal(ht, bobShutdownAddr.Address, bobUTXOConfirmed.Address)
|
||||||
require.Equal(ht, paymentAmount, bobUTXOConfirmed.AmountSat)
|
require.Equal(ht, paymentAmount, bobUTXOConfirmed.AmountSat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testChannelUpdateNotifications checks that clients subscribed to channel
|
||||||
|
// events receive real-time updates when the channel state changes.
|
||||||
|
func testChannelUpdateNotifications(ht *lntest.HarnessTest) {
|
||||||
|
// We'll start by creating two nodes, Alice and Bob, and a channel
|
||||||
|
// between them.
|
||||||
|
alice := ht.NewNodeWithCoins("Alice", nil)
|
||||||
|
bob := ht.NewNode("Bob", nil)
|
||||||
|
|
||||||
|
ht.EnsureConnected(alice, bob)
|
||||||
|
|
||||||
|
// We'll subscribe to channel events for both nodes.
|
||||||
|
aliceSub := alice.RPC.SubscribeChannelEvents()
|
||||||
|
bobSub := bob.RPC.SubscribeChannelEvents()
|
||||||
|
|
||||||
|
// We'll then open a channel between Alice and Bob.
|
||||||
|
chanPoint := ht.OpenChannel(
|
||||||
|
alice, bob, lntest.OpenChannelParams{
|
||||||
|
Amt: 1000000,
|
||||||
|
PushAmt: 500000,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// We'll wait for the channel to be active. We expect to receive one
|
||||||
|
// pending, one open, and one active notification.
|
||||||
|
ht.AssertChannelActive(alice, chanPoint)
|
||||||
|
ht.AssertChannelActive(bob, chanPoint)
|
||||||
|
|
||||||
|
ht.AssertChannelEventType(
|
||||||
|
aliceSub, lnrpc.ChannelEventUpdate_PENDING_OPEN_CHANNEL,
|
||||||
|
)
|
||||||
|
ht.AssertChannelEventType(
|
||||||
|
aliceSub, lnrpc.ChannelEventUpdate_OPEN_CHANNEL,
|
||||||
|
)
|
||||||
|
ht.AssertChannelEventType(
|
||||||
|
aliceSub, lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL,
|
||||||
|
)
|
||||||
|
|
||||||
|
ht.AssertChannelEventType(
|
||||||
|
bobSub, lnrpc.ChannelEventUpdate_PENDING_OPEN_CHANNEL,
|
||||||
|
)
|
||||||
|
ht.AssertChannelEventType(
|
||||||
|
bobSub, lnrpc.ChannelEventUpdate_OPEN_CHANNEL,
|
||||||
|
)
|
||||||
|
ht.AssertChannelEventType(
|
||||||
|
bobSub, lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL,
|
||||||
|
)
|
||||||
|
|
||||||
|
// We'll now make a payment from Alice to Bob to trigger a channel
|
||||||
|
// update.
|
||||||
|
payReqs, _, _ := ht.CreatePayReqs(bob, btcutil.Amount(1000), 1)
|
||||||
|
ht.CompletePaymentRequests(alice, payReqs)
|
||||||
|
|
||||||
|
// assertUpdates is a helper function to assert the number of commitment
|
||||||
|
// updates received by a node.
|
||||||
|
assertUpdates := func(sub rpc.ChannelEventsClient, numUpdates int) {
|
||||||
|
event := ht.AssertChannelEventType(
|
||||||
|
sub, lnrpc.ChannelEventUpdate_CHANNEL_UPDATE,
|
||||||
|
)
|
||||||
|
require.IsType(
|
||||||
|
ht, &lnrpc.ChannelEventUpdate_UpdatedChannel{},
|
||||||
|
event.Channel,
|
||||||
|
)
|
||||||
|
channel := event.GetUpdatedChannel().Channel
|
||||||
|
require.EqualValues(ht, numUpdates, channel.NumUpdates)
|
||||||
|
}
|
||||||
|
|
||||||
|
// expectNoMoreUpdates is a helper function to assert that no more
|
||||||
|
// channel updates are received by a node.
|
||||||
|
expectNoMoreUpdates := func(sub rpc.ChannelEventsClient) {
|
||||||
|
updates := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
_, err := sub.Recv()
|
||||||
|
// Only signal if we successfully received an update.
|
||||||
|
// If Recv fails (e.g., context canceled during test
|
||||||
|
// cleanup), that's fine - it means no update arrived.
|
||||||
|
if err == nil {
|
||||||
|
close(updates)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-updates:
|
||||||
|
ht.Fatalf("expected no more updates")
|
||||||
|
case <-time.After(defaultTimeout):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We expect to see two updates from each node's point of view. One for
|
||||||
|
// the addition of the HTLC, and a second for the settlement.
|
||||||
|
assertUpdates(aliceSub, 1)
|
||||||
|
assertUpdates(aliceSub, 2)
|
||||||
|
expectNoMoreUpdates(aliceSub)
|
||||||
|
|
||||||
|
assertUpdates(bobSub, 1)
|
||||||
|
assertUpdates(bobSub, 2)
|
||||||
|
expectNoMoreUpdates(bobSub)
|
||||||
|
}
|
||||||
+2917
-2827
File diff suppressed because it is too large.
Load diff
@@ -3064,6 +3064,10 @@ message PendingChannelsResponse {
|
|||||||
message ChannelEventSubscription {
|
message ChannelEventSubscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ChannelCommitUpdate {
|
||||||
|
Channel channel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message ChannelEventUpdate {
|
message ChannelEventUpdate {
|
||||||
oneof channel {
|
oneof channel {
|
||||||
Channel open_channel = 1;
|
Channel open_channel = 1;
|
||||||
@@ -3073,6 +3077,7 @@ message ChannelEventUpdate {
|
|||||||
PendingUpdate pending_open_channel = 6;
|
PendingUpdate pending_open_channel = 6;
|
||||||
ChannelPoint fully_resolved_channel = 7;
|
ChannelPoint fully_resolved_channel = 7;
|
||||||
ChannelPoint channel_funding_timeout = 8;
|
ChannelPoint channel_funding_timeout = 8;
|
||||||
|
ChannelCommitUpdate updated_channel = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UpdateType {
|
enum UpdateType {
|
||||||
@@ -3083,6 +3088,7 @@ message ChannelEventUpdate {
|
|||||||
PENDING_OPEN_CHANNEL = 4;
|
PENDING_OPEN_CHANNEL = 4;
|
||||||
FULLY_RESOLVED_CHANNEL = 5;
|
FULLY_RESOLVED_CHANNEL = 5;
|
||||||
CHANNEL_FUNDING_TIMEOUT = 6;
|
CHANNEL_FUNDING_TIMEOUT = 6;
|
||||||
|
CHANNEL_UPDATE = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateType type = 5;
|
UpdateType type = 5;
|
||||||
|
|||||||
@@ -3125,7 +3125,8 @@
|
|||||||
"INACTIVE_CHANNEL",
|
"INACTIVE_CHANNEL",
|
||||||
"PENDING_OPEN_CHANNEL",
|
"PENDING_OPEN_CHANNEL",
|
||||||
"FULLY_RESOLVED_CHANNEL",
|
"FULLY_RESOLVED_CHANNEL",
|
||||||
"CHANNEL_FUNDING_TIMEOUT"
|
"CHANNEL_FUNDING_TIMEOUT",
|
||||||
|
"CHANNEL_UPDATE"
|
||||||
],
|
],
|
||||||
"default": "OPEN_CHANNEL"
|
"default": "OPEN_CHANNEL"
|
||||||
},
|
},
|
||||||
@@ -4478,6 +4479,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lnrpcChannelCommitUpdate": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"channel": {
|
||||||
|
"$ref": "#/definitions/lnrpcChannel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"lnrpcChannelConstraints": {
|
"lnrpcChannelConstraints": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -4609,6 +4618,9 @@
|
|||||||
"channel_funding_timeout": {
|
"channel_funding_timeout": {
|
||||||
"$ref": "#/definitions/lnrpcChannelPoint"
|
"$ref": "#/definitions/lnrpcChannelPoint"
|
||||||
},
|
},
|
||||||
|
"updated_channel": {
|
||||||
|
"$ref": "#/definitions/lnrpcChannelCommitUpdate"
|
||||||
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/definitions/ChannelEventUpdateUpdateType"
|
"$ref": "#/definitions/ChannelEventUpdateUpdateType"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -425,6 +425,20 @@ func (h *HarnessTest) assertChannelStatus(hn *node.HarnessNode,
|
|||||||
return channel
|
return channel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssertChannelEventType consumes one event from a client and asserts the event
|
||||||
|
// type is matched.
|
||||||
|
func (h *HarnessTest) AssertChannelEventType(sub rpc.ChannelEventsClient,
|
||||||
|
updateType lnrpc.ChannelEventUpdate_UpdateType,
|
||||||
|
) *lnrpc.ChannelEventUpdate {
|
||||||
|
|
||||||
|
update := h.ReceiveChannelEvent(sub)
|
||||||
|
|
||||||
|
require.Equalf(h, updateType, update.Type, "wrong event type, "+
|
||||||
|
"want %v got %v", updateType, update.Type)
|
||||||
|
|
||||||
|
return update
|
||||||
|
}
|
||||||
|
|
||||||
// AssertOutputScriptClass checks that the specified transaction output has the
|
// AssertOutputScriptClass checks that the specified transaction output has the
|
||||||
// expected script class.
|
// expected script class.
|
||||||
func (h *HarnessTest) AssertOutputScriptClass(tx *btcutil.Tx,
|
func (h *HarnessTest) AssertOutputScriptClass(tx *btcutil.Tx,
|
||||||
|
|||||||
@@ -6576,6 +6576,13 @@ func (lc *LightningChannel) ChannelPoint() wire.OutPoint {
|
|||||||
return lc.channelState.FundingOutpoint
|
return lc.channelState.FundingOutpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChannelState returns a copy of the internal channeldb.OpenChannel state
|
||||||
|
// struct. Modifications to the returned struct will not be reflected within
|
||||||
|
// the LightningChannel.
|
||||||
|
func (lc *LightningChannel) ChannelState() *channeldb.OpenChannel {
|
||||||
|
return lc.channelState.Copy()
|
||||||
|
}
|
||||||
|
|
||||||
// ChannelID returns the ChannelID of this LightningChannel. This is the same
|
// ChannelID returns the ChannelID of this LightningChannel. This is the same
|
||||||
// ChannelID that is used in update messages for this channel.
|
// ChannelID that is used in update messages for this channel.
|
||||||
func (lc *LightningChannel) ChannelID() lnwire.ChannelID {
|
func (lc *LightningChannel) ChannelID() lnwire.ChannelID {
|
||||||
|
|||||||
@@ -1480,6 +1480,7 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint,
|
|||||||
NotifyActiveChannel: p.cfg.ChannelNotifier.NotifyActiveChannelEvent,
|
NotifyActiveChannel: p.cfg.ChannelNotifier.NotifyActiveChannelEvent,
|
||||||
NotifyInactiveChannel: p.cfg.ChannelNotifier.NotifyInactiveChannelEvent,
|
NotifyInactiveChannel: p.cfg.ChannelNotifier.NotifyInactiveChannelEvent,
|
||||||
NotifyInactiveLinkEvent: p.cfg.ChannelNotifier.NotifyInactiveLinkEvent,
|
NotifyInactiveLinkEvent: p.cfg.ChannelNotifier.NotifyInactiveLinkEvent,
|
||||||
|
NotifyChannelUpdate: p.cfg.ChannelNotifier.NotifyChannelUpdateEvent,
|
||||||
HtlcNotifier: p.cfg.HtlcNotifier,
|
HtlcNotifier: p.cfg.HtlcNotifier,
|
||||||
GetAliases: p.cfg.GetAliases,
|
GetAliases: p.cfg.GetAliases,
|
||||||
PreviouslySentShutdown: shutdownMsg,
|
PreviouslySentShutdown: shutdownMsg,
|
||||||
|
|||||||
@@ -5488,6 +5488,24 @@ func (r *rpcServer) SubscribeChannelEvents(req *lnrpc.ChannelEventSubscription,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case channelnotifier.ChannelUpdateEvent:
|
||||||
|
channel, err := createRPCOpenChannel(
|
||||||
|
updateStream.Context(),
|
||||||
|
r, event.Channel, true, false,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
update = &lnrpc.ChannelEventUpdate{
|
||||||
|
Type: lnrpc.ChannelEventUpdate_CHANNEL_UPDATE,
|
||||||
|
Channel: &lnrpc.ChannelEventUpdate_UpdatedChannel{
|
||||||
|
UpdatedChannel: &lnrpc.ChannelCommitUpdate{
|
||||||
|
Channel: channel,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
case channelnotifier.InactiveChannelEvent:
|
case channelnotifier.InactiveChannelEvent:
|
||||||
update = &lnrpc.ChannelEventUpdate{
|
update = &lnrpc.ChannelEventUpdate{
|
||||||
Type: lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL,
|
Type: lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL,
|
||||||
|
|||||||
Reference in new issue
Block a user