From 5181f100ed5cf288ee1e8b9a5d99d54db82d2212 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 12 Oct 2018 17:08:14 +0200 Subject: [PATCH 01/10] subscribe: add new subscribe package This commit creates a new package 'subscribe', that exposes a common Client-Server subscription system, that can be shared among packages. --- subscribe/subscribe.go | 216 ++++++++++++++++++++++++++++++++++++ subscribe/subscribe_test.go | 110 ++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 subscribe/subscribe.go create mode 100644 subscribe/subscribe_test.go diff --git a/subscribe/subscribe.go b/subscribe/subscribe.go new file mode 100644 index 000000000..1d413031c --- /dev/null +++ b/subscribe/subscribe.go @@ -0,0 +1,216 @@ +package subscribe + +import ( + "errors" + "sync" + "sync/atomic" + + "github.com/lightningnetwork/lnd/queue" +) + +// ErrServerShuttingDown is an error returned in case the server is in the +// process of shutting down. +var ErrServerShuttingDown = errors.New("subscription server shutting down") + +// Client is used to get notified about updates the caller has subscribed to, +type Client struct { + // Cancel should be called in case the client no longer wants to + // subscribe for updates from the server. + Cancel func() + + updates *queue.ConcurrentQueue + quit chan struct{} +} + +// Updates returns a read-only channel where the updates the client has +// subscribed to will be delivered. +func (c *Client) Updates() <-chan interface{} { + return c.updates.ChanOut() +} + +// Quit is a channel that will be closed in case the server decides to no +// longer deliver updates to this client. +func (c *Client) Quit() <-chan struct{} { + return c.quit +} + +// Server is a struct that manages a set of subscriptions and their +// corresponding clients. Any update will be delivered to all active clients. +type Server struct { + clientCounter uint64 // To be used atomically. + + started uint32 // To be used atomically. + stopped uint32 // To be used atomically. + + clients map[uint64]*Client + clientUpdates chan *clientUpdate + + updates chan interface{} + + quit chan struct{} + wg sync.WaitGroup +} + +// clientUpdate is an internal message sent to the subscriptionHandler to +// either register a new client for subscription or cancel an existing +// subscription. +type clientUpdate struct { + // cancel indicates if the update to the client is cancelling an + // existing client's subscription. If not then this update will be to + // subscribe a new client. + cancel bool + + // clientID is the unique identifier for this client. Any further + // updates (deleting or adding) to this notification client will be + // dispatched according to the target clientID. + clientID uint64 + + // client is the new client that will receive updates. Will be nil in + // case this is a cancallation update. + client *Client +} + +// NewServer returns a new Server. +func NewServer() *Server { + return &Server{ + clients: make(map[uint64]*Client), + clientUpdates: make(chan *clientUpdate), + updates: make(chan interface{}), + quit: make(chan struct{}), + } +} + +// Start starts the Server, making it ready to accept subscriptions and +// updates. +func (s *Server) Start() error { + if !atomic.CompareAndSwapUint32(&s.started, 0, 1) { + return nil + } + + s.wg.Add(1) + go s.subscriptionHandler() + + return nil +} + +// Stop stops the server. +func (s *Server) Stop() error { + if !atomic.CompareAndSwapUint32(&s.stopped, 0, 1) { + return nil + } + + close(s.quit) + s.wg.Wait() + + return nil +} + +// Subscribe returns a Client that will receive updates any time the Server is +// made aware of a new event. +func (s *Server) Subscribe() (*Client, error) { + // We'll first atomically obtain the next ID for this client from the + // incrementing client ID counter. + clientID := atomic.AddUint64(&s.clientCounter, 1) + + // Create the client that will be returned. The Cancel method is + // populated to send the cancellation intent to the + // subscriptionHandler. + client := &Client{ + updates: queue.NewConcurrentQueue(20), + quit: make(chan struct{}), + Cancel: func() { + select { + case s.clientUpdates <- &clientUpdate{ + cancel: true, + clientID: clientID, + }: + case <-s.quit: + return + } + }, + } + + select { + case s.clientUpdates <- &clientUpdate{ + cancel: false, + clientID: clientID, + client: client, + }: + case <-s.quit: + return nil, ErrServerShuttingDown + } + + return client, nil +} + +// SendUpdate is called to send the passed update to all currently active +// subscription clients. +func (s *Server) SendUpdate(update interface{}) error { + + select { + case s.updates <- update: + return nil + case <-s.quit: + return ErrServerShuttingDown + } +} + +// subscriptionHandler is the main handler for the Server. It will handle +// incoming updates and subscriptions, and forward the incoming updates to the +// registered clients. +// +// NOTE: MUST be run as a goroutine. +func (s *Server) subscriptionHandler() { + defer s.wg.Done() + + for { + select { + + // If a client update is received, the either a new + // subscription becomes active, or we cancel and existing one. + case update := <-s.clientUpdates: + clientID := update.clientID + + // In case this is a cancellation, stop the client's + // underlying queue, and remove the client from the set + // of active subscription clients. + if update.cancel { + client, ok := s.clients[update.clientID] + if ok { + client.updates.Stop() + close(client.quit) + delete(s.clients, clientID) + } + + continue + } + + // If this was not a cancellation, start the underlying + // queue and add the client to our set of subscription + // clients. It will be notified about any new updates + // the server receives. + update.client.updates.Start() + s.clients[update.clientID] = update.client + + // A new update was received, forward it to all active clients. + case upd := <-s.updates: + for _, client := range s.clients { + select { + case client.updates.ChanIn() <- upd: + case <-client.quit: + case <-s.quit: + return + } + } + + // In case the server is shutting down, stop the clients and + // close the quit channels to notify them. + case <-s.quit: + for _, client := range s.clients { + client.updates.Stop() + close(client.quit) + } + return + } + } +} diff --git a/subscribe/subscribe_test.go b/subscribe/subscribe_test.go new file mode 100644 index 000000000..b55f56daa --- /dev/null +++ b/subscribe/subscribe_test.go @@ -0,0 +1,110 @@ +package subscribe_test + +import ( + "testing" + "time" + + "github.com/lightningnetwork/lnd/subscribe" +) + +// TestSubscribe tests that the subscription clients receive the updates sent +// to them after they subscribe, and that cancelled clients don't get more +// updates. +func TestSubscribe(t *testing.T) { + t.Parallel() + + server := subscribe.NewServer() + if err := server.Start(); err != nil { + t.Fatalf("unable to start server") + } + + const numClients = 300 + const numUpdates = 1000 + + var clients [numClients]*subscribe.Client + + // Start by registering two thirds the clients. + for i := 0; i < numClients*2/3; i++ { + c, err := server.Subscribe() + if err != nil { + t.Fatalf("unable to subscribe: %v", err) + } + + clients[i] = c + } + + // Send half the updates. + for i := 0; i < numUpdates/2; i++ { + if err := server.SendUpdate(i); err != nil { + t.Fatalf("unable to send update") + } + } + + // Register the rest of the clients. + for i := numClients * 2 / 3; i < numClients; i++ { + c, err := server.Subscribe() + if err != nil { + t.Fatalf("unable to subscribe: %v", err) + } + + clients[i] = c + } + + // Cancel one third of the clients. + for i := 0; i < numClients/3; i++ { + clients[i].Cancel() + } + + // Send the rest of the updates. + for i := numUpdates / 2; i < numUpdates; i++ { + if err := server.SendUpdate(i); err != nil { + t.Fatalf("unable to send update") + } + } + + // Now ensure the clients got the updates we expect. + for i, c := range clients { + + var from, to int + switch { + + // We expect the first third of the clients to quit, since they + // were cancelled. + case i < numClients/3: + select { + case <-c.Quit(): + continue + case <-time.After(1 * time.Second): + t.Fatalf("cancelled client %v did not quit", i) + } + + // The next third should receive all updates. + case i < numClients*2/3: + from = 0 + to = numUpdates + + // And finally the last third should receive the last half of + // the updates. + default: + from = numUpdates / 2 + to = numUpdates + } + + for cnt := from; cnt < to; cnt++ { + select { + case upd := <-c.Updates(): + j := upd.(int) + if j != cnt { + t.Fatalf("expected %v, got %v, for "+ + "client %v", cnt, j, i) + } + + case <-time.After(1 * time.Second): + t.Fatalf("did not receive expected update %v "+ + "for client %v", cnt, i) + } + } + + } + +} From b0b6151cc1932d4e80b73d1c43eddf23daaf5d7e Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 27 Sep 2018 16:34:43 -0700 Subject: [PATCH 02/10] rpcserver: add helper functions to format open and closed RPC channels. `createRPCChannel` is used by the `listchannels` RPC call and will be used by `subscribechannels` as well. `createRPCClosedChannel` is used by the `closedchannels` RPC call and will also be used by `subscribechannels`. This is used by the `listchannels` RPC call and will be used by `subscribechannels` as well. Its purpose is to mitigate code duplication between the two RPC calls. --- rpcserver.go | 213 +++++++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 92 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index e675be304..933be7986 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2254,56 +2254,34 @@ func (r *rpcServer) ClosedChannels(ctx context.Context, continue } - nodePub := dbChannel.RemotePub - nodeID := hex.EncodeToString(nodePub.SerializeCompressed()) - - var closeType lnrpc.ChannelCloseSummary_ClosureType switch dbChannel.CloseType { case channeldb.CooperativeClose: if filterResults && !in.Cooperative { continue } - closeType = lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE case channeldb.LocalForceClose: if filterResults && !in.LocalForce { continue } - closeType = lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE case channeldb.RemoteForceClose: if filterResults && !in.RemoteForce { continue } - closeType = lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE case channeldb.BreachClose: if filterResults && !in.Breach { continue } - closeType = lnrpc.ChannelCloseSummary_BREACH_CLOSE case channeldb.FundingCanceled: if filterResults && !in.FundingCanceled { continue } - closeType = lnrpc.ChannelCloseSummary_FUNDING_CANCELED case channeldb.Abandoned: if filterResults && !in.Abandoned { continue } - closeType = lnrpc.ChannelCloseSummary_ABANDONED - } - - channel := &lnrpc.ChannelCloseSummary{ - Capacity: int64(dbChannel.Capacity), - RemotePubkey: nodeID, - CloseHeight: dbChannel.CloseHeight, - CloseType: closeType, - ChannelPoint: dbChannel.ChanPoint.String(), - ChanId: dbChannel.ShortChanID.ToUint64(), - SettledBalance: int64(dbChannel.SettledBalance), - TimeLockedBalance: int64(dbChannel.TimeLockedBalance), - ChainHash: dbChannel.ChainHash.String(), - ClosingTxHash: dbChannel.ClosingTXID.String(), } + channel := createRPCClosedChannel(dbChannel) resp.Channels = append(resp.Channels, channel) } @@ -2339,14 +2317,8 @@ func (r *rpcServer) ListChannels(ctx context.Context, for _, dbChannel := range dbChannels { nodePub := dbChannel.IdentityPub - nodeID := hex.EncodeToString(nodePub.SerializeCompressed()) chanPoint := dbChannel.FundingOutpoint - // With the channel point known, retrieve the network channel - // ID from the database. - var chanID uint64 - chanID, _ = graph.ChannelID(&chanPoint) - var peerOnline bool if _, err := r.server.FindPeer(nodePub); err == nil { peerOnline = true @@ -2364,7 +2336,7 @@ func (r *rpcServer) ListChannels(ctx context.Context, // Next, we'll determine whether we should add this channel to // our list depending on the type of channels requested to us. isActive := peerOnline && linkActive - isPublic := dbChannel.ChannelFlags&lnwire.FFAnnounceChannel != 0 + channel := createRPCOpenChannel(r, graph, dbChannel, isActive) // We'll only skip returning this channel if we were requested // for a specific kind and this channel doesn't satisfy it. @@ -2373,78 +2345,135 @@ func (r *rpcServer) ListChannels(ctx context.Context, continue case in.InactiveOnly && isActive: continue - case in.PublicOnly && !isPublic: + case in.PublicOnly && channel.Private: continue - case in.PrivateOnly && isPublic: + case in.PrivateOnly && !channel.Private: continue } - // As this is required for display purposes, we'll calculate - // the weight of the commitment transaction. We also add on the - // estimated weight of the witness to calculate the weight of - // the transaction if it were to be immediately unilaterally - // broadcast. - localCommit := dbChannel.LocalCommitment - utx := btcutil.NewTx(localCommit.CommitTx) - commitBaseWeight := blockchain.GetTransactionWeight(utx) - commitWeight := commitBaseWeight + input.WitnessCommitmentTxWeight - - localBalance := localCommit.LocalBalance - remoteBalance := localCommit.RemoteBalance - - // As an artifact of our usage of mSAT internally, either party - // may end up in a state where they're holding a fractional - // amount of satoshis which can't be expressed within the - // actual commitment output. Since we round down when going - // from mSAT -> SAT, we may at any point be adding an - // additional SAT to miners fees. As a result, we display a - // commitment fee that accounts for this externally. - var sumOutputs btcutil.Amount - for _, txOut := range localCommit.CommitTx.TxOut { - sumOutputs += btcutil.Amount(txOut.Value) - } - externalCommitFee := dbChannel.Capacity - sumOutputs - - channel := &lnrpc.Channel{ - Active: isActive, - Private: !isPublic, - RemotePubkey: nodeID, - ChannelPoint: chanPoint.String(), - ChanId: chanID, - Capacity: int64(dbChannel.Capacity), - LocalBalance: int64(localBalance.ToSatoshis()), - RemoteBalance: int64(remoteBalance.ToSatoshis()), - CommitFee: int64(externalCommitFee), - CommitWeight: commitWeight, - FeePerKw: int64(localCommit.FeePerKw), - TotalSatoshisSent: int64(dbChannel.TotalMSatSent.ToSatoshis()), - TotalSatoshisReceived: int64(dbChannel.TotalMSatReceived.ToSatoshis()), - NumUpdates: localCommit.CommitHeight, - PendingHtlcs: make([]*lnrpc.HTLC, len(localCommit.Htlcs)), - CsvDelay: uint32(dbChannel.LocalChanCfg.CsvDelay), - Initiator: dbChannel.IsInitiator, - } - - for i, htlc := range localCommit.Htlcs { - var rHash [32]byte - copy(rHash[:], htlc.RHash[:]) - channel.PendingHtlcs[i] = &lnrpc.HTLC{ - Incoming: htlc.Incoming, - Amount: int64(htlc.Amt.ToSatoshis()), - HashLock: rHash[:], - ExpirationHeight: htlc.RefundTimeout, - } - - // Add the Pending Htlc Amount to UnsettledBalance field. - channel.UnsettledBalance += channel.PendingHtlcs[i].Amount - } - resp.Channels = append(resp.Channels, channel) } return resp, nil } +// createRPCOpenChannel creates an *lnrpc.Channel from the *channeldb.Channel. +func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, + dbChannel *channeldb.OpenChannel, isActive bool) *lnrpc.Channel { + + nodePub := dbChannel.IdentityPub + nodeID := hex.EncodeToString(nodePub.SerializeCompressed()) + chanPoint := dbChannel.FundingOutpoint + + // With the channel point known, retrieve the network channel + // ID from the database. + var chanID uint64 + chanID, _ = graph.ChannelID(&chanPoint) + + // Next, we'll determine whether the channel is public or not. + isPublic := dbChannel.ChannelFlags&lnwire.FFAnnounceChannel != 0 + + // As this is required for display purposes, we'll calculate + // the weight of the commitment transaction. We also add on the + // estimated weight of the witness to calculate the weight of + // the transaction if it were to be immediately unilaterally + // broadcast. + localCommit := dbChannel.LocalCommitment + utx := btcutil.NewTx(localCommit.CommitTx) + commitBaseWeight := blockchain.GetTransactionWeight(utx) + commitWeight := commitBaseWeight + input.WitnessCommitmentTxWeight + + localBalance := localCommit.LocalBalance + remoteBalance := localCommit.RemoteBalance + + // As an artifact of our usage of mSAT internally, either party + // may end up in a state where they're holding a fractional + // amount of satoshis which can't be expressed within the + // actual commitment output. Since we round down when going + // from mSAT -> SAT, we may at any point be adding an + // additional SAT to miners fees. As a result, we display a + // commitment fee that accounts for this externally. + var sumOutputs btcutil.Amount + for _, txOut := range localCommit.CommitTx.TxOut { + sumOutputs += btcutil.Amount(txOut.Value) + } + externalCommitFee := dbChannel.Capacity - sumOutputs + + channel := &lnrpc.Channel{ + Active: isActive, + Private: !isPublic, + RemotePubkey: nodeID, + ChannelPoint: chanPoint.String(), + ChanId: chanID, + Capacity: int64(dbChannel.Capacity), + LocalBalance: int64(localBalance.ToSatoshis()), + RemoteBalance: int64(remoteBalance.ToSatoshis()), + CommitFee: int64(externalCommitFee), + CommitWeight: commitWeight, + FeePerKw: int64(localCommit.FeePerKw), + TotalSatoshisSent: int64(dbChannel.TotalMSatSent.ToSatoshis()), + TotalSatoshisReceived: int64(dbChannel.TotalMSatReceived.ToSatoshis()), + NumUpdates: localCommit.CommitHeight, + PendingHtlcs: make([]*lnrpc.HTLC, len(localCommit.Htlcs)), + CsvDelay: uint32(dbChannel.LocalChanCfg.CsvDelay), + Initiator: dbChannel.IsInitiator, + } + + for i, htlc := range localCommit.Htlcs { + var rHash [32]byte + copy(rHash[:], htlc.RHash[:]) + channel.PendingHtlcs[i] = &lnrpc.HTLC{ + Incoming: htlc.Incoming, + Amount: int64(htlc.Amt.ToSatoshis()), + HashLock: rHash[:], + ExpirationHeight: htlc.RefundTimeout, + } + + // Add the Pending Htlc Amount to UnsettledBalance field. + channel.UnsettledBalance += channel.PendingHtlcs[i].Amount + } + + return channel +} + +// createRPCClosedChannel creates an *lnrpc.ClosedChannelSummary from a +// *channeldb.ChannelCloseSummary. +func createRPCClosedChannel( + dbChannel *channeldb.ChannelCloseSummary) *lnrpc.ChannelCloseSummary { + + nodePub := dbChannel.RemotePub + nodeID := hex.EncodeToString(nodePub.SerializeCompressed()) + + var closeType lnrpc.ChannelCloseSummary_ClosureType + switch dbChannel.CloseType { + case channeldb.CooperativeClose: + closeType = lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE + case channeldb.LocalForceClose: + closeType = lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE + case channeldb.RemoteForceClose: + closeType = lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE + case channeldb.BreachClose: + closeType = lnrpc.ChannelCloseSummary_BREACH_CLOSE + case channeldb.FundingCanceled: + closeType = lnrpc.ChannelCloseSummary_FUNDING_CANCELED + case channeldb.Abandoned: + closeType = lnrpc.ChannelCloseSummary_ABANDONED + } + + return &lnrpc.ChannelCloseSummary{ + Capacity: int64(dbChannel.Capacity), + RemotePubkey: nodeID, + CloseHeight: dbChannel.CloseHeight, + CloseType: closeType, + ChannelPoint: dbChannel.ChanPoint.String(), + ChanId: dbChannel.ShortChanID.ToUint64(), + SettledBalance: int64(dbChannel.SettledBalance), + TimeLockedBalance: int64(dbChannel.TimeLockedBalance), + ChainHash: dbChannel.ChainHash.String(), + ClosingTxHash: dbChannel.ClosingTXID.String(), + } +} + // savePayment saves a successfully completed payment to the database for // historical record keeping. func (r *rpcServer) savePayment(route *routing.Route, From cb26fd8a173054180b6a59577279fd0a30bbc5c8 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Sun, 21 Oct 2018 20:36:56 -0700 Subject: [PATCH 03/10] lnd: introduce the ChannelNotifier. This commit introduces the channel notifier which is a central source of active, inactive, and closed channel events. This notifier was originally intended to be used by the `SubscribeChannels` streaming RPC call, but can be used by any subsystem that needs to be notified on a channel becoming active, inactive or closed. It may also be extended in the future to support other types of notifications. --- channelnotifier/channelnotifier.go | 137 +++++++++++++++++++++++++++++ channelnotifier/log.go | 45 ++++++++++ log.go | 4 + server.go | 9 ++ 4 files changed, 195 insertions(+) create mode 100644 channelnotifier/channelnotifier.go create mode 100644 channelnotifier/log.go diff --git a/channelnotifier/channelnotifier.go b/channelnotifier/channelnotifier.go new file mode 100644 index 000000000..58a1bf1c9 --- /dev/null +++ b/channelnotifier/channelnotifier.go @@ -0,0 +1,137 @@ +package channelnotifier + +import ( + "sync/atomic" + + "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/subscribe" +) + +// ChannelNotifier is a subsystem which all active, inactive, and closed channel +// events pipe through. It takes subscriptions for its events, and whenever +// it receives a new event it notifies its subscribers over the proper channel. +type ChannelNotifier struct { + started uint32 + stopped uint32 + + ntfnServer *subscribe.Server + + chanDB *channeldb.DB +} + +// OpenChannelEvent represents a new event where a channel goes from pending +// open to open. +type OpenChannelEvent struct { + // Channel is the channel that has become open. + Channel *channeldb.OpenChannel +} + +// ActiveChannelEvent represents a new event where a channel becomes active. +type ActiveChannelEvent struct { + // ChannelPoint is the channelpoint for the newly active channel. + ChannelPoint *wire.OutPoint +} + +// InactiveChannelEvent represents a new event where a channel becomes inactive. +type InactiveChannelEvent struct { + // ChannelPoint is the channelpoint for the newly inactive channel. + ChannelPoint *wire.OutPoint +} + +// ClosedChannelEvent represents a new event where a channel becomes closed. +type ClosedChannelEvent struct { + // CloseSummary is the summary of the channel close that has occurred. + CloseSummary *channeldb.ChannelCloseSummary +} + +// New creates a new channel notifier. The ChannelNotifier gets channel +// events from peers and from the chain arbitrator, and dispatches them to +// its clients. +func New(chanDB *channeldb.DB) *ChannelNotifier { + return &ChannelNotifier{ + ntfnServer: subscribe.NewServer(), + chanDB: chanDB, + } +} + +// Start starts the ChannelNotifier and all goroutines it needs to carry out its task. +func (c *ChannelNotifier) Start() error { + if !atomic.CompareAndSwapUint32(&c.started, 0, 1) { + return nil + } + + log.Tracef("ChannelNotifier %v starting", c) + + if err := c.ntfnServer.Start(); err != nil { + return err + } + + return nil +} + +// Stop signals the notifier for a graceful shutdown. +func (c *ChannelNotifier) Stop() { + if !atomic.CompareAndSwapUint32(&c.stopped, 0, 1) { + return + } + + c.ntfnServer.Stop() +} + +// SubscribeChannelEvents returns a subscribe.Client that will receive updates +// any time the Server is made aware of a new event. +func (c *ChannelNotifier) SubscribeChannelEvents() (*subscribe.Client, error) { + return c.ntfnServer.Subscribe() +} + +// NotifyOpenChannelEvent notifies the channelEventNotifier goroutine that a +// channel has gone from pending open to open. +func (c *ChannelNotifier) NotifyOpenChannelEvent(chanPoint wire.OutPoint) { + + // Fetch the relevant channel from the database. + channel, err := c.chanDB.FetchChannel(chanPoint) + if err != nil { + log.Warnf("Unable to fetch open channel from the db: %v", err) + } + + // Send the open event to all channel event subscribers. + event := OpenChannelEvent{Channel: channel} + if err := c.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send open channel update: %v", err) + } +} + +// NotifyClosedChannelEvent notifies the channelEventNotifier goroutine that a +// channel has closed. +func (c *ChannelNotifier) NotifyClosedChannelEvent(chanPoint wire.OutPoint) { + // Fetch the relevant closed channel from the database. + closeSummary, err := c.chanDB.FetchClosedChannel(&chanPoint) + if err != nil { + log.Warnf("Unable to fetch closed channel summary from the db: %v", err) + } + + // Send the closed event to all channel event subscribers. + event := ClosedChannelEvent{CloseSummary: closeSummary} + if err := c.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send closed channel update: %v", err) + } +} + +// NotifyActiveChannelEvent notifies the channelEventNotifier goroutine that a +// channel is active. +func (c *ChannelNotifier) NotifyActiveChannelEvent(chanPoint wire.OutPoint) { + event := ActiveChannelEvent{ChannelPoint: &chanPoint} + if err := c.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send active channel update: %v", err) + } +} + +// NotifyInactiveChannelEvent notifies the channelEventNotifier goroutine that a +// channel is inactive. +func (c *ChannelNotifier) NotifyInactiveChannelEvent(chanPoint wire.OutPoint) { + event := InactiveChannelEvent{ChannelPoint: &chanPoint} + if err := c.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send inactive channel update: %v", err) + } +} diff --git a/channelnotifier/log.go b/channelnotifier/log.go new file mode 100644 index 000000000..f44bb9b24 --- /dev/null +++ b/channelnotifier/log.go @@ -0,0 +1,45 @@ +package channelnotifier + +import ( + "github.com/btcsuite/btclog" + "github.com/lightningnetwork/lnd/build" +) + +// log is a logger that is initialized with no output filters. This means the +// package will not perform any logging by default until the caller requests +// it. +var log btclog.Logger + +// The default amount of logging is none. +func init() { + UseLogger(build.NewSubLogger("CHNF", nil)) +} + +// DisableLog disables all library log output. Logging output is disabled by +// default until UseLogger is called. +func DisableLog() { + UseLogger(btclog.Disabled) +} + +// UseLogger uses a specified Logger to output package logging info. This +// should be used in preference to SetLogWriter if the caller is also using +// btclog. +func UseLogger(logger btclog.Logger) { + log = logger +} + +// logClosure is used to provide a closure over expensive logging operations so +// don't have to be performed when the logging level doesn't warrant it. +type logClosure func() string + +// String invokes the underlying function and returns the result. +func (c logClosure) String() string { + return c() +} + +// newLogClosure returns a new closure over a function that returns a string +// which itself provides a Stringer interface so that it can be used with the +// logging system. +func newLogClosure(c func() string) logClosure { + return logClosure(c) +} diff --git a/log.go b/log.go index b066485ae..4232dbde4 100644 --- a/log.go +++ b/log.go @@ -15,6 +15,7 @@ import ( "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/discovery" "github.com/lightningnetwork/lnd/htlcswitch" @@ -80,6 +81,7 @@ var ( wtwrLog = build.NewSubLogger("WTWR", backendLog.Logger) ntfrLog = build.NewSubLogger("NTFR", backendLog.Logger) irpcLog = build.NewSubLogger("IRPC", backendLog.Logger) + chnfLog = build.NewSubLogger("CHNF", backendLog.Logger) ) // Initialize package-global logger variables. @@ -105,6 +107,7 @@ func init() { watchtower.UseLogger(wtwrLog) chainrpc.UseLogger(ntfrLog) invoicesrpc.UseLogger(irpcLog) + channelnotifier.UseLogger(chnfLog) } // subsystemLoggers maps each subsystem identifier to its associated logger. @@ -136,6 +139,7 @@ var subsystemLoggers = map[string]btclog.Logger{ "WTWR": wtwrLog, "NTFR": ntfnLog, "IRPC": irpcLog, + "CHNF": chnfLog, } // initLogRotator initializes the logging rotator to write logs to logFile and diff --git a/server.go b/server.go index ed5608070..fa563762d 100644 --- a/server.go +++ b/server.go @@ -28,6 +28,7 @@ import ( "github.com/lightningnetwork/lnd/autopilot" "github.com/lightningnetwork/lnd/brontide" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/discovery" "github.com/lightningnetwork/lnd/htlcswitch" @@ -145,6 +146,8 @@ type server struct { invoices *invoices.InvoiceRegistry + channelNotifier *channelnotifier.ChannelNotifier + witnessBeacon contractcourt.WitnessBeacon breachArbiter *breachArbiter @@ -274,6 +277,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl, invoices: invoices.NewRegistry(chanDB, activeNetParams.Params), + channelNotifier: channelnotifier.New(chanDB), + identityPriv: privKey, nodeSigner: netann.NewNodeSigner(privKey), @@ -986,6 +991,9 @@ func (s *server) Start() error { if err := s.cc.chainNotifier.Start(); err != nil { return err } + if err := s.channelNotifier.Start(); err != nil { + return err + } if err := s.sphinx.Start(); err != nil { return err } @@ -1083,6 +1091,7 @@ func (s *server) Stop() error { s.authGossiper.Stop() s.chainArb.Stop() s.sweeper.Stop() + s.channelNotifier.Stop() s.cc.wallet.Shutdown() s.cc.chainView.Stop() s.connMgr.Stop() From 5405028948e8ac05d3b4dee1edc5ef1830503e0c Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Wed, 16 Jan 2019 14:35:30 -0800 Subject: [PATCH 04/10] fundingmanager: inform ChannelNotifier about newly open channels. --- fundingmanager.go | 8 ++++++++ fundingmanager_test.go | 5 +++-- server.go | 7 ++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index 2babcaad3..1eb45b65a 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -333,6 +333,10 @@ type fundingConfig struct { // flood us with very small channels that would never really be usable // due to fees. MinChanSize btcutil.Amount + + // NotifyOpenChannelEvent informs the ChannelNotifier when channels + // transition from pending open to open. + NotifyOpenChannelEvent func(wire.OutPoint) } // fundingManager acts as an orchestrator/bridge between the wallet's @@ -1939,6 +1943,10 @@ func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.Open return } + // Inform the ChannelNotifier that the channel has transitioned from + // pending open to open. + f.cfg.NotifyOpenChannelEvent(completeChan.FundingOutpoint) + // TODO(roasbeef): ideally persistent state update for chan above // should be abstracted diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 6231ff4dd..22d0d7109 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -353,8 +353,9 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, publTxChan <- txn return nil }, - ZombieSweeperInterval: 1 * time.Hour, - ReservationTimeout: 1 * time.Nanosecond, + ZombieSweeperInterval: 1 * time.Hour, + ReservationTimeout: 1 * time.Nanosecond, + NotifyOpenChannelEvent: func(wire.OutPoint) {}, }) if err != nil { t.Fatalf("failed creating fundingManager: %v", err) diff --git a/server.go b/server.go index fa563762d..2d32239c2 100644 --- a/server.go +++ b/server.go @@ -927,9 +927,10 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl, // channel bandwidth. return uint16(input.MaxHTLCNumber / 2) }, - ZombieSweeperInterval: 1 * time.Minute, - ReservationTimeout: 10 * time.Minute, - MinChanSize: btcutil.Amount(cfg.MinChanSize), + ZombieSweeperInterval: 1 * time.Minute, + ReservationTimeout: 10 * time.Minute, + MinChanSize: btcutil.Amount(cfg.MinChanSize), + NotifyOpenChannelEvent: s.channelNotifier.NotifyOpenChannelEvent, }) if err != nil { return nil, err From f6cffa8f4b3ce238fc7ce347b631f913c33da92b Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Tue, 30 Oct 2018 02:36:27 -0700 Subject: [PATCH 05/10] htlcswitch/link: add ChannelPoint() to retrieve the channel outpoint. This function will be used in the switch to retrieve the channel point for a link, allowing the switch to retrieve individual channels from the database. --- htlcswitch/interfaces.go | 4 ++++ htlcswitch/link.go | 7 +++++++ htlcswitch/mock.go | 1 + 3 files changed, 12 insertions(+) diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go index 8614dfafa..c0b273fe6 100644 --- a/htlcswitch/interfaces.go +++ b/htlcswitch/interfaces.go @@ -1,6 +1,7 @@ package htlcswitch import ( + "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lntypes" @@ -58,6 +59,9 @@ type ChannelLink interface { // possible). HandleChannelUpdate(lnwire.Message) + // ChannelPoint returns the channel outpoint for the channel link. + ChannelPoint() *wire.OutPoint + // ChanID returns the channel ID for the channel link. The channel ID // is a more compact representation of a channel's full outpoint. ChanID() lnwire.ChannelID diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 87b4ebe5a..a6ebe502e 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -9,6 +9,7 @@ import ( "sync/atomic" "time" + "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" @@ -1743,6 +1744,12 @@ func (l *channelLink) Peer() lnpeer.Peer { return l.cfg.Peer } +// ChannelPoint returns the channel outpoint for the channel link. +// NOTE: Part of the ChannelLink interface. +func (l *channelLink) ChannelPoint() *wire.OutPoint { + return l.channel.ChannelPoint() +} + // ShortChanID returns the short channel ID for the channel link. The short // channel ID encodes the exact location in the main chain that the original // funding output can be found. diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index c9b44d5ce..4ac8c9471 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -673,6 +673,7 @@ func (f *mockChannelLink) ChanID() lnwire.ChannelID { return func (f *mockChannelLink) ShortChanID() lnwire.ShortChannelID { return f.shortChanID } func (f *mockChannelLink) Bandwidth() lnwire.MilliSatoshi { return 99999999 } func (f *mockChannelLink) Peer() lnpeer.Peer { return f.peer } +func (f *mockChannelLink) ChannelPoint() *wire.OutPoint { return &wire.OutPoint{} } func (f *mockChannelLink) Stop() {} func (f *mockChannelLink) EligibleToForward() bool { return f.eligible } func (f *mockChannelLink) setLiveShortChanID(sid lnwire.ShortChannelID) { f.shortChanID = sid } From bdd8ce14c9a6e0d9e5103d4d6ff1389420b40d32 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Tue, 22 Jan 2019 17:45:51 -0800 Subject: [PATCH 06/10] switch: notify the ChannelNotifier on newly active/inactive channels. --- htlcswitch/mock.go | 8 +++++--- htlcswitch/switch.go | 13 +++++++++++++ server.go | 2 ++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 4ac8c9471..9f35b9cd5 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -162,9 +162,11 @@ func initSwitchWithDB(startingHeight uint32, db *channeldb.DB) (*Switch, error) FetchLastChannelUpdate: func(lnwire.ShortChannelID) (*lnwire.ChannelUpdate, error) { return nil, nil }, - Notifier: &mockNotifier{}, - FwdEventTicker: ticker.MockNew(DefaultFwdEventInterval), - LogEventTicker: ticker.MockNew(DefaultLogInterval), + Notifier: &mockNotifier{}, + FwdEventTicker: ticker.MockNew(DefaultFwdEventInterval), + LogEventTicker: ticker.MockNew(DefaultLogInterval), + NotifyActiveChannel: func(wire.OutPoint) {}, + NotifyInactiveChannel: func(wire.OutPoint) {}, } return New(cfg, startingHeight) diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 0968cba50..63e19f33d 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -175,6 +175,11 @@ type Config struct { // LogEventTicker is a signal instructing the htlcswitch to log // aggregate stats about it's forwarding during the last interval. LogEventTicker ticker.Ticker + + // NotifyActiveChannel and NotifyInactiveChannel allow the link to tell + // the ChannelNotifier when channels become active and inactive. + NotifyActiveChannel func(wire.OutPoint) + NotifyInactiveChannel func(wire.OutPoint) } // Switch is the central messaging bus for all incoming/outgoing HTLCs. @@ -1956,6 +1961,11 @@ func (s *Switch) addLiveLink(link ChannelLink) { s.interfaceIndex[peerPub] = make(map[lnwire.ChannelID]ChannelLink) } s.interfaceIndex[peerPub][link.ChanID()] = link + + // Inform the channel notifier if the link has become active. + if link.EligibleToForward() { + s.cfg.NotifyActiveChannel(*link.ChannelPoint()) + } } // GetLink is used to initiate the handling of the get link command. The @@ -2031,6 +2041,9 @@ func (s *Switch) removeLink(chanID lnwire.ChannelID) ChannelLink { return nil } + // Inform the Channel Notifier about the link becoming inactive. + s.cfg.NotifyInactiveChannel(*link.ChannelPoint()) + // Remove the channel from live link indexes. delete(s.pendingLinkIndex, link.ChanID()) delete(s.linkIndex, link.ChanID()) diff --git a/server.go b/server.go index 2d32239c2..3be02cddc 100644 --- a/server.go +++ b/server.go @@ -362,6 +362,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl, htlcswitch.DefaultFwdEventInterval), LogEventTicker: ticker.New( htlcswitch.DefaultLogInterval), + NotifyActiveChannel: s.channelNotifier.NotifyActiveChannelEvent, + NotifyInactiveChannel: s.channelNotifier.NotifyInactiveChannelEvent, }, uint32(currentHeight)) if err != nil { return nil, err From 10090a978d4346cb90dc0cc0017ca75ff8cbd18c Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Sun, 21 Oct 2018 20:40:02 -0700 Subject: [PATCH 07/10] contractcourt/chain_arbitrator: notify the ChannelNotifier on newly closed channels. --- contractcourt/chain_arbitrator.go | 26 +++++++++++++++----------- server.go | 5 +++-- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index a9c772343..76be78731 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -141,6 +141,10 @@ type ChainArbitratorConfig struct { // the given payment hash. ErrInvoiceNotFound is returned if an invoice // is not found. SettleInvoice func(lntypes.Hash, lnwire.MilliSatoshi) error + + // NotifyClosedChannel is a function closure that the ChainArbitrator + // will use to notify the ChannelNotifier about a newly closed channel. + NotifyClosedChannel func(wire.OutPoint) } // ChainArbitrator is a sub-system that oversees the on-chain resolution of all @@ -245,10 +249,16 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel, return chanMachine.ForceClose() }, MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted, - MarkChannelClosed: channel.CloseChannel, - IsPendingClose: false, - ChainArbitratorConfig: c.cfg, - ChainEvents: chanEvents, + MarkChannelClosed: func(summary *channeldb.ChannelCloseSummary) error { + if err := channel.CloseChannel(summary); err != nil { + return err + } + c.cfg.NotifyClosedChannel(summary.ChanPoint) + return nil + }, + IsPendingClose: false, + ChainArbitratorConfig: c.cfg, + ChainEvents: chanEvents, } // The final component needed is an arbitrator log that the arbitrator @@ -719,13 +729,7 @@ func (c *ChainArbitrator) WatchNewChannel(newChan *channeldb.OpenChannel) error // SubscribeChannelEvents returns a new active subscription for the set of // possible on-chain events for a particular channel. The struct can be used by // callers to be notified whenever an event that changes the state of the -// channel on-chain occurs. If syncDispatch is true, then the sender of the -// notification will wait until an error is sent over the ProcessACK before -// modifying any database state. This allows callers to request a reliable hand -// off. -// -// TODO(roasbeef): can be used later to provide RPC hook for all channel -// lifetimes +// channel on-chain occurs. func (c *ChainArbitrator) SubscribeChannelEvents( chanPoint wire.OutPoint) (*ChainEventSubscription, error) { diff --git a/server.go b/server.go index 3be02cddc..38df7e348 100644 --- a/server.go +++ b/server.go @@ -742,8 +742,9 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl, DisableChannel: func(op wire.OutPoint) error { return s.announceChanStatus(op, true) }, - Sweeper: s.sweeper, - SettleInvoice: s.invoices.SettleInvoice, + Sweeper: s.sweeper, + SettleInvoice: s.invoices.SettleInvoice, + NotifyClosedChannel: s.channelNotifier.NotifyClosedChannelEvent, }, chanDB) s.breachArbiter = newBreachArbiter(&BreachConfig{ From 8b388b1301d74dbe7d42130ebc24dff1bdcfa213 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Tue, 22 Jan 2019 18:28:27 -0800 Subject: [PATCH 08/10] lnrpc: add SubscribeChannels RPC & relevant messages to RPC protos. --- lnrpc/autopilotrpc/autopilot.pb.go | 18 +- lnrpc/rpc.pb.go | 1471 +++++++++++++++++----------- lnrpc/rpc.proto | 29 + lnrpc/rpc.swagger.json | 30 + 4 files changed, 984 insertions(+), 564 deletions(-) diff --git a/lnrpc/autopilotrpc/autopilot.pb.go b/lnrpc/autopilotrpc/autopilot.pb.go index c3099d4be..c9fdda23d 100644 --- a/lnrpc/autopilotrpc/autopilot.pb.go +++ b/lnrpc/autopilotrpc/autopilot.pb.go @@ -33,7 +33,7 @@ func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_autopilot_52f30cf4d0055211, []int{0} + return fileDescriptor_autopilot_7db7978f022d4696, []int{0} } func (m *StatusRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StatusRequest.Unmarshal(m, b) @@ -65,7 +65,7 @@ func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_autopilot_52f30cf4d0055211, []int{1} + return fileDescriptor_autopilot_7db7978f022d4696, []int{1} } func (m *StatusResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StatusResponse.Unmarshal(m, b) @@ -104,7 +104,7 @@ func (m *ModifyStatusRequest) Reset() { *m = ModifyStatusRequest{} } func (m *ModifyStatusRequest) String() string { return proto.CompactTextString(m) } func (*ModifyStatusRequest) ProtoMessage() {} func (*ModifyStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_autopilot_52f30cf4d0055211, []int{2} + return fileDescriptor_autopilot_7db7978f022d4696, []int{2} } func (m *ModifyStatusRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ModifyStatusRequest.Unmarshal(m, b) @@ -141,7 +141,7 @@ func (m *ModifyStatusResponse) Reset() { *m = ModifyStatusResponse{} } func (m *ModifyStatusResponse) String() string { return proto.CompactTextString(m) } func (*ModifyStatusResponse) ProtoMessage() {} func (*ModifyStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_autopilot_52f30cf4d0055211, []int{3} + return fileDescriptor_autopilot_7db7978f022d4696, []int{3} } func (m *ModifyStatusResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ModifyStatusResponse.Unmarshal(m, b) @@ -172,7 +172,7 @@ func (m *QueryScoresRequest) Reset() { *m = QueryScoresRequest{} } func (m *QueryScoresRequest) String() string { return proto.CompactTextString(m) } func (*QueryScoresRequest) ProtoMessage() {} func (*QueryScoresRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_autopilot_52f30cf4d0055211, []int{4} + return fileDescriptor_autopilot_7db7978f022d4696, []int{4} } func (m *QueryScoresRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryScoresRequest.Unmarshal(m, b) @@ -210,7 +210,7 @@ func (m *QueryScoresResponse) Reset() { *m = QueryScoresResponse{} } func (m *QueryScoresResponse) String() string { return proto.CompactTextString(m) } func (*QueryScoresResponse) ProtoMessage() {} func (*QueryScoresResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_autopilot_52f30cf4d0055211, []int{5} + return fileDescriptor_autopilot_7db7978f022d4696, []int{5} } func (m *QueryScoresResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryScoresResponse.Unmarshal(m, b) @@ -249,7 +249,7 @@ func (m *QueryScoresResponse_HeuristicResult) Reset() { *m = QueryScores func (m *QueryScoresResponse_HeuristicResult) String() string { return proto.CompactTextString(m) } func (*QueryScoresResponse_HeuristicResult) ProtoMessage() {} func (*QueryScoresResponse_HeuristicResult) Descriptor() ([]byte, []int) { - return fileDescriptor_autopilot_52f30cf4d0055211, []int{5, 0} + return fileDescriptor_autopilot_7db7978f022d4696, []int{5, 0} } func (m *QueryScoresResponse_HeuristicResult) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryScoresResponse_HeuristicResult.Unmarshal(m, b) @@ -451,10 +451,10 @@ var _Autopilot_serviceDesc = grpc.ServiceDesc{ } func init() { - proto.RegisterFile("autopilotrpc/autopilot.proto", fileDescriptor_autopilot_52f30cf4d0055211) + proto.RegisterFile("autopilotrpc/autopilot.proto", fileDescriptor_autopilot_7db7978f022d4696) } -var fileDescriptor_autopilot_52f30cf4d0055211 = []byte{ +var fileDescriptor_autopilot_7db7978f022d4696 = []byte{ // 391 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x4d, 0xaf, 0xd2, 0x40, 0x14, 0xcd, 0x94, 0x58, 0xec, 0x05, 0xc5, 0x0c, 0x84, 0x34, 0x95, 0x45, 0xe9, 0xaa, 0x1b, 0xdb, diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 4919f0384..a13442923 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -49,7 +49,7 @@ func (x AddressType) String() string { return proto.EnumName(AddressType_name, int32(x)) } func (AddressType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{0} + return fileDescriptor_rpc_3a8b115cef624d58, []int{0} } type ChannelCloseSummary_ClosureType int32 @@ -84,7 +84,36 @@ func (x ChannelCloseSummary_ClosureType) String() string { return proto.EnumName(ChannelCloseSummary_ClosureType_name, int32(x)) } func (ChannelCloseSummary_ClosureType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{39, 0} + return fileDescriptor_rpc_3a8b115cef624d58, []int{39, 0} +} + +type ChannelEventUpdate_UpdateType int32 + +const ( + ChannelEventUpdate_OPEN_CHANNEL ChannelEventUpdate_UpdateType = 0 + ChannelEventUpdate_CLOSED_CHANNEL ChannelEventUpdate_UpdateType = 1 + ChannelEventUpdate_ACTIVE_CHANNEL ChannelEventUpdate_UpdateType = 2 + ChannelEventUpdate_INACTIVE_CHANNEL ChannelEventUpdate_UpdateType = 3 +) + +var ChannelEventUpdate_UpdateType_name = map[int32]string{ + 0: "OPEN_CHANNEL", + 1: "CLOSED_CHANNEL", + 2: "ACTIVE_CHANNEL", + 3: "INACTIVE_CHANNEL", +} +var ChannelEventUpdate_UpdateType_value = map[string]int32{ + "OPEN_CHANNEL": 0, + "CLOSED_CHANNEL": 1, + "ACTIVE_CHANNEL": 2, + "INACTIVE_CHANNEL": 3, +} + +func (x ChannelEventUpdate_UpdateType) String() string { + return proto.EnumName(ChannelEventUpdate_UpdateType_name, int32(x)) +} +func (ChannelEventUpdate_UpdateType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_rpc_3a8b115cef624d58, []int{60, 0} } type Invoice_InvoiceState int32 @@ -107,7 +136,7 @@ func (x Invoice_InvoiceState) String() string { return proto.EnumName(Invoice_InvoiceState_name, int32(x)) } func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{87, 0} + return fileDescriptor_rpc_3a8b115cef624d58, []int{89, 0} } type GenSeedRequest struct { @@ -128,7 +157,7 @@ func (m *GenSeedRequest) Reset() { *m = GenSeedRequest{} } func (m *GenSeedRequest) String() string { return proto.CompactTextString(m) } func (*GenSeedRequest) ProtoMessage() {} func (*GenSeedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{0} + return fileDescriptor_rpc_3a8b115cef624d58, []int{0} } func (m *GenSeedRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GenSeedRequest.Unmarshal(m, b) @@ -183,7 +212,7 @@ func (m *GenSeedResponse) Reset() { *m = GenSeedResponse{} } func (m *GenSeedResponse) String() string { return proto.CompactTextString(m) } func (*GenSeedResponse) ProtoMessage() {} func (*GenSeedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{1} + return fileDescriptor_rpc_3a8b115cef624d58, []int{1} } func (m *GenSeedResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GenSeedResponse.Unmarshal(m, b) @@ -248,7 +277,7 @@ func (m *InitWalletRequest) Reset() { *m = InitWalletRequest{} } func (m *InitWalletRequest) String() string { return proto.CompactTextString(m) } func (*InitWalletRequest) ProtoMessage() {} func (*InitWalletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{2} + return fileDescriptor_rpc_3a8b115cef624d58, []int{2} } func (m *InitWalletRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InitWalletRequest.Unmarshal(m, b) @@ -306,7 +335,7 @@ func (m *InitWalletResponse) Reset() { *m = InitWalletResponse{} } func (m *InitWalletResponse) String() string { return proto.CompactTextString(m) } func (*InitWalletResponse) ProtoMessage() {} func (*InitWalletResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{3} + return fileDescriptor_rpc_3a8b115cef624d58, []int{3} } func (m *InitWalletResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InitWalletResponse.Unmarshal(m, b) @@ -348,7 +377,7 @@ func (m *UnlockWalletRequest) Reset() { *m = UnlockWalletRequest{} } func (m *UnlockWalletRequest) String() string { return proto.CompactTextString(m) } func (*UnlockWalletRequest) ProtoMessage() {} func (*UnlockWalletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{4} + return fileDescriptor_rpc_3a8b115cef624d58, []int{4} } func (m *UnlockWalletRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UnlockWalletRequest.Unmarshal(m, b) @@ -392,7 +421,7 @@ func (m *UnlockWalletResponse) Reset() { *m = UnlockWalletResponse{} } func (m *UnlockWalletResponse) String() string { return proto.CompactTextString(m) } func (*UnlockWalletResponse) ProtoMessage() {} func (*UnlockWalletResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{5} + return fileDescriptor_rpc_3a8b115cef624d58, []int{5} } func (m *UnlockWalletResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UnlockWalletResponse.Unmarshal(m, b) @@ -430,7 +459,7 @@ func (m *ChangePasswordRequest) Reset() { *m = ChangePasswordRequest{} } func (m *ChangePasswordRequest) String() string { return proto.CompactTextString(m) } func (*ChangePasswordRequest) ProtoMessage() {} func (*ChangePasswordRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{6} + return fileDescriptor_rpc_3a8b115cef624d58, []int{6} } func (m *ChangePasswordRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChangePasswordRequest.Unmarshal(m, b) @@ -474,7 +503,7 @@ func (m *ChangePasswordResponse) Reset() { *m = ChangePasswordResponse{} func (m *ChangePasswordResponse) String() string { return proto.CompactTextString(m) } func (*ChangePasswordResponse) ProtoMessage() {} func (*ChangePasswordResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{7} + return fileDescriptor_rpc_3a8b115cef624d58, []int{7} } func (m *ChangePasswordResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChangePasswordResponse.Unmarshal(m, b) @@ -516,7 +545,7 @@ func (m *Utxo) Reset() { *m = Utxo{} } func (m *Utxo) String() string { return proto.CompactTextString(m) } func (*Utxo) ProtoMessage() {} func (*Utxo) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{8} + return fileDescriptor_rpc_3a8b115cef624d58, []int{8} } func (m *Utxo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Utxo.Unmarshal(m, b) @@ -604,7 +633,7 @@ func (m *Transaction) Reset() { *m = Transaction{} } func (m *Transaction) String() string { return proto.CompactTextString(m) } func (*Transaction) ProtoMessage() {} func (*Transaction) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{9} + return fileDescriptor_rpc_3a8b115cef624d58, []int{9} } func (m *Transaction) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Transaction.Unmarshal(m, b) @@ -690,7 +719,7 @@ func (m *GetTransactionsRequest) Reset() { *m = GetTransactionsRequest{} func (m *GetTransactionsRequest) String() string { return proto.CompactTextString(m) } func (*GetTransactionsRequest) ProtoMessage() {} func (*GetTransactionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{10} + return fileDescriptor_rpc_3a8b115cef624d58, []int{10} } func (m *GetTransactionsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetTransactionsRequest.Unmarshal(m, b) @@ -722,7 +751,7 @@ func (m *TransactionDetails) Reset() { *m = TransactionDetails{} } func (m *TransactionDetails) String() string { return proto.CompactTextString(m) } func (*TransactionDetails) ProtoMessage() {} func (*TransactionDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{11} + return fileDescriptor_rpc_3a8b115cef624d58, []int{11} } func (m *TransactionDetails) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransactionDetails.Unmarshal(m, b) @@ -763,7 +792,7 @@ func (m *FeeLimit) Reset() { *m = FeeLimit{} } func (m *FeeLimit) String() string { return proto.CompactTextString(m) } func (*FeeLimit) ProtoMessage() {} func (*FeeLimit) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{12} + return fileDescriptor_rpc_3a8b115cef624d58, []int{12} } func (m *FeeLimit) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeLimit.Unmarshal(m, b) @@ -919,7 +948,7 @@ func (m *SendRequest) Reset() { *m = SendRequest{} } func (m *SendRequest) String() string { return proto.CompactTextString(m) } func (*SendRequest) ProtoMessage() {} func (*SendRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{13} + return fileDescriptor_rpc_3a8b115cef624d58, []int{13} } func (m *SendRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendRequest.Unmarshal(m, b) @@ -1009,7 +1038,7 @@ func (m *SendResponse) Reset() { *m = SendResponse{} } func (m *SendResponse) String() string { return proto.CompactTextString(m) } func (*SendResponse) ProtoMessage() {} func (*SendResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{14} + return fileDescriptor_rpc_3a8b115cef624d58, []int{14} } func (m *SendResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendResponse.Unmarshal(m, b) @@ -1079,7 +1108,7 @@ func (m *SendToRouteRequest) Reset() { *m = SendToRouteRequest{} } func (m *SendToRouteRequest) String() string { return proto.CompactTextString(m) } func (*SendToRouteRequest) ProtoMessage() {} func (*SendToRouteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{15} + return fileDescriptor_rpc_3a8b115cef624d58, []int{15} } func (m *SendToRouteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendToRouteRequest.Unmarshal(m, b) @@ -1144,7 +1173,7 @@ func (m *ChannelPoint) Reset() { *m = ChannelPoint{} } func (m *ChannelPoint) String() string { return proto.CompactTextString(m) } func (*ChannelPoint) ProtoMessage() {} func (*ChannelPoint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{16} + return fileDescriptor_rpc_3a8b115cef624d58, []int{16} } func (m *ChannelPoint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelPoint.Unmarshal(m, b) @@ -1290,7 +1319,7 @@ func (m *OutPoint) Reset() { *m = OutPoint{} } func (m *OutPoint) String() string { return proto.CompactTextString(m) } func (*OutPoint) ProtoMessage() {} func (*OutPoint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{17} + return fileDescriptor_rpc_3a8b115cef624d58, []int{17} } func (m *OutPoint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OutPoint.Unmarshal(m, b) @@ -1345,7 +1374,7 @@ func (m *LightningAddress) Reset() { *m = LightningAddress{} } func (m *LightningAddress) String() string { return proto.CompactTextString(m) } func (*LightningAddress) ProtoMessage() {} func (*LightningAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{18} + return fileDescriptor_rpc_3a8b115cef624d58, []int{18} } func (m *LightningAddress) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LightningAddress.Unmarshal(m, b) @@ -1395,7 +1424,7 @@ func (m *SendManyRequest) Reset() { *m = SendManyRequest{} } func (m *SendManyRequest) String() string { return proto.CompactTextString(m) } func (*SendManyRequest) ProtoMessage() {} func (*SendManyRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{19} + return fileDescriptor_rpc_3a8b115cef624d58, []int{19} } func (m *SendManyRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendManyRequest.Unmarshal(m, b) @@ -1448,7 +1477,7 @@ func (m *SendManyResponse) Reset() { *m = SendManyResponse{} } func (m *SendManyResponse) String() string { return proto.CompactTextString(m) } func (*SendManyResponse) ProtoMessage() {} func (*SendManyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{20} + return fileDescriptor_rpc_3a8b115cef624d58, []int{20} } func (m *SendManyResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendManyResponse.Unmarshal(m, b) @@ -1498,7 +1527,7 @@ func (m *SendCoinsRequest) Reset() { *m = SendCoinsRequest{} } func (m *SendCoinsRequest) String() string { return proto.CompactTextString(m) } func (*SendCoinsRequest) ProtoMessage() {} func (*SendCoinsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{21} + return fileDescriptor_rpc_3a8b115cef624d58, []int{21} } func (m *SendCoinsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendCoinsRequest.Unmarshal(m, b) @@ -1565,7 +1594,7 @@ func (m *SendCoinsResponse) Reset() { *m = SendCoinsResponse{} } func (m *SendCoinsResponse) String() string { return proto.CompactTextString(m) } func (*SendCoinsResponse) ProtoMessage() {} func (*SendCoinsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{22} + return fileDescriptor_rpc_3a8b115cef624d58, []int{22} } func (m *SendCoinsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendCoinsResponse.Unmarshal(m, b) @@ -1606,7 +1635,7 @@ func (m *ListUnspentRequest) Reset() { *m = ListUnspentRequest{} } func (m *ListUnspentRequest) String() string { return proto.CompactTextString(m) } func (*ListUnspentRequest) ProtoMessage() {} func (*ListUnspentRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{23} + return fileDescriptor_rpc_3a8b115cef624d58, []int{23} } func (m *ListUnspentRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListUnspentRequest.Unmarshal(m, b) @@ -1652,7 +1681,7 @@ func (m *ListUnspentResponse) Reset() { *m = ListUnspentResponse{} } func (m *ListUnspentResponse) String() string { return proto.CompactTextString(m) } func (*ListUnspentResponse) ProtoMessage() {} func (*ListUnspentResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{24} + return fileDescriptor_rpc_3a8b115cef624d58, []int{24} } func (m *ListUnspentResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListUnspentResponse.Unmarshal(m, b) @@ -1691,7 +1720,7 @@ func (m *NewAddressRequest) Reset() { *m = NewAddressRequest{} } func (m *NewAddressRequest) String() string { return proto.CompactTextString(m) } func (*NewAddressRequest) ProtoMessage() {} func (*NewAddressRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{25} + return fileDescriptor_rpc_3a8b115cef624d58, []int{25} } func (m *NewAddressRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NewAddressRequest.Unmarshal(m, b) @@ -1730,7 +1759,7 @@ func (m *NewAddressResponse) Reset() { *m = NewAddressResponse{} } func (m *NewAddressResponse) String() string { return proto.CompactTextString(m) } func (*NewAddressResponse) ProtoMessage() {} func (*NewAddressResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{26} + return fileDescriptor_rpc_3a8b115cef624d58, []int{26} } func (m *NewAddressResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NewAddressResponse.Unmarshal(m, b) @@ -1769,7 +1798,7 @@ func (m *SignMessageRequest) Reset() { *m = SignMessageRequest{} } func (m *SignMessageRequest) String() string { return proto.CompactTextString(m) } func (*SignMessageRequest) ProtoMessage() {} func (*SignMessageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{27} + return fileDescriptor_rpc_3a8b115cef624d58, []int{27} } func (m *SignMessageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignMessageRequest.Unmarshal(m, b) @@ -1808,7 +1837,7 @@ func (m *SignMessageResponse) Reset() { *m = SignMessageResponse{} } func (m *SignMessageResponse) String() string { return proto.CompactTextString(m) } func (*SignMessageResponse) ProtoMessage() {} func (*SignMessageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{28} + return fileDescriptor_rpc_3a8b115cef624d58, []int{28} } func (m *SignMessageResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignMessageResponse.Unmarshal(m, b) @@ -1849,7 +1878,7 @@ func (m *VerifyMessageRequest) Reset() { *m = VerifyMessageRequest{} } func (m *VerifyMessageRequest) String() string { return proto.CompactTextString(m) } func (*VerifyMessageRequest) ProtoMessage() {} func (*VerifyMessageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{29} + return fileDescriptor_rpc_3a8b115cef624d58, []int{29} } func (m *VerifyMessageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VerifyMessageRequest.Unmarshal(m, b) @@ -1897,7 +1926,7 @@ func (m *VerifyMessageResponse) Reset() { *m = VerifyMessageResponse{} } func (m *VerifyMessageResponse) String() string { return proto.CompactTextString(m) } func (*VerifyMessageResponse) ProtoMessage() {} func (*VerifyMessageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{30} + return fileDescriptor_rpc_3a8b115cef624d58, []int{30} } func (m *VerifyMessageResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VerifyMessageResponse.Unmarshal(m, b) @@ -1946,7 +1975,7 @@ func (m *ConnectPeerRequest) Reset() { *m = ConnectPeerRequest{} } func (m *ConnectPeerRequest) String() string { return proto.CompactTextString(m) } func (*ConnectPeerRequest) ProtoMessage() {} func (*ConnectPeerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{31} + return fileDescriptor_rpc_3a8b115cef624d58, []int{31} } func (m *ConnectPeerRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConnectPeerRequest.Unmarshal(m, b) @@ -1990,7 +2019,7 @@ func (m *ConnectPeerResponse) Reset() { *m = ConnectPeerResponse{} } func (m *ConnectPeerResponse) String() string { return proto.CompactTextString(m) } func (*ConnectPeerResponse) ProtoMessage() {} func (*ConnectPeerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{32} + return fileDescriptor_rpc_3a8b115cef624d58, []int{32} } func (m *ConnectPeerResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConnectPeerResponse.Unmarshal(m, b) @@ -2022,7 +2051,7 @@ func (m *DisconnectPeerRequest) Reset() { *m = DisconnectPeerRequest{} } func (m *DisconnectPeerRequest) String() string { return proto.CompactTextString(m) } func (*DisconnectPeerRequest) ProtoMessage() {} func (*DisconnectPeerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{33} + return fileDescriptor_rpc_3a8b115cef624d58, []int{33} } func (m *DisconnectPeerRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DisconnectPeerRequest.Unmarshal(m, b) @@ -2059,7 +2088,7 @@ func (m *DisconnectPeerResponse) Reset() { *m = DisconnectPeerResponse{} func (m *DisconnectPeerResponse) String() string { return proto.CompactTextString(m) } func (*DisconnectPeerResponse) ProtoMessage() {} func (*DisconnectPeerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{34} + return fileDescriptor_rpc_3a8b115cef624d58, []int{34} } func (m *DisconnectPeerResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DisconnectPeerResponse.Unmarshal(m, b) @@ -2093,7 +2122,7 @@ func (m *HTLC) Reset() { *m = HTLC{} } func (m *HTLC) String() string { return proto.CompactTextString(m) } func (*HTLC) ProtoMessage() {} func (*HTLC) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{35} + return fileDescriptor_rpc_3a8b115cef624d58, []int{35} } func (m *HTLC) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HTLC.Unmarshal(m, b) @@ -2207,7 +2236,7 @@ func (m *Channel) Reset() { *m = Channel{} } func (m *Channel) String() string { return proto.CompactTextString(m) } func (*Channel) ProtoMessage() {} func (*Channel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{36} + return fileDescriptor_rpc_3a8b115cef624d58, []int{36} } func (m *Channel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Channel.Unmarshal(m, b) @@ -2367,7 +2396,7 @@ func (m *ListChannelsRequest) Reset() { *m = ListChannelsRequest{} } func (m *ListChannelsRequest) String() string { return proto.CompactTextString(m) } func (*ListChannelsRequest) ProtoMessage() {} func (*ListChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{37} + return fileDescriptor_rpc_3a8b115cef624d58, []int{37} } func (m *ListChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListChannelsRequest.Unmarshal(m, b) @@ -2427,7 +2456,7 @@ func (m *ListChannelsResponse) Reset() { *m = ListChannelsResponse{} } func (m *ListChannelsResponse) String() string { return proto.CompactTextString(m) } func (*ListChannelsResponse) ProtoMessage() {} func (*ListChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{38} + return fileDescriptor_rpc_3a8b115cef624d58, []int{38} } func (m *ListChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListChannelsResponse.Unmarshal(m, b) @@ -2484,7 +2513,7 @@ func (m *ChannelCloseSummary) Reset() { *m = ChannelCloseSummary{} } func (m *ChannelCloseSummary) String() string { return proto.CompactTextString(m) } func (*ChannelCloseSummary) ProtoMessage() {} func (*ChannelCloseSummary) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{39} + return fileDescriptor_rpc_3a8b115cef624d58, []int{39} } func (m *ChannelCloseSummary) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelCloseSummary.Unmarshal(m, b) @@ -2590,7 +2619,7 @@ func (m *ClosedChannelsRequest) Reset() { *m = ClosedChannelsRequest{} } func (m *ClosedChannelsRequest) String() string { return proto.CompactTextString(m) } func (*ClosedChannelsRequest) ProtoMessage() {} func (*ClosedChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{40} + return fileDescriptor_rpc_3a8b115cef624d58, []int{40} } func (m *ClosedChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelsRequest.Unmarshal(m, b) @@ -2663,7 +2692,7 @@ func (m *ClosedChannelsResponse) Reset() { *m = ClosedChannelsResponse{} func (m *ClosedChannelsResponse) String() string { return proto.CompactTextString(m) } func (*ClosedChannelsResponse) ProtoMessage() {} func (*ClosedChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{41} + return fileDescriptor_rpc_3a8b115cef624d58, []int{41} } func (m *ClosedChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelsResponse.Unmarshal(m, b) @@ -2716,7 +2745,7 @@ func (m *Peer) Reset() { *m = Peer{} } func (m *Peer) String() string { return proto.CompactTextString(m) } func (*Peer) ProtoMessage() {} func (*Peer) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{42} + return fileDescriptor_rpc_3a8b115cef624d58, []int{42} } func (m *Peer) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Peer.Unmarshal(m, b) @@ -2802,7 +2831,7 @@ func (m *ListPeersRequest) Reset() { *m = ListPeersRequest{} } func (m *ListPeersRequest) String() string { return proto.CompactTextString(m) } func (*ListPeersRequest) ProtoMessage() {} func (*ListPeersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{43} + return fileDescriptor_rpc_3a8b115cef624d58, []int{43} } func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPeersRequest.Unmarshal(m, b) @@ -2834,7 +2863,7 @@ func (m *ListPeersResponse) Reset() { *m = ListPeersResponse{} } func (m *ListPeersResponse) String() string { return proto.CompactTextString(m) } func (*ListPeersResponse) ProtoMessage() {} func (*ListPeersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{44} + return fileDescriptor_rpc_3a8b115cef624d58, []int{44} } func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPeersResponse.Unmarshal(m, b) @@ -2871,7 +2900,7 @@ func (m *GetInfoRequest) Reset() { *m = GetInfoRequest{} } func (m *GetInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetInfoRequest) ProtoMessage() {} func (*GetInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{45} + return fileDescriptor_rpc_3a8b115cef624d58, []int{45} } func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetInfoRequest.Unmarshal(m, b) @@ -2931,7 +2960,7 @@ func (m *GetInfoResponse) Reset() { *m = GetInfoResponse{} } func (m *GetInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetInfoResponse) ProtoMessage() {} func (*GetInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{46} + return fileDescriptor_rpc_3a8b115cef624d58, []int{46} } func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetInfoResponse.Unmarshal(m, b) @@ -3064,7 +3093,7 @@ func (m *Chain) Reset() { *m = Chain{} } func (m *Chain) String() string { return proto.CompactTextString(m) } func (*Chain) ProtoMessage() {} func (*Chain) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{47} + return fileDescriptor_rpc_3a8b115cef624d58, []int{47} } func (m *Chain) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Chain.Unmarshal(m, b) @@ -3111,7 +3140,7 @@ func (m *ConfirmationUpdate) Reset() { *m = ConfirmationUpdate{} } func (m *ConfirmationUpdate) String() string { return proto.CompactTextString(m) } func (*ConfirmationUpdate) ProtoMessage() {} func (*ConfirmationUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{48} + return fileDescriptor_rpc_3a8b115cef624d58, []int{48} } func (m *ConfirmationUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConfirmationUpdate.Unmarshal(m, b) @@ -3163,7 +3192,7 @@ func (m *ChannelOpenUpdate) Reset() { *m = ChannelOpenUpdate{} } func (m *ChannelOpenUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelOpenUpdate) ProtoMessage() {} func (*ChannelOpenUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{49} + return fileDescriptor_rpc_3a8b115cef624d58, []int{49} } func (m *ChannelOpenUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelOpenUpdate.Unmarshal(m, b) @@ -3202,7 +3231,7 @@ func (m *ChannelCloseUpdate) Reset() { *m = ChannelCloseUpdate{} } func (m *ChannelCloseUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelCloseUpdate) ProtoMessage() {} func (*ChannelCloseUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{50} + return fileDescriptor_rpc_3a8b115cef624d58, []int{50} } func (m *ChannelCloseUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelCloseUpdate.Unmarshal(m, b) @@ -3257,7 +3286,7 @@ func (m *CloseChannelRequest) Reset() { *m = CloseChannelRequest{} } func (m *CloseChannelRequest) String() string { return proto.CompactTextString(m) } func (*CloseChannelRequest) ProtoMessage() {} func (*CloseChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{51} + return fileDescriptor_rpc_3a8b115cef624d58, []int{51} } func (m *CloseChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CloseChannelRequest.Unmarshal(m, b) @@ -3319,7 +3348,7 @@ func (m *CloseStatusUpdate) Reset() { *m = CloseStatusUpdate{} } func (m *CloseStatusUpdate) String() string { return proto.CompactTextString(m) } func (*CloseStatusUpdate) ProtoMessage() {} func (*CloseStatusUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{52} + return fileDescriptor_rpc_3a8b115cef624d58, []int{52} } func (m *CloseStatusUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CloseStatusUpdate.Unmarshal(m, b) @@ -3462,7 +3491,7 @@ func (m *PendingUpdate) Reset() { *m = PendingUpdate{} } func (m *PendingUpdate) String() string { return proto.CompactTextString(m) } func (*PendingUpdate) ProtoMessage() {} func (*PendingUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{53} + return fileDescriptor_rpc_3a8b115cef624d58, []int{53} } func (m *PendingUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingUpdate.Unmarshal(m, b) @@ -3528,7 +3557,7 @@ func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} } func (m *OpenChannelRequest) String() string { return proto.CompactTextString(m) } func (*OpenChannelRequest) ProtoMessage() {} func (*OpenChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{54} + return fileDescriptor_rpc_3a8b115cef624d58, []int{54} } func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OpenChannelRequest.Unmarshal(m, b) @@ -3639,7 +3668,7 @@ func (m *OpenStatusUpdate) Reset() { *m = OpenStatusUpdate{} } func (m *OpenStatusUpdate) String() string { return proto.CompactTextString(m) } func (*OpenStatusUpdate) ProtoMessage() {} func (*OpenStatusUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{55} + return fileDescriptor_rpc_3a8b115cef624d58, []int{55} } func (m *OpenStatusUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OpenStatusUpdate.Unmarshal(m, b) @@ -3795,7 +3824,7 @@ func (m *PendingHTLC) Reset() { *m = PendingHTLC{} } func (m *PendingHTLC) String() string { return proto.CompactTextString(m) } func (*PendingHTLC) ProtoMessage() {} func (*PendingHTLC) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{56} + return fileDescriptor_rpc_3a8b115cef624d58, []int{56} } func (m *PendingHTLC) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingHTLC.Unmarshal(m, b) @@ -3867,7 +3896,7 @@ func (m *PendingChannelsRequest) Reset() { *m = PendingChannelsRequest{} func (m *PendingChannelsRequest) String() string { return proto.CompactTextString(m) } func (*PendingChannelsRequest) ProtoMessage() {} func (*PendingChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{57} + return fileDescriptor_rpc_3a8b115cef624d58, []int{57} } func (m *PendingChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsRequest.Unmarshal(m, b) @@ -3907,7 +3936,7 @@ func (m *PendingChannelsResponse) Reset() { *m = PendingChannelsResponse func (m *PendingChannelsResponse) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse) ProtoMessage() {} func (*PendingChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{58} + return fileDescriptor_rpc_3a8b115cef624d58, []int{58} } func (m *PendingChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse.Unmarshal(m, b) @@ -3979,7 +4008,7 @@ func (m *PendingChannelsResponse_PendingChannel) Reset() { func (m *PendingChannelsResponse_PendingChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_PendingChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{58, 0} + return fileDescriptor_rpc_3a8b115cef624d58, []int{58, 0} } func (m *PendingChannelsResponse_PendingChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_PendingChannel.Unmarshal(m, b) @@ -4066,7 +4095,7 @@ func (m *PendingChannelsResponse_PendingOpenChannel) String() string { } func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingOpenChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{58, 1} + return fileDescriptor_rpc_3a8b115cef624d58, []int{58, 1} } func (m *PendingChannelsResponse_PendingOpenChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_PendingOpenChannel.Unmarshal(m, b) @@ -4139,7 +4168,7 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) String() string { } func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {} func (*PendingChannelsResponse_WaitingCloseChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{58, 2} + return fileDescriptor_rpc_3a8b115cef624d58, []int{58, 2} } func (m *PendingChannelsResponse_WaitingCloseChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_WaitingCloseChannel.Unmarshal(m, b) @@ -4187,7 +4216,7 @@ func (m *PendingChannelsResponse_ClosedChannel) Reset() { *m = PendingCh func (m *PendingChannelsResponse_ClosedChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_ClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{58, 3} + return fileDescriptor_rpc_3a8b115cef624d58, []int{58, 3} } func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_ClosedChannel.Unmarshal(m, b) @@ -4251,7 +4280,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string { } func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{58, 4} + return fileDescriptor_rpc_3a8b115cef624d58, []int{58, 4} } func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_ForceClosedChannel.Unmarshal(m, b) @@ -4320,6 +4349,255 @@ func (m *PendingChannelsResponse_ForceClosedChannel) GetPendingHtlcs() []*Pendin return nil } +type ChannelEventSubscription struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ChannelEventSubscription) Reset() { *m = ChannelEventSubscription{} } +func (m *ChannelEventSubscription) String() string { return proto.CompactTextString(m) } +func (*ChannelEventSubscription) ProtoMessage() {} +func (*ChannelEventSubscription) Descriptor() ([]byte, []int) { + return fileDescriptor_rpc_3a8b115cef624d58, []int{59} +} +func (m *ChannelEventSubscription) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ChannelEventSubscription.Unmarshal(m, b) +} +func (m *ChannelEventSubscription) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ChannelEventSubscription.Marshal(b, m, deterministic) +} +func (dst *ChannelEventSubscription) XXX_Merge(src proto.Message) { + xxx_messageInfo_ChannelEventSubscription.Merge(dst, src) +} +func (m *ChannelEventSubscription) XXX_Size() int { + return xxx_messageInfo_ChannelEventSubscription.Size(m) +} +func (m *ChannelEventSubscription) XXX_DiscardUnknown() { + xxx_messageInfo_ChannelEventSubscription.DiscardUnknown(m) +} + +var xxx_messageInfo_ChannelEventSubscription proto.InternalMessageInfo + +type ChannelEventUpdate struct { + // Types that are valid to be assigned to Channel: + // *ChannelEventUpdate_OpenChannel + // *ChannelEventUpdate_ClosedChannel + // *ChannelEventUpdate_ActiveChannel + // *ChannelEventUpdate_InactiveChannel + Channel isChannelEventUpdate_Channel `protobuf_oneof:"channel"` + Type ChannelEventUpdate_UpdateType `protobuf:"varint,5,opt,name=type,proto3,enum=lnrpc.ChannelEventUpdate_UpdateType" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ChannelEventUpdate) Reset() { *m = ChannelEventUpdate{} } +func (m *ChannelEventUpdate) String() string { return proto.CompactTextString(m) } +func (*ChannelEventUpdate) ProtoMessage() {} +func (*ChannelEventUpdate) Descriptor() ([]byte, []int) { + return fileDescriptor_rpc_3a8b115cef624d58, []int{60} +} +func (m *ChannelEventUpdate) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ChannelEventUpdate.Unmarshal(m, b) +} +func (m *ChannelEventUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ChannelEventUpdate.Marshal(b, m, deterministic) +} +func (dst *ChannelEventUpdate) XXX_Merge(src proto.Message) { + xxx_messageInfo_ChannelEventUpdate.Merge(dst, src) +} +func (m *ChannelEventUpdate) XXX_Size() int { + return xxx_messageInfo_ChannelEventUpdate.Size(m) +} +func (m *ChannelEventUpdate) XXX_DiscardUnknown() { + xxx_messageInfo_ChannelEventUpdate.DiscardUnknown(m) +} + +var xxx_messageInfo_ChannelEventUpdate proto.InternalMessageInfo + +type isChannelEventUpdate_Channel interface { + isChannelEventUpdate_Channel() +} + +type ChannelEventUpdate_OpenChannel struct { + OpenChannel *Channel `protobuf:"bytes,1,opt,name=open_channel,proto3,oneof"` +} + +type ChannelEventUpdate_ClosedChannel struct { + ClosedChannel *ChannelCloseSummary `protobuf:"bytes,2,opt,name=closed_channel,proto3,oneof"` +} + +type ChannelEventUpdate_ActiveChannel struct { + ActiveChannel *ChannelPoint `protobuf:"bytes,3,opt,name=active_channel,proto3,oneof"` +} + +type ChannelEventUpdate_InactiveChannel struct { + InactiveChannel *ChannelPoint `protobuf:"bytes,4,opt,name=inactive_channel,proto3,oneof"` +} + +func (*ChannelEventUpdate_OpenChannel) isChannelEventUpdate_Channel() {} + +func (*ChannelEventUpdate_ClosedChannel) isChannelEventUpdate_Channel() {} + +func (*ChannelEventUpdate_ActiveChannel) isChannelEventUpdate_Channel() {} + +func (*ChannelEventUpdate_InactiveChannel) isChannelEventUpdate_Channel() {} + +func (m *ChannelEventUpdate) GetChannel() isChannelEventUpdate_Channel { + if m != nil { + return m.Channel + } + return nil +} + +func (m *ChannelEventUpdate) GetOpenChannel() *Channel { + if x, ok := m.GetChannel().(*ChannelEventUpdate_OpenChannel); ok { + return x.OpenChannel + } + return nil +} + +func (m *ChannelEventUpdate) GetClosedChannel() *ChannelCloseSummary { + if x, ok := m.GetChannel().(*ChannelEventUpdate_ClosedChannel); ok { + return x.ClosedChannel + } + return nil +} + +func (m *ChannelEventUpdate) GetActiveChannel() *ChannelPoint { + if x, ok := m.GetChannel().(*ChannelEventUpdate_ActiveChannel); ok { + return x.ActiveChannel + } + return nil +} + +func (m *ChannelEventUpdate) GetInactiveChannel() *ChannelPoint { + if x, ok := m.GetChannel().(*ChannelEventUpdate_InactiveChannel); ok { + return x.InactiveChannel + } + return nil +} + +func (m *ChannelEventUpdate) GetType() ChannelEventUpdate_UpdateType { + if m != nil { + return m.Type + } + return ChannelEventUpdate_OPEN_CHANNEL +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ChannelEventUpdate) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ChannelEventUpdate_OneofMarshaler, _ChannelEventUpdate_OneofUnmarshaler, _ChannelEventUpdate_OneofSizer, []interface{}{ + (*ChannelEventUpdate_OpenChannel)(nil), + (*ChannelEventUpdate_ClosedChannel)(nil), + (*ChannelEventUpdate_ActiveChannel)(nil), + (*ChannelEventUpdate_InactiveChannel)(nil), + } +} + +func _ChannelEventUpdate_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ChannelEventUpdate) + // channel + switch x := m.Channel.(type) { + case *ChannelEventUpdate_OpenChannel: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.OpenChannel); err != nil { + return err + } + case *ChannelEventUpdate_ClosedChannel: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ClosedChannel); err != nil { + return err + } + case *ChannelEventUpdate_ActiveChannel: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ActiveChannel); err != nil { + return err + } + case *ChannelEventUpdate_InactiveChannel: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InactiveChannel); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("ChannelEventUpdate.Channel has unexpected type %T", x) + } + return nil +} + +func _ChannelEventUpdate_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ChannelEventUpdate) + switch tag { + case 1: // channel.open_channel + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Channel) + err := b.DecodeMessage(msg) + m.Channel = &ChannelEventUpdate_OpenChannel{msg} + return true, err + case 2: // channel.closed_channel + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ChannelCloseSummary) + err := b.DecodeMessage(msg) + m.Channel = &ChannelEventUpdate_ClosedChannel{msg} + return true, err + case 3: // channel.active_channel + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ChannelPoint) + err := b.DecodeMessage(msg) + m.Channel = &ChannelEventUpdate_ActiveChannel{msg} + return true, err + case 4: // channel.inactive_channel + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ChannelPoint) + err := b.DecodeMessage(msg) + m.Channel = &ChannelEventUpdate_InactiveChannel{msg} + return true, err + default: + return false, nil + } +} + +func _ChannelEventUpdate_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ChannelEventUpdate) + // channel + switch x := m.Channel.(type) { + case *ChannelEventUpdate_OpenChannel: + s := proto.Size(x.OpenChannel) + n += 1 // tag and wire + n += proto.SizeVarint(uint64(s)) + n += s + case *ChannelEventUpdate_ClosedChannel: + s := proto.Size(x.ClosedChannel) + n += 1 // tag and wire + n += proto.SizeVarint(uint64(s)) + n += s + case *ChannelEventUpdate_ActiveChannel: + s := proto.Size(x.ActiveChannel) + n += 1 // tag and wire + n += proto.SizeVarint(uint64(s)) + n += s + case *ChannelEventUpdate_InactiveChannel: + s := proto.Size(x.InactiveChannel) + n += 1 // tag and wire + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + type WalletBalanceRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -4330,7 +4608,7 @@ func (m *WalletBalanceRequest) Reset() { *m = WalletBalanceRequest{} } func (m *WalletBalanceRequest) String() string { return proto.CompactTextString(m) } func (*WalletBalanceRequest) ProtoMessage() {} func (*WalletBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{59} + return fileDescriptor_rpc_3a8b115cef624d58, []int{61} } func (m *WalletBalanceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WalletBalanceRequest.Unmarshal(m, b) @@ -4366,7 +4644,7 @@ func (m *WalletBalanceResponse) Reset() { *m = WalletBalanceResponse{} } func (m *WalletBalanceResponse) String() string { return proto.CompactTextString(m) } func (*WalletBalanceResponse) ProtoMessage() {} func (*WalletBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{60} + return fileDescriptor_rpc_3a8b115cef624d58, []int{62} } func (m *WalletBalanceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WalletBalanceResponse.Unmarshal(m, b) @@ -4417,7 +4695,7 @@ func (m *ChannelBalanceRequest) Reset() { *m = ChannelBalanceRequest{} } func (m *ChannelBalanceRequest) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceRequest) ProtoMessage() {} func (*ChannelBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{61} + return fileDescriptor_rpc_3a8b115cef624d58, []int{63} } func (m *ChannelBalanceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelBalanceRequest.Unmarshal(m, b) @@ -4451,7 +4729,7 @@ func (m *ChannelBalanceResponse) Reset() { *m = ChannelBalanceResponse{} func (m *ChannelBalanceResponse) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceResponse) ProtoMessage() {} func (*ChannelBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{62} + return fileDescriptor_rpc_3a8b115cef624d58, []int{64} } func (m *ChannelBalanceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelBalanceResponse.Unmarshal(m, b) @@ -4509,7 +4787,7 @@ func (m *QueryRoutesRequest) Reset() { *m = QueryRoutesRequest{} } func (m *QueryRoutesRequest) String() string { return proto.CompactTextString(m) } func (*QueryRoutesRequest) ProtoMessage() {} func (*QueryRoutesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{63} + return fileDescriptor_rpc_3a8b115cef624d58, []int{65} } func (m *QueryRoutesRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryRoutesRequest.Unmarshal(m, b) @@ -4575,7 +4853,7 @@ func (m *QueryRoutesResponse) Reset() { *m = QueryRoutesResponse{} } func (m *QueryRoutesResponse) String() string { return proto.CompactTextString(m) } func (*QueryRoutesResponse) ProtoMessage() {} func (*QueryRoutesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{64} + return fileDescriptor_rpc_3a8b115cef624d58, []int{66} } func (m *QueryRoutesResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryRoutesResponse.Unmarshal(m, b) @@ -4627,7 +4905,7 @@ func (m *Hop) Reset() { *m = Hop{} } func (m *Hop) String() string { return proto.CompactTextString(m) } func (*Hop) ProtoMessage() {} func (*Hop) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{65} + return fileDescriptor_rpc_3a8b115cef624d58, []int{67} } func (m *Hop) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Hop.Unmarshal(m, b) @@ -4748,7 +5026,7 @@ func (m *Route) Reset() { *m = Route{} } func (m *Route) String() string { return proto.CompactTextString(m) } func (*Route) ProtoMessage() {} func (*Route) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{66} + return fileDescriptor_rpc_3a8b115cef624d58, []int{68} } func (m *Route) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Route.Unmarshal(m, b) @@ -4824,7 +5102,7 @@ func (m *NodeInfoRequest) Reset() { *m = NodeInfoRequest{} } func (m *NodeInfoRequest) String() string { return proto.CompactTextString(m) } func (*NodeInfoRequest) ProtoMessage() {} func (*NodeInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{67} + return fileDescriptor_rpc_3a8b115cef624d58, []int{69} } func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeInfoRequest.Unmarshal(m, b) @@ -4869,7 +5147,7 @@ func (m *NodeInfo) Reset() { *m = NodeInfo{} } func (m *NodeInfo) String() string { return proto.CompactTextString(m) } func (*NodeInfo) ProtoMessage() {} func (*NodeInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{68} + return fileDescriptor_rpc_3a8b115cef624d58, []int{70} } func (m *NodeInfo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeInfo.Unmarshal(m, b) @@ -4930,7 +5208,7 @@ func (m *LightningNode) Reset() { *m = LightningNode{} } func (m *LightningNode) String() string { return proto.CompactTextString(m) } func (*LightningNode) ProtoMessage() {} func (*LightningNode) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{69} + return fileDescriptor_rpc_3a8b115cef624d58, []int{71} } func (m *LightningNode) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LightningNode.Unmarshal(m, b) @@ -4997,7 +5275,7 @@ func (m *NodeAddress) Reset() { *m = NodeAddress{} } func (m *NodeAddress) String() string { return proto.CompactTextString(m) } func (*NodeAddress) ProtoMessage() {} func (*NodeAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{70} + return fileDescriptor_rpc_3a8b115cef624d58, []int{72} } func (m *NodeAddress) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeAddress.Unmarshal(m, b) @@ -5046,7 +5324,7 @@ func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} } func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) } func (*RoutingPolicy) ProtoMessage() {} func (*RoutingPolicy) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{71} + return fileDescriptor_rpc_3a8b115cef624d58, []int{73} } func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RoutingPolicy.Unmarshal(m, b) @@ -5129,7 +5407,7 @@ func (m *ChannelEdge) Reset() { *m = ChannelEdge{} } func (m *ChannelEdge) String() string { return proto.CompactTextString(m) } func (*ChannelEdge) ProtoMessage() {} func (*ChannelEdge) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{72} + return fileDescriptor_rpc_3a8b115cef624d58, []int{74} } func (m *ChannelEdge) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEdge.Unmarshal(m, b) @@ -5220,7 +5498,7 @@ func (m *ChannelGraphRequest) Reset() { *m = ChannelGraphRequest{} } func (m *ChannelGraphRequest) String() string { return proto.CompactTextString(m) } func (*ChannelGraphRequest) ProtoMessage() {} func (*ChannelGraphRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{73} + return fileDescriptor_rpc_3a8b115cef624d58, []int{75} } func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelGraphRequest.Unmarshal(m, b) @@ -5262,7 +5540,7 @@ func (m *ChannelGraph) Reset() { *m = ChannelGraph{} } func (m *ChannelGraph) String() string { return proto.CompactTextString(m) } func (*ChannelGraph) ProtoMessage() {} func (*ChannelGraph) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{74} + return fileDescriptor_rpc_3a8b115cef624d58, []int{76} } func (m *ChannelGraph) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelGraph.Unmarshal(m, b) @@ -5311,7 +5589,7 @@ func (m *ChanInfoRequest) Reset() { *m = ChanInfoRequest{} } func (m *ChanInfoRequest) String() string { return proto.CompactTextString(m) } func (*ChanInfoRequest) ProtoMessage() {} func (*ChanInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{75} + return fileDescriptor_rpc_3a8b115cef624d58, []int{77} } func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChanInfoRequest.Unmarshal(m, b) @@ -5348,7 +5626,7 @@ func (m *NetworkInfoRequest) Reset() { *m = NetworkInfoRequest{} } func (m *NetworkInfoRequest) String() string { return proto.CompactTextString(m) } func (*NetworkInfoRequest) ProtoMessage() {} func (*NetworkInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{76} + return fileDescriptor_rpc_3a8b115cef624d58, []int{78} } func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NetworkInfoRequest.Unmarshal(m, b) @@ -5387,7 +5665,7 @@ func (m *NetworkInfo) Reset() { *m = NetworkInfo{} } func (m *NetworkInfo) String() string { return proto.CompactTextString(m) } func (*NetworkInfo) ProtoMessage() {} func (*NetworkInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{77} + return fileDescriptor_rpc_3a8b115cef624d58, []int{79} } func (m *NetworkInfo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NetworkInfo.Unmarshal(m, b) @@ -5480,7 +5758,7 @@ func (m *StopRequest) Reset() { *m = StopRequest{} } func (m *StopRequest) String() string { return proto.CompactTextString(m) } func (*StopRequest) ProtoMessage() {} func (*StopRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{78} + return fileDescriptor_rpc_3a8b115cef624d58, []int{80} } func (m *StopRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StopRequest.Unmarshal(m, b) @@ -5510,7 +5788,7 @@ func (m *StopResponse) Reset() { *m = StopResponse{} } func (m *StopResponse) String() string { return proto.CompactTextString(m) } func (*StopResponse) ProtoMessage() {} func (*StopResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{79} + return fileDescriptor_rpc_3a8b115cef624d58, []int{81} } func (m *StopResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StopResponse.Unmarshal(m, b) @@ -5540,7 +5818,7 @@ func (m *GraphTopologySubscription) Reset() { *m = GraphTopologySubscrip func (m *GraphTopologySubscription) String() string { return proto.CompactTextString(m) } func (*GraphTopologySubscription) ProtoMessage() {} func (*GraphTopologySubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{80} + return fileDescriptor_rpc_3a8b115cef624d58, []int{82} } func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GraphTopologySubscription.Unmarshal(m, b) @@ -5573,7 +5851,7 @@ func (m *GraphTopologyUpdate) Reset() { *m = GraphTopologyUpdate{} } func (m *GraphTopologyUpdate) String() string { return proto.CompactTextString(m) } func (*GraphTopologyUpdate) ProtoMessage() {} func (*GraphTopologyUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{81} + return fileDescriptor_rpc_3a8b115cef624d58, []int{83} } func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GraphTopologyUpdate.Unmarshal(m, b) @@ -5628,7 +5906,7 @@ func (m *NodeUpdate) Reset() { *m = NodeUpdate{} } func (m *NodeUpdate) String() string { return proto.CompactTextString(m) } func (*NodeUpdate) ProtoMessage() {} func (*NodeUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{82} + return fileDescriptor_rpc_3a8b115cef624d58, []int{84} } func (m *NodeUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeUpdate.Unmarshal(m, b) @@ -5696,7 +5974,7 @@ func (m *ChannelEdgeUpdate) Reset() { *m = ChannelEdgeUpdate{} } func (m *ChannelEdgeUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelEdgeUpdate) ProtoMessage() {} func (*ChannelEdgeUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{83} + return fileDescriptor_rpc_3a8b115cef624d58, []int{85} } func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEdgeUpdate.Unmarshal(m, b) @@ -5776,7 +6054,7 @@ func (m *ClosedChannelUpdate) Reset() { *m = ClosedChannelUpdate{} } func (m *ClosedChannelUpdate) String() string { return proto.CompactTextString(m) } func (*ClosedChannelUpdate) ProtoMessage() {} func (*ClosedChannelUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{84} + return fileDescriptor_rpc_3a8b115cef624d58, []int{86} } func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelUpdate.Unmarshal(m, b) @@ -5846,7 +6124,7 @@ func (m *HopHint) Reset() { *m = HopHint{} } func (m *HopHint) String() string { return proto.CompactTextString(m) } func (*HopHint) ProtoMessage() {} func (*HopHint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{85} + return fileDescriptor_rpc_3a8b115cef624d58, []int{87} } func (m *HopHint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HopHint.Unmarshal(m, b) @@ -5915,7 +6193,7 @@ func (m *RouteHint) Reset() { *m = RouteHint{} } func (m *RouteHint) String() string { return proto.CompactTextString(m) } func (*RouteHint) ProtoMessage() {} func (*RouteHint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{86} + return fileDescriptor_rpc_3a8b115cef624d58, []int{88} } func (m *RouteHint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RouteHint.Unmarshal(m, b) @@ -6030,7 +6308,7 @@ func (m *Invoice) Reset() { *m = Invoice{} } func (m *Invoice) String() string { return proto.CompactTextString(m) } func (*Invoice) ProtoMessage() {} func (*Invoice) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{87} + return fileDescriptor_rpc_3a8b115cef624d58, []int{89} } func (m *Invoice) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Invoice.Unmarshal(m, b) @@ -6222,7 +6500,7 @@ func (m *AddInvoiceResponse) Reset() { *m = AddInvoiceResponse{} } func (m *AddInvoiceResponse) String() string { return proto.CompactTextString(m) } func (*AddInvoiceResponse) ProtoMessage() {} func (*AddInvoiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{88} + return fileDescriptor_rpc_3a8b115cef624d58, []int{90} } func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AddInvoiceResponse.Unmarshal(m, b) @@ -6279,7 +6557,7 @@ func (m *PaymentHash) Reset() { *m = PaymentHash{} } func (m *PaymentHash) String() string { return proto.CompactTextString(m) } func (*PaymentHash) ProtoMessage() {} func (*PaymentHash) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{89} + return fileDescriptor_rpc_3a8b115cef624d58, []int{91} } func (m *PaymentHash) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PaymentHash.Unmarshal(m, b) @@ -6335,7 +6613,7 @@ func (m *ListInvoiceRequest) Reset() { *m = ListInvoiceRequest{} } func (m *ListInvoiceRequest) String() string { return proto.CompactTextString(m) } func (*ListInvoiceRequest) ProtoMessage() {} func (*ListInvoiceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{90} + return fileDescriptor_rpc_3a8b115cef624d58, []int{92} } func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListInvoiceRequest.Unmarshal(m, b) @@ -6405,7 +6683,7 @@ func (m *ListInvoiceResponse) Reset() { *m = ListInvoiceResponse{} } func (m *ListInvoiceResponse) String() string { return proto.CompactTextString(m) } func (*ListInvoiceResponse) ProtoMessage() {} func (*ListInvoiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{91} + return fileDescriptor_rpc_3a8b115cef624d58, []int{93} } func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListInvoiceResponse.Unmarshal(m, b) @@ -6468,7 +6746,7 @@ func (m *InvoiceSubscription) Reset() { *m = InvoiceSubscription{} } func (m *InvoiceSubscription) String() string { return proto.CompactTextString(m) } func (*InvoiceSubscription) ProtoMessage() {} func (*InvoiceSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{92} + return fileDescriptor_rpc_3a8b115cef624d58, []int{94} } func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InvoiceSubscription.Unmarshal(m, b) @@ -6528,7 +6806,7 @@ func (m *Payment) Reset() { *m = Payment{} } func (m *Payment) String() string { return proto.CompactTextString(m) } func (*Payment) ProtoMessage() {} func (*Payment) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{93} + return fileDescriptor_rpc_3a8b115cef624d58, []int{95} } func (m *Payment) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Payment.Unmarshal(m, b) @@ -6615,7 +6893,7 @@ func (m *ListPaymentsRequest) Reset() { *m = ListPaymentsRequest{} } func (m *ListPaymentsRequest) String() string { return proto.CompactTextString(m) } func (*ListPaymentsRequest) ProtoMessage() {} func (*ListPaymentsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{94} + return fileDescriptor_rpc_3a8b115cef624d58, []int{96} } func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPaymentsRequest.Unmarshal(m, b) @@ -6647,7 +6925,7 @@ func (m *ListPaymentsResponse) Reset() { *m = ListPaymentsResponse{} } func (m *ListPaymentsResponse) String() string { return proto.CompactTextString(m) } func (*ListPaymentsResponse) ProtoMessage() {} func (*ListPaymentsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{95} + return fileDescriptor_rpc_3a8b115cef624d58, []int{97} } func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPaymentsResponse.Unmarshal(m, b) @@ -6684,7 +6962,7 @@ func (m *DeleteAllPaymentsRequest) Reset() { *m = DeleteAllPaymentsReque func (m *DeleteAllPaymentsRequest) String() string { return proto.CompactTextString(m) } func (*DeleteAllPaymentsRequest) ProtoMessage() {} func (*DeleteAllPaymentsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{96} + return fileDescriptor_rpc_3a8b115cef624d58, []int{98} } func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DeleteAllPaymentsRequest.Unmarshal(m, b) @@ -6714,7 +6992,7 @@ func (m *DeleteAllPaymentsResponse) Reset() { *m = DeleteAllPaymentsResp func (m *DeleteAllPaymentsResponse) String() string { return proto.CompactTextString(m) } func (*DeleteAllPaymentsResponse) ProtoMessage() {} func (*DeleteAllPaymentsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{97} + return fileDescriptor_rpc_3a8b115cef624d58, []int{99} } func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DeleteAllPaymentsResponse.Unmarshal(m, b) @@ -6745,7 +7023,7 @@ func (m *AbandonChannelRequest) Reset() { *m = AbandonChannelRequest{} } func (m *AbandonChannelRequest) String() string { return proto.CompactTextString(m) } func (*AbandonChannelRequest) ProtoMessage() {} func (*AbandonChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{98} + return fileDescriptor_rpc_3a8b115cef624d58, []int{100} } func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AbandonChannelRequest.Unmarshal(m, b) @@ -6782,7 +7060,7 @@ func (m *AbandonChannelResponse) Reset() { *m = AbandonChannelResponse{} func (m *AbandonChannelResponse) String() string { return proto.CompactTextString(m) } func (*AbandonChannelResponse) ProtoMessage() {} func (*AbandonChannelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{99} + return fileDescriptor_rpc_3a8b115cef624d58, []int{101} } func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AbandonChannelResponse.Unmarshal(m, b) @@ -6814,7 +7092,7 @@ func (m *DebugLevelRequest) Reset() { *m = DebugLevelRequest{} } func (m *DebugLevelRequest) String() string { return proto.CompactTextString(m) } func (*DebugLevelRequest) ProtoMessage() {} func (*DebugLevelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{100} + return fileDescriptor_rpc_3a8b115cef624d58, []int{102} } func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DebugLevelRequest.Unmarshal(m, b) @@ -6859,7 +7137,7 @@ func (m *DebugLevelResponse) Reset() { *m = DebugLevelResponse{} } func (m *DebugLevelResponse) String() string { return proto.CompactTextString(m) } func (*DebugLevelResponse) ProtoMessage() {} func (*DebugLevelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{101} + return fileDescriptor_rpc_3a8b115cef624d58, []int{103} } func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DebugLevelResponse.Unmarshal(m, b) @@ -6898,7 +7176,7 @@ func (m *PayReqString) Reset() { *m = PayReqString{} } func (m *PayReqString) String() string { return proto.CompactTextString(m) } func (*PayReqString) ProtoMessage() {} func (*PayReqString) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{102} + return fileDescriptor_rpc_3a8b115cef624d58, []int{104} } func (m *PayReqString) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PayReqString.Unmarshal(m, b) @@ -6945,7 +7223,7 @@ func (m *PayReq) Reset() { *m = PayReq{} } func (m *PayReq) String() string { return proto.CompactTextString(m) } func (*PayReq) ProtoMessage() {} func (*PayReq) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{103} + return fileDescriptor_rpc_3a8b115cef624d58, []int{105} } func (m *PayReq) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PayReq.Unmarshal(m, b) @@ -7045,7 +7323,7 @@ func (m *FeeReportRequest) Reset() { *m = FeeReportRequest{} } func (m *FeeReportRequest) String() string { return proto.CompactTextString(m) } func (*FeeReportRequest) ProtoMessage() {} func (*FeeReportRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{104} + return fileDescriptor_rpc_3a8b115cef624d58, []int{106} } func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeReportRequest.Unmarshal(m, b) @@ -7083,7 +7361,7 @@ func (m *ChannelFeeReport) Reset() { *m = ChannelFeeReport{} } func (m *ChannelFeeReport) String() string { return proto.CompactTextString(m) } func (*ChannelFeeReport) ProtoMessage() {} func (*ChannelFeeReport) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{105} + return fileDescriptor_rpc_3a8b115cef624d58, []int{107} } func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelFeeReport.Unmarshal(m, b) @@ -7149,7 +7427,7 @@ func (m *FeeReportResponse) Reset() { *m = FeeReportResponse{} } func (m *FeeReportResponse) String() string { return proto.CompactTextString(m) } func (*FeeReportResponse) ProtoMessage() {} func (*FeeReportResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{106} + return fileDescriptor_rpc_3a8b115cef624d58, []int{108} } func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeReportResponse.Unmarshal(m, b) @@ -7217,7 +7495,7 @@ func (m *PolicyUpdateRequest) Reset() { *m = PolicyUpdateRequest{} } func (m *PolicyUpdateRequest) String() string { return proto.CompactTextString(m) } func (*PolicyUpdateRequest) ProtoMessage() {} func (*PolicyUpdateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{107} + return fileDescriptor_rpc_3a8b115cef624d58, []int{109} } func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PolicyUpdateRequest.Unmarshal(m, b) @@ -7378,7 +7656,7 @@ func (m *PolicyUpdateResponse) Reset() { *m = PolicyUpdateResponse{} } func (m *PolicyUpdateResponse) String() string { return proto.CompactTextString(m) } func (*PolicyUpdateResponse) ProtoMessage() {} func (*PolicyUpdateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{108} + return fileDescriptor_rpc_3a8b115cef624d58, []int{110} } func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PolicyUpdateResponse.Unmarshal(m, b) @@ -7416,7 +7694,7 @@ func (m *ForwardingHistoryRequest) Reset() { *m = ForwardingHistoryReque func (m *ForwardingHistoryRequest) String() string { return proto.CompactTextString(m) } func (*ForwardingHistoryRequest) ProtoMessage() {} func (*ForwardingHistoryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{109} + return fileDescriptor_rpc_3a8b115cef624d58, []int{111} } func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingHistoryRequest.Unmarshal(m, b) @@ -7488,7 +7766,7 @@ func (m *ForwardingEvent) Reset() { *m = ForwardingEvent{} } func (m *ForwardingEvent) String() string { return proto.CompactTextString(m) } func (*ForwardingEvent) ProtoMessage() {} func (*ForwardingEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{110} + return fileDescriptor_rpc_3a8b115cef624d58, []int{112} } func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingEvent.Unmarshal(m, b) @@ -7571,7 +7849,7 @@ func (m *ForwardingHistoryResponse) Reset() { *m = ForwardingHistoryResp func (m *ForwardingHistoryResponse) String() string { return proto.CompactTextString(m) } func (*ForwardingHistoryResponse) ProtoMessage() {} func (*ForwardingHistoryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_7b059397c6314ddc, []int{111} + return fileDescriptor_rpc_3a8b115cef624d58, []int{113} } func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingHistoryResponse.Unmarshal(m, b) @@ -7671,6 +7949,8 @@ func init() { proto.RegisterType((*PendingChannelsResponse_WaitingCloseChannel)(nil), "lnrpc.PendingChannelsResponse.WaitingCloseChannel") proto.RegisterType((*PendingChannelsResponse_ClosedChannel)(nil), "lnrpc.PendingChannelsResponse.ClosedChannel") proto.RegisterType((*PendingChannelsResponse_ForceClosedChannel)(nil), "lnrpc.PendingChannelsResponse.ForceClosedChannel") + proto.RegisterType((*ChannelEventSubscription)(nil), "lnrpc.ChannelEventSubscription") + proto.RegisterType((*ChannelEventUpdate)(nil), "lnrpc.ChannelEventUpdate") proto.RegisterType((*WalletBalanceRequest)(nil), "lnrpc.WalletBalanceRequest") proto.RegisterType((*WalletBalanceResponse)(nil), "lnrpc.WalletBalanceResponse") proto.RegisterType((*ChannelBalanceRequest)(nil), "lnrpc.ChannelBalanceRequest") @@ -7726,6 +8006,7 @@ func init() { proto.RegisterType((*ForwardingHistoryResponse)(nil), "lnrpc.ForwardingHistoryResponse") proto.RegisterEnum("lnrpc.AddressType", AddressType_name, AddressType_value) proto.RegisterEnum("lnrpc.ChannelCloseSummary_ClosureType", ChannelCloseSummary_ClosureType_name, ChannelCloseSummary_ClosureType_value) + proto.RegisterEnum("lnrpc.ChannelEventUpdate_UpdateType", ChannelEventUpdate_UpdateType_name, ChannelEventUpdate_UpdateType_value) proto.RegisterEnum("lnrpc.Invoice_InvoiceState", Invoice_InvoiceState_name, Invoice_InvoiceState_value) } @@ -8037,6 +8318,12 @@ type LightningClient interface { // ListChannels returns a description of all the open channels that this node // is a participant in. ListChannels(ctx context.Context, in *ListChannelsRequest, opts ...grpc.CallOption) (*ListChannelsResponse, error) + // * lncli: `subscribechannelevents` + // SubscribeChannelEvents creates a uni-directional stream from the server to + // the client in which any updates relevant to the state of the channels are + // sent over. Events include new active channels, inactive channels, and closed + // channels. + SubscribeChannelEvents(ctx context.Context, in *ChannelEventSubscription, opts ...grpc.CallOption) (Lightning_SubscribeChannelEventsClient, error) // * lncli: `closedchannels` // ClosedChannels returns a description of all the closed channels that // this node was a participant in. @@ -8376,6 +8663,38 @@ func (c *lightningClient) ListChannels(ctx context.Context, in *ListChannelsRequ return out, nil } +func (c *lightningClient) SubscribeChannelEvents(ctx context.Context, in *ChannelEventSubscription, opts ...grpc.CallOption) (Lightning_SubscribeChannelEventsClient, error) { + stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[1], "/lnrpc.Lightning/SubscribeChannelEvents", opts...) + if err != nil { + return nil, err + } + x := &lightningSubscribeChannelEventsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Lightning_SubscribeChannelEventsClient interface { + Recv() (*ChannelEventUpdate, error) + grpc.ClientStream +} + +type lightningSubscribeChannelEventsClient struct { + grpc.ClientStream +} + +func (x *lightningSubscribeChannelEventsClient) Recv() (*ChannelEventUpdate, error) { + m := new(ChannelEventUpdate) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *lightningClient) ClosedChannels(ctx context.Context, in *ClosedChannelsRequest, opts ...grpc.CallOption) (*ClosedChannelsResponse, error) { out := new(ClosedChannelsResponse) err := c.cc.Invoke(ctx, "/lnrpc.Lightning/ClosedChannels", in, out, opts...) @@ -8395,7 +8714,7 @@ func (c *lightningClient) OpenChannelSync(ctx context.Context, in *OpenChannelRe } func (c *lightningClient) OpenChannel(ctx context.Context, in *OpenChannelRequest, opts ...grpc.CallOption) (Lightning_OpenChannelClient, error) { - stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[1], "/lnrpc.Lightning/OpenChannel", opts...) + stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[2], "/lnrpc.Lightning/OpenChannel", opts...) if err != nil { return nil, err } @@ -8427,7 +8746,7 @@ func (x *lightningOpenChannelClient) Recv() (*OpenStatusUpdate, error) { } func (c *lightningClient) CloseChannel(ctx context.Context, in *CloseChannelRequest, opts ...grpc.CallOption) (Lightning_CloseChannelClient, error) { - stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[2], "/lnrpc.Lightning/CloseChannel", opts...) + stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[3], "/lnrpc.Lightning/CloseChannel", opts...) if err != nil { return nil, err } @@ -8468,7 +8787,7 @@ func (c *lightningClient) AbandonChannel(ctx context.Context, in *AbandonChannel } func (c *lightningClient) SendPayment(ctx context.Context, opts ...grpc.CallOption) (Lightning_SendPaymentClient, error) { - stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[3], "/lnrpc.Lightning/SendPayment", opts...) + stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[4], "/lnrpc.Lightning/SendPayment", opts...) if err != nil { return nil, err } @@ -8508,7 +8827,7 @@ func (c *lightningClient) SendPaymentSync(ctx context.Context, in *SendRequest, } func (c *lightningClient) SendToRoute(ctx context.Context, opts ...grpc.CallOption) (Lightning_SendToRouteClient, error) { - stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[4], "/lnrpc.Lightning/SendToRoute", opts...) + stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[5], "/lnrpc.Lightning/SendToRoute", opts...) if err != nil { return nil, err } @@ -8575,7 +8894,7 @@ func (c *lightningClient) LookupInvoice(ctx context.Context, in *PaymentHash, op } func (c *lightningClient) SubscribeInvoices(ctx context.Context, in *InvoiceSubscription, opts ...grpc.CallOption) (Lightning_SubscribeInvoicesClient, error) { - stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[5], "/lnrpc.Lightning/SubscribeInvoices", opts...) + stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[6], "/lnrpc.Lightning/SubscribeInvoices", opts...) if err != nil { return nil, err } @@ -8688,7 +9007,7 @@ func (c *lightningClient) StopDaemon(ctx context.Context, in *StopRequest, opts } func (c *lightningClient) SubscribeChannelGraph(ctx context.Context, in *GraphTopologySubscription, opts ...grpc.CallOption) (Lightning_SubscribeChannelGraphClient, error) { - stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[6], "/lnrpc.Lightning/SubscribeChannelGraph", opts...) + stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[7], "/lnrpc.Lightning/SubscribeChannelGraph", opts...) if err != nil { return nil, err } @@ -8834,6 +9153,12 @@ type LightningServer interface { // ListChannels returns a description of all the open channels that this node // is a participant in. ListChannels(context.Context, *ListChannelsRequest) (*ListChannelsResponse, error) + // * lncli: `subscribechannelevents` + // SubscribeChannelEvents creates a uni-directional stream from the server to + // the client in which any updates relevant to the state of the channels are + // sent over. Events include new active channels, inactive channels, and closed + // channels. + SubscribeChannelEvents(*ChannelEventSubscription, Lightning_SubscribeChannelEventsServer) error // * lncli: `closedchannels` // ClosedChannels returns a description of all the closed channels that // this node was a participant in. @@ -9293,6 +9618,27 @@ func _Lightning_ListChannels_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Lightning_SubscribeChannelEvents_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ChannelEventSubscription) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(LightningServer).SubscribeChannelEvents(m, &lightningSubscribeChannelEventsServer{stream}) +} + +type Lightning_SubscribeChannelEventsServer interface { + Send(*ChannelEventUpdate) error + grpc.ServerStream +} + +type lightningSubscribeChannelEventsServer struct { + grpc.ServerStream +} + +func (x *lightningSubscribeChannelEventsServer) Send(m *ChannelEventUpdate) error { + return x.ServerStream.SendMsg(m) +} + func _Lightning_ClosedChannels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ClosedChannelsRequest) if err := dec(in); err != nil { @@ -9962,6 +10308,11 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{ Handler: _Lightning_SubscribeTransactions_Handler, ServerStreams: true, }, + { + StreamName: "SubscribeChannelEvents", + Handler: _Lightning_SubscribeChannelEvents_Handler, + ServerStreams: true, + }, { StreamName: "OpenChannel", Handler: _Lightning_OpenChannel_Handler, @@ -9998,434 +10349,444 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{ Metadata: "rpc.proto", } -func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_7b059397c6314ddc) } +func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_3a8b115cef624d58) } -var fileDescriptor_rpc_7b059397c6314ddc = []byte{ - // 6801 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7c, 0x4f, 0x6c, 0x1c, 0xc9, - 0x79, 0xaf, 0x7a, 0x38, 0x43, 0xce, 0x7c, 0x33, 0x24, 0x87, 0xc5, 0x7f, 0xa3, 0x59, 0xad, 0x56, - 0x5b, 0x96, 0x57, 0x32, 0xbd, 0x4f, 0xd4, 0xca, 0xf6, 0xbe, 0xf5, 0xee, 0x7b, 0x7e, 0x8f, 0x22, - 0x29, 0x51, 0x36, 0x57, 0xa2, 0x9b, 0x92, 0xf5, 0xbc, 0x7e, 0x0f, 0xe3, 0xe6, 0x4c, 0x71, 0xd8, - 0xab, 0x9e, 0xee, 0x71, 0x77, 0x0f, 0xa9, 0xf1, 0xbe, 0x05, 0x1e, 0x5e, 0x82, 0x04, 0x08, 0x12, - 0x04, 0x49, 0x2e, 0x71, 0xe0, 0x20, 0x80, 0x13, 0x20, 0xf6, 0x31, 0x87, 0x18, 0x01, 0x92, 0xdc, - 0x72, 0x49, 0x80, 0x20, 0x08, 0x7c, 0x0c, 0x90, 0x4b, 0x72, 0x71, 0x02, 0xe4, 0x10, 0x20, 0x87, - 0x1c, 0x02, 0x04, 0xf5, 0xd5, 0x9f, 0xae, 0xea, 0x6e, 0x8a, 0x5a, 0xdb, 0xc9, 0x89, 0xac, 0x5f, - 0x7d, 0x5d, 0x7f, 0xbf, 0x7f, 0xf5, 0xd5, 0x57, 0x03, 0x8d, 0x78, 0xdc, 0xbf, 0x35, 0x8e, 0xa3, - 0x34, 0x22, 0xb5, 0x20, 0x8c, 0xc7, 0xfd, 0xee, 0x95, 0x61, 0x14, 0x0d, 0x03, 0xb6, 0xe9, 0x8d, - 0xfd, 0x4d, 0x2f, 0x0c, 0xa3, 0xd4, 0x4b, 0xfd, 0x28, 0x4c, 0x04, 0x11, 0xfd, 0x26, 0x2c, 0xdc, - 0x67, 0xe1, 0x21, 0x63, 0x03, 0x97, 0x7d, 0x6b, 0xc2, 0x92, 0x94, 0x7c, 0x16, 0x96, 0x3c, 0xf6, - 0x6d, 0xc6, 0x06, 0xbd, 0xb1, 0x97, 0x24, 0xe3, 0x93, 0xd8, 0x4b, 0x58, 0xc7, 0xb9, 0xe6, 0xdc, - 0x6c, 0xb9, 0x6d, 0x51, 0x71, 0xa0, 0x71, 0xf2, 0x3a, 0xb4, 0x12, 0x4e, 0xca, 0xc2, 0x34, 0x8e, - 0xc6, 0xd3, 0x4e, 0x05, 0xe9, 0x9a, 0x1c, 0xdb, 0x15, 0x10, 0x0d, 0x60, 0x51, 0xf7, 0x90, 0x8c, - 0xa3, 0x30, 0x61, 0xe4, 0x36, 0xac, 0xf4, 0xfd, 0xf1, 0x09, 0x8b, 0x7b, 0xf8, 0xf1, 0x28, 0x64, - 0xa3, 0x28, 0xf4, 0xfb, 0x1d, 0xe7, 0xda, 0xcc, 0xcd, 0x86, 0x4b, 0x44, 0x1d, 0xff, 0xe2, 0x7d, - 0x59, 0x43, 0x6e, 0xc0, 0x22, 0x0b, 0x05, 0xce, 0x06, 0xf8, 0x95, 0xec, 0x6a, 0x21, 0x83, 0xf9, - 0x07, 0xf4, 0xcf, 0x1c, 0x58, 0x7a, 0x10, 0xfa, 0xe9, 0x53, 0x2f, 0x08, 0x58, 0xaa, 0xe6, 0x74, - 0x03, 0x16, 0xcf, 0x10, 0xc0, 0x39, 0x9d, 0x45, 0xf1, 0x40, 0xce, 0x68, 0x41, 0xc0, 0x07, 0x12, - 0x3d, 0x77, 0x64, 0x95, 0x73, 0x47, 0x56, 0xba, 0x5c, 0x33, 0xe7, 0x2c, 0xd7, 0x0d, 0x58, 0x8c, - 0x59, 0x3f, 0x3a, 0x65, 0xf1, 0xb4, 0x77, 0xe6, 0x87, 0x83, 0xe8, 0xac, 0x53, 0xbd, 0xe6, 0xdc, - 0xac, 0xb9, 0x0b, 0x0a, 0x7e, 0x8a, 0x28, 0x5d, 0x01, 0x62, 0xce, 0x42, 0xac, 0x1b, 0x1d, 0xc2, - 0xf2, 0x93, 0x30, 0x88, 0xfa, 0xcf, 0x7e, 0xc2, 0xd9, 0x95, 0x74, 0x5f, 0x29, 0xed, 0x7e, 0x0d, - 0x56, 0xec, 0x8e, 0xe4, 0x00, 0x18, 0xac, 0x6e, 0x9f, 0x78, 0xe1, 0x90, 0xa9, 0x26, 0xd5, 0x10, - 0x3e, 0x03, 0xed, 0xfe, 0x24, 0x8e, 0x59, 0x58, 0x18, 0xc3, 0xa2, 0xc4, 0xf5, 0x20, 0x5e, 0x87, - 0x56, 0xc8, 0xce, 0x32, 0x32, 0xc9, 0x32, 0x21, 0x3b, 0x53, 0x24, 0xb4, 0x03, 0x6b, 0xf9, 0x6e, - 0xe4, 0x00, 0x7e, 0xec, 0x40, 0xf5, 0x49, 0xfa, 0x3c, 0x22, 0xb7, 0xa0, 0x9a, 0x4e, 0xc7, 0x82, - 0x31, 0x17, 0xee, 0x90, 0x5b, 0xc8, 0xeb, 0xb7, 0xb6, 0x06, 0x83, 0x98, 0x25, 0xc9, 0xe3, 0xe9, - 0x98, 0xb9, 0x2d, 0x4f, 0x14, 0x7a, 0x9c, 0x8e, 0x74, 0x60, 0x4e, 0x96, 0xb1, 0xc3, 0x86, 0xab, - 0x8a, 0xe4, 0x2a, 0x80, 0x37, 0x8a, 0x26, 0x61, 0xda, 0x4b, 0xbc, 0x14, 0x77, 0x6e, 0xc6, 0x35, - 0x10, 0x72, 0x1d, 0xe6, 0x93, 0x7e, 0xec, 0x8f, 0xd3, 0xde, 0x78, 0x72, 0xf4, 0x8c, 0x4d, 0x71, - 0xc7, 0x1a, 0xae, 0x0d, 0x92, 0xcf, 0x42, 0x3d, 0x9a, 0xa4, 0xe3, 0xc8, 0x0f, 0xd3, 0x4e, 0xed, - 0x9a, 0x73, 0xb3, 0x79, 0x67, 0x51, 0x8e, 0xe9, 0xd1, 0x24, 0x3d, 0xe0, 0xb0, 0xab, 0x09, 0x78, - 0x93, 0xfd, 0x28, 0x3c, 0xf6, 0xe3, 0x91, 0x90, 0xc5, 0xce, 0x2c, 0xf6, 0x6a, 0x83, 0xf4, 0x3b, - 0x15, 0x68, 0x3e, 0x8e, 0xbd, 0x30, 0xf1, 0xfa, 0x1c, 0xe0, 0x53, 0x48, 0x9f, 0xf7, 0x4e, 0xbc, - 0xe4, 0x04, 0x67, 0xdd, 0x70, 0x55, 0x91, 0xac, 0xc1, 0xac, 0x18, 0x30, 0xce, 0x6d, 0xc6, 0x95, - 0x25, 0xf2, 0x26, 0x2c, 0x85, 0x93, 0x51, 0xcf, 0xee, 0x6b, 0x06, 0x77, 0xbc, 0x58, 0xc1, 0x17, - 0xe2, 0x88, 0xef, 0xb9, 0xe8, 0x42, 0xcc, 0xd2, 0x40, 0x08, 0x85, 0x96, 0x2c, 0x31, 0x7f, 0x78, - 0x22, 0xa6, 0x59, 0x73, 0x2d, 0x8c, 0xb7, 0x91, 0xfa, 0x23, 0xd6, 0x4b, 0x52, 0x6f, 0x34, 0x96, - 0xd3, 0x32, 0x10, 0xac, 0x8f, 0x52, 0x2f, 0xe8, 0x1d, 0x33, 0x96, 0x74, 0xe6, 0x64, 0xbd, 0x46, - 0xc8, 0x1b, 0xb0, 0x30, 0x60, 0x49, 0xda, 0x93, 0x9b, 0xc3, 0x92, 0x4e, 0x1d, 0x25, 0x2f, 0x87, - 0x72, 0x0e, 0xb9, 0xcf, 0x52, 0x63, 0x75, 0x12, 0xc9, 0x89, 0x74, 0x1f, 0x88, 0x01, 0xef, 0xb0, - 0xd4, 0xf3, 0x83, 0x84, 0xbc, 0x0d, 0xad, 0xd4, 0x20, 0x46, 0x4d, 0xd3, 0xd4, 0x6c, 0x63, 0x7c, - 0xe0, 0x5a, 0x74, 0xf4, 0x3e, 0xd4, 0xef, 0x31, 0xb6, 0xef, 0x8f, 0xfc, 0x94, 0xac, 0x41, 0xed, - 0xd8, 0x7f, 0xce, 0x04, 0x63, 0xcf, 0xec, 0x5d, 0x72, 0x45, 0x91, 0x74, 0x61, 0x6e, 0xcc, 0xe2, - 0x3e, 0x53, 0xcb, 0xbf, 0x77, 0xc9, 0x55, 0xc0, 0xdd, 0x39, 0xa8, 0x05, 0xfc, 0x63, 0xfa, 0xfd, - 0x0a, 0x34, 0x0f, 0x59, 0xa8, 0x05, 0x86, 0x40, 0x95, 0x4f, 0x49, 0x0a, 0x09, 0xfe, 0x4f, 0x5e, - 0x83, 0x26, 0x4e, 0x33, 0x49, 0x63, 0x3f, 0x1c, 0x4a, 0x3e, 0x05, 0x0e, 0x1d, 0x22, 0x42, 0xda, - 0x30, 0xe3, 0x8d, 0x14, 0x8f, 0xf2, 0x7f, 0xb9, 0x30, 0x8d, 0xbd, 0xe9, 0x88, 0xcb, 0x9d, 0xde, - 0xb5, 0x96, 0xdb, 0x94, 0xd8, 0x1e, 0xdf, 0xb6, 0x5b, 0xb0, 0x6c, 0x92, 0xa8, 0xd6, 0x6b, 0xd8, - 0xfa, 0x92, 0x41, 0x29, 0x3b, 0xb9, 0x01, 0x8b, 0x8a, 0x3e, 0x16, 0x83, 0xc5, 0x7d, 0x6c, 0xb8, - 0x0b, 0x12, 0x56, 0x53, 0xb8, 0x09, 0xed, 0x63, 0x3f, 0xf4, 0x82, 0x5e, 0x3f, 0x48, 0x4f, 0x7b, - 0x03, 0x16, 0xa4, 0x1e, 0xee, 0x68, 0xcd, 0x5d, 0x40, 0x7c, 0x3b, 0x48, 0x4f, 0x77, 0x38, 0x4a, - 0xde, 0x84, 0xc6, 0x31, 0x63, 0x3d, 0x5c, 0x89, 0x4e, 0xdd, 0x92, 0x0e, 0xb5, 0xba, 0x6e, 0xfd, - 0x58, 0xfe, 0x47, 0xff, 0xc8, 0x81, 0x96, 0x58, 0x2a, 0x69, 0x2e, 0xae, 0xc3, 0xbc, 0x1a, 0x11, - 0x8b, 0xe3, 0x28, 0x96, 0xec, 0x6f, 0x83, 0x64, 0x03, 0xda, 0x0a, 0x18, 0xc7, 0xcc, 0x1f, 0x79, - 0x43, 0x26, 0x75, 0x4b, 0x01, 0x27, 0x77, 0xb2, 0x16, 0xe3, 0x68, 0x92, 0x0a, 0x85, 0xdd, 0xbc, - 0xd3, 0x92, 0x83, 0x72, 0x39, 0xe6, 0xda, 0x24, 0x9c, 0xfd, 0x4b, 0x96, 0xda, 0xc2, 0xe8, 0x1f, - 0x3a, 0x40, 0xf8, 0xd0, 0x1f, 0x47, 0xa2, 0x09, 0xb9, 0x52, 0xf9, 0x5d, 0x72, 0x5e, 0x7a, 0x97, - 0x2a, 0xe7, 0xed, 0xd2, 0x4d, 0x98, 0xc5, 0x61, 0x71, 0x79, 0x9e, 0xc9, 0x0f, 0xfd, 0x6e, 0xa5, - 0xe3, 0xb8, 0xb2, 0x9e, 0x50, 0xa8, 0x89, 0x39, 0x56, 0x4b, 0xe6, 0x28, 0xaa, 0xe8, 0xf7, 0x1c, - 0x68, 0x71, 0x8d, 0x1b, 0xb2, 0x00, 0x75, 0x15, 0xb9, 0x0d, 0xe4, 0x78, 0x12, 0x0e, 0xfc, 0x70, - 0xd8, 0x4b, 0x9f, 0xfb, 0x83, 0xde, 0xd1, 0x94, 0x77, 0x85, 0xe3, 0xde, 0xbb, 0xe4, 0x96, 0xd4, - 0x91, 0x37, 0xa1, 0x6d, 0xa1, 0x49, 0x1a, 0x8b, 0xd1, 0xef, 0x5d, 0x72, 0x0b, 0x35, 0x7c, 0x31, - 0xb9, 0x36, 0x9c, 0xa4, 0x3d, 0x3f, 0x1c, 0xb0, 0xe7, 0xb8, 0xfe, 0xf3, 0xae, 0x85, 0xdd, 0x5d, - 0x80, 0x96, 0xf9, 0x1d, 0xfd, 0x10, 0xea, 0x4a, 0x97, 0xa2, 0x1e, 0xc9, 0x8d, 0xcb, 0x35, 0x10, - 0xd2, 0x85, 0xba, 0x3d, 0x0a, 0xb7, 0xfe, 0x49, 0xfa, 0xa6, 0x5f, 0x82, 0xf6, 0x3e, 0x57, 0x68, - 0xa1, 0x1f, 0x0e, 0xa5, 0x51, 0xe1, 0x5a, 0x56, 0x5a, 0x00, 0xc1, 0x7f, 0xb2, 0xc4, 0x45, 0xf9, - 0x24, 0x4a, 0x52, 0xd9, 0x0f, 0xfe, 0x4f, 0xff, 0xce, 0x81, 0x45, 0xce, 0x08, 0xef, 0x7b, 0xe1, - 0x54, 0x71, 0xc1, 0x3e, 0xb4, 0x78, 0x53, 0x8f, 0xa3, 0x2d, 0xa1, 0xab, 0x85, 0x0e, 0xba, 0x29, - 0xf7, 0x23, 0x47, 0x7d, 0xcb, 0x24, 0xe5, 0xae, 0xd4, 0xd4, 0xb5, 0xbe, 0xe6, 0xca, 0x22, 0xf5, - 0xe2, 0x21, 0x4b, 0x51, 0x8b, 0x4b, 0xad, 0x0e, 0x02, 0xda, 0x8e, 0xc2, 0x63, 0x72, 0x0d, 0x5a, - 0x89, 0x97, 0xf6, 0xc6, 0x2c, 0xc6, 0x35, 0x41, 0x81, 0x9f, 0x71, 0x21, 0xf1, 0xd2, 0x03, 0x16, - 0xdf, 0x9d, 0xa6, 0xac, 0xfb, 0x3f, 0x60, 0xa9, 0xd0, 0x0b, 0xd7, 0x31, 0xd9, 0x14, 0xf9, 0xbf, - 0x64, 0x05, 0x6a, 0xa7, 0x5e, 0x30, 0x61, 0xd2, 0xb8, 0x88, 0xc2, 0xbb, 0x95, 0x77, 0x1c, 0xfa, - 0x06, 0xb4, 0xb3, 0x61, 0x4b, 0x61, 0x25, 0x50, 0xe5, 0x2b, 0x2d, 0x1b, 0xc0, 0xff, 0xe9, 0x77, - 0x1d, 0x41, 0xb8, 0x1d, 0xf9, 0x5a, 0x51, 0x73, 0x42, 0xae, 0xcf, 0x15, 0x21, 0xff, 0xff, 0x5c, - 0x43, 0xf6, 0xd3, 0x4f, 0x96, 0x5c, 0x86, 0x7a, 0xc2, 0xc2, 0x41, 0xcf, 0x0b, 0x02, 0xd4, 0x67, - 0x75, 0x77, 0x8e, 0x97, 0xb7, 0x82, 0x80, 0xde, 0x80, 0x25, 0x63, 0x74, 0x2f, 0x98, 0xc7, 0x43, - 0x20, 0xfb, 0x7e, 0x92, 0x3e, 0x09, 0x93, 0xb1, 0xa1, 0x07, 0x5f, 0x81, 0xc6, 0xc8, 0x0f, 0x71, - 0x64, 0x82, 0x15, 0x6b, 0x6e, 0x7d, 0xe4, 0x87, 0x7c, 0x5c, 0x09, 0x56, 0x7a, 0xcf, 0x65, 0x65, - 0x45, 0x56, 0x7a, 0xcf, 0xb1, 0x92, 0xbe, 0x03, 0xcb, 0x56, 0x7b, 0xb2, 0xeb, 0xd7, 0xa1, 0x36, - 0x49, 0x9f, 0x47, 0xca, 0x4a, 0x35, 0x25, 0x87, 0x70, 0xbf, 0xc7, 0x15, 0x35, 0xf4, 0x3d, 0x58, - 0x7a, 0xc8, 0xce, 0x24, 0x67, 0xaa, 0x81, 0xbc, 0x71, 0xa1, 0x4f, 0x84, 0xf5, 0xf4, 0x16, 0x10, - 0xf3, 0x63, 0xd9, 0xab, 0xe1, 0x21, 0x39, 0x96, 0x87, 0x44, 0xdf, 0x00, 0x72, 0xe8, 0x0f, 0xc3, - 0xf7, 0x59, 0x92, 0x78, 0x43, 0xad, 0xd4, 0xda, 0x30, 0x33, 0x4a, 0x86, 0x52, 0xf6, 0xf8, 0xbf, - 0xf4, 0x73, 0xb0, 0x6c, 0xd1, 0xc9, 0x86, 0xaf, 0x40, 0x23, 0xf1, 0x87, 0xa1, 0x97, 0x4e, 0x62, - 0x26, 0x9b, 0xce, 0x00, 0x7a, 0x0f, 0x56, 0xbe, 0xc6, 0x62, 0xff, 0x78, 0x7a, 0x51, 0xf3, 0x76, - 0x3b, 0x95, 0x7c, 0x3b, 0xbb, 0xb0, 0x9a, 0x6b, 0x47, 0x76, 0x2f, 0xd8, 0x57, 0xee, 0x64, 0xdd, - 0x15, 0x05, 0x43, 0x98, 0x2b, 0xa6, 0x30, 0xd3, 0x27, 0x40, 0xb6, 0xa3, 0x30, 0x64, 0xfd, 0xf4, - 0x80, 0xb1, 0x38, 0x3b, 0x13, 0x65, 0xbc, 0xda, 0xbc, 0xb3, 0x2e, 0x57, 0x36, 0xaf, 0x21, 0x24, - 0x13, 0x13, 0xa8, 0x8e, 0x59, 0x3c, 0xc2, 0x86, 0xeb, 0x2e, 0xfe, 0x4f, 0x57, 0x61, 0xd9, 0x6a, - 0x56, 0xba, 0xb3, 0x6f, 0xc1, 0xea, 0x8e, 0x9f, 0xf4, 0x8b, 0x1d, 0x76, 0x60, 0x6e, 0x3c, 0x39, - 0xea, 0x65, 0x92, 0xa8, 0x8a, 0xdc, 0xf3, 0xc9, 0x7f, 0x22, 0x1b, 0xfb, 0x05, 0x07, 0xaa, 0x7b, - 0x8f, 0xf7, 0xb7, 0xb9, 0xf2, 0xf3, 0xc3, 0x7e, 0x34, 0xe2, 0x06, 0x44, 0x4c, 0x5a, 0x97, 0xcf, - 0x95, 0xb0, 0x2b, 0xd0, 0x40, 0xbb, 0xc3, 0x9d, 0x39, 0x79, 0x7c, 0xc9, 0x00, 0xee, 0x48, 0xb2, - 0xe7, 0x63, 0x3f, 0x46, 0x4f, 0x51, 0xf9, 0x7f, 0x55, 0xd4, 0x9b, 0xc5, 0x0a, 0xfa, 0xdd, 0x1a, - 0xcc, 0x49, 0x6b, 0x82, 0xfd, 0xf5, 0x53, 0xff, 0x94, 0xc9, 0x91, 0xc8, 0x12, 0xb7, 0xe9, 0x31, - 0x1b, 0x45, 0x29, 0xeb, 0x59, 0xdb, 0x60, 0x83, 0xe8, 0x28, 0x8b, 0x86, 0x7a, 0xc2, 0xb5, 0x9e, - 0x11, 0x54, 0x16, 0xc8, 0x17, 0x8b, 0x03, 0x3d, 0x7f, 0x80, 0x63, 0xaa, 0xba, 0xaa, 0xc8, 0x57, - 0xa2, 0xef, 0x8d, 0xbd, 0xbe, 0x9f, 0x4e, 0xa5, 0x4a, 0xd0, 0x65, 0xde, 0x76, 0x10, 0xf5, 0xbd, - 0xa0, 0x77, 0xe4, 0x05, 0x5e, 0xd8, 0x67, 0xca, 0x09, 0xb7, 0x40, 0xee, 0x90, 0xca, 0x21, 0x29, - 0x32, 0xe1, 0xb4, 0xe6, 0x50, 0x6e, 0x90, 0xfa, 0xd1, 0x68, 0xe4, 0xa7, 0xdc, 0x8f, 0x45, 0x1f, - 0x67, 0xc6, 0x35, 0x10, 0xe1, 0xf2, 0x63, 0xe9, 0x4c, 0xac, 0x5e, 0x43, 0xb9, 0xfc, 0x06, 0xc8, - 0x5b, 0xe1, 0x8e, 0x12, 0x57, 0x63, 0xcf, 0xce, 0x3a, 0x20, 0x5a, 0xc9, 0x10, 0xbe, 0x0f, 0x93, - 0x30, 0x61, 0x69, 0x1a, 0xb0, 0x81, 0x1e, 0x50, 0x13, 0xc9, 0x8a, 0x15, 0xe4, 0x36, 0x2c, 0x0b, - 0xd7, 0x3a, 0xf1, 0xd2, 0x28, 0x39, 0xf1, 0x93, 0x5e, 0xc2, 0x9d, 0xd4, 0x16, 0xd2, 0x97, 0x55, - 0x91, 0x77, 0x60, 0x3d, 0x07, 0xc7, 0xac, 0xcf, 0xfc, 0x53, 0x36, 0xe8, 0xcc, 0xe3, 0x57, 0xe7, - 0x55, 0x93, 0x6b, 0xd0, 0xe4, 0x27, 0x8a, 0xc9, 0x78, 0xe0, 0x71, 0x8b, 0xbc, 0x80, 0xfb, 0x60, - 0x42, 0xe4, 0x2d, 0x98, 0x1f, 0x33, 0x61, 0xce, 0x4f, 0xd2, 0xa0, 0x9f, 0x74, 0x16, 0x2d, 0xed, - 0xc6, 0x39, 0xd7, 0xb5, 0x29, 0x38, 0x53, 0xf6, 0x13, 0x74, 0x2d, 0xbd, 0x69, 0xa7, 0x8d, 0xec, - 0x96, 0x01, 0x28, 0x23, 0xb1, 0x7f, 0xea, 0xa5, 0xac, 0xb3, 0x24, 0x14, 0xba, 0x2c, 0xf2, 0xef, - 0xfc, 0xd0, 0x4f, 0x7d, 0x2f, 0x8d, 0xe2, 0x0e, 0xc1, 0xba, 0x0c, 0xa0, 0xbf, 0xe3, 0x08, 0xb5, - 0x2b, 0x59, 0x54, 0xab, 0xcf, 0xd7, 0xa0, 0x29, 0x98, 0xb3, 0x17, 0x85, 0xc1, 0x54, 0xf2, 0x2b, - 0x08, 0xe8, 0x51, 0x18, 0x4c, 0xc9, 0xa7, 0x60, 0xde, 0x0f, 0x4d, 0x12, 0x21, 0xe1, 0x2d, 0x05, - 0x22, 0xd1, 0x6b, 0xd0, 0x1c, 0x4f, 0x8e, 0x02, 0xbf, 0x2f, 0x48, 0x66, 0x44, 0x2b, 0x02, 0x42, - 0x02, 0xee, 0x0c, 0x8a, 0x71, 0x0a, 0x8a, 0x2a, 0x52, 0x34, 0x25, 0xc6, 0x49, 0xe8, 0x5d, 0x58, - 0xb1, 0x07, 0x28, 0x55, 0xd9, 0x06, 0xd4, 0x25, 0xe7, 0x27, 0x9d, 0x26, 0xae, 0xde, 0x82, 0x5c, - 0x3d, 0x49, 0xea, 0xea, 0x7a, 0xfa, 0xc3, 0x2a, 0x2c, 0x4b, 0x74, 0x3b, 0x88, 0x12, 0x76, 0x38, - 0x19, 0x8d, 0xbc, 0xb8, 0x44, 0xa4, 0x9c, 0x0b, 0x44, 0xaa, 0x62, 0x8b, 0x14, 0x67, 0xf4, 0x13, - 0xcf, 0x0f, 0x85, 0x27, 0x2b, 0xe4, 0xd1, 0x40, 0xc8, 0x4d, 0x58, 0xec, 0x07, 0x51, 0x22, 0xbc, - 0x36, 0xf3, 0x28, 0x99, 0x87, 0x8b, 0x2a, 0xa0, 0x56, 0xa6, 0x02, 0x4c, 0x11, 0x9e, 0xcd, 0x89, - 0x30, 0x85, 0x16, 0x6f, 0x94, 0x29, 0x8d, 0x34, 0x27, 0x3c, 0x39, 0x13, 0xe3, 0xe3, 0xc9, 0x0b, - 0x8c, 0x90, 0xce, 0xc5, 0x32, 0x71, 0xe1, 0x27, 0x55, 0xae, 0xf1, 0x0c, 0xea, 0x86, 0x14, 0x97, - 0x62, 0x15, 0xb9, 0x07, 0x20, 0xfa, 0x42, 0xb3, 0x0b, 0x68, 0x76, 0xdf, 0xb0, 0x77, 0xc4, 0x5c, - 0xfb, 0x5b, 0xbc, 0x30, 0x89, 0x19, 0x9a, 0x62, 0xe3, 0x4b, 0xfa, 0x4b, 0x0e, 0x34, 0x8d, 0x3a, - 0xb2, 0x0a, 0x4b, 0xdb, 0x8f, 0x1e, 0x1d, 0xec, 0xba, 0x5b, 0x8f, 0x1f, 0x7c, 0x6d, 0xb7, 0xb7, - 0xbd, 0xff, 0xe8, 0x70, 0xb7, 0x7d, 0x89, 0xc3, 0xfb, 0x8f, 0xb6, 0xb7, 0xf6, 0x7b, 0xf7, 0x1e, - 0xb9, 0xdb, 0x0a, 0x76, 0xc8, 0x1a, 0x10, 0x77, 0xf7, 0xfd, 0x47, 0x8f, 0x77, 0x2d, 0xbc, 0x42, - 0xda, 0xd0, 0xba, 0xeb, 0xee, 0x6e, 0x6d, 0xef, 0x49, 0x64, 0x86, 0xac, 0x40, 0xfb, 0xde, 0x93, - 0x87, 0x3b, 0x0f, 0x1e, 0xde, 0xef, 0x6d, 0x6f, 0x3d, 0xdc, 0xde, 0xdd, 0xdf, 0xdd, 0x69, 0x57, - 0xc9, 0x3c, 0x34, 0xb6, 0xee, 0x6e, 0x3d, 0xdc, 0x79, 0xf4, 0x70, 0x77, 0xa7, 0x5d, 0xa3, 0x7f, - 0xeb, 0xc0, 0x2a, 0x8e, 0x7a, 0x90, 0x17, 0x90, 0x6b, 0xd0, 0xec, 0x47, 0xd1, 0x98, 0x71, 0x6d, - 0xaf, 0x15, 0xba, 0x09, 0x71, 0xe6, 0x17, 0xea, 0xf3, 0x38, 0x8a, 0xfb, 0x4c, 0xca, 0x07, 0x20, - 0x74, 0x8f, 0x23, 0x9c, 0xf9, 0xe5, 0xf6, 0x0a, 0x0a, 0x21, 0x1e, 0x4d, 0x81, 0x09, 0x92, 0x35, - 0x98, 0x3d, 0x8a, 0x99, 0xd7, 0x3f, 0x91, 0x92, 0x21, 0x4b, 0xe4, 0x33, 0xd9, 0x01, 0xa3, 0xcf, - 0x57, 0x3f, 0x60, 0x03, 0xe4, 0x98, 0xba, 0xbb, 0x28, 0xf1, 0x6d, 0x09, 0x73, 0xf9, 0xf7, 0x8e, - 0xbc, 0x70, 0x10, 0x85, 0x6c, 0x20, 0x9d, 0xbd, 0x0c, 0xa0, 0x07, 0xb0, 0x96, 0x9f, 0x9f, 0x94, - 0xaf, 0xb7, 0x0d, 0xf9, 0x12, 0xbe, 0x57, 0xf7, 0xfc, 0xdd, 0x34, 0x64, 0xed, 0x1f, 0x1c, 0xa8, - 0x72, 0x53, 0x7c, 0xbe, 0xd9, 0x36, 0xbd, 0xab, 0x99, 0x42, 0xfc, 0x09, 0xcf, 0x2c, 0x42, 0x39, - 0x0b, 0x03, 0x66, 0x20, 0x59, 0x7d, 0xcc, 0xfa, 0xa7, 0x38, 0x63, 0x5d, 0xcf, 0x11, 0x2e, 0x20, - 0xdc, 0xf5, 0xc5, 0xaf, 0xa5, 0x80, 0xa8, 0xb2, 0xaa, 0xc3, 0x2f, 0xe7, 0xb2, 0x3a, 0xfc, 0xae, - 0x03, 0x73, 0x7e, 0x78, 0x14, 0x4d, 0xc2, 0x01, 0x0a, 0x44, 0xdd, 0x55, 0x45, 0xbe, 0x7c, 0x63, - 0x14, 0x54, 0x7f, 0xa4, 0xd8, 0x3f, 0x03, 0x28, 0xe1, 0x47, 0xa3, 0x04, 0x5d, 0x0f, 0x1d, 0x74, - 0x79, 0x1b, 0x96, 0x0c, 0x2c, 0x73, 0x63, 0xc7, 0x1c, 0xc8, 0xb9, 0xb1, 0xe8, 0xb3, 0x88, 0x1a, - 0xda, 0x86, 0x85, 0xfb, 0x2c, 0x7d, 0x10, 0x1e, 0x47, 0xaa, 0xa5, 0xdf, 0xaf, 0xc2, 0xa2, 0x86, - 0x64, 0x43, 0x37, 0x61, 0xd1, 0x1f, 0xb0, 0x30, 0xf5, 0xd3, 0x69, 0xcf, 0x3a, 0x81, 0xe5, 0x61, - 0xee, 0xeb, 0x79, 0x81, 0xef, 0xa9, 0x18, 0x9f, 0x28, 0x90, 0x3b, 0xb0, 0xc2, 0x0d, 0x91, 0xb2, - 0x2d, 0x7a, 0x8b, 0xc5, 0xc1, 0xaf, 0xb4, 0x8e, 0x2b, 0x03, 0x8e, 0x4b, 0x6d, 0xaf, 0x3f, 0x11, - 0x3e, 0x4f, 0x59, 0x15, 0x5f, 0x35, 0xd1, 0x12, 0x9f, 0x72, 0x4d, 0x18, 0x2b, 0x0d, 0x14, 0x82, - 0x67, 0xb3, 0x42, 0x55, 0xe5, 0x83, 0x67, 0x46, 0x00, 0xae, 0x5e, 0x08, 0xc0, 0x71, 0x55, 0x36, - 0x0d, 0xfb, 0x6c, 0xd0, 0x4b, 0xa3, 0x1e, 0xaa, 0x5c, 0xdc, 0x9d, 0xba, 0x9b, 0x87, 0xc9, 0x15, - 0x98, 0x4b, 0x59, 0x92, 0x86, 0x2c, 0x45, 0xad, 0x54, 0xc7, 0x80, 0x80, 0x82, 0xb8, 0x83, 0x3a, - 0x89, 0xfd, 0xa4, 0xd3, 0xc2, 0xd0, 0x1a, 0xfe, 0x4f, 0x3e, 0x0f, 0xab, 0x47, 0x2c, 0x49, 0x7b, - 0x27, 0xcc, 0x1b, 0xb0, 0x18, 0x77, 0x5a, 0xc4, 0xf0, 0x84, 0xdd, 0x2f, 0xaf, 0xe4, 0x3c, 0x74, - 0xca, 0xe2, 0xc4, 0x8f, 0x42, 0xb4, 0xf8, 0x0d, 0x57, 0x15, 0x79, 0x7b, 0x7c, 0xf2, 0xda, 0x5e, - 0xea, 0x15, 0x5c, 0xc4, 0x89, 0x97, 0x57, 0x92, 0xeb, 0x30, 0x8b, 0x13, 0x48, 0x3a, 0x6d, 0x2b, - 0xaa, 0xb1, 0xcd, 0x41, 0x57, 0xd6, 0x7d, 0xb9, 0x5a, 0x6f, 0xb6, 0x5b, 0xf4, 0xbf, 0x42, 0x0d, - 0x61, 0xbe, 0xe9, 0x62, 0x31, 0x04, 0x53, 0x88, 0x02, 0x1f, 0x5a, 0xc8, 0xd2, 0xb3, 0x28, 0x7e, - 0xa6, 0x02, 0xbe, 0xb2, 0x48, 0xbf, 0x8d, 0x2e, 0xbe, 0x0e, 0x7c, 0x3e, 0x41, 0xff, 0x84, 0x1f, - 0xd4, 0xc4, 0x52, 0x27, 0x27, 0x9e, 0x3c, 0x75, 0xd4, 0x11, 0x38, 0x3c, 0xf1, 0xb8, 0xda, 0xb2, - 0x76, 0x4f, 0x1c, 0xe4, 0x9a, 0x88, 0xed, 0x89, 0xcd, 0xbb, 0x0e, 0x0b, 0x2a, 0xa4, 0x9a, 0xf4, - 0x02, 0x76, 0x9c, 0xaa, 0xb8, 0x42, 0x38, 0x19, 0xe1, 0x69, 0x6f, 0x9f, 0x1d, 0xa7, 0xf4, 0x21, - 0x2c, 0x49, 0x55, 0xf2, 0x68, 0xcc, 0x54, 0xd7, 0x5f, 0x2c, 0x33, 0xc9, 0xcd, 0x3b, 0xcb, 0xb6, - 0xee, 0x11, 0x41, 0x64, 0x9b, 0x92, 0xba, 0x40, 0x4c, 0xd5, 0x24, 0x1b, 0x94, 0x76, 0x51, 0x45, - 0x4e, 0xe4, 0x74, 0x2c, 0x8c, 0xaf, 0x4f, 0x32, 0xe9, 0xf7, 0x55, 0x40, 0x9c, 0x1f, 0x87, 0x45, - 0x91, 0x7e, 0xdf, 0x81, 0x65, 0x6c, 0x4d, 0x39, 0x15, 0x52, 0xfd, 0xbf, 0xf3, 0x09, 0x86, 0xd9, - 0xea, 0x9b, 0xd1, 0xa4, 0x15, 0xa8, 0x99, 0x06, 0x41, 0x14, 0x3e, 0xf9, 0xa1, 0xbe, 0x9a, 0x3f, - 0xd4, 0xd3, 0xdf, 0x74, 0x60, 0x49, 0xe8, 0xe4, 0xd4, 0x4b, 0x27, 0x89, 0x9c, 0xfe, 0x7f, 0x83, - 0x79, 0x61, 0x5c, 0xa5, 0x54, 0xcb, 0x81, 0xae, 0x68, 0x05, 0x84, 0xa8, 0x20, 0xde, 0xbb, 0xe4, - 0xda, 0xc4, 0xe4, 0x3d, 0x74, 0x70, 0xc2, 0x1e, 0xa2, 0x32, 0x30, 0x78, 0xb9, 0xc4, 0x0c, 0xe8, - 0xef, 0x0d, 0xf2, 0xbb, 0x75, 0x98, 0x15, 0xfe, 0x2e, 0xbd, 0x0f, 0xf3, 0x56, 0x47, 0x56, 0x40, - 0xa1, 0x25, 0x02, 0x0a, 0x85, 0x50, 0x54, 0xa5, 0x24, 0x14, 0xf5, 0x07, 0x33, 0x40, 0x38, 0xb3, - 0xe4, 0x76, 0x83, 0x3b, 0xdc, 0xd1, 0xc0, 0x3a, 0x3e, 0xb5, 0x5c, 0x13, 0x22, 0xb7, 0x80, 0x18, - 0x45, 0x15, 0x51, 0x14, 0xd6, 0xa7, 0xa4, 0x86, 0xab, 0x49, 0x69, 0xbc, 0xa5, 0x99, 0x95, 0x07, - 0x45, 0xb1, 0xec, 0xa5, 0x75, 0xdc, 0xc0, 0x8c, 0x27, 0xc9, 0x09, 0x5e, 0x9d, 0xc8, 0x03, 0x96, - 0x2a, 0xe7, 0xf7, 0x77, 0xf6, 0xc2, 0xfd, 0x9d, 0x2b, 0x04, 0x6d, 0x0c, 0x17, 0xbf, 0x6e, 0xbb, - 0xf8, 0xd7, 0x61, 0x7e, 0xc4, 0x5d, 0xce, 0x34, 0xe8, 0xf7, 0x46, 0xbc, 0x77, 0x79, 0x9e, 0xb2, - 0x40, 0xb2, 0x01, 0x6d, 0xe9, 0x6e, 0x64, 0xe7, 0x08, 0xc0, 0x35, 0x2e, 0xe0, 0x5c, 0x7f, 0x67, - 0x61, 0x9c, 0x26, 0x0e, 0x36, 0x03, 0xf8, 0xc9, 0x2b, 0xe1, 0x1c, 0xd2, 0x9b, 0x84, 0xf2, 0xd6, - 0x84, 0x0d, 0xf0, 0x24, 0x55, 0x77, 0x8b, 0x15, 0xf4, 0xd7, 0x1d, 0x68, 0xf3, 0x3d, 0xb3, 0xd8, - 0xf2, 0x5d, 0x40, 0xa9, 0x78, 0x49, 0xae, 0xb4, 0x68, 0xc9, 0x3b, 0xd0, 0xc0, 0x72, 0x34, 0x66, - 0xa1, 0xe4, 0xc9, 0x8e, 0xcd, 0x93, 0x99, 0x3e, 0xd9, 0xbb, 0xe4, 0x66, 0xc4, 0x06, 0x47, 0xfe, - 0x95, 0x03, 0x4d, 0xd9, 0xcb, 0x4f, 0x1c, 0x26, 0xe8, 0x1a, 0xd7, 0x5c, 0x82, 0x93, 0xb2, 0x5b, - 0xad, 0x9b, 0xb0, 0x38, 0xf2, 0xd2, 0x49, 0xcc, 0xed, 0xb1, 0x15, 0x22, 0xc8, 0xc3, 0xdc, 0xb8, - 0xa2, 0xea, 0x4c, 0x7a, 0xa9, 0x1f, 0xf4, 0x54, 0xad, 0xbc, 0x50, 0x2a, 0xab, 0xe2, 0x1a, 0x24, - 0x49, 0xbd, 0x21, 0x93, 0x76, 0x53, 0x14, 0x68, 0x07, 0xd6, 0xe4, 0x84, 0x72, 0xae, 0x2a, 0xfd, - 0xd3, 0x16, 0xac, 0x17, 0xaa, 0xf4, 0xed, 0xb3, 0x3c, 0xfb, 0x06, 0xfe, 0xe8, 0x28, 0xd2, 0x7e, - 0xbe, 0x63, 0x1e, 0x8b, 0xad, 0x2a, 0x32, 0x84, 0x55, 0xe5, 0x20, 0xf0, 0x35, 0xcd, 0x8c, 0x59, - 0x05, 0xad, 0xd4, 0x5b, 0xf6, 0x16, 0xe6, 0x3b, 0x54, 0xb8, 0x29, 0xc4, 0xe5, 0xed, 0x91, 0x13, - 0xe8, 0x68, 0x4f, 0x44, 0x2a, 0x6b, 0xc3, 0x5b, 0xe1, 0x7d, 0xbd, 0x79, 0x41, 0x5f, 0x96, 0x67, - 0xeb, 0x9e, 0xdb, 0x1a, 0x99, 0xc2, 0x55, 0x55, 0x87, 0xda, 0xb8, 0xd8, 0x5f, 0xf5, 0xa5, 0xe6, - 0x86, 0x3e, 0xbb, 0xdd, 0xe9, 0x05, 0x0d, 0x93, 0x0f, 0x61, 0xed, 0xcc, 0xf3, 0x53, 0x35, 0x2c, - 0xc3, 0x37, 0xa8, 0x61, 0x97, 0x77, 0x2e, 0xe8, 0xf2, 0xa9, 0xf8, 0xd8, 0x32, 0x51, 0xe7, 0xb4, - 0xd8, 0xfd, 0x0b, 0x07, 0x16, 0xec, 0x76, 0x38, 0x9b, 0x4a, 0xd9, 0x57, 0x3a, 0x50, 0x79, 0x93, - 0x39, 0xb8, 0x78, 0x54, 0xae, 0x94, 0x1d, 0x95, 0xcd, 0x03, 0xea, 0xcc, 0x45, 0x31, 0xa6, 0xea, - 0xcb, 0xc5, 0x98, 0x6a, 0x65, 0x31, 0xa6, 0xee, 0xbf, 0x38, 0x40, 0x8a, 0xbc, 0x44, 0xee, 0x8b, - 0xb3, 0x7a, 0xc8, 0x02, 0xa9, 0x52, 0xfe, 0xcb, 0xcb, 0xf1, 0xa3, 0x5a, 0x3b, 0xf5, 0x35, 0x17, - 0x0c, 0xf3, 0x46, 0xd8, 0x74, 0x76, 0xe6, 0xdd, 0xb2, 0xaa, 0x5c, 0xd4, 0xab, 0x7a, 0x71, 0xd4, - 0xab, 0x76, 0x71, 0xd4, 0x6b, 0x36, 0x1f, 0xf5, 0xea, 0xfe, 0xbc, 0x03, 0xcb, 0x25, 0x9b, 0xfe, - 0xb3, 0x9b, 0x38, 0xdf, 0x26, 0x4b, 0x17, 0x54, 0xe4, 0x36, 0x99, 0x60, 0xf7, 0xff, 0xc2, 0xbc, - 0xc5, 0xe8, 0x3f, 0xbb, 0xfe, 0xf3, 0xfe, 0x9a, 0xe0, 0x33, 0x0b, 0xeb, 0xfe, 0x63, 0x05, 0x48, - 0x51, 0xd8, 0xfe, 0x53, 0xc7, 0x50, 0x5c, 0xa7, 0x99, 0x92, 0x75, 0xfa, 0x0f, 0xb5, 0x03, 0x6f, - 0xc2, 0x92, 0x4c, 0x55, 0x31, 0x22, 0x34, 0x82, 0x63, 0x8a, 0x15, 0xdc, 0x63, 0xb5, 0x43, 0x8e, - 0x75, 0xeb, 0xda, 0xdf, 0x30, 0x86, 0xb9, 0xc8, 0x23, 0x5d, 0x83, 0x15, 0x91, 0xfa, 0x72, 0x57, - 0x34, 0xa5, 0xec, 0xca, 0x6f, 0x3b, 0xb0, 0x9a, 0xab, 0xc8, 0x2e, 0xa9, 0x85, 0xe9, 0xb0, 0xed, - 0x89, 0x0d, 0xf2, 0xf1, 0x6b, 0x2f, 0x21, 0xc7, 0x6d, 0xc5, 0x0a, 0xbe, 0x3e, 0x86, 0x57, 0x91, - 0x5b, 0xf5, 0xb2, 0x2a, 0xba, 0x2e, 0x12, 0x74, 0x42, 0x16, 0xe4, 0x06, 0x7e, 0x2c, 0x52, 0x6a, - 0xcc, 0x8a, 0xec, 0xde, 0xc7, 0x1e, 0xb2, 0x2a, 0x72, 0x87, 0xd0, 0x32, 0x53, 0xf6, 0x78, 0x4b, - 0xeb, 0xe8, 0x0f, 0x1d, 0x20, 0x5f, 0x9d, 0xb0, 0x78, 0x8a, 0xf7, 0xcb, 0x3a, 0x74, 0xb4, 0x9e, - 0x0f, 0x8c, 0xcc, 0x8e, 0x27, 0x47, 0x5f, 0x61, 0x53, 0x95, 0xd2, 0x50, 0xc9, 0x52, 0x1a, 0x5e, - 0x05, 0xe0, 0x07, 0x29, 0x7d, 0xbb, 0x8d, 0x8e, 0x58, 0x38, 0x19, 0x89, 0x06, 0x4b, 0xb3, 0x0e, - 0xaa, 0x17, 0x67, 0x1d, 0xd4, 0x2e, 0xca, 0x3a, 0x78, 0x0f, 0x96, 0xad, 0x71, 0xeb, 0x6d, 0x55, - 0xf7, 0xec, 0x4e, 0xf1, 0x9e, 0x5d, 0xdd, 0xb1, 0xd3, 0x5f, 0xac, 0xc0, 0xcc, 0x5e, 0x34, 0x36, - 0xc3, 0xa6, 0x8e, 0x1d, 0x36, 0x95, 0xb6, 0xa4, 0xa7, 0x4d, 0x85, 0x54, 0x31, 0x16, 0x48, 0x36, - 0x60, 0xc1, 0x1b, 0xa5, 0xfc, 0x1c, 0x7f, 0x1c, 0xc5, 0x67, 0x5e, 0x3c, 0x10, 0x7b, 0x8d, 0xc7, - 0xf7, 0x5c, 0x0d, 0x59, 0x81, 0x19, 0xad, 0x74, 0x91, 0x80, 0x17, 0xb9, 0xe3, 0x86, 0x17, 0x32, - 0x53, 0x19, 0x82, 0x90, 0x25, 0xce, 0x4a, 0xf6, 0xf7, 0xc2, 0x6b, 0x16, 0xa2, 0x53, 0x56, 0xc5, - 0xed, 0x1a, 0x5f, 0x3e, 0x24, 0x93, 0xb1, 0x23, 0x55, 0x36, 0xe3, 0x5c, 0x75, 0xfb, 0x7a, 0xea, - 0xc7, 0x0e, 0xd4, 0x70, 0x6d, 0xb8, 0x1a, 0x10, 0xbc, 0xaf, 0x23, 0xa7, 0xb8, 0x26, 0xf3, 0x6e, - 0x1e, 0x26, 0xd4, 0x4a, 0x0a, 0xaa, 0xe8, 0x09, 0x99, 0x89, 0x41, 0xd7, 0xa0, 0x21, 0x4a, 0x3a, - 0x01, 0x06, 0x49, 0x32, 0x90, 0x5c, 0x85, 0xea, 0x49, 0x34, 0x56, 0x7e, 0x0b, 0xa8, 0x6b, 0x85, - 0x68, 0xec, 0x22, 0x9e, 0x8d, 0x87, 0xb7, 0x27, 0xa6, 0x25, 0xac, 0x51, 0x1e, 0xe6, 0xf6, 0x58, - 0x37, 0x6b, 0x2e, 0x53, 0x0e, 0xa5, 0x1b, 0xb0, 0xf8, 0x30, 0x1a, 0x30, 0x23, 0x7c, 0x75, 0x2e, - 0x9f, 0xd3, 0xff, 0xe7, 0x40, 0x5d, 0x11, 0x93, 0x9b, 0x50, 0xe5, 0x4e, 0x46, 0xee, 0x04, 0xa0, - 0xaf, 0x13, 0x39, 0x9d, 0x8b, 0x14, 0x5c, 0x2b, 0x63, 0x54, 0x21, 0x73, 0x38, 0x55, 0x4c, 0x21, - 0xf3, 0xa7, 0xf4, 0x70, 0x73, 0x6e, 0x48, 0x0e, 0xa5, 0x3f, 0x70, 0x60, 0xde, 0xea, 0x83, 0x9f, - 0x21, 0x03, 0x2f, 0x49, 0xe5, 0x15, 0x8d, 0xdc, 0x1e, 0x13, 0x32, 0x37, 0xba, 0x62, 0x07, 0x34, - 0x75, 0xa8, 0x6d, 0xc6, 0x0c, 0xb5, 0xdd, 0x86, 0x46, 0x96, 0xba, 0x55, 0xb5, 0xb4, 0x2d, 0xef, - 0x51, 0x5d, 0x94, 0x66, 0x44, 0x18, 0xbd, 0x89, 0x82, 0x28, 0x96, 0xd1, 0x7f, 0x51, 0xa0, 0xef, - 0x41, 0xd3, 0xa0, 0x37, 0x83, 0x39, 0x8e, 0x15, 0xcc, 0xd1, 0x59, 0x04, 0x95, 0x2c, 0x8b, 0x80, - 0xfe, 0xb9, 0x03, 0xf3, 0x9c, 0x07, 0xfd, 0x70, 0x78, 0x10, 0x05, 0x7e, 0x7f, 0x8a, 0x7b, 0xaf, - 0xd8, 0x4d, 0xea, 0x0c, 0xc5, 0x8b, 0x36, 0xcc, 0xb9, 0x5e, 0x1d, 0x21, 0xa5, 0x88, 0xea, 0x32, - 0x97, 0x61, 0x2e, 0x01, 0x47, 0x5e, 0x22, 0xc5, 0x42, 0x9a, 0x3f, 0x0b, 0xe4, 0x92, 0xc6, 0x81, - 0xd8, 0x4b, 0x59, 0x6f, 0xe4, 0x07, 0x81, 0x2f, 0x68, 0x85, 0x73, 0x54, 0x56, 0xc5, 0xfb, 0x1c, - 0xf8, 0x89, 0x77, 0x94, 0x45, 0xb4, 0x75, 0x99, 0xfe, 0x71, 0x05, 0x9a, 0x52, 0x71, 0xef, 0x0e, - 0x86, 0x4c, 0x5e, 0xbf, 0xa0, 0xfb, 0xa9, 0x95, 0x8c, 0x81, 0xa8, 0x7a, 0xcb, 0x61, 0x35, 0x90, - 0xfc, 0x96, 0xcf, 0x14, 0xb7, 0xfc, 0x0a, 0x34, 0x38, 0xeb, 0xbd, 0x85, 0x9e, 0xb1, 0xb8, 0xba, - 0xc9, 0x00, 0x55, 0x7b, 0x07, 0x6b, 0x6b, 0x59, 0x2d, 0x02, 0x2f, 0xbc, 0xac, 0x79, 0x07, 0x5a, - 0xb2, 0x19, 0xdc, 0x13, 0xd4, 0x29, 0x19, 0xf3, 0x5b, 0xfb, 0xe5, 0x5a, 0x94, 0xea, 0xcb, 0x3b, - 0xea, 0xcb, 0xfa, 0x45, 0x5f, 0x2a, 0x4a, 0x7a, 0x5f, 0xdf, 0x81, 0xdd, 0x8f, 0xbd, 0xf1, 0x89, - 0x92, 0xd2, 0xdb, 0xb0, 0xec, 0x87, 0xfd, 0x60, 0x32, 0x60, 0xbd, 0x49, 0xe8, 0x85, 0x61, 0x34, - 0x09, 0xfb, 0x4c, 0x25, 0x08, 0x94, 0x55, 0xd1, 0x81, 0xce, 0x8f, 0xc2, 0x86, 0xc8, 0x06, 0xd4, - 0x78, 0x47, 0xca, 0x2a, 0x94, 0x8b, 0xb0, 0x20, 0x21, 0x37, 0xa1, 0xc6, 0x06, 0x43, 0xa6, 0x4e, - 0x8b, 0xc4, 0x3e, 0xb7, 0xf3, 0x5d, 0x75, 0x05, 0x01, 0x57, 0x28, 0x1c, 0xcd, 0x29, 0x14, 0xdb, - 0xa2, 0xcc, 0xf2, 0xe2, 0x83, 0x01, 0x5d, 0x01, 0xf2, 0x50, 0xc8, 0x80, 0x19, 0x3e, 0xff, 0xb9, - 0x19, 0x68, 0x1a, 0x30, 0xd7, 0x0d, 0x43, 0x3e, 0xe0, 0xde, 0xc0, 0xf7, 0x46, 0x2c, 0x65, 0xb1, - 0xe4, 0xfb, 0x1c, 0xca, 0xe9, 0xbc, 0xd3, 0x61, 0x2f, 0x9a, 0xa4, 0xbd, 0x01, 0x1b, 0xc6, 0x4c, - 0x18, 0x79, 0x6e, 0x74, 0x2c, 0x94, 0xd3, 0x8d, 0xbc, 0xe7, 0x26, 0x9d, 0xe0, 0xa0, 0x1c, 0xaa, - 0x82, 0xe1, 0x62, 0x8d, 0xaa, 0x59, 0x30, 0x5c, 0xac, 0x48, 0x5e, 0xab, 0xd5, 0x4a, 0xb4, 0xda, - 0xdb, 0xb0, 0x26, 0xf4, 0x97, 0x94, 0xf4, 0x5e, 0x8e, 0xb1, 0xce, 0xa9, 0x25, 0x1b, 0xd0, 0xe6, - 0x63, 0x56, 0x22, 0x91, 0xf8, 0xdf, 0x16, 0x81, 0x25, 0xc7, 0x2d, 0xe0, 0x9c, 0x16, 0x23, 0x3c, - 0x26, 0xad, 0xb8, 0x1c, 0x2c, 0xe0, 0x48, 0xeb, 0x3d, 0xb7, 0x69, 0x1b, 0x92, 0x36, 0x87, 0xd3, - 0x79, 0x68, 0x1e, 0xa6, 0xd1, 0x58, 0x6d, 0xca, 0x02, 0xb4, 0x44, 0x51, 0x26, 0x6a, 0xbc, 0x02, - 0x97, 0x91, 0x8b, 0x1e, 0x47, 0xe3, 0x28, 0x88, 0x86, 0xd3, 0xc3, 0xc9, 0x91, 0x48, 0x26, 0xf6, - 0xa3, 0x90, 0xfe, 0xa5, 0x03, 0xcb, 0x56, 0xad, 0x8c, 0x1e, 0x7d, 0x5e, 0x08, 0x81, 0xbe, 0x61, - 0x17, 0x8c, 0xb7, 0x64, 0x28, 0x57, 0x41, 0x28, 0x62, 0x80, 0x4f, 0xe4, 0xa5, 0xfb, 0x16, 0x2c, - 0xaa, 0x91, 0xa9, 0x0f, 0x05, 0x17, 0x76, 0x8a, 0x5c, 0x28, 0xbf, 0x5f, 0x90, 0x1f, 0xa8, 0x26, - 0xfe, 0xbb, 0xbc, 0x64, 0x1d, 0xe0, 0x1c, 0x55, 0x1c, 0x42, 0x5f, 0x8c, 0x99, 0xa7, 0x11, 0x35, - 0x82, 0xbe, 0x06, 0x13, 0xfa, 0xcb, 0x0e, 0x40, 0x36, 0x3a, 0xbc, 0x9a, 0xd3, 0x06, 0x42, 0xe4, - 0xfb, 0x1b, 0xc6, 0xe0, 0x75, 0x68, 0xe9, 0x2b, 0x9d, 0xcc, 0xe6, 0x34, 0x15, 0xc6, 0x1d, 0xc6, - 0x1b, 0xb0, 0x38, 0x0c, 0xa2, 0x23, 0x34, 0xd8, 0x98, 0xf9, 0x93, 0xc8, 0x74, 0x95, 0x05, 0x01, - 0xdf, 0x93, 0x68, 0x66, 0xa0, 0xaa, 0x86, 0x81, 0xa2, 0xbf, 0x52, 0xd1, 0x11, 0xf8, 0x6c, 0xce, - 0xe7, 0x4a, 0x19, 0xb9, 0x53, 0x50, 0xa7, 0xe7, 0x04, 0xbc, 0x31, 0xe2, 0x76, 0x70, 0x61, 0x40, - 0xe0, 0x3d, 0x58, 0x88, 0x85, 0xbe, 0x52, 0xca, 0xac, 0xfa, 0x02, 0x65, 0x36, 0x1f, 0x5b, 0x56, - 0xec, 0x33, 0xd0, 0xf6, 0x06, 0xa7, 0x2c, 0x4e, 0x7d, 0x3c, 0x92, 0xa1, 0x0b, 0x21, 0x54, 0xf0, - 0xa2, 0x81, 0xa3, 0x65, 0xbf, 0x01, 0x8b, 0x32, 0x45, 0x48, 0x53, 0xca, 0x24, 0xde, 0x0c, 0xe6, - 0x84, 0xf4, 0x77, 0x55, 0xb0, 0xdf, 0xde, 0xc3, 0xf3, 0x57, 0xc4, 0x9c, 0x5d, 0x25, 0x37, 0xbb, - 0x4f, 0xc9, 0xc0, 0xfb, 0x40, 0x9d, 0xfb, 0x66, 0x8c, 0x0b, 0xf9, 0x81, 0xbc, 0x28, 0xb1, 0x97, - 0xb4, 0xfa, 0x32, 0x4b, 0x4a, 0x7f, 0xe4, 0xc0, 0xdc, 0x5e, 0x34, 0xde, 0x93, 0xa9, 0x09, 0x28, - 0x08, 0x3a, 0x37, 0x4f, 0x15, 0x5f, 0x90, 0xb4, 0x50, 0x6a, 0xb9, 0xe7, 0xf3, 0x96, 0xfb, 0x7f, - 0xc2, 0x2b, 0x18, 0x75, 0x88, 0xa3, 0x71, 0x14, 0x73, 0x61, 0xf4, 0x02, 0x61, 0xa6, 0xa3, 0x30, - 0x3d, 0x51, 0x6a, 0xec, 0x45, 0x24, 0x78, 0xbc, 0xe3, 0xc7, 0x12, 0xe1, 0x74, 0x4b, 0x4f, 0x43, - 0x68, 0xb7, 0x62, 0x05, 0xfd, 0x22, 0x34, 0xd0, 0x55, 0xc6, 0x69, 0xbd, 0x09, 0x8d, 0x93, 0x68, - 0xdc, 0x3b, 0xf1, 0xc3, 0x54, 0x09, 0xf7, 0x42, 0xe6, 0xc3, 0xee, 0xe1, 0x82, 0x68, 0x02, 0xfa, - 0xaf, 0x35, 0x98, 0x7b, 0x10, 0x9e, 0x46, 0x7e, 0x1f, 0x2f, 0x16, 0x46, 0x6c, 0x14, 0xa9, 0x4c, - 0x45, 0xfe, 0x3f, 0xb9, 0x02, 0x73, 0x98, 0x9a, 0x33, 0x16, 0x4c, 0xdb, 0x12, 0x17, 0x80, 0x12, - 0xe2, 0x4e, 0x42, 0x9c, 0x25, 0x49, 0x0b, 0xf1, 0x31, 0x10, 0x7e, 0x88, 0x88, 0xcd, 0x24, 0x67, - 0x59, 0xca, 0x32, 0x41, 0x6b, 0x46, 0x26, 0x28, 0xef, 0x4b, 0xa6, 0x52, 0x88, 0xbb, 0x76, 0xd1, - 0x97, 0x84, 0xf0, 0xe0, 0x13, 0x33, 0x11, 0x35, 0x42, 0x97, 0x63, 0x4e, 0x1e, 0x7c, 0x4c, 0x90, - 0xbb, 0x25, 0xe2, 0x03, 0x41, 0x23, 0x94, 0xb0, 0x09, 0x71, 0x17, 0x2e, 0x9f, 0x96, 0xde, 0x10, - 0xbc, 0x9f, 0x83, 0xb9, 0xa6, 0x1e, 0x30, 0xad, 0x50, 0xc5, 0x3c, 0x40, 0x24, 0x82, 0xe7, 0x71, - 0xe3, 0xb8, 0x24, 0xb2, 0xa8, 0xd4, 0x71, 0x89, 0x33, 0x8c, 0x17, 0x04, 0x47, 0x5e, 0xff, 0x19, - 0xbe, 0x3a, 0xc0, 0x50, 0x7f, 0xc3, 0xb5, 0x41, 0x4c, 0x88, 0xc8, 0x76, 0x15, 0xaf, 0x4a, 0xab, - 0xae, 0x09, 0x91, 0x3b, 0xd0, 0xc4, 0x23, 0xa2, 0xdc, 0xd7, 0x05, 0xdc, 0xd7, 0xb6, 0x79, 0x86, - 0xc4, 0x9d, 0x35, 0x89, 0xcc, 0x4b, 0x8f, 0xc5, 0x42, 0x5e, 0x93, 0x37, 0x18, 0xc8, 0xbb, 0xa2, - 0x36, 0xf6, 0x96, 0x01, 0xdc, 0xaa, 0xca, 0x05, 0x13, 0x04, 0x4b, 0x48, 0x60, 0x61, 0xe4, 0x2a, - 0xd4, 0xf9, 0xf1, 0x65, 0xec, 0xf9, 0x03, 0x4c, 0x8c, 0x12, 0xa7, 0x28, 0x8d, 0xf1, 0x36, 0xd4, - 0xff, 0x78, 0xa7, 0xb3, 0x8c, 0xab, 0x62, 0x61, 0x7c, 0x6d, 0x74, 0x19, 0x85, 0x69, 0x45, 0xec, - 0xa8, 0x05, 0x92, 0xb7, 0x30, 0x62, 0x9f, 0xb2, 0xce, 0x2a, 0xa6, 0xc5, 0xbc, 0x22, 0xe7, 0x2c, - 0x99, 0x56, 0xfd, 0x3d, 0xe4, 0x24, 0xae, 0xa0, 0xa4, 0x9f, 0x86, 0x96, 0x09, 0x93, 0x3a, 0x54, - 0x1f, 0x1d, 0xec, 0x3e, 0x6c, 0x5f, 0x22, 0x4d, 0x98, 0x3b, 0xdc, 0x7d, 0xfc, 0x78, 0x7f, 0x77, - 0xa7, 0xed, 0xd0, 0x14, 0xc8, 0xd6, 0x60, 0x20, 0x29, 0xf5, 0x41, 0x3d, 0xe3, 0x59, 0xc7, 0xe2, - 0xd9, 0x12, 0xbe, 0xa9, 0x94, 0xf3, 0xcd, 0x0b, 0x57, 0x97, 0xee, 0x42, 0xf3, 0xc0, 0xc8, 0xd7, - 0x47, 0x11, 0x52, 0x99, 0xfa, 0x52, 0xf4, 0x0c, 0xc4, 0x18, 0x4e, 0xc5, 0x1c, 0x0e, 0xfd, 0x3d, - 0x47, 0xe4, 0x10, 0xeb, 0xe1, 0x8b, 0xbe, 0x29, 0xb4, 0x74, 0x38, 0x25, 0x4b, 0x3e, 0xb3, 0x30, - 0x4e, 0x83, 0x43, 0xe9, 0x45, 0xc7, 0xc7, 0x09, 0x53, 0xa9, 0x22, 0x16, 0xc6, 0x79, 0x9f, 0x7b, - 0x51, 0xdc, 0x23, 0xf1, 0x45, 0x0f, 0x89, 0x4c, 0x19, 0x29, 0xe0, 0x5c, 0x93, 0xc7, 0xec, 0x94, - 0xc5, 0x89, 0x4e, 0x92, 0xd1, 0x65, 0x9d, 0x23, 0x97, 0x5f, 0xe5, 0x0d, 0xa8, 0xeb, 0x76, 0x6d, - 0x25, 0xa5, 0x28, 0x75, 0x3d, 0x57, 0x86, 0x78, 0xae, 0xb0, 0x06, 0x2d, 0x14, 0x73, 0xb1, 0x82, - 0xdc, 0x02, 0x72, 0xec, 0xc7, 0x79, 0xf2, 0x19, 0x24, 0x2f, 0xa9, 0xa1, 0x4f, 0x61, 0x59, 0x31, - 0x8b, 0xe1, 0x3e, 0xd9, 0x9b, 0xe8, 0x5c, 0x24, 0x22, 0x95, 0xa2, 0x88, 0xd0, 0x7f, 0x73, 0x60, - 0x4e, 0xee, 0x74, 0xe1, 0xcd, 0x87, 0xd8, 0x67, 0x0b, 0x23, 0x1d, 0x2b, 0x3d, 0x1e, 0xe5, 0x49, - 0x2a, 0xc6, 0x82, 0xea, 0x9b, 0x29, 0x53, 0x7d, 0x04, 0xaa, 0x63, 0x2f, 0x3d, 0xc1, 0xd3, 0x72, - 0xc3, 0xc5, 0xff, 0x49, 0x5b, 0xc4, 0x76, 0x84, 0x9a, 0xc5, 0xb8, 0x4e, 0xd9, 0xeb, 0x16, 0x61, - 0xd1, 0x8b, 0xaf, 0x5b, 0xae, 0x40, 0x03, 0x07, 0xd0, 0xcb, 0x42, 0x37, 0x19, 0xc0, 0x39, 0x57, - 0x14, 0x50, 0x76, 0x65, 0xa6, 0x6a, 0x86, 0xd0, 0x55, 0xb1, 0xf3, 0x72, 0x09, 0xf4, 0x8d, 0x9a, - 0xcc, 0x49, 0xcc, 0xe0, 0x8c, 0x23, 0xe4, 0x00, 0xf2, 0x1c, 0x21, 0x49, 0x5d, 0x5d, 0x4f, 0xbb, - 0xd0, 0xd9, 0x61, 0x01, 0x4b, 0xd9, 0x56, 0x10, 0xe4, 0xdb, 0x7f, 0x05, 0x2e, 0x97, 0xd4, 0x49, - 0x8f, 0xf9, 0xab, 0xb0, 0xba, 0x25, 0xf2, 0xb7, 0x7e, 0x56, 0x39, 0x09, 0xb4, 0x03, 0x6b, 0xf9, - 0x26, 0x65, 0x67, 0xf7, 0x60, 0x69, 0x87, 0x1d, 0x4d, 0x86, 0xfb, 0xec, 0x34, 0xeb, 0x88, 0x40, - 0x35, 0x39, 0x89, 0xce, 0xa4, 0x60, 0xe2, 0xff, 0xe4, 0x55, 0x80, 0x80, 0xd3, 0xf4, 0x92, 0x31, - 0xeb, 0xab, 0x8c, 0x74, 0x44, 0x0e, 0xc7, 0xac, 0x4f, 0xdf, 0x06, 0x62, 0xb6, 0x23, 0xd7, 0x8b, - 0x5b, 0xba, 0xc9, 0x51, 0x2f, 0x99, 0x26, 0x29, 0x1b, 0xa9, 0x54, 0x7b, 0x13, 0xa2, 0x37, 0xa0, - 0x75, 0xe0, 0x4d, 0x5d, 0xf6, 0x2d, 0xf9, 0xd4, 0x67, 0x1d, 0xe6, 0xc6, 0xde, 0x94, 0xab, 0x29, - 0x1d, 0x53, 0xc2, 0x6a, 0xfa, 0xcf, 0x15, 0x98, 0x15, 0x94, 0xbc, 0xd5, 0x01, 0x4b, 0x52, 0x3f, - 0x44, 0xc6, 0x52, 0xad, 0x1a, 0x50, 0x81, 0x95, 0x2b, 0x25, 0xac, 0x2c, 0xcf, 0x65, 0x2a, 0xbb, - 0x57, 0xf2, 0xab, 0x85, 0x71, 0xe6, 0xca, 0x92, 0x83, 0x44, 0x50, 0x23, 0x03, 0x72, 0xe1, 0xc7, - 0xcc, 0x9e, 0x8a, 0xf1, 0x29, 0x29, 0x95, 0x9c, 0x6b, 0x42, 0xa5, 0x56, 0x7b, 0x4e, 0x30, 0x78, - 0xc1, 0x6a, 0x17, 0xac, 0x73, 0xfd, 0x25, 0xac, 0xb3, 0x38, 0xac, 0xbd, 0xc8, 0x3a, 0xc3, 0x4b, - 0x58, 0x67, 0x4a, 0xa0, 0x7d, 0x8f, 0x31, 0x97, 0x71, 0xff, 0x4f, 0xf1, 0xee, 0x77, 0x1c, 0x68, - 0x4b, 0x2e, 0xd2, 0x75, 0xe4, 0x75, 0xcb, 0xcf, 0x2d, 0xcd, 0xb2, 0xbd, 0x0e, 0xf3, 0xe8, 0x7d, - 0xea, 0x38, 0xab, 0x0c, 0x0a, 0x5b, 0x20, 0x9f, 0x87, 0xba, 0x0c, 0x1b, 0xf9, 0x81, 0xdc, 0x14, - 0x13, 0x52, 0xa1, 0xda, 0xd8, 0x93, 0x49, 0x32, 0x8e, 0xab, 0xcb, 0xf4, 0x4f, 0x1c, 0x58, 0x32, - 0x06, 0x2c, 0xb9, 0xf0, 0x3d, 0x50, 0xd2, 0x20, 0x82, 0xae, 0x42, 0x72, 0xd7, 0x6d, 0xb1, 0xc9, - 0x3e, 0xb3, 0x88, 0x71, 0x33, 0xbd, 0x29, 0x0e, 0x30, 0x99, 0x8c, 0xa4, 0x12, 0x35, 0x21, 0xce, - 0x48, 0x67, 0x8c, 0x3d, 0xd3, 0x24, 0x42, 0x8d, 0x5b, 0x18, 0x66, 0x70, 0x70, 0xaf, 0x59, 0x13, - 0x09, 0x7b, 0x66, 0x83, 0xf4, 0x6f, 0x1c, 0x58, 0x16, 0xc7, 0x1f, 0x79, 0xb8, 0xd4, 0x0f, 0x24, - 0x66, 0xc5, 0x79, 0x4f, 0x48, 0xe4, 0xde, 0x25, 0x57, 0x96, 0xc9, 0x17, 0x5e, 0xf2, 0xc8, 0xa6, - 0x33, 0x77, 0xce, 0xd9, 0x8b, 0x99, 0xb2, 0xbd, 0x78, 0xc1, 0x4a, 0x97, 0x05, 0x19, 0x6b, 0xa5, - 0x41, 0xc6, 0xbb, 0x73, 0x50, 0x4b, 0xfa, 0xd1, 0x98, 0xd1, 0x35, 0x58, 0xb1, 0x27, 0x27, 0x55, - 0xd0, 0xf7, 0x1c, 0xe8, 0xdc, 0x13, 0xc1, 0x78, 0x3f, 0x1c, 0xee, 0xf9, 0x49, 0x1a, 0xc5, 0xfa, - 0x1d, 0xd9, 0x55, 0x80, 0x24, 0xf5, 0xe2, 0x54, 0xe4, 0x67, 0xca, 0x10, 0x60, 0x86, 0xf0, 0x31, - 0xb2, 0x70, 0x20, 0x6a, 0xc5, 0xde, 0xe8, 0x72, 0xc1, 0x87, 0x90, 0x07, 0x34, 0xcb, 0x12, 0xbf, - 0x21, 0x32, 0xd9, 0xb8, 0xaf, 0xc0, 0x4e, 0x51, 0xaf, 0x8b, 0x93, 0x4f, 0x0e, 0xa5, 0x7f, 0xed, - 0xc0, 0x62, 0x36, 0xc8, 0x5d, 0x0e, 0xda, 0xda, 0x41, 0x9a, 0xdf, 0x4c, 0x3b, 0xa8, 0xe0, 0xa4, - 0xcf, 0xed, 0xb1, 0x1c, 0x9b, 0x81, 0xa0, 0xc4, 0xca, 0x52, 0x34, 0x51, 0x0e, 0x8e, 0x09, 0x89, - 0xbc, 0x14, 0xee, 0x09, 0x48, 0xaf, 0x46, 0x96, 0x30, 0xbd, 0x76, 0x94, 0xe2, 0x57, 0xb3, 0xe2, - 0xe8, 0x27, 0x8b, 0xca, 0x94, 0xce, 0x21, 0x8a, 0xa6, 0xd4, 0xbc, 0xd8, 0xa8, 0x8b, 0xf5, 0x51, - 0x65, 0xfa, 0xab, 0x0e, 0x5c, 0x2e, 0x59, 0x78, 0x29, 0x35, 0x3b, 0xb0, 0x74, 0xac, 0x2b, 0xd5, - 0xe2, 0x08, 0xd1, 0x59, 0x53, 0x37, 0x4b, 0xf6, 0x82, 0xb8, 0xc5, 0x0f, 0xb4, 0x5f, 0x24, 0x96, - 0xdb, 0xca, 0xfc, 0x2a, 0x56, 0x6c, 0x7c, 0x09, 0x9a, 0xc6, 0x0b, 0x2e, 0xb2, 0x0e, 0xcb, 0x4f, - 0x1f, 0x3c, 0x7e, 0xb8, 0x7b, 0x78, 0xd8, 0x3b, 0x78, 0x72, 0xf7, 0x2b, 0xbb, 0x5f, 0xef, 0xed, - 0x6d, 0x1d, 0xee, 0xb5, 0x2f, 0x91, 0x35, 0x20, 0x0f, 0x77, 0x0f, 0x1f, 0xef, 0xee, 0x58, 0xb8, - 0x73, 0xe7, 0xd7, 0x66, 0x60, 0x41, 0xdc, 0x58, 0x8a, 0x17, 0xfd, 0x2c, 0x26, 0xef, 0xc3, 0x9c, - 0xfc, 0x45, 0x06, 0xb2, 0x2a, 0x87, 0x6d, 0xff, 0x06, 0x44, 0x77, 0x2d, 0x0f, 0x4b, 0xbe, 0x5c, - 0xfe, 0xff, 0x3f, 0xfa, 0xfb, 0xdf, 0xa8, 0xcc, 0x93, 0xe6, 0xe6, 0xe9, 0x5b, 0x9b, 0x43, 0x16, - 0x26, 0xbc, 0x8d, 0xff, 0x0d, 0x90, 0xfd, 0x56, 0x01, 0xe9, 0x68, 0x7f, 0x30, 0xf7, 0x23, 0x0c, - 0xdd, 0xcb, 0x25, 0x35, 0xb2, 0xdd, 0xcb, 0xd8, 0xee, 0x32, 0x5d, 0xe0, 0xed, 0xfa, 0xa1, 0x9f, - 0x8a, 0x1f, 0x2e, 0x78, 0xd7, 0xd9, 0x20, 0x03, 0x68, 0x99, 0x3f, 0x45, 0x40, 0x54, 0xe0, 0xa9, - 0xe4, 0x87, 0x10, 0xba, 0xaf, 0x94, 0xd6, 0xa9, 0xa8, 0x1b, 0xf6, 0xb1, 0x4a, 0xdb, 0xbc, 0x8f, - 0x09, 0x52, 0x64, 0xbd, 0x04, 0xb0, 0x60, 0xff, 0xe2, 0x00, 0xb9, 0x62, 0xa8, 0x8c, 0xc2, 0xef, - 0x1d, 0x74, 0x5f, 0x3d, 0xa7, 0x56, 0xf6, 0xf5, 0x2a, 0xf6, 0xb5, 0x4e, 0x09, 0xef, 0xab, 0x8f, - 0x34, 0xea, 0xf7, 0x0e, 0xde, 0x75, 0x36, 0xee, 0xfc, 0xd3, 0x6b, 0xd0, 0xd0, 0xa1, 0x62, 0xf2, - 0x21, 0xcc, 0x5b, 0x57, 0xca, 0x44, 0x4d, 0xa3, 0xec, 0x06, 0xba, 0x7b, 0xa5, 0xbc, 0x52, 0x76, - 0x7c, 0x15, 0x3b, 0xee, 0x90, 0x35, 0xde, 0xb1, 0xbc, 0x93, 0xdd, 0xc4, 0x8b, 0x74, 0x91, 0x15, - 0xfb, 0x4c, 0xcc, 0x33, 0xbb, 0x06, 0xb6, 0xe6, 0x59, 0xb8, 0x36, 0xb6, 0xe6, 0x59, 0xbc, 0x3b, - 0xa6, 0x57, 0xb0, 0xbb, 0x35, 0xb2, 0x62, 0x76, 0xa7, 0x43, 0xb8, 0x0c, 0x53, 0xb9, 0xcd, 0x47, - 0xfa, 0xe4, 0x55, 0xcd, 0x58, 0x65, 0x8f, 0xf7, 0x35, 0x8b, 0x14, 0x5f, 0xf0, 0xd3, 0x0e, 0x76, - 0x45, 0x08, 0x6e, 0x9f, 0xf9, 0x46, 0x9f, 0x7c, 0x03, 0x1a, 0xfa, 0xf9, 0x26, 0x59, 0x37, 0x9e, - 0xd3, 0x9a, 0xcf, 0x4d, 0xbb, 0x9d, 0x62, 0x45, 0x19, 0x63, 0x98, 0x2d, 0x73, 0xc6, 0x78, 0x0a, - 0x4d, 0xe3, 0x89, 0x26, 0xb9, 0xac, 0x03, 0xfd, 0xf9, 0x67, 0xa0, 0xdd, 0x6e, 0x59, 0x95, 0xec, - 0x62, 0x09, 0xbb, 0x68, 0x92, 0x06, 0xf2, 0x5e, 0xfa, 0x3c, 0x4a, 0xc8, 0x3e, 0xac, 0xca, 0x83, - 0xcb, 0x11, 0xfb, 0x24, 0x4b, 0x54, 0xf2, 0x9b, 0x05, 0xb7, 0x1d, 0xf2, 0x1e, 0xd4, 0xd5, 0x4b, - 0x5c, 0xb2, 0x56, 0xfe, 0xa2, 0xb8, 0xbb, 0x5e, 0xc0, 0xa5, 0x5a, 0xfb, 0x3a, 0x40, 0xf6, 0x1e, - 0x54, 0x0b, 0x70, 0xe1, 0x7d, 0xa9, 0xde, 0x9d, 0xe2, 0xe3, 0x51, 0xba, 0x86, 0x13, 0x6c, 0x13, - 0x14, 0xe0, 0x90, 0x9d, 0xa9, 0xc7, 0x0d, 0xdf, 0x84, 0xa6, 0xf1, 0x24, 0x54, 0x2f, 0x5f, 0xf1, - 0x39, 0xa9, 0x5e, 0xbe, 0x92, 0x17, 0xa4, 0xb4, 0x8b, 0xad, 0xaf, 0xd0, 0x45, 0xde, 0x7a, 0xe2, - 0x0f, 0xc3, 0x91, 0x20, 0xe0, 0x1b, 0x74, 0x02, 0xf3, 0xd6, 0xbb, 0x4f, 0x2d, 0x3d, 0x65, 0xaf, - 0x4a, 0xb5, 0xf4, 0x94, 0x3e, 0x15, 0x55, 0xec, 0x4c, 0x97, 0x78, 0x3f, 0xa7, 0x48, 0x62, 0xf4, - 0xf4, 0x01, 0x34, 0x8d, 0x37, 0x9c, 0x7a, 0x2e, 0xc5, 0xe7, 0xa2, 0x7a, 0x2e, 0x65, 0x4f, 0x3e, - 0x57, 0xb0, 0x8f, 0x05, 0x8a, 0xac, 0x80, 0x6f, 0x03, 0x78, 0xdb, 0x1f, 0xc2, 0x82, 0xfd, 0xaa, - 0x53, 0xcb, 0x65, 0xe9, 0xfb, 0x50, 0x2d, 0x97, 0xe7, 0x3c, 0x05, 0x95, 0x2c, 0xbd, 0xb1, 0xac, - 0x3b, 0xd9, 0xfc, 0x48, 0x5e, 0xdc, 0x7e, 0x4c, 0xbe, 0xca, 0x95, 0x8f, 0x7c, 0xac, 0x41, 0xd6, - 0x0d, 0xae, 0x35, 0x9f, 0x74, 0x68, 0x79, 0x29, 0xbc, 0xeb, 0xb0, 0x99, 0x59, 0xbc, 0x6e, 0x40, - 0x8b, 0x82, 0x8f, 0x36, 0x0c, 0x8b, 0x62, 0xbe, 0xeb, 0x30, 0x2c, 0x8a, 0xf5, 0xb6, 0x23, 0x6f, - 0x51, 0x52, 0x9f, 0xb7, 0x11, 0xc2, 0x62, 0x2e, 0x7d, 0x49, 0x4b, 0x45, 0x79, 0xbe, 0x67, 0xf7, - 0xea, 0x8b, 0xb3, 0x9e, 0x6c, 0x45, 0xa5, 0x14, 0xd4, 0xa6, 0xca, 0xae, 0xfd, 0x3f, 0xd0, 0x32, - 0xdf, 0xdb, 0x11, 0x53, 0x94, 0xf3, 0x3d, 0xbd, 0x52, 0x5a, 0x67, 0x6f, 0x2e, 0x69, 0x99, 0xdd, - 0xf0, 0xcd, 0xb5, 0x1f, 0x1c, 0x65, 0x4a, 0xb7, 0xec, 0x9d, 0x55, 0xa6, 0x74, 0x4b, 0x5f, 0x29, - 0xa9, 0xcd, 0x25, 0xcb, 0xd6, 0x5c, 0x44, 0x8c, 0x9d, 0x7c, 0x00, 0x8b, 0x46, 0x6e, 0xe0, 0xe1, - 0x34, 0xec, 0x6b, 0x46, 0x2d, 0x26, 0x91, 0x77, 0xcb, 0xfc, 0x62, 0xba, 0x8e, 0xed, 0x2f, 0x51, - 0x6b, 0x12, 0x9c, 0x49, 0xb7, 0xa1, 0x69, 0xe6, 0x1d, 0xbe, 0xa0, 0xdd, 0x75, 0xa3, 0xca, 0xcc, - 0x81, 0xbe, 0xed, 0x90, 0xdf, 0x72, 0xa0, 0x65, 0x65, 0xf1, 0x59, 0x37, 0x49, 0xb9, 0x76, 0x3a, - 0x66, 0x9d, 0xd9, 0x10, 0x75, 0x71, 0x90, 0xfb, 0x1b, 0x5f, 0xb6, 0x16, 0xe1, 0x23, 0xeb, 0x7c, - 0x75, 0x2b, 0xff, 0xb3, 0x13, 0x1f, 0xe7, 0x09, 0xcc, 0x44, 0xfb, 0x8f, 0x6f, 0x3b, 0xe4, 0x07, - 0x0e, 0x2c, 0xd8, 0x51, 0x01, 0xbd, 0x55, 0xa5, 0xf1, 0x07, 0xbd, 0x55, 0xe7, 0x84, 0x12, 0x3e, - 0xc0, 0x51, 0x3e, 0xde, 0x70, 0xad, 0x51, 0xca, 0xa7, 0x68, 0x3f, 0xdd, 0x68, 0xc9, 0xbb, 0xe2, - 0x07, 0x65, 0x54, 0xa8, 0x8a, 0x18, 0xda, 0x3d, 0xbf, 0xbd, 0xe6, 0xaf, 0xa9, 0xdc, 0x74, 0x6e, - 0x3b, 0xe4, 0x9b, 0xe2, 0xd7, 0x29, 0xe4, 0xb7, 0xc8, 0x25, 0x2f, 0xfb, 0x3d, 0xbd, 0x8e, 0x73, - 0xba, 0x4a, 0x2f, 0x5b, 0x73, 0xca, 0xdb, 0xcd, 0x2d, 0x31, 0x3a, 0xf9, 0x43, 0x28, 0x99, 0xe2, - 0x2f, 0xfc, 0x38, 0xca, 0xf9, 0x83, 0x1c, 0x89, 0x41, 0x4a, 0x72, 0x8b, 0x95, 0x5f, 0xb2, 0x19, - 0xba, 0x81, 0x63, 0xbd, 0x4e, 0x5f, 0x3b, 0x77, 0xac, 0x9b, 0x78, 0xb6, 0xe7, 0x23, 0x3e, 0x00, - 0xc8, 0xc2, 0xca, 0x24, 0x17, 0xd6, 0xd4, 0xb6, 0xaf, 0x18, 0x79, 0xb6, 0xe5, 0x45, 0x45, 0x3f, - 0x79, 0x8b, 0xdf, 0x10, 0x6a, 0xe5, 0x81, 0x0a, 0x88, 0x9a, 0xce, 0x83, 0x1d, 0xff, 0xb5, 0x9c, - 0x87, 0x7c, 0xfb, 0x96, 0x52, 0xd1, 0xd1, 0xd5, 0x27, 0x30, 0xbf, 0x1f, 0x45, 0xcf, 0x26, 0x63, - 0x7d, 0x0d, 0x64, 0x87, 0xdd, 0xf6, 0xbc, 0xe4, 0xa4, 0x9b, 0x9b, 0x05, 0xbd, 0x86, 0x4d, 0x75, - 0x49, 0xc7, 0x68, 0x6a, 0xf3, 0xa3, 0x2c, 0x6c, 0xfd, 0x31, 0xf1, 0x60, 0x49, 0xbb, 0x25, 0x7a, - 0xe0, 0x5d, 0xbb, 0x19, 0x33, 0xe0, 0x5a, 0xe8, 0xc2, 0xf2, 0x40, 0xd5, 0x68, 0x37, 0x13, 0xd5, - 0xe6, 0x6d, 0x87, 0x1c, 0x40, 0x6b, 0x87, 0xf5, 0xa3, 0x01, 0x93, 0xb1, 0xab, 0xe5, 0x6c, 0xe0, - 0x3a, 0xe8, 0xd5, 0x9d, 0xb7, 0x40, 0x5b, 0x7f, 0x8f, 0xbd, 0x69, 0xcc, 0xbe, 0xb5, 0xf9, 0x91, - 0x8c, 0x8a, 0x7d, 0xac, 0xf4, 0xb7, 0x0a, 0x1b, 0x5a, 0xfa, 0x3b, 0x17, 0x67, 0xb4, 0xf4, 0x77, - 0x21, 0xce, 0x68, 0x2d, 0xb5, 0x0a, 0x5b, 0x92, 0x00, 0x96, 0x0a, 0xa1, 0x49, 0xf2, 0x9a, 0xb2, - 0xc0, 0xe7, 0x04, 0x34, 0xbb, 0xd7, 0xce, 0x27, 0xb0, 0x7b, 0xdb, 0xb0, 0x7b, 0x3b, 0x84, 0xf9, - 0x1d, 0x26, 0x16, 0x4b, 0xe4, 0x9a, 0xe4, 0xde, 0xa0, 0x9a, 0x99, 0x2c, 0x79, 0x05, 0x8e, 0x75, - 0xb6, 0x81, 0xc6, 0x44, 0x0f, 0xf2, 0x0d, 0x68, 0xde, 0x67, 0xa9, 0x4a, 0x2e, 0xd1, 0x2e, 0x62, - 0x2e, 0xdb, 0xa4, 0x5b, 0x92, 0x9b, 0x62, 0xf3, 0x0c, 0xb6, 0xb6, 0xc9, 0x06, 0x43, 0x26, 0x94, - 0x53, 0xcf, 0x1f, 0x7c, 0x4c, 0xfe, 0x17, 0x36, 0xae, 0xb3, 0xdb, 0xd6, 0x8c, 0x9c, 0x04, 0xb3, - 0xf1, 0xc5, 0x1c, 0x5e, 0xd6, 0x72, 0x18, 0x0d, 0x98, 0xe1, 0xaa, 0x84, 0xd0, 0x34, 0x92, 0x32, - 0xb5, 0x00, 0x15, 0x13, 0x4c, 0xb5, 0x00, 0x95, 0xe4, 0x70, 0xd2, 0x9b, 0xd8, 0x0f, 0x25, 0xd7, - 0xb2, 0x7e, 0x44, 0xde, 0x66, 0xd6, 0xd3, 0xe6, 0x47, 0xde, 0x28, 0xfd, 0x98, 0x3c, 0xc5, 0xf7, - 0xa8, 0x66, 0x02, 0x4d, 0xe6, 0xf3, 0xe6, 0x73, 0x6d, 0xf4, 0x62, 0x19, 0x55, 0xb6, 0x1f, 0x2c, - 0xba, 0x42, 0x8f, 0xe6, 0x0b, 0x00, 0x87, 0x69, 0x34, 0xde, 0xf1, 0xd8, 0x28, 0x0a, 0x33, 0x5d, - 0x9b, 0x25, 0x89, 0x64, 0xfa, 0xcb, 0xc8, 0x14, 0x21, 0x4f, 0x8d, 0x43, 0x82, 0x95, 0x7f, 0xa4, - 0x98, 0xeb, 0xdc, 0x3c, 0x12, 0xbd, 0x20, 0x25, 0xb9, 0x24, 0xb7, 0x1d, 0xb2, 0x05, 0x90, 0xc5, - 0xa6, 0xb5, 0xcb, 0x5f, 0x08, 0x7b, 0x6b, 0xb5, 0x57, 0x12, 0xc8, 0x3e, 0x80, 0x46, 0x16, 0xec, - 0x5c, 0xcf, 0x12, 0x6b, 0xad, 0xd0, 0xa8, 0xb6, 0xe0, 0x85, 0x10, 0x24, 0x6d, 0xe3, 0x52, 0x01, - 0xa9, 0xf3, 0xa5, 0xc2, 0xb8, 0xa2, 0x0f, 0xcb, 0x62, 0x80, 0xda, 0x1d, 0xc1, 0xb4, 0x07, 0x35, - 0x93, 0x92, 0x30, 0xa0, 0x96, 0xe6, 0xd2, 0x28, 0x9a, 0x15, 0x55, 0xe0, 0xdc, 0x2a, 0x52, 0x2e, - 0xb8, 0x6a, 0x1e, 0xc1, 0x52, 0x21, 0xcc, 0xa3, 0x45, 0xfa, 0xbc, 0xc8, 0x9b, 0x16, 0xe9, 0x73, - 0x23, 0x44, 0x74, 0x15, 0xbb, 0x5c, 0xa4, 0x80, 0x27, 0x95, 0x33, 0x3f, 0xed, 0x9f, 0xbc, 0xeb, - 0x6c, 0xdc, 0xbd, 0xf1, 0xc1, 0xa7, 0x87, 0x7e, 0x7a, 0x32, 0x39, 0xba, 0xd5, 0x8f, 0x46, 0x9b, - 0x81, 0x3a, 0xfa, 0xcb, 0xe4, 0xa5, 0xcd, 0x20, 0x1c, 0x6c, 0x62, 0xcb, 0x47, 0xb3, 0xf8, 0xab, - 0x9c, 0x9f, 0xfb, 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x93, 0xfe, 0x9d, 0xc7, 0x53, 0x00, - 0x00, +var fileDescriptor_rpc_3a8b115cef624d58 = []byte{ + // 6971 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7c, 0x5d, 0x6c, 0x24, 0xd9, + 0x55, 0xff, 0x54, 0x7f, 0xd8, 0xdd, 0xa7, 0xdb, 0xed, 0xf6, 0xf5, 0x57, 0x4f, 0xef, 0xec, 0xec, + 0x6c, 0x65, 0xb2, 0x33, 0x71, 0xf6, 0x3f, 0x9e, 0x9d, 0x24, 0xfb, 0xdf, 0xec, 0x92, 0x80, 0xc7, + 0xf6, 0x8c, 0x27, 0xf1, 0x7a, 0x9c, 0xf2, 0x4c, 0x86, 0x6c, 0x82, 0x3a, 0xe5, 0xee, 0xeb, 0x76, + 0xed, 0x54, 0x57, 0x75, 0xaa, 0xaa, 0xed, 0xe9, 0x2c, 0x2b, 0x21, 0x40, 0x20, 0x21, 0x10, 0x02, + 0x5e, 0x08, 0x0a, 0x42, 0x0a, 0x48, 0x24, 0x8f, 0x3c, 0x24, 0x42, 0x02, 0xde, 0x10, 0x12, 0x48, + 0x08, 0xa1, 0x3c, 0x22, 0xf1, 0x02, 0x2f, 0x81, 0x37, 0x24, 0x1e, 0x78, 0x40, 0x42, 0xf7, 0xdc, + 0x8f, 0xba, 0xb7, 0xaa, 0x7a, 0x3c, 0x9b, 0x04, 0x9e, 0xec, 0xfb, 0xbb, 0xa7, 0xee, 0xe7, 0xf9, + 0xba, 0xe7, 0x9e, 0xdb, 0x50, 0x8f, 0xc6, 0xfd, 0x5b, 0xe3, 0x28, 0x4c, 0x42, 0x52, 0xf5, 0x83, + 0x68, 0xdc, 0xef, 0x5e, 0x19, 0x86, 0xe1, 0xd0, 0xa7, 0x9b, 0xee, 0xd8, 0xdb, 0x74, 0x83, 0x20, + 0x4c, 0xdc, 0xc4, 0x0b, 0x83, 0x98, 0x13, 0xd9, 0x5f, 0x87, 0xd6, 0x7d, 0x1a, 0x1c, 0x51, 0x3a, + 0x70, 0xe8, 0x37, 0x26, 0x34, 0x4e, 0xc8, 0x27, 0x61, 0xc9, 0xa5, 0xdf, 0xa4, 0x74, 0xd0, 0x1b, + 0xbb, 0x71, 0x3c, 0x3e, 0x8d, 0xdc, 0x98, 0x76, 0xac, 0x6b, 0xd6, 0xcd, 0xa6, 0xd3, 0xe6, 0x15, + 0x87, 0x0a, 0x27, 0xaf, 0x42, 0x33, 0x66, 0xa4, 0x34, 0x48, 0xa2, 0x70, 0x3c, 0xed, 0x94, 0x90, + 0xae, 0xc1, 0xb0, 0x5d, 0x0e, 0xd9, 0x3e, 0x2c, 0xaa, 0x1e, 0xe2, 0x71, 0x18, 0xc4, 0x94, 0xdc, + 0x86, 0x95, 0xbe, 0x37, 0x3e, 0xa5, 0x51, 0x0f, 0x3f, 0x1e, 0x05, 0x74, 0x14, 0x06, 0x5e, 0xbf, + 0x63, 0x5d, 0x2b, 0xdf, 0xac, 0x3b, 0x84, 0xd7, 0xb1, 0x2f, 0xde, 0x15, 0x35, 0xe4, 0x06, 0x2c, + 0xd2, 0x80, 0xe3, 0x74, 0x80, 0x5f, 0x89, 0xae, 0x5a, 0x29, 0xcc, 0x3e, 0xb0, 0xff, 0xda, 0x82, + 0xa5, 0x07, 0x81, 0x97, 0x3c, 0x71, 0x7d, 0x9f, 0x26, 0x72, 0x4e, 0x37, 0x60, 0xf1, 0x1c, 0x01, + 0x9c, 0xd3, 0x79, 0x18, 0x0d, 0xc4, 0x8c, 0x5a, 0x1c, 0x3e, 0x14, 0xe8, 0xcc, 0x91, 0x95, 0x66, + 0x8e, 0xac, 0x70, 0xb9, 0xca, 0x33, 0x96, 0xeb, 0x06, 0x2c, 0x46, 0xb4, 0x1f, 0x9e, 0xd1, 0x68, + 0xda, 0x3b, 0xf7, 0x82, 0x41, 0x78, 0xde, 0xa9, 0x5c, 0xb3, 0x6e, 0x56, 0x9d, 0x96, 0x84, 0x9f, + 0x20, 0x6a, 0xaf, 0x00, 0xd1, 0x67, 0xc1, 0xd7, 0xcd, 0x1e, 0xc2, 0xf2, 0xe3, 0xc0, 0x0f, 0xfb, + 0x4f, 0x7f, 0xcc, 0xd9, 0x15, 0x74, 0x5f, 0x2a, 0xec, 0x7e, 0x0d, 0x56, 0xcc, 0x8e, 0xc4, 0x00, + 0x28, 0xac, 0x6e, 0x9f, 0xba, 0xc1, 0x90, 0xca, 0x26, 0xe5, 0x10, 0x3e, 0x01, 0xed, 0xfe, 0x24, + 0x8a, 0x68, 0x90, 0x1b, 0xc3, 0xa2, 0xc0, 0xd5, 0x20, 0x5e, 0x85, 0x66, 0x40, 0xcf, 0x53, 0x32, + 0xc1, 0x32, 0x01, 0x3d, 0x97, 0x24, 0x76, 0x07, 0xd6, 0xb2, 0xdd, 0x88, 0x01, 0xfc, 0xc8, 0x82, + 0xca, 0xe3, 0xe4, 0x59, 0x48, 0x6e, 0x41, 0x25, 0x99, 0x8e, 0x39, 0x63, 0xb6, 0xee, 0x90, 0x5b, + 0xc8, 0xeb, 0xb7, 0xb6, 0x06, 0x83, 0x88, 0xc6, 0xf1, 0xa3, 0xe9, 0x98, 0x3a, 0x4d, 0x97, 0x17, + 0x7a, 0x8c, 0x8e, 0x74, 0x60, 0x5e, 0x94, 0xb1, 0xc3, 0xba, 0x23, 0x8b, 0xe4, 0x2a, 0x80, 0x3b, + 0x0a, 0x27, 0x41, 0xd2, 0x8b, 0xdd, 0x04, 0x77, 0xae, 0xec, 0x68, 0x08, 0xb9, 0x0e, 0x0b, 0x71, + 0x3f, 0xf2, 0xc6, 0x49, 0x6f, 0x3c, 0x39, 0x7e, 0x4a, 0xa7, 0xb8, 0x63, 0x75, 0xc7, 0x04, 0xc9, + 0x27, 0xa1, 0x16, 0x4e, 0x92, 0x71, 0xe8, 0x05, 0x49, 0xa7, 0x7a, 0xcd, 0xba, 0xd9, 0xb8, 0xb3, + 0x28, 0xc6, 0xf4, 0x70, 0x92, 0x1c, 0x32, 0xd8, 0x51, 0x04, 0xac, 0xc9, 0x7e, 0x18, 0x9c, 0x78, + 0xd1, 0x88, 0xcb, 0x62, 0x67, 0x0e, 0x7b, 0x35, 0x41, 0xfb, 0x5b, 0x25, 0x68, 0x3c, 0x8a, 0xdc, + 0x20, 0x76, 0xfb, 0x0c, 0x60, 0x53, 0x48, 0x9e, 0xf5, 0x4e, 0xdd, 0xf8, 0x14, 0x67, 0x5d, 0x77, + 0x64, 0x91, 0xac, 0xc1, 0x1c, 0x1f, 0x30, 0xce, 0xad, 0xec, 0x88, 0x12, 0x79, 0x1d, 0x96, 0x82, + 0xc9, 0xa8, 0x67, 0xf6, 0x55, 0xc6, 0x1d, 0xcf, 0x57, 0xb0, 0x85, 0x38, 0x66, 0x7b, 0xce, 0xbb, + 0xe0, 0xb3, 0xd4, 0x10, 0x62, 0x43, 0x53, 0x94, 0xa8, 0x37, 0x3c, 0xe5, 0xd3, 0xac, 0x3a, 0x06, + 0xc6, 0xda, 0x48, 0xbc, 0x11, 0xed, 0xc5, 0x89, 0x3b, 0x1a, 0x8b, 0x69, 0x69, 0x08, 0xd6, 0x87, + 0x89, 0xeb, 0xf7, 0x4e, 0x28, 0x8d, 0x3b, 0xf3, 0xa2, 0x5e, 0x21, 0xe4, 0x35, 0x68, 0x0d, 0x68, + 0x9c, 0xf4, 0xc4, 0xe6, 0xd0, 0xb8, 0x53, 0x43, 0xc9, 0xcb, 0xa0, 0x8c, 0x43, 0xee, 0xd3, 0x44, + 0x5b, 0x9d, 0x58, 0x70, 0xa2, 0xbd, 0x0f, 0x44, 0x83, 0x77, 0x68, 0xe2, 0x7a, 0x7e, 0x4c, 0xde, + 0x84, 0x66, 0xa2, 0x11, 0xa3, 0xa6, 0x69, 0x28, 0xb6, 0xd1, 0x3e, 0x70, 0x0c, 0x3a, 0xfb, 0x3e, + 0xd4, 0xee, 0x51, 0xba, 0xef, 0x8d, 0xbc, 0x84, 0xac, 0x41, 0xf5, 0xc4, 0x7b, 0x46, 0x39, 0x63, + 0x97, 0xf7, 0x2e, 0x39, 0xbc, 0x48, 0xba, 0x30, 0x3f, 0xa6, 0x51, 0x9f, 0xca, 0xe5, 0xdf, 0xbb, + 0xe4, 0x48, 0xe0, 0xee, 0x3c, 0x54, 0x7d, 0xf6, 0xb1, 0xfd, 0xdd, 0x12, 0x34, 0x8e, 0x68, 0xa0, + 0x04, 0x86, 0x40, 0x85, 0x4d, 0x49, 0x08, 0x09, 0xfe, 0x4f, 0x5e, 0x81, 0x06, 0x4e, 0x33, 0x4e, + 0x22, 0x2f, 0x18, 0x0a, 0x3e, 0x05, 0x06, 0x1d, 0x21, 0x42, 0xda, 0x50, 0x76, 0x47, 0x92, 0x47, + 0xd9, 0xbf, 0x4c, 0x98, 0xc6, 0xee, 0x74, 0xc4, 0xe4, 0x4e, 0xed, 0x5a, 0xd3, 0x69, 0x08, 0x6c, + 0x8f, 0x6d, 0xdb, 0x2d, 0x58, 0xd6, 0x49, 0x64, 0xeb, 0x55, 0x6c, 0x7d, 0x49, 0xa3, 0x14, 0x9d, + 0xdc, 0x80, 0x45, 0x49, 0x1f, 0xf1, 0xc1, 0xe2, 0x3e, 0xd6, 0x9d, 0x96, 0x80, 0xe5, 0x14, 0x6e, + 0x42, 0xfb, 0xc4, 0x0b, 0x5c, 0xbf, 0xd7, 0xf7, 0x93, 0xb3, 0xde, 0x80, 0xfa, 0x89, 0x8b, 0x3b, + 0x5a, 0x75, 0x5a, 0x88, 0x6f, 0xfb, 0xc9, 0xd9, 0x0e, 0x43, 0xc9, 0xeb, 0x50, 0x3f, 0xa1, 0xb4, + 0x87, 0x2b, 0xd1, 0xa9, 0x19, 0xd2, 0x21, 0x57, 0xd7, 0xa9, 0x9d, 0x88, 0xff, 0xec, 0x3f, 0xb7, + 0xa0, 0xc9, 0x97, 0x4a, 0x98, 0x8b, 0xeb, 0xb0, 0x20, 0x47, 0x44, 0xa3, 0x28, 0x8c, 0x04, 0xfb, + 0x9b, 0x20, 0xd9, 0x80, 0xb6, 0x04, 0xc6, 0x11, 0xf5, 0x46, 0xee, 0x90, 0x0a, 0xdd, 0x92, 0xc3, + 0xc9, 0x9d, 0xb4, 0xc5, 0x28, 0x9c, 0x24, 0x5c, 0x61, 0x37, 0xee, 0x34, 0xc5, 0xa0, 0x1c, 0x86, + 0x39, 0x26, 0x09, 0x63, 0xff, 0x82, 0xa5, 0x36, 0x30, 0xfb, 0xfb, 0x16, 0x10, 0x36, 0xf4, 0x47, + 0x21, 0x6f, 0x42, 0xac, 0x54, 0x76, 0x97, 0xac, 0x17, 0xde, 0xa5, 0xd2, 0xac, 0x5d, 0xba, 0x09, + 0x73, 0x38, 0x2c, 0x26, 0xcf, 0xe5, 0xec, 0xd0, 0xef, 0x96, 0x3a, 0x96, 0x23, 0xea, 0x89, 0x0d, + 0x55, 0x3e, 0xc7, 0x4a, 0xc1, 0x1c, 0x79, 0x95, 0xfd, 0x1d, 0x0b, 0x9a, 0x4c, 0xe3, 0x06, 0xd4, + 0x47, 0x5d, 0x45, 0x6e, 0x03, 0x39, 0x99, 0x04, 0x03, 0x2f, 0x18, 0xf6, 0x92, 0x67, 0xde, 0xa0, + 0x77, 0x3c, 0x65, 0x5d, 0xe1, 0xb8, 0xf7, 0x2e, 0x39, 0x05, 0x75, 0xe4, 0x75, 0x68, 0x1b, 0x68, + 0x9c, 0x44, 0x7c, 0xf4, 0x7b, 0x97, 0x9c, 0x5c, 0x0d, 0x5b, 0x4c, 0xa6, 0x0d, 0x27, 0x49, 0xcf, + 0x0b, 0x06, 0xf4, 0x19, 0xae, 0xff, 0x82, 0x63, 0x60, 0x77, 0x5b, 0xd0, 0xd4, 0xbf, 0xb3, 0xdf, + 0x87, 0x9a, 0xd4, 0xa5, 0xa8, 0x47, 0x32, 0xe3, 0x72, 0x34, 0x84, 0x74, 0xa1, 0x66, 0x8e, 0xc2, + 0xa9, 0x7d, 0x94, 0xbe, 0xed, 0xcf, 0x43, 0x7b, 0x9f, 0x29, 0xb4, 0xc0, 0x0b, 0x86, 0xc2, 0xa8, + 0x30, 0x2d, 0x2b, 0x2c, 0x00, 0xe7, 0x3f, 0x51, 0x62, 0xa2, 0x7c, 0x1a, 0xc6, 0x89, 0xe8, 0x07, + 0xff, 0xb7, 0xff, 0xc5, 0x82, 0x45, 0xc6, 0x08, 0xef, 0xba, 0xc1, 0x54, 0x72, 0xc1, 0x3e, 0x34, + 0x59, 0x53, 0x8f, 0xc2, 0x2d, 0xae, 0xab, 0xb9, 0x0e, 0xba, 0x29, 0xf6, 0x23, 0x43, 0x7d, 0x4b, + 0x27, 0x65, 0xae, 0xd4, 0xd4, 0x31, 0xbe, 0x66, 0xca, 0x22, 0x71, 0xa3, 0x21, 0x4d, 0x50, 0x8b, + 0x0b, 0xad, 0x0e, 0x1c, 0xda, 0x0e, 0x83, 0x13, 0x72, 0x0d, 0x9a, 0xb1, 0x9b, 0xf4, 0xc6, 0x34, + 0xc2, 0x35, 0x41, 0x81, 0x2f, 0x3b, 0x10, 0xbb, 0xc9, 0x21, 0x8d, 0xee, 0x4e, 0x13, 0xda, 0xfd, + 0x59, 0x58, 0xca, 0xf5, 0xc2, 0x74, 0x4c, 0x3a, 0x45, 0xf6, 0x2f, 0x59, 0x81, 0xea, 0x99, 0xeb, + 0x4f, 0xa8, 0x30, 0x2e, 0xbc, 0xf0, 0x76, 0xe9, 0x2d, 0xcb, 0x7e, 0x0d, 0xda, 0xe9, 0xb0, 0x85, + 0xb0, 0x12, 0xa8, 0xb0, 0x95, 0x16, 0x0d, 0xe0, 0xff, 0xf6, 0xb7, 0x2d, 0x4e, 0xb8, 0x1d, 0x7a, + 0x4a, 0x51, 0x33, 0x42, 0xa6, 0xcf, 0x25, 0x21, 0xfb, 0x7f, 0xa6, 0x21, 0xfb, 0xc9, 0x27, 0x4b, + 0x2e, 0x43, 0x2d, 0xa6, 0xc1, 0xa0, 0xe7, 0xfa, 0x3e, 0xea, 0xb3, 0x9a, 0x33, 0xcf, 0xca, 0x5b, + 0xbe, 0x6f, 0xdf, 0x80, 0x25, 0x6d, 0x74, 0xcf, 0x99, 0xc7, 0x01, 0x90, 0x7d, 0x2f, 0x4e, 0x1e, + 0x07, 0xf1, 0x58, 0xd3, 0x83, 0x2f, 0x41, 0x7d, 0xe4, 0x05, 0x38, 0x32, 0xce, 0x8a, 0x55, 0xa7, + 0x36, 0xf2, 0x02, 0x36, 0xae, 0x18, 0x2b, 0xdd, 0x67, 0xa2, 0xb2, 0x24, 0x2a, 0xdd, 0x67, 0x58, + 0x69, 0xbf, 0x05, 0xcb, 0x46, 0x7b, 0xa2, 0xeb, 0x57, 0xa1, 0x3a, 0x49, 0x9e, 0x85, 0xd2, 0x4a, + 0x35, 0x04, 0x87, 0x30, 0xbf, 0xc7, 0xe1, 0x35, 0xf6, 0x3b, 0xb0, 0x74, 0x40, 0xcf, 0x05, 0x67, + 0xca, 0x81, 0xbc, 0x76, 0xa1, 0x4f, 0x84, 0xf5, 0xf6, 0x2d, 0x20, 0xfa, 0xc7, 0xa2, 0x57, 0xcd, + 0x43, 0xb2, 0x0c, 0x0f, 0xc9, 0x7e, 0x0d, 0xc8, 0x91, 0x37, 0x0c, 0xde, 0xa5, 0x71, 0xec, 0x0e, + 0x95, 0x52, 0x6b, 0x43, 0x79, 0x14, 0x0f, 0x85, 0xec, 0xb1, 0x7f, 0xed, 0x4f, 0xc1, 0xb2, 0x41, + 0x27, 0x1a, 0xbe, 0x02, 0xf5, 0xd8, 0x1b, 0x06, 0x6e, 0x32, 0x89, 0xa8, 0x68, 0x3a, 0x05, 0xec, + 0x7b, 0xb0, 0xf2, 0x65, 0x1a, 0x79, 0x27, 0xd3, 0x8b, 0x9a, 0x37, 0xdb, 0x29, 0x65, 0xdb, 0xd9, + 0x85, 0xd5, 0x4c, 0x3b, 0xa2, 0x7b, 0xce, 0xbe, 0x62, 0x27, 0x6b, 0x0e, 0x2f, 0x68, 0xc2, 0x5c, + 0xd2, 0x85, 0xd9, 0x7e, 0x0c, 0x64, 0x3b, 0x0c, 0x02, 0xda, 0x4f, 0x0e, 0x29, 0x8d, 0xd2, 0x33, + 0x51, 0xca, 0xab, 0x8d, 0x3b, 0xeb, 0x62, 0x65, 0xb3, 0x1a, 0x42, 0x30, 0x31, 0x81, 0xca, 0x98, + 0x46, 0x23, 0x6c, 0xb8, 0xe6, 0xe0, 0xff, 0xf6, 0x2a, 0x2c, 0x1b, 0xcd, 0x0a, 0x77, 0xf6, 0x0d, + 0x58, 0xdd, 0xf1, 0xe2, 0x7e, 0xbe, 0xc3, 0x0e, 0xcc, 0x8f, 0x27, 0xc7, 0xbd, 0x54, 0x12, 0x65, + 0x91, 0x79, 0x3e, 0xd9, 0x4f, 0x44, 0x63, 0xbf, 0x66, 0x41, 0x65, 0xef, 0xd1, 0xfe, 0x36, 0x53, + 0x7e, 0x5e, 0xd0, 0x0f, 0x47, 0xcc, 0x80, 0xf0, 0x49, 0xab, 0xf2, 0x4c, 0x09, 0xbb, 0x02, 0x75, + 0xb4, 0x3b, 0xcc, 0x99, 0x13, 0xc7, 0x97, 0x14, 0x60, 0x8e, 0x24, 0x7d, 0x36, 0xf6, 0x22, 0xf4, + 0x14, 0xa5, 0xff, 0x57, 0x41, 0xbd, 0x99, 0xaf, 0xb0, 0xbf, 0x5d, 0x85, 0x79, 0x61, 0x4d, 0xb0, + 0xbf, 0x7e, 0xe2, 0x9d, 0x51, 0x31, 0x12, 0x51, 0x62, 0x36, 0x3d, 0xa2, 0xa3, 0x30, 0xa1, 0x3d, + 0x63, 0x1b, 0x4c, 0x10, 0x1d, 0x65, 0xde, 0x50, 0x8f, 0xbb, 0xd6, 0x65, 0x4e, 0x65, 0x80, 0x6c, + 0xb1, 0x18, 0xd0, 0xf3, 0x06, 0x38, 0xa6, 0x8a, 0x23, 0x8b, 0x6c, 0x25, 0xfa, 0xee, 0xd8, 0xed, + 0x7b, 0xc9, 0x54, 0xa8, 0x04, 0x55, 0x66, 0x6d, 0xfb, 0x61, 0xdf, 0xf5, 0x7b, 0xc7, 0xae, 0xef, + 0x06, 0x7d, 0x2a, 0x9d, 0x70, 0x03, 0x64, 0x0e, 0xa9, 0x18, 0x92, 0x24, 0xe3, 0x4e, 0x6b, 0x06, + 0x65, 0x06, 0xa9, 0x1f, 0x8e, 0x46, 0x5e, 0xc2, 0xfc, 0x58, 0xf4, 0x71, 0xca, 0x8e, 0x86, 0x70, + 0x97, 0x1f, 0x4b, 0xe7, 0x7c, 0xf5, 0xea, 0xd2, 0xe5, 0xd7, 0x40, 0xd6, 0x0a, 0x73, 0x94, 0x98, + 0x1a, 0x7b, 0x7a, 0xde, 0x01, 0xde, 0x4a, 0x8a, 0xb0, 0x7d, 0x98, 0x04, 0x31, 0x4d, 0x12, 0x9f, + 0x0e, 0xd4, 0x80, 0x1a, 0x48, 0x96, 0xaf, 0x20, 0xb7, 0x61, 0x99, 0xbb, 0xd6, 0xb1, 0x9b, 0x84, + 0xf1, 0xa9, 0x17, 0xf7, 0x62, 0xe6, 0xa4, 0x36, 0x91, 0xbe, 0xa8, 0x8a, 0xbc, 0x05, 0xeb, 0x19, + 0x38, 0xa2, 0x7d, 0xea, 0x9d, 0xd1, 0x41, 0x67, 0x01, 0xbf, 0x9a, 0x55, 0x4d, 0xae, 0x41, 0x83, + 0x9d, 0x28, 0x26, 0xe3, 0x81, 0xcb, 0x2c, 0x72, 0x0b, 0xf7, 0x41, 0x87, 0xc8, 0x1b, 0xb0, 0x30, + 0xa6, 0xdc, 0x9c, 0x9f, 0x26, 0x7e, 0x3f, 0xee, 0x2c, 0x1a, 0xda, 0x8d, 0x71, 0xae, 0x63, 0x52, + 0x30, 0xa6, 0xec, 0xc7, 0xe8, 0x5a, 0xba, 0xd3, 0x4e, 0x1b, 0xd9, 0x2d, 0x05, 0x50, 0x46, 0x22, + 0xef, 0xcc, 0x4d, 0x68, 0x67, 0x89, 0x2b, 0x74, 0x51, 0x64, 0xdf, 0x79, 0x81, 0x97, 0x78, 0x6e, + 0x12, 0x46, 0x1d, 0x82, 0x75, 0x29, 0x60, 0xff, 0x91, 0xc5, 0xd5, 0xae, 0x60, 0x51, 0xa5, 0x3e, + 0x5f, 0x81, 0x06, 0x67, 0xce, 0x5e, 0x18, 0xf8, 0x53, 0xc1, 0xaf, 0xc0, 0xa1, 0x87, 0x81, 0x3f, + 0x25, 0x1f, 0x83, 0x05, 0x2f, 0xd0, 0x49, 0xb8, 0x84, 0x37, 0x25, 0x88, 0x44, 0xaf, 0x40, 0x63, + 0x3c, 0x39, 0xf6, 0xbd, 0x3e, 0x27, 0x29, 0xf3, 0x56, 0x38, 0x84, 0x04, 0xcc, 0x19, 0xe4, 0xe3, + 0xe4, 0x14, 0x15, 0xa4, 0x68, 0x08, 0x8c, 0x91, 0xd8, 0x77, 0x61, 0xc5, 0x1c, 0xa0, 0x50, 0x65, + 0x1b, 0x50, 0x13, 0x9c, 0x1f, 0x77, 0x1a, 0xb8, 0x7a, 0x2d, 0xb1, 0x7a, 0x82, 0xd4, 0x51, 0xf5, + 0xf6, 0x0f, 0x2a, 0xb0, 0x2c, 0xd0, 0x6d, 0x3f, 0x8c, 0xe9, 0xd1, 0x64, 0x34, 0x72, 0xa3, 0x02, + 0x91, 0xb2, 0x2e, 0x10, 0xa9, 0x92, 0x29, 0x52, 0x8c, 0xd1, 0x4f, 0x5d, 0x2f, 0xe0, 0x9e, 0x2c, + 0x97, 0x47, 0x0d, 0x21, 0x37, 0x61, 0xb1, 0xef, 0x87, 0x31, 0xf7, 0xda, 0xf4, 0xa3, 0x64, 0x16, + 0xce, 0xab, 0x80, 0x6a, 0x91, 0x0a, 0xd0, 0x45, 0x78, 0x2e, 0x23, 0xc2, 0x36, 0x34, 0x59, 0xa3, + 0x54, 0x6a, 0xa4, 0x79, 0xee, 0xc9, 0xe9, 0x18, 0x1b, 0x4f, 0x56, 0x60, 0xb8, 0x74, 0x2e, 0x16, + 0x89, 0x0b, 0x3b, 0xa9, 0x32, 0x8d, 0xa7, 0x51, 0xd7, 0x85, 0xb8, 0xe4, 0xab, 0xc8, 0x3d, 0x00, + 0xde, 0x17, 0x9a, 0x5d, 0x40, 0xb3, 0xfb, 0x9a, 0xb9, 0x23, 0xfa, 0xda, 0xdf, 0x62, 0x85, 0x49, + 0x44, 0xd1, 0x14, 0x6b, 0x5f, 0xda, 0xbf, 0x61, 0x41, 0x43, 0xab, 0x23, 0xab, 0xb0, 0xb4, 0xfd, + 0xf0, 0xe1, 0xe1, 0xae, 0xb3, 0xf5, 0xe8, 0xc1, 0x97, 0x77, 0x7b, 0xdb, 0xfb, 0x0f, 0x8f, 0x76, + 0xdb, 0x97, 0x18, 0xbc, 0xff, 0x70, 0x7b, 0x6b, 0xbf, 0x77, 0xef, 0xa1, 0xb3, 0x2d, 0x61, 0x8b, + 0xac, 0x01, 0x71, 0x76, 0xdf, 0x7d, 0xf8, 0x68, 0xd7, 0xc0, 0x4b, 0xa4, 0x0d, 0xcd, 0xbb, 0xce, + 0xee, 0xd6, 0xf6, 0x9e, 0x40, 0xca, 0x64, 0x05, 0xda, 0xf7, 0x1e, 0x1f, 0xec, 0x3c, 0x38, 0xb8, + 0xdf, 0xdb, 0xde, 0x3a, 0xd8, 0xde, 0xdd, 0xdf, 0xdd, 0x69, 0x57, 0xc8, 0x02, 0xd4, 0xb7, 0xee, + 0x6e, 0x1d, 0xec, 0x3c, 0x3c, 0xd8, 0xdd, 0x69, 0x57, 0xed, 0x7f, 0xb6, 0x60, 0x15, 0x47, 0x3d, + 0xc8, 0x0a, 0xc8, 0x35, 0x68, 0xf4, 0xc3, 0x70, 0x4c, 0x99, 0xb6, 0x57, 0x0a, 0x5d, 0x87, 0x18, + 0xf3, 0x73, 0xf5, 0x79, 0x12, 0x46, 0x7d, 0x2a, 0xe4, 0x03, 0x10, 0xba, 0xc7, 0x10, 0xc6, 0xfc, + 0x62, 0x7b, 0x39, 0x05, 0x17, 0x8f, 0x06, 0xc7, 0x38, 0xc9, 0x1a, 0xcc, 0x1d, 0x47, 0xd4, 0xed, + 0x9f, 0x0a, 0xc9, 0x10, 0x25, 0xf2, 0x89, 0xf4, 0x80, 0xd1, 0x67, 0xab, 0xef, 0xd3, 0x01, 0x72, + 0x4c, 0xcd, 0x59, 0x14, 0xf8, 0xb6, 0x80, 0x99, 0xfc, 0xbb, 0xc7, 0x6e, 0x30, 0x08, 0x03, 0x3a, + 0x10, 0xce, 0x5e, 0x0a, 0xd8, 0x87, 0xb0, 0x96, 0x9d, 0x9f, 0x90, 0xaf, 0x37, 0x35, 0xf9, 0xe2, + 0xbe, 0x57, 0x77, 0xf6, 0x6e, 0x6a, 0xb2, 0xf6, 0x6f, 0x16, 0x54, 0x98, 0x29, 0x9e, 0x6d, 0xb6, + 0x75, 0xef, 0xaa, 0x9c, 0x8b, 0x3f, 0xe1, 0x99, 0x85, 0x2b, 0x67, 0x6e, 0xc0, 0x34, 0x24, 0xad, + 0x8f, 0x68, 0xff, 0x0c, 0x67, 0xac, 0xea, 0x19, 0xc2, 0x04, 0x84, 0xb9, 0xbe, 0xf8, 0xb5, 0x10, + 0x10, 0x59, 0x96, 0x75, 0xf8, 0xe5, 0x7c, 0x5a, 0x87, 0xdf, 0x75, 0x60, 0xde, 0x0b, 0x8e, 0xc3, + 0x49, 0x30, 0x40, 0x81, 0xa8, 0x39, 0xb2, 0xc8, 0x96, 0x6f, 0x8c, 0x82, 0xea, 0x8d, 0x24, 0xfb, + 0xa7, 0x80, 0x4d, 0xd8, 0xd1, 0x28, 0x46, 0xd7, 0x43, 0x05, 0x5d, 0xde, 0x84, 0x25, 0x0d, 0x4b, + 0xdd, 0xd8, 0x31, 0x03, 0x32, 0x6e, 0x2c, 0xfa, 0x2c, 0xbc, 0xc6, 0x6e, 0x43, 0xeb, 0x3e, 0x4d, + 0x1e, 0x04, 0x27, 0xa1, 0x6c, 0xe9, 0x4f, 0x2b, 0xb0, 0xa8, 0x20, 0xd1, 0xd0, 0x4d, 0x58, 0xf4, + 0x06, 0x34, 0x48, 0xbc, 0x64, 0xda, 0x33, 0x4e, 0x60, 0x59, 0x98, 0xf9, 0x7a, 0xae, 0xef, 0xb9, + 0x32, 0xc6, 0xc7, 0x0b, 0xe4, 0x0e, 0xac, 0x30, 0x43, 0x24, 0x6d, 0x8b, 0xda, 0x62, 0x7e, 0xf0, + 0x2b, 0xac, 0x63, 0xca, 0x80, 0xe1, 0x42, 0xdb, 0xab, 0x4f, 0xb8, 0xcf, 0x53, 0x54, 0xc5, 0x56, + 0x8d, 0xb7, 0xc4, 0xa6, 0x5c, 0xe5, 0xc6, 0x4a, 0x01, 0xb9, 0xe0, 0xd9, 0x1c, 0x57, 0x55, 0xd9, + 0xe0, 0x99, 0x16, 0x80, 0xab, 0xe5, 0x02, 0x70, 0x4c, 0x95, 0x4d, 0x83, 0x3e, 0x1d, 0xf4, 0x92, + 0xb0, 0x87, 0x2a, 0x17, 0x77, 0xa7, 0xe6, 0x64, 0x61, 0x72, 0x05, 0xe6, 0x13, 0x1a, 0x27, 0x01, + 0x4d, 0x50, 0x2b, 0xd5, 0x30, 0x20, 0x20, 0x21, 0xe6, 0xa0, 0x4e, 0x22, 0x2f, 0xee, 0x34, 0x31, + 0xb4, 0x86, 0xff, 0x93, 0x4f, 0xc3, 0xea, 0x31, 0x8d, 0x93, 0xde, 0x29, 0x75, 0x07, 0x34, 0xc2, + 0x9d, 0xe6, 0x31, 0x3c, 0x6e, 0xf7, 0x8b, 0x2b, 0x19, 0x0f, 0x9d, 0xd1, 0x28, 0xf6, 0xc2, 0x00, + 0x2d, 0x7e, 0xdd, 0x91, 0x45, 0xd6, 0x1e, 0x9b, 0xbc, 0xb2, 0x97, 0x6a, 0x05, 0x17, 0x71, 0xe2, + 0xc5, 0x95, 0xe4, 0x3a, 0xcc, 0xe1, 0x04, 0xe2, 0x4e, 0xdb, 0x88, 0x6a, 0x6c, 0x33, 0xd0, 0x11, + 0x75, 0x5f, 0xa8, 0xd4, 0x1a, 0xed, 0xa6, 0xfd, 0xff, 0xa1, 0x8a, 0x30, 0xdb, 0x74, 0xbe, 0x18, + 0x9c, 0x29, 0x78, 0x81, 0x0d, 0x2d, 0xa0, 0xc9, 0x79, 0x18, 0x3d, 0x95, 0x01, 0x5f, 0x51, 0xb4, + 0xbf, 0x89, 0x2e, 0xbe, 0x0a, 0x7c, 0x3e, 0x46, 0xff, 0x84, 0x1d, 0xd4, 0xf8, 0x52, 0xc7, 0xa7, + 0xae, 0x38, 0x75, 0xd4, 0x10, 0x38, 0x3a, 0x75, 0x99, 0xda, 0x32, 0x76, 0x8f, 0x1f, 0xe4, 0x1a, + 0x88, 0xed, 0xf1, 0xcd, 0xbb, 0x0e, 0x2d, 0x19, 0x52, 0x8d, 0x7b, 0x3e, 0x3d, 0x49, 0x64, 0x5c, + 0x21, 0x98, 0x8c, 0xf0, 0xb4, 0xb7, 0x4f, 0x4f, 0x12, 0xfb, 0x00, 0x96, 0x84, 0x2a, 0x79, 0x38, + 0xa6, 0xb2, 0xeb, 0xcf, 0x16, 0x99, 0xe4, 0xc6, 0x9d, 0x65, 0x53, 0xf7, 0xf0, 0x20, 0xb2, 0x49, + 0x69, 0x3b, 0x40, 0x74, 0xd5, 0x24, 0x1a, 0x14, 0x76, 0x51, 0x46, 0x4e, 0xc4, 0x74, 0x0c, 0x8c, + 0xad, 0x4f, 0x3c, 0xe9, 0xf7, 0x65, 0x40, 0x9c, 0x1d, 0x87, 0x79, 0xd1, 0xfe, 0xae, 0x05, 0xcb, + 0xd8, 0x9a, 0x74, 0x2a, 0x84, 0xfa, 0x7f, 0xeb, 0x23, 0x0c, 0xb3, 0xd9, 0xd7, 0xa3, 0x49, 0x2b, + 0x50, 0xd5, 0x0d, 0x02, 0x2f, 0x7c, 0xf4, 0x43, 0x7d, 0x25, 0x7b, 0xa8, 0xb7, 0x7f, 0xdf, 0x82, + 0x25, 0xae, 0x93, 0x13, 0x37, 0x99, 0xc4, 0x62, 0xfa, 0x3f, 0x03, 0x0b, 0xdc, 0xb8, 0x0a, 0xa9, + 0x16, 0x03, 0x5d, 0x51, 0x0a, 0x08, 0x51, 0x4e, 0xbc, 0x77, 0xc9, 0x31, 0x89, 0xc9, 0x3b, 0xe8, + 0xe0, 0x04, 0x3d, 0x44, 0x45, 0x60, 0xf0, 0x72, 0x81, 0x19, 0x50, 0xdf, 0x6b, 0xe4, 0x77, 0x6b, + 0x30, 0xc7, 0xfd, 0x5d, 0xfb, 0x3e, 0x2c, 0x18, 0x1d, 0x19, 0x01, 0x85, 0x26, 0x0f, 0x28, 0xe4, + 0x42, 0x51, 0xa5, 0x82, 0x50, 0xd4, 0x9f, 0x95, 0x81, 0x30, 0x66, 0xc9, 0xec, 0x06, 0x73, 0xb8, + 0xc3, 0x81, 0x71, 0x7c, 0x6a, 0x3a, 0x3a, 0x44, 0x6e, 0x01, 0xd1, 0x8a, 0x32, 0xa2, 0xc8, 0xad, + 0x4f, 0x41, 0x0d, 0x53, 0x93, 0xc2, 0x78, 0x0b, 0x33, 0x2b, 0x0e, 0x8a, 0x7c, 0xd9, 0x0b, 0xeb, + 0x98, 0x81, 0x19, 0x4f, 0xe2, 0x53, 0xbc, 0x3a, 0x11, 0x07, 0x2c, 0x59, 0xce, 0xee, 0xef, 0xdc, + 0x85, 0xfb, 0x3b, 0x9f, 0x0b, 0xda, 0x68, 0x2e, 0x7e, 0xcd, 0x74, 0xf1, 0xaf, 0xc3, 0xc2, 0x88, + 0xb9, 0x9c, 0x89, 0xdf, 0xef, 0x8d, 0x58, 0xef, 0xe2, 0x3c, 0x65, 0x80, 0x64, 0x03, 0xda, 0xc2, + 0xdd, 0x48, 0xcf, 0x11, 0x80, 0x6b, 0x9c, 0xc3, 0x99, 0xfe, 0x4e, 0xc3, 0x38, 0x0d, 0x1c, 0x6c, + 0x0a, 0xb0, 0x93, 0x57, 0xcc, 0x38, 0xa4, 0x37, 0x09, 0xc4, 0xad, 0x09, 0x1d, 0xe0, 0x49, 0xaa, + 0xe6, 0xe4, 0x2b, 0xec, 0xdf, 0xb5, 0xa0, 0xcd, 0xf6, 0xcc, 0x60, 0xcb, 0xb7, 0x01, 0xa5, 0xe2, + 0x05, 0xb9, 0xd2, 0xa0, 0x25, 0x6f, 0x41, 0x1d, 0xcb, 0xe1, 0x98, 0x06, 0x82, 0x27, 0x3b, 0x26, + 0x4f, 0xa6, 0xfa, 0x64, 0xef, 0x92, 0x93, 0x12, 0x6b, 0x1c, 0xf9, 0x0f, 0x16, 0x34, 0x44, 0x2f, + 0x3f, 0x76, 0x98, 0xa0, 0xab, 0x5d, 0x73, 0x71, 0x4e, 0x4a, 0x6f, 0xb5, 0x6e, 0xc2, 0xe2, 0xc8, + 0x4d, 0x26, 0x11, 0xb3, 0xc7, 0x46, 0x88, 0x20, 0x0b, 0x33, 0xe3, 0x8a, 0xaa, 0x33, 0xee, 0x25, + 0x9e, 0xdf, 0x93, 0xb5, 0xe2, 0x42, 0xa9, 0xa8, 0x8a, 0x69, 0x90, 0x38, 0x71, 0x87, 0x54, 0xd8, + 0x4d, 0x5e, 0xb0, 0x3b, 0xb0, 0x26, 0x26, 0x94, 0x71, 0x55, 0xed, 0xbf, 0x6a, 0xc2, 0x7a, 0xae, + 0x4a, 0xdd, 0x3e, 0x8b, 0xb3, 0xaf, 0xef, 0x8d, 0x8e, 0x43, 0xe5, 0xe7, 0x5b, 0xfa, 0xb1, 0xd8, + 0xa8, 0x22, 0x43, 0x58, 0x95, 0x0e, 0x02, 0x5b, 0xd3, 0xd4, 0x98, 0x95, 0xd0, 0x4a, 0xbd, 0x61, + 0x6e, 0x61, 0xb6, 0x43, 0x89, 0xeb, 0x42, 0x5c, 0xdc, 0x1e, 0x39, 0x85, 0x8e, 0xf2, 0x44, 0x84, + 0xb2, 0xd6, 0xbc, 0x15, 0xd6, 0xd7, 0xeb, 0x17, 0xf4, 0x65, 0x78, 0xb6, 0xce, 0xcc, 0xd6, 0xc8, + 0x14, 0xae, 0xca, 0x3a, 0xd4, 0xc6, 0xf9, 0xfe, 0x2a, 0x2f, 0x34, 0x37, 0xf4, 0xd9, 0xcd, 0x4e, + 0x2f, 0x68, 0x98, 0xbc, 0x0f, 0x6b, 0xe7, 0xae, 0x97, 0xc8, 0x61, 0x69, 0xbe, 0x41, 0x15, 0xbb, + 0xbc, 0x73, 0x41, 0x97, 0x4f, 0xf8, 0xc7, 0x86, 0x89, 0x9a, 0xd1, 0x62, 0xf7, 0xef, 0x2c, 0x68, + 0x99, 0xed, 0x30, 0x36, 0x15, 0xb2, 0x2f, 0x75, 0xa0, 0xf4, 0x26, 0x33, 0x70, 0xfe, 0xa8, 0x5c, + 0x2a, 0x3a, 0x2a, 0xeb, 0x07, 0xd4, 0xf2, 0x45, 0x31, 0xa6, 0xca, 0x8b, 0xc5, 0x98, 0xaa, 0x45, + 0x31, 0xa6, 0xee, 0x7f, 0x5a, 0x40, 0xf2, 0xbc, 0x44, 0xee, 0xf3, 0xb3, 0x7a, 0x40, 0x7d, 0xa1, + 0x52, 0xfe, 0xdf, 0x8b, 0xf1, 0xa3, 0x5c, 0x3b, 0xf9, 0x35, 0x13, 0x0c, 0xfd, 0x46, 0x58, 0x77, + 0x76, 0x16, 0x9c, 0xa2, 0xaa, 0x4c, 0xd4, 0xab, 0x72, 0x71, 0xd4, 0xab, 0x7a, 0x71, 0xd4, 0x6b, + 0x2e, 0x1b, 0xf5, 0xea, 0xfe, 0xaa, 0x05, 0xcb, 0x05, 0x9b, 0xfe, 0xd3, 0x9b, 0x38, 0xdb, 0x26, + 0x43, 0x17, 0x94, 0xc4, 0x36, 0xe9, 0x60, 0xf7, 0x17, 0x61, 0xc1, 0x60, 0xf4, 0x9f, 0x5e, 0xff, + 0x59, 0x7f, 0x8d, 0xf3, 0x99, 0x81, 0x75, 0xff, 0xbd, 0x04, 0x24, 0x2f, 0x6c, 0xff, 0xa7, 0x63, + 0xc8, 0xaf, 0x53, 0xb9, 0x60, 0x9d, 0xfe, 0x57, 0xed, 0xc0, 0xeb, 0xb0, 0x24, 0x52, 0x55, 0xb4, + 0x08, 0x0d, 0xe7, 0x98, 0x7c, 0x05, 0xf3, 0x58, 0xcd, 0x90, 0x63, 0xcd, 0xb8, 0xf6, 0xd7, 0x8c, + 0x61, 0x26, 0xf2, 0x68, 0x77, 0xa1, 0x23, 0x56, 0x68, 0xf7, 0x8c, 0x06, 0xc9, 0xd1, 0xe4, 0x98, + 0xa7, 0x7b, 0x78, 0x61, 0x60, 0x7f, 0xbf, 0xac, 0x9c, 0x6e, 0xac, 0x14, 0xe6, 0xfd, 0xd3, 0xd0, + 0xd4, 0x95, 0xb9, 0xd8, 0x8e, 0x4c, 0x80, 0x8e, 0x19, 0x76, 0x9d, 0x8a, 0xec, 0x40, 0x0b, 0x55, + 0xd6, 0x40, 0x7d, 0x57, 0xc2, 0xef, 0x9e, 0x13, 0x78, 0xd8, 0xbb, 0xe4, 0x64, 0xbe, 0x21, 0x9f, + 0x83, 0x96, 0x79, 0x94, 0x12, 0x3e, 0x42, 0x91, 0x6f, 0xce, 0x3e, 0x37, 0x89, 0xc9, 0x16, 0xb4, + 0xb3, 0x67, 0x31, 0x71, 0x5b, 0x3c, 0xa3, 0x81, 0x1c, 0x39, 0x79, 0x4b, 0xdc, 0x3d, 0x55, 0x31, + 0x08, 0x76, 0xdd, 0xfc, 0x4c, 0x5b, 0xa6, 0x5b, 0xfc, 0x8f, 0x76, 0x1b, 0xf5, 0x35, 0x80, 0x14, + 0x23, 0x6d, 0x68, 0x3e, 0x3c, 0xdc, 0x3d, 0xe8, 0x6d, 0xef, 0x6d, 0x1d, 0x1c, 0xec, 0xee, 0xb7, + 0x2f, 0x11, 0x02, 0x2d, 0x8c, 0x5f, 0xed, 0x28, 0xcc, 0x62, 0xd8, 0xd6, 0x36, 0x8f, 0x8d, 0x09, + 0xac, 0x44, 0x56, 0xa0, 0xfd, 0xe0, 0x20, 0x83, 0x96, 0xef, 0xd6, 0x95, 0x7c, 0xd8, 0x6b, 0xb0, + 0xc2, 0xd3, 0x99, 0xee, 0x72, 0xf6, 0x90, 0xbe, 0xc2, 0x1f, 0x5a, 0xb0, 0x9a, 0xa9, 0x48, 0x13, + 0x0f, 0xb8, 0x3b, 0x60, 0xfa, 0x08, 0x26, 0xc8, 0x78, 0x52, 0x79, 0x7e, 0x19, 0x0d, 0x92, 0xaf, + 0x60, 0x3c, 0xaf, 0x79, 0x8a, 0x19, 0x49, 0x2a, 0xaa, 0xb2, 0xd7, 0x79, 0xd2, 0x55, 0x40, 0xfd, + 0xcc, 0xc0, 0x4f, 0x78, 0x9a, 0x94, 0x5e, 0x91, 0xde, 0xe5, 0x99, 0x43, 0x96, 0x45, 0xe6, 0xe4, + 0x1b, 0xae, 0x87, 0x39, 0xde, 0xc2, 0x3a, 0xfb, 0x07, 0x16, 0x90, 0x2f, 0x4d, 0x68, 0x34, 0xc5, + 0x9c, 0x01, 0x15, 0x0e, 0x5c, 0xcf, 0x06, 0xbb, 0xe6, 0xc6, 0x93, 0xe3, 0x2f, 0xd2, 0xa9, 0x4c, + 0x53, 0x29, 0xa5, 0x69, 0x2a, 0x2f, 0x03, 0xb0, 0xc3, 0xb1, 0xca, 0x58, 0x40, 0xe7, 0x3a, 0x98, + 0x8c, 0x78, 0x83, 0x85, 0x99, 0x24, 0x95, 0x8b, 0x33, 0x49, 0xaa, 0x17, 0x65, 0x92, 0xbc, 0x03, + 0xcb, 0xc6, 0xb8, 0xd5, 0xb6, 0xca, 0xdc, 0x09, 0x2b, 0x9f, 0x3b, 0x21, 0xf3, 0x26, 0xec, 0x5f, + 0x2f, 0x41, 0x79, 0x2f, 0x1c, 0xeb, 0xa1, 0x70, 0xcb, 0x0c, 0x85, 0x0b, 0xff, 0xa0, 0xa7, 0xcc, + 0xbf, 0x30, 0x1b, 0x06, 0x48, 0x36, 0xa0, 0xe5, 0x8e, 0x92, 0x5e, 0x12, 0x32, 0x7f, 0xe8, 0xdc, + 0x8d, 0x06, 0x7c, 0xaf, 0x31, 0x24, 0x93, 0xa9, 0x21, 0x2b, 0x50, 0x56, 0x86, 0x14, 0x09, 0x58, + 0x91, 0x39, 0xe3, 0x78, 0xc9, 0x36, 0x15, 0x61, 0x25, 0x51, 0x62, 0xac, 0x64, 0x7e, 0xcf, 0x4f, + 0x42, 0x5c, 0x1d, 0x16, 0x55, 0x31, 0x5f, 0x85, 0x2d, 0x1f, 0x92, 0x89, 0x78, 0xa0, 0x2c, 0xeb, + 0xb1, 0xcb, 0x9a, 0x79, 0xe5, 0xf8, 0x23, 0x0b, 0xaa, 0xb8, 0x36, 0x4c, 0xb5, 0x73, 0xde, 0x57, + 0xd1, 0x70, 0x5c, 0x93, 0x05, 0x27, 0x0b, 0x13, 0xdb, 0x48, 0xf4, 0x2a, 0xa9, 0x09, 0xe9, 0xc9, + 0x5e, 0xd7, 0xa0, 0xce, 0x4b, 0x2a, 0xa9, 0x09, 0x49, 0x52, 0x90, 0x5c, 0x85, 0xca, 0x69, 0x38, + 0x96, 0xbe, 0x28, 0xc8, 0xab, 0xa2, 0x70, 0xec, 0x20, 0x9e, 0x8e, 0x87, 0xb5, 0xc7, 0xa7, 0xc5, + 0x3d, 0x8c, 0x2c, 0xcc, 0x7c, 0x2c, 0xd5, 0xac, 0xbe, 0x4c, 0x19, 0xd4, 0xde, 0x80, 0xc5, 0x83, + 0x70, 0x40, 0xb5, 0x90, 0xe4, 0x4c, 0x3e, 0xb7, 0x7f, 0xc9, 0x82, 0x9a, 0x24, 0x26, 0x37, 0xa1, + 0xc2, 0x1c, 0xc7, 0xcc, 0xa9, 0x4e, 0x5d, 0x11, 0x33, 0x3a, 0x07, 0x29, 0x98, 0xa5, 0xc5, 0x48, + 0x51, 0x7a, 0x88, 0x90, 0x71, 0xa2, 0xd4, 0x47, 0x56, 0xc3, 0xcd, 0xb8, 0x96, 0x19, 0xd4, 0xfe, + 0x9e, 0x05, 0x0b, 0x46, 0x1f, 0xe4, 0x1a, 0x34, 0x7c, 0x37, 0x4e, 0xc4, 0xb5, 0x9b, 0xd8, 0x1e, + 0x1d, 0xd2, 0x37, 0xba, 0x64, 0x06, 0xa9, 0x55, 0xf8, 0xb4, 0xac, 0x87, 0x4f, 0x6f, 0x43, 0x3d, + 0x4d, 0xc7, 0xab, 0x18, 0x16, 0x94, 0xf5, 0x28, 0x2f, 0xbf, 0x53, 0x22, 0x8c, 0xc8, 0x85, 0x7e, + 0x18, 0x89, 0x1b, 0x1d, 0x5e, 0xb0, 0xdf, 0x81, 0x86, 0x46, 0xaf, 0x07, 0xe8, 0x2c, 0x23, 0x40, + 0xa7, 0x32, 0x43, 0x4a, 0x69, 0x66, 0x88, 0xfd, 0xb7, 0x16, 0x2c, 0x30, 0x1e, 0xf4, 0x82, 0xe1, + 0x61, 0xe8, 0x7b, 0xfd, 0x29, 0xee, 0xbd, 0x64, 0x37, 0xa1, 0x33, 0x24, 0x2f, 0x9a, 0x30, 0xe3, + 0x7a, 0x19, 0x16, 0x10, 0x22, 0xaa, 0xca, 0x4c, 0x86, 0x99, 0x04, 0x1c, 0xbb, 0xb1, 0x10, 0x0b, + 0xe1, 0xd2, 0x18, 0x20, 0x93, 0x34, 0x06, 0x44, 0x6e, 0x42, 0x7b, 0x23, 0xcf, 0xf7, 0x3d, 0x4e, + 0xcb, 0x1d, 0xde, 0xa2, 0x2a, 0xd6, 0xe7, 0xc0, 0x8b, 0xdd, 0xe3, 0xf4, 0x96, 0x42, 0x95, 0xed, + 0xbf, 0x28, 0x41, 0x43, 0x5a, 0xc6, 0xc1, 0x90, 0x8a, 0x2b, 0x35, 0x3c, 0x52, 0x28, 0x25, 0xa3, + 0x21, 0xb2, 0xde, 0x38, 0x84, 0x68, 0x48, 0x76, 0xcb, 0xcb, 0xf9, 0x2d, 0xbf, 0x02, 0x75, 0xc6, + 0x7a, 0x6f, 0xe0, 0x69, 0x87, 0x5f, 0xc7, 0xa5, 0x80, 0xac, 0xbd, 0x83, 0xb5, 0xd5, 0xb4, 0x16, + 0x81, 0xe7, 0x5e, 0xc0, 0xbd, 0x05, 0x4d, 0xd1, 0x0c, 0xee, 0x09, 0xea, 0x94, 0x94, 0xf9, 0x8d, + 0xfd, 0x72, 0x0c, 0x4a, 0xf9, 0xe5, 0x1d, 0xf9, 0x65, 0xed, 0xa2, 0x2f, 0x25, 0xa5, 0x7d, 0x5f, + 0xdd, 0x6b, 0xde, 0x8f, 0xdc, 0xf1, 0xa9, 0x94, 0xd2, 0xdb, 0xb0, 0xec, 0x05, 0x7d, 0x7f, 0x32, + 0xa0, 0xbd, 0x49, 0xe0, 0x06, 0x41, 0x38, 0x09, 0xfa, 0x54, 0x26, 0x7d, 0x14, 0x55, 0xd9, 0x03, + 0x95, 0xf3, 0x86, 0x0d, 0x91, 0x0d, 0xa8, 0xb2, 0x8e, 0xa4, 0x55, 0x28, 0x16, 0x61, 0x4e, 0x42, + 0x6e, 0x42, 0x95, 0x0e, 0x86, 0x54, 0x46, 0x00, 0x48, 0xc6, 0xdf, 0x19, 0x0c, 0xa9, 0xc3, 0x09, + 0x98, 0x42, 0x61, 0x68, 0x46, 0xa1, 0x98, 0x16, 0x65, 0x8e, 0x15, 0x1f, 0x0c, 0xec, 0x15, 0x20, + 0x07, 0x5c, 0x06, 0xf4, 0x2b, 0x91, 0x5f, 0x29, 0x43, 0x43, 0x83, 0x99, 0x6e, 0x18, 0xb2, 0x01, + 0xf7, 0x06, 0x9e, 0x3b, 0xa2, 0x09, 0x8d, 0x04, 0xdf, 0x67, 0x50, 0x46, 0xe7, 0x9e, 0x0d, 0x7b, + 0xe1, 0x24, 0xe9, 0x0d, 0xe8, 0x30, 0xa2, 0xdc, 0xc8, 0x33, 0xa3, 0x63, 0xa0, 0x8c, 0x6e, 0xe4, + 0x3e, 0xd3, 0xe9, 0x38, 0x07, 0x65, 0x50, 0x79, 0xc1, 0xc1, 0xd7, 0xa8, 0x92, 0x5e, 0x70, 0xf0, + 0x15, 0xc9, 0x6a, 0xb5, 0x6a, 0x81, 0x56, 0x7b, 0x13, 0xd6, 0xb8, 0xfe, 0x12, 0x92, 0xde, 0xcb, + 0x30, 0xd6, 0x8c, 0x5a, 0xb2, 0x01, 0x6d, 0x36, 0x66, 0x29, 0x12, 0xb1, 0xf7, 0x4d, 0x1e, 0x2c, + 0xb4, 0x9c, 0x1c, 0xce, 0x68, 0x31, 0x6a, 0xa7, 0xd3, 0xf2, 0x0b, 0xdf, 0x1c, 0x8e, 0xb4, 0xee, + 0x33, 0x93, 0xb6, 0x2e, 0x68, 0x33, 0xb8, 0xbd, 0x00, 0x8d, 0xa3, 0x24, 0x1c, 0xcb, 0x4d, 0x69, + 0x41, 0x93, 0x17, 0x45, 0xf2, 0xcd, 0x4b, 0x70, 0x19, 0xb9, 0xe8, 0x51, 0x38, 0x0e, 0xfd, 0x70, + 0x38, 0x35, 0x4e, 0x0c, 0x7f, 0x6f, 0xc1, 0xb2, 0x51, 0x9b, 0x1e, 0x19, 0x30, 0xd8, 0x20, 0xb3, + 0x26, 0x38, 0xe3, 0x2d, 0x69, 0xca, 0x95, 0x13, 0xf2, 0xb8, 0xee, 0x63, 0x91, 0x48, 0xb1, 0x05, + 0x8b, 0x72, 0x64, 0xf2, 0x43, 0xce, 0x85, 0x9d, 0x3c, 0x17, 0x8a, 0xef, 0x5b, 0xe2, 0x03, 0xd9, + 0xc4, 0xe7, 0xc4, 0xc5, 0x39, 0x3f, 0x41, 0xc8, 0xd8, 0x92, 0x3a, 0x73, 0xe8, 0x27, 0x4c, 0x39, + 0x82, 0xbe, 0x02, 0x63, 0xfb, 0x37, 0x2d, 0x80, 0x74, 0x74, 0x78, 0xdd, 0xaa, 0x0c, 0x04, 0x7f, + 0xc3, 0xa1, 0x19, 0x83, 0x57, 0xa1, 0xa9, 0xae, 0xe9, 0x52, 0x9b, 0xd3, 0x90, 0x18, 0x73, 0x18, + 0x6f, 0xc0, 0xe2, 0xd0, 0x0f, 0x8f, 0xd1, 0x60, 0x63, 0x36, 0x57, 0x2c, 0x52, 0x90, 0x5a, 0x1c, + 0xbe, 0x27, 0xd0, 0xd4, 0x40, 0x55, 0x34, 0x03, 0x65, 0xff, 0x56, 0x49, 0xdd, 0xaa, 0xa4, 0x73, + 0x9e, 0x29, 0x65, 0xe4, 0x4e, 0x4e, 0x9d, 0xce, 0xb8, 0xc4, 0xc0, 0x28, 0xea, 0xe1, 0x85, 0x41, + 0x9e, 0x77, 0xa0, 0x15, 0x71, 0x7d, 0x25, 0x95, 0x59, 0xe5, 0x39, 0xca, 0x6c, 0x21, 0x32, 0xac, + 0xd8, 0x27, 0xa0, 0xed, 0x0e, 0xce, 0x68, 0x94, 0x78, 0x78, 0xcc, 0x46, 0x17, 0x82, 0xab, 0xe0, + 0x45, 0x0d, 0x47, 0xcb, 0x7e, 0x03, 0x16, 0x45, 0xda, 0x97, 0xa2, 0x14, 0x89, 0xd9, 0x29, 0xcc, + 0x08, 0xed, 0x3f, 0x96, 0x17, 0x38, 0xe6, 0x1e, 0xce, 0x5e, 0x11, 0x7d, 0x76, 0xa5, 0xcc, 0xec, + 0x3e, 0x26, 0x2e, 0x53, 0x06, 0xf2, 0x2c, 0x5f, 0xd6, 0x92, 0x2c, 0x06, 0xe2, 0xf2, 0xcb, 0x5c, + 0xd2, 0xca, 0x8b, 0x2c, 0xa9, 0xfd, 0x43, 0x0b, 0xe6, 0xf7, 0xc2, 0xf1, 0x9e, 0x48, 0x37, 0x41, + 0x41, 0x50, 0xf9, 0x96, 0xb2, 0xf8, 0x9c, 0x44, 0x94, 0x42, 0xcb, 0xbd, 0x90, 0xb5, 0xdc, 0x3f, + 0x07, 0x2f, 0x61, 0x24, 0x29, 0x0a, 0xc7, 0x61, 0xc4, 0x84, 0xd1, 0xf5, 0xb9, 0x99, 0x0e, 0x83, + 0xe4, 0x54, 0xaa, 0xb1, 0xe7, 0x91, 0xe0, 0xf1, 0x8e, 0x1d, 0x4b, 0xb8, 0xd3, 0x2d, 0x3c, 0x0d, + 0xae, 0xdd, 0xf2, 0x15, 0xf6, 0x67, 0xa1, 0x8e, 0xae, 0x32, 0x4e, 0xeb, 0x75, 0xa8, 0x9f, 0x86, + 0xe3, 0xde, 0xa9, 0x17, 0x24, 0x52, 0xb8, 0x5b, 0xa9, 0x0f, 0xbb, 0x87, 0x0b, 0xa2, 0x08, 0xec, + 0xff, 0xaa, 0xc2, 0xfc, 0x83, 0xe0, 0x2c, 0xf4, 0xfa, 0x78, 0x59, 0x34, 0xa2, 0xa3, 0x50, 0x66, + 0x9f, 0xb2, 0xff, 0xc9, 0x15, 0x98, 0xc7, 0x74, 0xab, 0x31, 0x67, 0xda, 0x26, 0xbf, 0xd4, 0x15, + 0x10, 0x73, 0x12, 0xa2, 0x34, 0xf1, 0x9d, 0x8b, 0x8f, 0x86, 0xb0, 0x43, 0x44, 0xa4, 0x27, 0xae, + 0x8b, 0x52, 0x9a, 0xdd, 0x5b, 0xd5, 0xb2, 0x7b, 0x59, 0x5f, 0x22, 0x3d, 0x86, 0xe7, 0x4f, 0xf0, + 0xbe, 0x04, 0x84, 0x07, 0x9f, 0x88, 0xf2, 0x48, 0x20, 0xba, 0x1c, 0xf3, 0xe2, 0xe0, 0xa3, 0x83, + 0xcc, 0x2d, 0xe1, 0x1f, 0x70, 0x1a, 0xae, 0x84, 0x75, 0x88, 0xb9, 0x70, 0xd9, 0xa7, 0x06, 0x75, + 0xce, 0xfb, 0x19, 0x98, 0x69, 0xea, 0x01, 0x55, 0x0a, 0x95, 0xcf, 0x03, 0x78, 0x72, 0x7f, 0x16, + 0xd7, 0x8e, 0x4b, 0x3c, 0x33, 0x4e, 0x1e, 0x97, 0x18, 0xc3, 0xb8, 0xbe, 0x7f, 0xec, 0xf6, 0x9f, + 0xe2, 0x4b, 0x12, 0xbc, 0xbe, 0xa9, 0x3b, 0x26, 0x88, 0x49, 0x2e, 0xe9, 0xae, 0xe2, 0xf5, 0x77, + 0xc5, 0xd1, 0x21, 0x72, 0x07, 0x1a, 0x78, 0x44, 0x14, 0xfb, 0xda, 0xc2, 0x7d, 0x6d, 0xeb, 0x67, + 0x48, 0xdc, 0x59, 0x9d, 0x48, 0xbf, 0xc8, 0x5a, 0xcc, 0xe5, 0xaa, 0xb9, 0x83, 0x81, 0xb8, 0xff, + 0x6b, 0x63, 0x6f, 0x29, 0xc0, 0xac, 0xaa, 0x58, 0x30, 0x4e, 0xb0, 0x84, 0x04, 0x06, 0x46, 0xae, + 0x42, 0x8d, 0x1d, 0x5f, 0xc6, 0xae, 0x37, 0xc0, 0x64, 0x37, 0x7e, 0x8a, 0x52, 0x18, 0x6b, 0x43, + 0xfe, 0x8f, 0xf7, 0x74, 0xcb, 0xb8, 0x2a, 0x06, 0xc6, 0xd6, 0x46, 0x95, 0x51, 0x98, 0x56, 0xf8, + 0x8e, 0x1a, 0x20, 0x79, 0x03, 0x6f, 0x61, 0x12, 0xda, 0x59, 0xc5, 0x28, 0xcf, 0x4b, 0x62, 0xce, + 0x82, 0x69, 0xe5, 0xdf, 0x23, 0x46, 0xe2, 0x70, 0x4a, 0xfb, 0xe3, 0xd0, 0xd4, 0x61, 0x52, 0x83, + 0xca, 0xc3, 0xc3, 0xdd, 0x83, 0xf6, 0x25, 0xd2, 0x80, 0xf9, 0xa3, 0xdd, 0x47, 0x8f, 0xf6, 0x77, + 0x77, 0xda, 0x96, 0x9d, 0x00, 0xd9, 0x1a, 0x0c, 0x04, 0xa5, 0x3a, 0xa8, 0xa7, 0x3c, 0x6b, 0x19, + 0x3c, 0x5b, 0xc0, 0x37, 0xa5, 0x62, 0xbe, 0x79, 0xee, 0xea, 0xda, 0xbb, 0xd0, 0x38, 0xd4, 0xde, + 0x60, 0xa0, 0x08, 0xc9, 0xd7, 0x17, 0x42, 0xf4, 0x34, 0x44, 0x1b, 0x4e, 0x49, 0x1f, 0x8e, 0xfd, + 0x27, 0x16, 0xcf, 0x0b, 0x57, 0xc3, 0xe7, 0x7d, 0xdb, 0xd0, 0x54, 0xe1, 0x94, 0x34, 0xa1, 0xd0, + 0xc0, 0x18, 0x0d, 0x0e, 0xa5, 0x17, 0x9e, 0x9c, 0xc4, 0x54, 0xa6, 0xff, 0x18, 0x18, 0xe3, 0x7d, + 0xe6, 0x45, 0x31, 0x8f, 0xc4, 0xe3, 0x3d, 0xc4, 0x22, 0x0d, 0x28, 0x87, 0x33, 0x4d, 0x1e, 0xd1, + 0x33, 0x1a, 0xc5, 0x2a, 0xf1, 0x49, 0x95, 0x55, 0xde, 0x63, 0x76, 0x95, 0x37, 0xa0, 0xa6, 0xda, + 0x35, 0x95, 0x94, 0xa4, 0x54, 0xf5, 0x4c, 0x19, 0xe2, 0xb9, 0xc2, 0x18, 0x34, 0x57, 0xcc, 0xf9, + 0x0a, 0x72, 0x0b, 0xc8, 0x89, 0x17, 0x65, 0xc9, 0xcb, 0x48, 0x5e, 0x50, 0x63, 0x3f, 0x81, 0x65, + 0xc9, 0x2c, 0x9a, 0xfb, 0x64, 0x6e, 0xa2, 0x75, 0x91, 0x88, 0x94, 0xf2, 0x22, 0x62, 0xff, 0xb7, + 0x05, 0xf3, 0x62, 0xa7, 0x73, 0xef, 0x78, 0xf8, 0x3e, 0x1b, 0x18, 0xe9, 0x18, 0x4f, 0x1e, 0x50, + 0x9e, 0x84, 0x62, 0xcc, 0xa9, 0xbe, 0x72, 0x91, 0xea, 0x23, 0x50, 0x19, 0xbb, 0xc9, 0x29, 0x9e, + 0x96, 0xeb, 0x0e, 0xfe, 0x4f, 0xda, 0x3c, 0xb6, 0xc3, 0xd5, 0x2c, 0xc6, 0x75, 0x8a, 0x5e, 0x2c, + 0x71, 0x8b, 0x9e, 0x7f, 0xb1, 0x74, 0x05, 0xea, 0x38, 0x80, 0x5e, 0x1a, 0xba, 0x49, 0x01, 0xc6, + 0xb9, 0xbc, 0x80, 0xb2, 0x2b, 0xb2, 0x8f, 0x53, 0xc4, 0x5e, 0xe5, 0x3b, 0x2f, 0x96, 0x40, 0xdd, + 0x92, 0x8a, 0x3c, 0xd3, 0x14, 0x4e, 0x39, 0x42, 0x0c, 0x20, 0xcb, 0x11, 0x82, 0xd4, 0x51, 0xf5, + 0x76, 0x17, 0x3a, 0x3b, 0xd4, 0xa7, 0x09, 0xdd, 0xf2, 0xfd, 0x6c, 0xfb, 0x2f, 0xc1, 0xe5, 0x82, + 0x3a, 0xe1, 0x31, 0x7f, 0x09, 0x56, 0xb7, 0x78, 0x4e, 0xde, 0x4f, 0x2b, 0xcf, 0xc4, 0xee, 0xc0, + 0x5a, 0xb6, 0x49, 0xd1, 0xd9, 0x3d, 0x58, 0xda, 0xa1, 0xc7, 0x93, 0xe1, 0x3e, 0x3d, 0x4b, 0x3b, + 0x22, 0x50, 0x89, 0x4f, 0xc3, 0x73, 0x21, 0x98, 0xf8, 0x3f, 0x79, 0x19, 0xc0, 0x67, 0x34, 0xbd, + 0x78, 0x4c, 0xfb, 0xf2, 0x95, 0x01, 0x22, 0x47, 0x63, 0xda, 0xb7, 0xdf, 0x04, 0xa2, 0xb7, 0x23, + 0xd6, 0x8b, 0x59, 0xba, 0xc9, 0x71, 0x2f, 0x9e, 0xc6, 0x09, 0x1d, 0xc9, 0xe7, 0x13, 0x3a, 0x64, + 0xdf, 0x80, 0xe6, 0xa1, 0x3b, 0x75, 0xe8, 0x37, 0xc4, 0xf3, 0xad, 0x75, 0x98, 0x1f, 0xbb, 0x53, + 0xa6, 0xa6, 0x54, 0x4c, 0x09, 0xab, 0xed, 0xff, 0x28, 0xc1, 0x1c, 0xa7, 0x64, 0xad, 0x0e, 0x68, + 0x9c, 0x78, 0x01, 0x32, 0x96, 0x6c, 0x55, 0x83, 0x72, 0xac, 0x5c, 0x2a, 0x60, 0x65, 0x71, 0x2e, + 0x93, 0x19, 0xdb, 0x82, 0x5f, 0x0d, 0x8c, 0x31, 0x57, 0x9a, 0xf0, 0xc5, 0x83, 0x1a, 0x29, 0x90, + 0x09, 0x3f, 0xa6, 0xf6, 0x94, 0x8f, 0x4f, 0x4a, 0xa9, 0xe0, 0x5c, 0x1d, 0x2a, 0xb4, 0xda, 0xf3, + 0x9c, 0xc1, 0x73, 0x56, 0x3b, 0x67, 0x9d, 0x6b, 0x2f, 0x60, 0x9d, 0xf9, 0x61, 0xed, 0x79, 0xd6, + 0x19, 0x5e, 0xc0, 0x3a, 0xdb, 0x04, 0xda, 0xf7, 0x28, 0x75, 0x28, 0xf3, 0xff, 0x24, 0xef, 0x7e, + 0xcb, 0x82, 0xb6, 0xe0, 0x22, 0x55, 0x47, 0x5e, 0x35, 0xfc, 0xdc, 0xc2, 0xcc, 0xe9, 0xeb, 0xb0, + 0x80, 0xde, 0xa7, 0x8a, 0xb3, 0x8a, 0xa0, 0xb0, 0x01, 0xb2, 0x79, 0xc8, 0x0b, 0xce, 0x91, 0xe7, + 0x8b, 0x4d, 0xd1, 0x21, 0x19, 0xaa, 0x8d, 0x5c, 0x91, 0xf8, 0x64, 0x39, 0xaa, 0x6c, 0xff, 0xa5, + 0x05, 0x4b, 0xda, 0x80, 0x05, 0x17, 0xbe, 0x03, 0x52, 0x1a, 0x78, 0xd0, 0x95, 0x4b, 0xee, 0xba, + 0x29, 0x36, 0xe9, 0x67, 0x06, 0x31, 0x6e, 0xa6, 0x3b, 0xc5, 0x01, 0xc6, 0x93, 0x91, 0x50, 0xa2, + 0x3a, 0xc4, 0x18, 0xe9, 0x9c, 0xd2, 0xa7, 0x8a, 0x84, 0xab, 0x71, 0x03, 0xc3, 0xac, 0x1c, 0xe6, + 0x35, 0x2b, 0x22, 0x6e, 0xcf, 0x4c, 0xd0, 0xfe, 0x27, 0x0b, 0x96, 0xf9, 0xf1, 0x47, 0x1c, 0x2e, + 0xd5, 0xa3, 0x97, 0x39, 0x7e, 0xde, 0xe3, 0x12, 0xb9, 0x77, 0xc9, 0x11, 0x65, 0xf2, 0x99, 0x17, + 0x3c, 0xb2, 0xa9, 0x6c, 0xac, 0x19, 0x7b, 0x51, 0x2e, 0xda, 0x8b, 0xe7, 0xac, 0x74, 0x51, 0x90, + 0xb1, 0x5a, 0x18, 0x64, 0xbc, 0x3b, 0x0f, 0xd5, 0xb8, 0x1f, 0x8e, 0xa9, 0xbd, 0x06, 0x2b, 0xe6, + 0xe4, 0x84, 0x0a, 0xfa, 0x8e, 0x05, 0x9d, 0x7b, 0x3c, 0x18, 0xef, 0x05, 0xc3, 0x3d, 0x2f, 0x4e, + 0xc2, 0x48, 0xbd, 0x0d, 0xbc, 0x0a, 0x10, 0x27, 0x6e, 0x94, 0xf0, 0x9c, 0x5b, 0x11, 0x02, 0x4c, + 0x11, 0x36, 0x46, 0x1a, 0x0c, 0x78, 0x2d, 0xdf, 0x1b, 0x55, 0xce, 0xf9, 0x10, 0xe2, 0x80, 0x66, + 0x58, 0xe2, 0xd7, 0x78, 0x76, 0x22, 0xf3, 0x15, 0xe8, 0x19, 0xea, 0x75, 0x7e, 0xf2, 0xc9, 0xa0, + 0xf6, 0x3f, 0x5a, 0xb0, 0x98, 0x0e, 0x12, 0xef, 0xed, 0x4c, 0xed, 0x20, 0xcc, 0x6f, 0xaa, 0x1d, + 0x64, 0x70, 0xd2, 0x63, 0xf6, 0x58, 0x8c, 0x4d, 0x43, 0x50, 0x62, 0x45, 0x29, 0x9c, 0x48, 0x07, + 0x47, 0x87, 0x78, 0xae, 0x11, 0xf3, 0x04, 0x84, 0x57, 0x23, 0x4a, 0x98, 0x32, 0x3d, 0x4a, 0xf0, + 0xab, 0x39, 0x7e, 0xf4, 0x13, 0x45, 0x69, 0x4a, 0xe7, 0x11, 0x45, 0x53, 0xaa, 0x5f, 0x6c, 0xd4, + 0xf8, 0xfa, 0xc8, 0xb2, 0xfd, 0xdb, 0x16, 0x5c, 0x2e, 0x58, 0x78, 0x21, 0x35, 0x3b, 0xb0, 0x74, + 0xa2, 0x2a, 0xe5, 0xe2, 0x70, 0xd1, 0x59, 0x93, 0x37, 0x4b, 0xe6, 0x82, 0x38, 0xf9, 0x0f, 0x94, + 0x5f, 0xc4, 0x97, 0xdb, 0xc8, 0xe6, 0xcb, 0x57, 0x6c, 0x7c, 0x1e, 0x1a, 0xda, 0xab, 0x3c, 0xb2, + 0x0e, 0xcb, 0x4f, 0x1e, 0x3c, 0x3a, 0xd8, 0x3d, 0x3a, 0xea, 0x1d, 0x3e, 0xbe, 0xfb, 0xc5, 0xdd, + 0xaf, 0xf4, 0xf6, 0xb6, 0x8e, 0xf6, 0xda, 0x97, 0xc8, 0x1a, 0x90, 0x83, 0xdd, 0xa3, 0x47, 0xbb, + 0x3b, 0x06, 0x6e, 0xdd, 0xf9, 0x9d, 0x32, 0xb4, 0xf8, 0x8d, 0x25, 0xff, 0x95, 0x06, 0x1a, 0x91, + 0x77, 0x61, 0x5e, 0xfc, 0xca, 0x06, 0x59, 0x15, 0xc3, 0x36, 0x7f, 0xd7, 0xa3, 0xbb, 0x96, 0x85, + 0x05, 0x5f, 0x2e, 0xff, 0xf2, 0x0f, 0xff, 0xf5, 0xf7, 0x4a, 0x0b, 0xa4, 0xb1, 0x79, 0xf6, 0xc6, + 0xe6, 0x90, 0x06, 0x31, 0x6b, 0xe3, 0x6b, 0x00, 0xe9, 0xef, 0x4f, 0x90, 0x8e, 0xf2, 0x07, 0x33, + 0x3f, 0xac, 0xd1, 0xbd, 0x5c, 0x50, 0x23, 0xda, 0xbd, 0x8c, 0xed, 0x2e, 0xdb, 0x2d, 0xd6, 0xae, + 0x17, 0x78, 0x09, 0xff, 0x31, 0x8a, 0xb7, 0xad, 0x0d, 0x32, 0x80, 0xa6, 0xfe, 0xf3, 0x12, 0x44, + 0x06, 0x9e, 0x0a, 0x7e, 0xdc, 0xa2, 0xfb, 0x52, 0x61, 0x9d, 0x8c, 0xba, 0x61, 0x1f, 0xab, 0x76, + 0x9b, 0xf5, 0x31, 0x41, 0x8a, 0xb4, 0x17, 0x1f, 0x5a, 0xe6, 0xaf, 0x48, 0x90, 0x2b, 0x9a, 0xca, + 0xc8, 0xfd, 0x86, 0x45, 0xf7, 0xe5, 0x19, 0xb5, 0xa2, 0xaf, 0x97, 0xb1, 0xaf, 0x75, 0x9b, 0xb0, + 0xbe, 0xfa, 0x48, 0x23, 0x7f, 0xc3, 0xe2, 0x6d, 0x6b, 0xe3, 0xce, 0xdf, 0x5c, 0x83, 0xba, 0x0a, + 0x15, 0x93, 0xf7, 0x61, 0xc1, 0xb8, 0x52, 0x26, 0x72, 0x1a, 0x45, 0x37, 0xd0, 0xdd, 0x2b, 0xc5, + 0x95, 0xa2, 0xe3, 0xab, 0xd8, 0x71, 0x87, 0xac, 0xb1, 0x8e, 0xc5, 0x9d, 0xec, 0x26, 0x26, 0x47, + 0xf0, 0x4c, 0xe7, 0xa7, 0x7c, 0x9e, 0xe9, 0x35, 0xb0, 0x31, 0xcf, 0xdc, 0xb5, 0xb1, 0x31, 0xcf, + 0xfc, 0xdd, 0xb1, 0x7d, 0x05, 0xbb, 0x5b, 0x23, 0x2b, 0x7a, 0x77, 0x2a, 0x84, 0x4b, 0x31, 0x3d, + 0x5f, 0xff, 0xe1, 0x05, 0xf2, 0xb2, 0x62, 0xac, 0xa2, 0x1f, 0x64, 0x50, 0x2c, 0x92, 0xff, 0x55, + 0x06, 0xbb, 0x83, 0x5d, 0x11, 0x82, 0xdb, 0xa7, 0xff, 0xee, 0x02, 0xf9, 0x2a, 0xd4, 0xd5, 0x93, + 0x5c, 0xb2, 0xae, 0x3d, 0x91, 0xd6, 0x9f, 0x10, 0x77, 0x3b, 0xf9, 0x8a, 0x22, 0xc6, 0xd0, 0x5b, + 0x66, 0x8c, 0xf1, 0x04, 0x1a, 0xda, 0xb3, 0x5b, 0x72, 0x59, 0x05, 0xfa, 0xb3, 0x4f, 0x7b, 0xbb, + 0xdd, 0xa2, 0x2a, 0xd1, 0xc5, 0x12, 0x76, 0xd1, 0x20, 0x75, 0xe4, 0xbd, 0xe4, 0x59, 0x18, 0x93, + 0x7d, 0x58, 0x15, 0x07, 0x97, 0x63, 0xfa, 0x51, 0x96, 0xa8, 0xe0, 0x77, 0x28, 0x6e, 0x5b, 0xe4, + 0x1d, 0xa8, 0xc9, 0xd7, 0xd5, 0x64, 0xad, 0xf8, 0x95, 0x78, 0x77, 0x3d, 0x87, 0x0b, 0xb5, 0xf6, + 0x15, 0x80, 0xf4, 0x8d, 0xaf, 0x12, 0xe0, 0xdc, 0x9b, 0x61, 0xb5, 0x3b, 0xf9, 0x07, 0xc1, 0xf6, + 0x1a, 0x4e, 0xb0, 0x4d, 0x50, 0x80, 0x03, 0x7a, 0x2e, 0x1f, 0xac, 0x7c, 0x1d, 0x1a, 0xda, 0x33, + 0x5f, 0xb5, 0x7c, 0xf9, 0x27, 0xc2, 0x6a, 0xf9, 0x0a, 0x5e, 0x05, 0xdb, 0x5d, 0x6c, 0x7d, 0xc5, + 0x5e, 0x64, 0xad, 0xc7, 0xde, 0x30, 0x18, 0x71, 0x02, 0xb6, 0x41, 0xa7, 0xb0, 0x60, 0xbc, 0xe5, + 0x55, 0xd2, 0x53, 0xf4, 0x52, 0x58, 0x49, 0x4f, 0xe1, 0xf3, 0x5f, 0xc9, 0xce, 0xf6, 0x12, 0xeb, + 0xe7, 0x0c, 0x49, 0xb4, 0x9e, 0xde, 0x83, 0x86, 0xf6, 0x2e, 0x57, 0xcd, 0x25, 0xff, 0x04, 0x58, + 0xcd, 0xa5, 0xe8, 0x19, 0xef, 0x0a, 0xf6, 0xd1, 0xb2, 0x91, 0x15, 0xf0, 0xbd, 0x07, 0x6b, 0xfb, + 0x7d, 0x68, 0x99, 0x2f, 0x75, 0x95, 0x5c, 0x16, 0xbe, 0xf9, 0x55, 0x72, 0x39, 0xe3, 0x79, 0xaf, + 0x60, 0xe9, 0x8d, 0x65, 0xd5, 0xc9, 0xe6, 0x07, 0xe2, 0xe2, 0xf6, 0x43, 0xf2, 0x25, 0xa6, 0x7c, + 0xc4, 0x03, 0x1c, 0xb2, 0xae, 0x71, 0xad, 0xfe, 0x4c, 0x47, 0xc9, 0x4b, 0xee, 0xad, 0x8e, 0xc9, + 0xcc, 0xfc, 0xc5, 0x0a, 0x5a, 0x14, 0x7c, 0x88, 0xa3, 0x59, 0x14, 0xfd, 0xad, 0x8e, 0x66, 0x51, + 0x8c, 0xf7, 0x3a, 0x59, 0x8b, 0x92, 0x78, 0xac, 0x8d, 0x00, 0x16, 0x33, 0x29, 0x69, 0x4a, 0x2a, + 0x8a, 0x73, 0x78, 0xbb, 0x57, 0x9f, 0x9f, 0xc9, 0x66, 0x2a, 0x2a, 0xa9, 0xa0, 0x36, 0x65, 0xc6, + 0xf4, 0x2f, 0x40, 0x53, 0x7f, 0x43, 0x49, 0x74, 0x51, 0xce, 0xf6, 0xf4, 0x52, 0x61, 0x9d, 0xb9, + 0xb9, 0xa4, 0xa9, 0x77, 0x43, 0xbe, 0x0c, 0x6b, 0x4a, 0xd4, 0xf5, 0x2c, 0xa7, 0x98, 0xbc, 0x52, + 0x90, 0xfb, 0xa4, 0x87, 0x33, 0xba, 0x97, 0x67, 0x26, 0x47, 0xdd, 0xb6, 0x18, 0xd3, 0x98, 0x8f, + 0xd3, 0x52, 0x65, 0x5e, 0xf4, 0x26, 0x2f, 0x55, 0xe6, 0x85, 0x2f, 0xda, 0x24, 0xd3, 0x90, 0x65, + 0x63, 0x8d, 0x78, 0xec, 0x9e, 0xbc, 0x07, 0x8b, 0x5a, 0x1e, 0xe9, 0xd1, 0x34, 0xe8, 0x2b, 0x01, + 0xc8, 0x3f, 0x38, 0xe8, 0x16, 0xf9, 0xdb, 0xf6, 0x3a, 0xb6, 0xbf, 0x64, 0x1b, 0x8b, 0xc3, 0x98, + 0x7f, 0x1b, 0x1a, 0x7a, 0x8e, 0xea, 0x73, 0xda, 0x5d, 0xd7, 0xaa, 0xf4, 0x7c, 0xf9, 0xdb, 0x16, + 0xf9, 0x03, 0x0b, 0x9a, 0x46, 0xc6, 0xa7, 0x71, 0x43, 0x95, 0x69, 0xa7, 0xa3, 0xd7, 0xe9, 0x0d, + 0xd9, 0x0e, 0x0e, 0x72, 0x7f, 0xe3, 0x0b, 0xc6, 0x22, 0x7c, 0x60, 0x9c, 0xdb, 0x6e, 0x65, 0x7f, + 0xa2, 0xe4, 0xc3, 0x2c, 0x81, 0xfe, 0x28, 0xe3, 0xc3, 0xdb, 0x16, 0xf9, 0x9e, 0x05, 0x2d, 0x33, + 0xda, 0xa0, 0xb6, 0xaa, 0x30, 0xae, 0xa1, 0xb6, 0x6a, 0x46, 0x88, 0xe2, 0x3d, 0x1c, 0xe5, 0xa3, + 0x0d, 0xc7, 0x18, 0xa5, 0x78, 0xb6, 0xf8, 0x93, 0x8d, 0x96, 0xbc, 0xcd, 0x7f, 0x7c, 0x48, 0x86, + 0xc0, 0x88, 0x66, 0x35, 0xb2, 0xdb, 0xab, 0xff, 0xf2, 0xce, 0x4d, 0xeb, 0xb6, 0x45, 0xbe, 0xce, + 0x7f, 0xc9, 0x44, 0x7c, 0x8b, 0x5c, 0xf2, 0xa2, 0xdf, 0xdb, 0xd7, 0x71, 0x4e, 0x57, 0xed, 0xcb, + 0xc6, 0x9c, 0xb2, 0xf6, 0x78, 0x8b, 0x8f, 0x4e, 0xfc, 0x68, 0x4e, 0x6a, 0x50, 0x72, 0x3f, 0xa4, + 0x33, 0x7b, 0x90, 0x23, 0x3e, 0x48, 0x41, 0x6e, 0xb0, 0xf2, 0x0b, 0x36, 0x63, 0x6f, 0xe0, 0x58, + 0xaf, 0xdb, 0xaf, 0xcc, 0x1c, 0xeb, 0x26, 0xc6, 0x0c, 0xd8, 0x88, 0x0f, 0x01, 0xd2, 0x70, 0x35, + 0xc9, 0x84, 0x4b, 0x95, 0x80, 0xe7, 0x23, 0xda, 0xa6, 0xbc, 0xc8, 0xa8, 0x2a, 0x6b, 0xf1, 0xab, + 0x5c, 0x5d, 0x3d, 0x90, 0x81, 0x56, 0xdd, 0x29, 0x31, 0xe3, 0xca, 0x86, 0x53, 0x92, 0x6d, 0xdf, + 0x50, 0x56, 0x2a, 0x6a, 0xfb, 0x18, 0x16, 0xf6, 0xc3, 0xf0, 0xe9, 0x64, 0xac, 0xae, 0x97, 0xcc, + 0x70, 0xde, 0x9e, 0x1b, 0x9f, 0x76, 0x33, 0xb3, 0xb0, 0xaf, 0x61, 0x53, 0x5d, 0xd2, 0xd1, 0x9a, + 0xda, 0xfc, 0x20, 0x0d, 0x87, 0x7f, 0x48, 0x5c, 0x58, 0x52, 0x3a, 0x50, 0x0d, 0xbc, 0x6b, 0x36, + 0x63, 0x68, 0xbe, 0x6c, 0x17, 0x86, 0x67, 0x2b, 0x47, 0xbb, 0x19, 0xcb, 0x36, 0x6f, 0x5b, 0xe4, + 0x10, 0x9a, 0x3b, 0xb4, 0x1f, 0x0e, 0xa8, 0x88, 0x89, 0x2d, 0xa7, 0x03, 0x57, 0xc1, 0xb4, 0xee, + 0x82, 0x01, 0x9a, 0x76, 0x61, 0xec, 0x4e, 0x23, 0xfa, 0x8d, 0xcd, 0x0f, 0x44, 0xb4, 0xed, 0x43, + 0x69, 0x17, 0x64, 0x38, 0xd2, 0xb0, 0x0b, 0x99, 0xf8, 0xa5, 0x61, 0x17, 0x72, 0xf1, 0x4b, 0x63, + 0xa9, 0x65, 0x38, 0x94, 0xf8, 0xb0, 0x94, 0x0b, 0x79, 0x2a, 0x93, 0x30, 0x2b, 0x50, 0xda, 0xbd, + 0x36, 0x9b, 0xc0, 0xec, 0x6d, 0xc3, 0xec, 0xed, 0x08, 0x16, 0x76, 0x28, 0x5f, 0x2c, 0x9e, 0xc3, + 0x92, 0x49, 0x1b, 0xd6, 0x33, 0x64, 0xb2, 0x0a, 0x1c, 0xeb, 0x4c, 0xc3, 0x8f, 0x09, 0x24, 0xe4, + 0xab, 0xd0, 0xb8, 0x4f, 0x13, 0x99, 0xb4, 0xa2, 0x5c, 0xcf, 0x4c, 0x16, 0x4b, 0xb7, 0x20, 0xe7, + 0xc5, 0xe4, 0x19, 0x6c, 0x6d, 0x93, 0x0e, 0x86, 0x94, 0x2b, 0xa7, 0x9e, 0x37, 0xf8, 0x90, 0xfc, + 0x3c, 0x36, 0xae, 0xb2, 0xe6, 0xd6, 0xb4, 0x5c, 0x07, 0xbd, 0xf1, 0xc5, 0x0c, 0x5e, 0xd4, 0x72, + 0x10, 0x0e, 0xa8, 0xe6, 0x02, 0x05, 0xd0, 0xd0, 0x92, 0x3d, 0x95, 0x00, 0xe5, 0x13, 0x57, 0x95, + 0x00, 0x15, 0xe4, 0x86, 0xda, 0x37, 0xb1, 0x1f, 0x9b, 0x5c, 0x4b, 0xfb, 0xe1, 0xf9, 0xa0, 0x69, + 0x4f, 0x9b, 0x1f, 0xb8, 0xa3, 0xe4, 0x43, 0xf2, 0x04, 0xdf, 0x2e, 0xeb, 0x89, 0x39, 0xa9, 0x2f, + 0x9d, 0xcd, 0xe1, 0x51, 0x8b, 0xa5, 0x55, 0x99, 0xfe, 0x35, 0xef, 0x0a, 0x3d, 0xa5, 0xcf, 0x00, + 0x1c, 0x25, 0xe1, 0x78, 0xc7, 0xa5, 0xa3, 0x30, 0x48, 0x75, 0x6d, 0x9a, 0x7c, 0x92, 0xea, 0x2f, + 0x2d, 0x03, 0x85, 0x3c, 0xd1, 0x0e, 0x1f, 0x46, 0x5e, 0x93, 0x64, 0xae, 0x99, 0xf9, 0x29, 0x6a, + 0x41, 0x0a, 0x72, 0x54, 0x6e, 0x5b, 0x64, 0x0b, 0x20, 0x8d, 0x79, 0xab, 0xa3, 0x44, 0x2e, 0x9c, + 0xae, 0xd4, 0x5e, 0x41, 0x80, 0xfc, 0x10, 0xea, 0x69, 0x10, 0x75, 0x3d, 0x4d, 0xd8, 0x35, 0x42, + 0xae, 0xca, 0x82, 0xe7, 0x42, 0x9b, 0x76, 0x1b, 0x97, 0x0a, 0x48, 0x8d, 0x2d, 0x15, 0xc6, 0x2b, + 0x3d, 0x58, 0xe6, 0x03, 0x54, 0xee, 0x08, 0xa6, 0x53, 0xc8, 0x99, 0x14, 0x84, 0x17, 0x95, 0x34, + 0x17, 0x46, 0xe7, 0x8c, 0x68, 0x05, 0xe3, 0x56, 0x9e, 0xca, 0xc1, 0x54, 0xf3, 0x08, 0x96, 0x72, + 0xe1, 0x23, 0x25, 0xd2, 0xb3, 0x22, 0x7a, 0x4a, 0xa4, 0x67, 0x46, 0x9e, 0xec, 0x55, 0xec, 0x72, + 0xd1, 0x06, 0x3c, 0x01, 0x9d, 0x7b, 0x49, 0xff, 0xf4, 0x6d, 0x6b, 0xe3, 0xee, 0x8d, 0xf7, 0x3e, + 0x3e, 0xf4, 0x92, 0xd3, 0xc9, 0xf1, 0xad, 0x7e, 0x38, 0xda, 0xf4, 0x65, 0x48, 0x41, 0x24, 0x45, + 0x6d, 0xfa, 0xc1, 0x60, 0x13, 0x5b, 0x3e, 0x9e, 0xc3, 0x5f, 0x70, 0xfd, 0xd4, 0xff, 0x04, 0x00, + 0x00, 0xff, 0xff, 0x9b, 0xe6, 0x7a, 0xde, 0xf3, 0x55, 0x00, 0x00, } diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 0171be62a..661d02302 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -359,6 +359,14 @@ service Lightning { }; } + /** lncli: `subscribechannelevents` + SubscribeChannelEvents creates a uni-directional stream from the server to + the client in which any updates relevant to the state of the channels are + sent over. Events include new active channels, inactive channels, and closed + channels. + */ + rpc SubscribeChannelEvents (ChannelEventSubscription) returns (stream ChannelEventUpdate); + /** lncli: `closedchannels` ClosedChannels returns a description of all the closed channels that this node was a participant in. @@ -1401,6 +1409,27 @@ message PendingChannelsResponse { repeated WaitingCloseChannel waiting_close_channels = 5 [ json_name = "waiting_close_channels" ]; } +message ChannelEventSubscription { +} + +message ChannelEventUpdate { + oneof channel { + Channel open_channel = 1 [ json_name = "open_channel" ]; + ChannelCloseSummary closed_channel = 2 [ json_name = "closed_channel" ]; + ChannelPoint active_channel = 3 [ json_name = "active_channel" ]; + ChannelPoint inactive_channel = 4 [ json_name = "inactive_channel" ]; + } + + enum UpdateType { + OPEN_CHANNEL = 0; + CLOSED_CHANNEL = 1; + ACTIVE_CHANNEL = 2; + INACTIVE_CHANNEL = 3; + } + + UpdateType type = 5 [ json_name = "type" ]; +} + message WalletBalanceRequest { } message WalletBalanceResponse { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index b1b8e7301..2817d5aec 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1127,6 +1127,16 @@ ], "default": "COOPERATIVE_CLOSE" }, + "ChannelEventUpdateUpdateType": { + "type": "string", + "enum": [ + "OPEN_CHANNEL", + "CLOSED_CHANNEL", + "ACTIVE_CHANNEL", + "INACTIVE_CHANNEL" + ], + "default": "OPEN_CHANNEL" + }, "InvoiceInvoiceState": { "type": "string", "enum": [ @@ -1548,6 +1558,26 @@ } } }, + "lnrpcChannelEventUpdate": { + "type": "object", + "properties": { + "open_channel": { + "$ref": "#/definitions/lnrpcChannel" + }, + "closed_channel": { + "$ref": "#/definitions/lnrpcChannelCloseSummary" + }, + "active_channel": { + "$ref": "#/definitions/lnrpcChannelPoint" + }, + "inactive_channel": { + "$ref": "#/definitions/lnrpcChannelPoint" + }, + "type": { + "$ref": "#/definitions/ChannelEventUpdateUpdateType" + } + } + }, "lnrpcChannelFeeReport": { "type": "object", "properties": { From ff0339a186debc95e53bd78ba343fa027fed95cf Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Tue, 22 Jan 2019 18:28:35 -0800 Subject: [PATCH 09/10] rpcserver: implement SubscribeChannels RPC call. --- rpcserver.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index 933be7986..b4326ca62 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -30,6 +30,7 @@ import ( "github.com/lightningnetwork/lnd/autopilot" "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/invoices" @@ -245,6 +246,10 @@ var ( Entity: "offchain", Action: "read", }}, + "/lnrpc.Lightning/SubscribeChannelEvents": {{ + Entity: "offchain", + Action: "read", + }}, "/lnrpc.Lightning/ClosedChannels": {{ Entity: "offchain", Action: "read", @@ -2474,6 +2479,84 @@ func createRPCClosedChannel( } } +// SubscribeChannelEvents returns a uni-directional stream (server -> client) +// for notifying the client of newly active, inactive or closed channels. +func (r *rpcServer) SubscribeChannelEvents(req *lnrpc.ChannelEventSubscription, + updateStream lnrpc.Lightning_SubscribeChannelEventsServer) error { + + channelEventSub, err := r.server.channelNotifier.SubscribeChannelEvents() + if err != nil { + return err + } + + // Ensure that the resources for the client is cleaned up once either + // the server, or client exits. + defer channelEventSub.Cancel() + + graph := r.server.chanDB.ChannelGraph() + + for { + select { + // A new update has been sent by the channel router, we'll + // marshal it into the form expected by the gRPC client, then + // send it off to the client(s). + case e := <-channelEventSub.Updates(): + var update *lnrpc.ChannelEventUpdate + switch event := e.(type) { + case channelnotifier.OpenChannelEvent: + channel := createRPCOpenChannel(r, graph, + event.Channel, true) + update = &lnrpc.ChannelEventUpdate{ + Type: lnrpc.ChannelEventUpdate_OPEN_CHANNEL, + Channel: &lnrpc.ChannelEventUpdate_OpenChannel{ + OpenChannel: channel, + }, + } + case channelnotifier.ClosedChannelEvent: + closedChannel := createRPCClosedChannel(event.CloseSummary) + update = &lnrpc.ChannelEventUpdate{ + Type: lnrpc.ChannelEventUpdate_CLOSED_CHANNEL, + Channel: &lnrpc.ChannelEventUpdate_ClosedChannel{ + ClosedChannel: closedChannel, + }, + } + case channelnotifier.ActiveChannelEvent: + update = &lnrpc.ChannelEventUpdate{ + Type: lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL, + Channel: &lnrpc.ChannelEventUpdate_ActiveChannel{ + ActiveChannel: &lnrpc.ChannelPoint{ + FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ + FundingTxidBytes: event.ChannelPoint.Hash[:], + }, + OutputIndex: event.ChannelPoint.Index, + }, + }, + } + case channelnotifier.InactiveChannelEvent: + update = &lnrpc.ChannelEventUpdate{ + Type: lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL, + Channel: &lnrpc.ChannelEventUpdate_InactiveChannel{ + InactiveChannel: &lnrpc.ChannelPoint{ + FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ + FundingTxidBytes: event.ChannelPoint.Hash[:], + }, + OutputIndex: event.ChannelPoint.Index, + }, + }, + } + default: + return fmt.Errorf("unexpected channel event update: %v", event) + } + + if err := updateStream.Send(update); err != nil { + return err + } + case <-r.quit: + return nil + } + } +} + // savePayment saves a successfully completed payment to the database for // historical record keeping. func (r *rpcServer) savePayment(route *routing.Route, From b826101aae0da95c4d6ede4d6d5e58df87590298 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 1 Nov 2018 20:20:21 -0700 Subject: [PATCH 10/10] lnd_test: alter basic channel creation test to test chan subscription. Because the integration tests are already long-running, it is preferable to add testing for the RPC channel update subscription to an existing test rather than adding additional tests. --- lnd_test.go | 220 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 210 insertions(+), 10 deletions(-) diff --git a/lnd_test.go b/lnd_test.go index 07025a611..194f692cb 100644 --- a/lnd_test.go +++ b/lnd_test.go @@ -5694,15 +5694,137 @@ func testInvoiceSubscriptions(net *lntest.NetworkHarness, t *harnessTest) { closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false) } -// testBasicChannelCreation test multiple channel opening and closing. -func testBasicChannelCreation(net *lntest.NetworkHarness, t *harnessTest) { - ctxb := context.Background() +// channelSubscription houses the proxied update and error chans for a node's +// channel subscriptions. +type channelSubscription struct { + updateChan chan *lnrpc.ChannelEventUpdate + errChan chan error + quit chan struct{} +} +// subscribeChannelNotifications subscribes to channel updates and launches a +// goroutine that forwards these to the returned channel. +func subscribeChannelNotifications(ctxb context.Context, t *harnessTest, + node *lntest.HarnessNode) channelSubscription { + + // We'll first start by establishing a notification client which will + // send us notifications upon channels becoming active, inactive or + // closed. + req := &lnrpc.ChannelEventSubscription{} + ctx, cancelFunc := context.WithCancel(ctxb) + + chanUpdateClient, err := node.SubscribeChannelEvents(ctx, req) + if err != nil { + t.Fatalf("unable to create channel update client: %v", err) + } + + // We'll launch a goroutine that will be responsible for proxying all + // notifications recv'd from the client into the channel below. + errChan := make(chan error, 1) + quit := make(chan struct{}) + chanUpdates := make(chan *lnrpc.ChannelEventUpdate, 20) + go func() { + defer cancelFunc() + for { + select { + case <-quit: + return + default: + chanUpdate, err := chanUpdateClient.Recv() + select { + case <-quit: + return + default: + } + + if err == io.EOF { + return + } else if err != nil { + select { + case errChan <- err: + case <-quit: + } + return + } + + select { + case chanUpdates <- chanUpdate: + case <-quit: + return + } + } + } + }() + + return channelSubscription{ + updateChan: chanUpdates, + errChan: errChan, + quit: quit, + } +} + +// verifyCloseUpdate is used to verify that a closed channel update is of the +// expected type. +func verifyCloseUpdate(chanUpdate *lnrpc.ChannelEventUpdate, + force bool, forceType lnrpc.ChannelCloseSummary_ClosureType) error { + + // We should receive one inactive and one closed notification + // for each channel. + switch update := chanUpdate.Channel.(type) { + case *lnrpc.ChannelEventUpdate_InactiveChannel: + if chanUpdate.Type != lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL { + return fmt.Errorf("update type mismatch: expected %v, got %v", + lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL, + chanUpdate.Type) + } + case *lnrpc.ChannelEventUpdate_ClosedChannel: + if chanUpdate.Type != + lnrpc.ChannelEventUpdate_CLOSED_CHANNEL { + return fmt.Errorf("update type mismatch: expected %v, got %v", + lnrpc.ChannelEventUpdate_CLOSED_CHANNEL, + chanUpdate.Type) + } + + switch force { + case true: + if update.ClosedChannel.CloseType != forceType { + return fmt.Errorf("channel closure type mismatch: "+ + "expected %v, got %v", + forceType, + update.ClosedChannel.CloseType) + } + case false: + if update.ClosedChannel.CloseType != + lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE { + return fmt.Errorf("channel closure type "+ + "mismatch: expected %v, got %v", + lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE, + update.ClosedChannel.CloseType) + } + } + default: + return fmt.Errorf("channel update channel of wrong type, "+ + "expected closed channel, got %T", + update) + } + + return nil +} + +// testBasicChannelCreationAndUpdates tests multiple channel opening and closing, +// and ensures that if a node is subscribed to channel updates they will be +// received correctly for both cooperative and force closed channels. +func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() const ( numChannels = 2 amount = maxBtcFundingAmount ) + // Let Bob subscribe to channel notifications. + bobChanSub := subscribeChannelNotifications(ctxb, t, net.Bob) + defer close(bobChanSub.quit) + // Open the channel between Alice and Bob, asserting that the // channel has been properly open on-chain. chanPoints := make([]*lnrpc.ChannelPoint, numChannels) @@ -5716,11 +5838,89 @@ func testBasicChannelCreation(net *lntest.NetworkHarness, t *harnessTest) { ) } - // Close the channel between Alice and Bob, asserting that the - // channel has been properly closed on-chain. - for _, chanPoint := range chanPoints { - ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false) + // Since each of the channels just became open, Bob should we receive an + // open and an active notification for each channel. + var numChannelUpds int + for numChannelUpds < 2*numChannels { + select { + case update := <-bobChanSub.updateChan: + switch update.Type { + case lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL: + case lnrpc.ChannelEventUpdate_OPEN_CHANNEL: + default: + t.Fatalf("update type mismatch: expected open or active "+ + "channel notification, got: %v", update.Type) + } + numChannelUpds++ + case <-time.After(time.Second * 10): + t.Fatalf("timeout waiting for channel notifications, "+ + "only received %d/%d chanupds", numChannelUpds, + numChannels) + } + } + + // Subscribe Alice to channel updates so we can test that both remote + // and local force close notifications are received correctly. + aliceChanSub := subscribeChannelNotifications(ctxb, t, net.Alice) + defer close(aliceChanSub.quit) + + // Close the channel between Alice and Bob, asserting that the channel + // has been properly closed on-chain. + for i, chanPoint := range chanPoints { + ctx, _ := context.WithTimeout(context.Background(), defaultTimeout) + + // Force close half of the channels. + force := i%2 == 0 + closeChannelAndAssert(ctx, t, net, net.Alice, chanPoint, force) + if force { + cleanupForceClose(t, net, net.Alice, chanPoint) + } + } + + // verifyCloseUpdatesReceived is used to verify that Alice and Bob + // receive the correct channel updates in order. + verifyCloseUpdatesReceived := func(sub channelSubscription, + forceType lnrpc.ChannelCloseSummary_ClosureType) error { + + // Ensure one inactive and one closed notification is received for each + // closed channel. + numChannelUpds := 0 + for numChannelUpds < 2*numChannels { + // Every other channel should be force closed. + force := (numChannelUpds/2)%2 == 0 + + select { + case chanUpdate := <-sub.updateChan: + err := verifyCloseUpdate(chanUpdate, force, forceType) + if err != nil { + return err + } + + numChannelUpds++ + case err := <-sub.errChan: + return err + case <-time.After(time.Second * 10): + return fmt.Errorf("timeout waiting for channel "+ + "notifications, only received %d/%d "+ + "chanupds", numChannelUpds, 2*numChannels) + } + } + + return nil + } + + // Verify Bob receives all closed channel notifications. He should + // receive a remote force close notification for force closed channels. + if err := verifyCloseUpdatesReceived(bobChanSub, + lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE); err != nil { + t.Fatalf("errored verifying close updates: %v", err) + } + + // Verify Alice receives all closed channel notifications. She should + // receive a remote force close notification for force closed channels. + if err := verifyCloseUpdatesReceived(aliceChanSub, + lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE); err != nil { + t.Fatalf("errored verifying close updates: %v", err) } } @@ -12943,8 +13143,8 @@ var testsCases = []*testCase{ test: testMultiHopOverPrivateChannels, }, { - name: "multiple channel creation", - test: testBasicChannelCreation, + name: "multiple channel creation and update subscription", + test: testBasicChannelCreationAndUpdates, }, { name: "invoice update subscription",