Merge pull request #2740 from wpaulino/gossip-sync-manager
discovery: introduce gossiper syncManager subsystem
This commit is contained in:
commit
30f2b1ca01
@ -248,7 +248,7 @@ type config struct {
|
||||
Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"`
|
||||
MinChanSize int64 `long:"minchansize" description:"The smallest channel size (in satoshis) that we should accept. Incoming channels smaller than this will be rejected"`
|
||||
|
||||
NoChanUpdates bool `long:"nochanupdates" description:"If specified, lnd will not request real-time channel updates from connected peers. This option should be used by routing nodes to save bandwidth."`
|
||||
NumGraphSyncPeers int `long:"numgraphsyncpeers" description:"The number of peers that we should receive new graph updates from. This option can be tuned to save bandwidth for light clients or routing nodes."`
|
||||
|
||||
RejectPush bool `long:"rejectpush" description:"If true, lnd will not accept channel opening requests with non-zero push amounts. This should prevent accidental pushes to merchant nodes."`
|
||||
|
||||
@ -335,6 +335,7 @@ func loadConfig() (*config, error) {
|
||||
Alias: defaultAlias,
|
||||
Color: defaultColor,
|
||||
MinChanSize: int64(minChanFundingSize),
|
||||
NumGraphSyncPeers: defaultMinPeers,
|
||||
Tor: &torConfig{
|
||||
SOCKS: defaultTorSOCKS,
|
||||
DNS: defaultTorDNS,
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/multimutex"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -75,7 +76,7 @@ type Config struct {
|
||||
Router routing.ChannelGraphSource
|
||||
|
||||
// ChanSeries is an interfaces that provides access to a time series
|
||||
// view of the current known channel graph. Each gossipSyncer enabled
|
||||
// view of the current known channel graph. Each GossipSyncer enabled
|
||||
// peer will utilize this in order to create and respond to channel
|
||||
// graph time series queries.
|
||||
ChanSeries ChannelGraphTimeSeries
|
||||
@ -143,6 +144,28 @@ type Config struct {
|
||||
// TODO(roasbeef): extract ann crafting + sign from fundingMgr into
|
||||
// here?
|
||||
AnnSigner lnwallet.MessageSigner
|
||||
|
||||
// NumActiveSyncers is the number of peers for which we should have
|
||||
// active syncers with. After reaching NumActiveSyncers, any future
|
||||
// gossip syncers will be passive.
|
||||
NumActiveSyncers int
|
||||
|
||||
// RotateTicker is a ticker responsible for notifying the SyncManager
|
||||
// when it should rotate its active syncers. A single active syncer with
|
||||
// a chansSynced state will be exchanged for a passive syncer in order
|
||||
// to ensure we don't keep syncing with the same peers.
|
||||
RotateTicker ticker.Ticker
|
||||
|
||||
// HistoricalSyncTicker is a ticker responsible for notifying the
|
||||
// syncManager when it should attempt a historical sync with a gossip
|
||||
// sync peer.
|
||||
HistoricalSyncTicker ticker.Ticker
|
||||
|
||||
// ActiveSyncerTimeoutTicker is a ticker responsible for notifying the
|
||||
// syncManager when it should attempt to start the next pending
|
||||
// activeSyncer due to the current one not completing its state machine
|
||||
// within the timeout.
|
||||
ActiveSyncerTimeoutTicker ticker.Ticker
|
||||
}
|
||||
|
||||
// AuthenticatedGossiper is a subsystem which is responsible for receiving
|
||||
@ -212,13 +235,14 @@ type AuthenticatedGossiper struct {
|
||||
rejectMtx sync.RWMutex
|
||||
recentRejects map[uint64]struct{}
|
||||
|
||||
// peerSyncers keeps track of all the gossip syncers we're maintain for
|
||||
// peers that understand this mode of operation. When we go to send out
|
||||
// new updates, for all peers in the map, we'll send the messages
|
||||
// directly to their gossiper, rather than broadcasting them. With this
|
||||
// change, we ensure we filter out all updates properly.
|
||||
syncerMtx sync.RWMutex
|
||||
peerSyncers map[routing.Vertex]*gossipSyncer
|
||||
// syncMgr is a subsystem responsible for managing the gossip syncers
|
||||
// for peers currently connected. When a new peer is connected, the
|
||||
// manager will create its accompanying gossip syncer and determine
|
||||
// whether it should have an activeSync or passiveSync sync type based
|
||||
// on how many other gossip syncers are currently active. Any activeSync
|
||||
// gossip syncers are started in a round-robin manner to ensure we're
|
||||
// not syncing with multiple peers at the same time.
|
||||
syncMgr *SyncManager
|
||||
|
||||
// reliableSender is a subsystem responsible for handling reliable
|
||||
// message send requests to peers. This should only be used for channels
|
||||
@ -243,7 +267,14 @@ func New(cfg Config, selfKey *btcec.PublicKey) *AuthenticatedGossiper {
|
||||
prematureChannelUpdates: make(map[uint64][]*networkMsg),
|
||||
channelMtx: multimutex.NewMutex(),
|
||||
recentRejects: make(map[uint64]struct{}),
|
||||
peerSyncers: make(map[routing.Vertex]*gossipSyncer),
|
||||
syncMgr: newSyncManager(&SyncManagerCfg{
|
||||
ChainHash: cfg.ChainHash,
|
||||
ChanSeries: cfg.ChanSeries,
|
||||
RotateTicker: cfg.RotateTicker,
|
||||
HistoricalSyncTicker: cfg.HistoricalSyncTicker,
|
||||
ActiveSyncerTimeoutTicker: cfg.ActiveSyncerTimeoutTicker,
|
||||
NumActiveSyncers: cfg.NumActiveSyncers,
|
||||
}),
|
||||
}
|
||||
|
||||
gossiper.reliableSender = newReliableSender(&reliableSenderCfg{
|
||||
@ -419,6 +450,8 @@ func (d *AuthenticatedGossiper) Start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
d.syncMgr.Start()
|
||||
|
||||
d.wg.Add(1)
|
||||
go d.networkHandler()
|
||||
|
||||
@ -435,11 +468,7 @@ func (d *AuthenticatedGossiper) Stop() {
|
||||
|
||||
d.blockEpochs.Cancel()
|
||||
|
||||
d.syncerMtx.RLock()
|
||||
for _, syncer := range d.peerSyncers {
|
||||
syncer.Stop()
|
||||
}
|
||||
d.syncerMtx.RUnlock()
|
||||
d.syncMgr.Stop()
|
||||
|
||||
close(d.quit)
|
||||
d.wg.Wait()
|
||||
@ -463,7 +492,7 @@ func (d *AuthenticatedGossiper) ProcessRemoteAnnouncement(msg lnwire.Message,
|
||||
errChan := make(chan error, 1)
|
||||
|
||||
// For messages in the known set of channel series queries, we'll
|
||||
// dispatch the message directly to the gossipSyncer, and skip the main
|
||||
// dispatch the message directly to the GossipSyncer, and skip the main
|
||||
// processing loop.
|
||||
switch m := msg.(type) {
|
||||
case *lnwire.QueryShortChanIDs,
|
||||
@ -471,12 +500,12 @@ func (d *AuthenticatedGossiper) ProcessRemoteAnnouncement(msg lnwire.Message,
|
||||
*lnwire.ReplyChannelRange,
|
||||
*lnwire.ReplyShortChanIDsEnd:
|
||||
|
||||
syncer, err := d.findGossipSyncer(peer.IdentityKey())
|
||||
if err != nil {
|
||||
log.Warnf("Unable to find gossip syncer for "+
|
||||
"peer=%x: %v", peer.PubKey(), err)
|
||||
syncer, ok := d.syncMgr.GossipSyncer(peer.PubKey())
|
||||
if !ok {
|
||||
log.Warnf("Gossip syncer for peer=%x not found",
|
||||
peer.PubKey())
|
||||
|
||||
errChan <- err
|
||||
errChan <- ErrGossipSyncerNotFound
|
||||
return errChan
|
||||
}
|
||||
|
||||
@ -488,24 +517,22 @@ func (d *AuthenticatedGossiper) ProcessRemoteAnnouncement(msg lnwire.Message,
|
||||
return errChan
|
||||
|
||||
// If a peer is updating its current update horizon, then we'll dispatch
|
||||
// that directly to the proper gossipSyncer.
|
||||
// that directly to the proper GossipSyncer.
|
||||
case *lnwire.GossipTimestampRange:
|
||||
syncer, err := d.findGossipSyncer(peer.IdentityKey())
|
||||
if err != nil {
|
||||
log.Warnf("Unable to find gossip syncer for "+
|
||||
"peer=%x: %v", peer.PubKey(), err)
|
||||
syncer, ok := d.syncMgr.GossipSyncer(peer.PubKey())
|
||||
if !ok {
|
||||
log.Warnf("Gossip syncer for peer=%x not found",
|
||||
peer.PubKey())
|
||||
|
||||
errChan <- err
|
||||
errChan <- ErrGossipSyncerNotFound
|
||||
return errChan
|
||||
}
|
||||
|
||||
// If we've found the message target, then we'll dispatch the
|
||||
// message directly to it.
|
||||
err = syncer.ApplyGossipFilter(m)
|
||||
if err != nil {
|
||||
log.Warnf("unable to apply gossip "+
|
||||
"filter for peer=%x: %v",
|
||||
peer.PubKey(), err)
|
||||
if err := syncer.ApplyGossipFilter(m); err != nil {
|
||||
log.Warnf("Unable to apply gossip filter for peer=%x: "+
|
||||
"%v", peer.PubKey(), err)
|
||||
|
||||
errChan <- err
|
||||
return errChan
|
||||
@ -590,10 +617,10 @@ type msgWithSenders struct {
|
||||
}
|
||||
|
||||
// mergeSyncerMap is used to merge the set of senders of a particular message
|
||||
// with peers that we have an active gossipSyncer with. We do this to ensure
|
||||
// with peers that we have an active GossipSyncer with. We do this to ensure
|
||||
// that we don't broadcast messages to any peers that we have active gossip
|
||||
// syncers for.
|
||||
func (m *msgWithSenders) mergeSyncerMap(syncers map[routing.Vertex]*gossipSyncer) {
|
||||
func (m *msgWithSenders) mergeSyncerMap(syncers map[routing.Vertex]*GossipSyncer) {
|
||||
for peerPub := range syncers {
|
||||
m.senders[peerPub] = struct{}{}
|
||||
}
|
||||
@ -812,28 +839,6 @@ func (d *deDupedAnnouncements) Emit() []msgWithSenders {
|
||||
return msgs
|
||||
}
|
||||
|
||||
// findGossipSyncer is a utility method used by the gossiper to locate the
|
||||
// gossip syncer for an inbound message so we can properly dispatch the
|
||||
// incoming message. If a gossip syncer isn't found, then one will be created
|
||||
// for the target peer.
|
||||
func (d *AuthenticatedGossiper) findGossipSyncer(pub *btcec.PublicKey) (
|
||||
*gossipSyncer, error) {
|
||||
|
||||
target := routing.NewVertex(pub)
|
||||
|
||||
// First, we'll try to find an existing gossiper for this peer.
|
||||
d.syncerMtx.RLock()
|
||||
syncer, ok := d.peerSyncers[target]
|
||||
d.syncerMtx.RUnlock()
|
||||
|
||||
// If one exists, then we'll return it directly.
|
||||
if ok {
|
||||
return syncer, nil
|
||||
}
|
||||
|
||||
return nil, ErrGossipSyncerNotFound
|
||||
}
|
||||
|
||||
// networkHandler is the primary goroutine that drives this service. The roles
|
||||
// of this goroutine includes answering queries related to the state of the
|
||||
// network, syncing up newly connected peers, and also periodically
|
||||
@ -1028,12 +1033,7 @@ func (d *AuthenticatedGossiper) networkHandler() {
|
||||
// For the set of peers that have an active gossip
|
||||
// syncers, we'll collect their pubkeys so we can avoid
|
||||
// sending them the full message blast below.
|
||||
d.syncerMtx.RLock()
|
||||
syncerPeers := make(map[routing.Vertex]*gossipSyncer)
|
||||
for peerPub, syncer := range d.peerSyncers {
|
||||
syncerPeers[peerPub] = syncer
|
||||
}
|
||||
d.syncerMtx.RUnlock()
|
||||
syncerPeers := d.syncMgr.GossipSyncers()
|
||||
|
||||
log.Infof("Broadcasting batch of %v new announcements",
|
||||
len(announcementBatch))
|
||||
@ -1088,62 +1088,16 @@ func (d *AuthenticatedGossiper) networkHandler() {
|
||||
// InitSyncState is called by outside sub-systems when a connection is
|
||||
// established to a new peer that understands how to perform channel range
|
||||
// queries. We'll allocate a new gossip syncer for it, and start any goroutines
|
||||
// needed to handle new queries. The recvUpdates bool indicates if we should
|
||||
// continue to receive real-time updates from the remote peer once we've synced
|
||||
// channel state.
|
||||
func (d *AuthenticatedGossiper) InitSyncState(syncPeer lnpeer.Peer,
|
||||
recvUpdates bool) {
|
||||
|
||||
d.syncerMtx.Lock()
|
||||
defer d.syncerMtx.Unlock()
|
||||
|
||||
// If we already have a syncer, then we'll exit early as we don't want
|
||||
// to override it.
|
||||
nodeID := routing.Vertex(syncPeer.PubKey())
|
||||
if _, ok := d.peerSyncers[nodeID]; ok {
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("Creating new gossipSyncer for peer=%x", nodeID[:])
|
||||
|
||||
encoding := lnwire.EncodingSortedPlain
|
||||
syncer := newGossiperSyncer(gossipSyncerCfg{
|
||||
chainHash: d.cfg.ChainHash,
|
||||
syncChanUpdates: recvUpdates,
|
||||
channelSeries: d.cfg.ChanSeries,
|
||||
encodingType: encoding,
|
||||
chunkSize: encodingTypeToChunkSize[encoding],
|
||||
sendToPeer: func(msgs ...lnwire.Message) error {
|
||||
return syncPeer.SendMessageLazy(false, msgs...)
|
||||
},
|
||||
})
|
||||
copy(syncer.peerPub[:], nodeID[:])
|
||||
d.peerSyncers[nodeID] = syncer
|
||||
|
||||
syncer.Start()
|
||||
// needed to handle new queries.
|
||||
func (d *AuthenticatedGossiper) InitSyncState(syncPeer lnpeer.Peer) {
|
||||
d.syncMgr.InitSyncState(syncPeer)
|
||||
}
|
||||
|
||||
// PruneSyncState is called by outside sub-systems once a peer that we were
|
||||
// previously connected to has been disconnected. In this case we can stop the
|
||||
// existing gossipSyncer assigned to the peer and free up resources.
|
||||
func (d *AuthenticatedGossiper) PruneSyncState(peer *btcec.PublicKey) {
|
||||
d.syncerMtx.Lock()
|
||||
defer d.syncerMtx.Unlock()
|
||||
|
||||
log.Infof("Removing gossipSyncer for peer=%x",
|
||||
peer.SerializeCompressed())
|
||||
|
||||
vertex := routing.NewVertex(peer)
|
||||
syncer, ok := d.peerSyncers[vertex]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
syncer.Stop()
|
||||
|
||||
delete(d.peerSyncers, vertex)
|
||||
|
||||
return
|
||||
// existing GossipSyncer assigned to the peer and free up resources.
|
||||
func (d *AuthenticatedGossiper) PruneSyncState(peer routing.Vertex) {
|
||||
d.syncMgr.PruneSyncState(peer)
|
||||
}
|
||||
|
||||
// isRecentlyRejectedMsg returns true if we recently rejected a message, and
|
||||
@ -2514,3 +2468,8 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
||||
|
||||
return chanAnn, chanUpdate, err
|
||||
}
|
||||
|
||||
// SyncManager returns the gossiper's SyncManager instance.
|
||||
func (d *AuthenticatedGossiper) SyncManager() *SyncManager {
|
||||
return d.syncMgr
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -713,12 +714,16 @@ func createTestCtx(startHeight uint32) (*testCtx, func(), error) {
|
||||
c := make(chan struct{})
|
||||
return c
|
||||
},
|
||||
Router: router,
|
||||
TrickleDelay: trickleDelay,
|
||||
RetransmitDelay: retransmitDelay,
|
||||
ProofMatureDelta: proofMatureDelta,
|
||||
WaitingProofStore: waitingProofStore,
|
||||
MessageStore: newMockMessageStore(),
|
||||
Router: router,
|
||||
TrickleDelay: trickleDelay,
|
||||
RetransmitDelay: retransmitDelay,
|
||||
ProofMatureDelta: proofMatureDelta,
|
||||
WaitingProofStore: waitingProofStore,
|
||||
MessageStore: newMockMessageStore(),
|
||||
RotateTicker: ticker.NewForce(DefaultSyncerRotationInterval),
|
||||
HistoricalSyncTicker: ticker.NewForce(DefaultHistoricalSyncInterval),
|
||||
ActiveSyncerTimeoutTicker: ticker.NewForce(DefaultActiveSyncerTimeout),
|
||||
NumActiveSyncers: 3,
|
||||
}, nodeKeyPub1)
|
||||
|
||||
if err := gossiper.Start(); err != nil {
|
||||
@ -1447,16 +1452,20 @@ func TestSignatureAnnouncementRetryAtStartup(t *testing.T) {
|
||||
// the message to the peer.
|
||||
ctx.gossiper.Stop()
|
||||
gossiper := New(Config{
|
||||
Notifier: ctx.gossiper.cfg.Notifier,
|
||||
Broadcast: ctx.gossiper.cfg.Broadcast,
|
||||
NotifyWhenOnline: ctx.gossiper.reliableSender.cfg.NotifyWhenOnline,
|
||||
NotifyWhenOffline: ctx.gossiper.reliableSender.cfg.NotifyWhenOffline,
|
||||
Router: ctx.gossiper.cfg.Router,
|
||||
TrickleDelay: trickleDelay,
|
||||
RetransmitDelay: retransmitDelay,
|
||||
ProofMatureDelta: proofMatureDelta,
|
||||
WaitingProofStore: ctx.gossiper.cfg.WaitingProofStore,
|
||||
MessageStore: ctx.gossiper.cfg.MessageStore,
|
||||
Notifier: ctx.gossiper.cfg.Notifier,
|
||||
Broadcast: ctx.gossiper.cfg.Broadcast,
|
||||
NotifyWhenOnline: ctx.gossiper.reliableSender.cfg.NotifyWhenOnline,
|
||||
NotifyWhenOffline: ctx.gossiper.reliableSender.cfg.NotifyWhenOffline,
|
||||
Router: ctx.gossiper.cfg.Router,
|
||||
TrickleDelay: trickleDelay,
|
||||
RetransmitDelay: retransmitDelay,
|
||||
ProofMatureDelta: proofMatureDelta,
|
||||
WaitingProofStore: ctx.gossiper.cfg.WaitingProofStore,
|
||||
MessageStore: ctx.gossiper.cfg.MessageStore,
|
||||
RotateTicker: ticker.NewForce(DefaultSyncerRotationInterval),
|
||||
HistoricalSyncTicker: ticker.NewForce(DefaultHistoricalSyncInterval),
|
||||
ActiveSyncerTimeoutTicker: ticker.NewForce(DefaultActiveSyncerTimeout),
|
||||
NumActiveSyncers: 3,
|
||||
}, ctx.gossiper.selfKey)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to recreate gossiper: %v", err)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
@ -59,29 +60,6 @@ func assertMsgsSent(t *testing.T, msgChan chan lnwire.Message,
|
||||
}
|
||||
}
|
||||
|
||||
// waitPredicate is a helper test function that will wait for a timeout period
|
||||
// of time until the passed predicate returns true.
|
||||
func waitPredicate(t *testing.T, timeout time.Duration, pred func() bool) {
|
||||
t.Helper()
|
||||
|
||||
const pollInterval = 20 * time.Millisecond
|
||||
exitTimer := time.After(timeout)
|
||||
|
||||
for {
|
||||
<-time.After(pollInterval)
|
||||
|
||||
select {
|
||||
case <-exitTimer:
|
||||
t.Fatalf("predicate not satisfied after timeout")
|
||||
default:
|
||||
}
|
||||
|
||||
if pred() {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestReliableSenderFlow ensures that the flow for sending messages reliably to
|
||||
// a peer while taking into account its connection lifecycle works as expected.
|
||||
func TestReliableSenderFlow(t *testing.T) {
|
||||
@ -262,27 +240,23 @@ func TestReliableSenderStaleMessages(t *testing.T) {
|
||||
// message store since it is seen as stale and has been sent at least
|
||||
// once. Once the message is removed, the peerHandler should be torn
|
||||
// down as there are no longer any pending messages within the store.
|
||||
var predErr error
|
||||
waitPredicate(t, time.Second, func() bool {
|
||||
err := lntest.WaitNoError(func() error {
|
||||
msgs, err := reliableSender.cfg.MessageStore.MessagesForPeer(
|
||||
peerPubKey,
|
||||
)
|
||||
if err != nil {
|
||||
predErr = fmt.Errorf("unable to retrieve messages for "+
|
||||
return fmt.Errorf("unable to retrieve messages for "+
|
||||
"peer: %v", err)
|
||||
return false
|
||||
}
|
||||
if len(msgs) != 0 {
|
||||
predErr = fmt.Errorf("expected to not find any "+
|
||||
return fmt.Errorf("expected to not find any "+
|
||||
"messages for peer, found %d", len(msgs))
|
||||
return false
|
||||
}
|
||||
|
||||
predErr = nil
|
||||
return true
|
||||
})
|
||||
if predErr != nil {
|
||||
t.Fatal(predErr)
|
||||
return nil
|
||||
}, time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Override IsMsgStale to no longer mark messages as stale.
|
||||
|
735
discovery/sync_manager.go
Normal file
735
discovery/sync_manager.go
Normal file
@ -0,0 +1,735 @@
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultSyncerRotationInterval is the default interval in which we'll
|
||||
// rotate a single active syncer.
|
||||
DefaultSyncerRotationInterval = 20 * time.Minute
|
||||
|
||||
// DefaultHistoricalSyncInterval is the default interval in which we'll
|
||||
// force a historical sync to ensure we have as much of the public
|
||||
// network as possible.
|
||||
DefaultHistoricalSyncInterval = 20 * time.Minute
|
||||
|
||||
// DefaultActiveSyncerTimeout is the default timeout interval in which
|
||||
// we'll wait until an active syncer has completed its state machine and
|
||||
// reached its final chansSynced state.
|
||||
DefaultActiveSyncerTimeout = 5 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrSyncManagerExiting is an error returned when we attempt to
|
||||
// start/stop a gossip syncer for a connected/disconnected peer, but the
|
||||
// SyncManager has already been stopped.
|
||||
ErrSyncManagerExiting = errors.New("sync manager exiting")
|
||||
)
|
||||
|
||||
// staleActiveSyncer is an internal message the SyncManager will use in order to
|
||||
// handle a peer corresponding to an active syncer being disconnected.
|
||||
type staleActiveSyncer struct {
|
||||
// syncer is the active syncer to be removed.
|
||||
syncer *GossipSyncer
|
||||
|
||||
// transitioned, if true, signals that the active GossipSyncer is stale
|
||||
// due to being transitioned to a PassiveSync state.
|
||||
transitioned bool
|
||||
|
||||
// done serves as a signal to the caller that the SyncManager's internal
|
||||
// state correctly reflects the stale active syncer. This is needed to
|
||||
// ensure we always create a new syncer for a flappy peer after they
|
||||
// disconnect if they happened to be an active syncer.
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
// SyncManagerCfg contains all of the dependencies required for the SyncManager
|
||||
// to carry out its duties.
|
||||
type SyncManagerCfg struct {
|
||||
// ChainHash is a hash that indicates the specific network of the active
|
||||
// chain.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// ChanSeries is an interface that provides access to a time series view
|
||||
// of the current known channel graph. Each GossipSyncer enabled peer
|
||||
// will utilize this in order to create and respond to channel graph
|
||||
// time series queries.
|
||||
ChanSeries ChannelGraphTimeSeries
|
||||
|
||||
// NumActiveSyncers is the number of peers for which we should have
|
||||
// active syncers with. After reaching NumActiveSyncers, any future
|
||||
// gossip syncers will be passive.
|
||||
NumActiveSyncers int
|
||||
|
||||
// RotateTicker is a ticker responsible for notifying the SyncManager
|
||||
// when it should rotate its active syncers. A single active syncer with
|
||||
// a chansSynced state will be exchanged for a passive syncer in order
|
||||
// to ensure we don't keep syncing with the same peers.
|
||||
RotateTicker ticker.Ticker
|
||||
|
||||
// HistoricalSyncTicker is a ticker responsible for notifying the
|
||||
// SyncManager when it should attempt a historical sync with a gossip
|
||||
// sync peer.
|
||||
HistoricalSyncTicker ticker.Ticker
|
||||
|
||||
// ActiveSyncerTimeoutTicker is a ticker responsible for notifying the
|
||||
// SyncManager when it should attempt to start the next pending
|
||||
// activeSyncer due to the current one not completing its state machine
|
||||
// within the timeout.
|
||||
ActiveSyncerTimeoutTicker ticker.Ticker
|
||||
}
|
||||
|
||||
// SyncManager is a subsystem of the gossiper that manages the gossip syncers
|
||||
// for peers currently connected. When a new peer is connected, the manager will
|
||||
// create its accompanying gossip syncer and determine whether it should have an
|
||||
// ActiveSync or PassiveSync sync type based on how many other gossip syncers
|
||||
// are currently active. Any ActiveSync gossip syncers are started in a
|
||||
// round-robin manner to ensure we're not syncing with multiple peers at the
|
||||
// same time. The first GossipSyncer registered with the SyncManager will
|
||||
// attempt a historical sync to ensure we have as much of the public channel
|
||||
// graph as possible.
|
||||
type SyncManager struct {
|
||||
start sync.Once
|
||||
stop sync.Once
|
||||
|
||||
cfg SyncManagerCfg
|
||||
|
||||
// historicalSync allows us to perform an initial historical sync only
|
||||
// _once_ with a peer during the SyncManager's startup.
|
||||
historicalSync sync.Once
|
||||
|
||||
// activeSyncers is the set of all syncers for which we are currently
|
||||
// receiving graph updates from. The number of possible active syncers
|
||||
// is bounded by NumActiveSyncers.
|
||||
activeSyncers map[routing.Vertex]*GossipSyncer
|
||||
|
||||
// inactiveSyncers is the set of all syncers for which we are not
|
||||
// currently receiving new graph updates from.
|
||||
inactiveSyncers map[routing.Vertex]*GossipSyncer
|
||||
|
||||
// pendingActiveSyncers is a map that tracks our set of pending active
|
||||
// syncers. This map will be queried when choosing the next pending
|
||||
// active syncer in the queue to ensure it is not stale.
|
||||
pendingActiveSyncers map[routing.Vertex]*GossipSyncer
|
||||
|
||||
// pendingActiveSyncerQueue is the list of active syncers which are
|
||||
// pending to be started. Syncers will be added to this list through the
|
||||
// newActiveSyncers and staleActiveSyncers channels.
|
||||
pendingActiveSyncerQueue *list.List
|
||||
|
||||
// newActiveSyncers is a channel that will serve as a signal to the
|
||||
// roundRobinHandler to allow it to transition the next pending active
|
||||
// syncer in the queue.
|
||||
newActiveSyncers chan struct{}
|
||||
|
||||
// staleActiveSyncers is a channel through which we'll send any stale
|
||||
// active syncers that should be removed from the round-robin.
|
||||
staleActiveSyncers chan *staleActiveSyncer
|
||||
|
||||
sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
}
|
||||
|
||||
// newSyncManager constructs a new SyncManager backed by the given config.
|
||||
func newSyncManager(cfg *SyncManagerCfg) *SyncManager {
|
||||
return &SyncManager{
|
||||
cfg: *cfg,
|
||||
activeSyncers: make(
|
||||
map[routing.Vertex]*GossipSyncer, cfg.NumActiveSyncers,
|
||||
),
|
||||
inactiveSyncers: make(map[routing.Vertex]*GossipSyncer),
|
||||
pendingActiveSyncers: make(map[routing.Vertex]*GossipSyncer),
|
||||
pendingActiveSyncerQueue: list.New(),
|
||||
newActiveSyncers: make(chan struct{}),
|
||||
staleActiveSyncers: make(chan *staleActiveSyncer),
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts the SyncManager in order to properly carry out its duties.
|
||||
func (m *SyncManager) Start() {
|
||||
m.start.Do(func() {
|
||||
m.wg.Add(2)
|
||||
go m.syncerHandler()
|
||||
go m.roundRobinHandler()
|
||||
})
|
||||
}
|
||||
|
||||
// Stop stops the SyncManager from performing its duties.
|
||||
func (m *SyncManager) Stop() {
|
||||
m.stop.Do(func() {
|
||||
close(m.quit)
|
||||
m.wg.Wait()
|
||||
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
for _, syncer := range m.inactiveSyncers {
|
||||
syncer.Stop()
|
||||
}
|
||||
for _, syncer := range m.pendingActiveSyncers {
|
||||
syncer.Stop()
|
||||
}
|
||||
for _, syncer := range m.activeSyncers {
|
||||
syncer.Stop()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// syncerHandler is the SyncManager's main event loop responsible for:
|
||||
//
|
||||
// 1. Finding new peers to receive graph updates from to ensure we don't only
|
||||
// receive them from the same set of peers.
|
||||
//
|
||||
// 2. Finding new peers to force a historical sync with to ensure we have as
|
||||
// much of the public network as possible.
|
||||
//
|
||||
// NOTE: This must be run as a goroutine.
|
||||
func (m *SyncManager) syncerHandler() {
|
||||
defer m.wg.Done()
|
||||
|
||||
m.cfg.RotateTicker.Resume()
|
||||
defer m.cfg.RotateTicker.Stop()
|
||||
|
||||
m.cfg.HistoricalSyncTicker.Resume()
|
||||
defer m.cfg.HistoricalSyncTicker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
// Our RotateTicker has ticked, so we'll attempt to rotate a
|
||||
// single active syncer with a passive one.
|
||||
case <-m.cfg.RotateTicker.Ticks():
|
||||
m.rotateActiveSyncerCandidate()
|
||||
|
||||
// Our HistoricalSyncTicker has ticked, so we'll randomly select
|
||||
// a peer and force a historical sync with them.
|
||||
case <-m.cfg.HistoricalSyncTicker.Ticks():
|
||||
m.forceHistoricalSync()
|
||||
|
||||
case <-m.quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// signalNewActiveSyncer sends a signal to the roundRobinHandler to ensure it
|
||||
// transitions any pending active syncers.
|
||||
func (m *SyncManager) signalNewActiveSyncer() {
|
||||
select {
|
||||
case m.newActiveSyncers <- struct{}{}:
|
||||
case <-m.quit:
|
||||
}
|
||||
}
|
||||
|
||||
// signalStaleActiveSyncer removes the syncer for the given peer from the
|
||||
// round-robin queue.
|
||||
func (m *SyncManager) signalStaleActiveSyncer(s *GossipSyncer, transitioned bool) {
|
||||
done := make(chan struct{})
|
||||
|
||||
select {
|
||||
case m.staleActiveSyncers <- &staleActiveSyncer{
|
||||
syncer: s,
|
||||
transitioned: transitioned,
|
||||
done: done,
|
||||
}:
|
||||
case <-m.quit:
|
||||
}
|
||||
|
||||
// Before returning to the caller, we'll wait for the roundRobinHandler
|
||||
// to signal us that the SyncManager has correctly updated its internal
|
||||
// state after handling the stale active syncer.
|
||||
select {
|
||||
case <-done:
|
||||
case <-m.quit:
|
||||
}
|
||||
}
|
||||
|
||||
// roundRobinHandler is the SyncManager's event loop responsible for managing
|
||||
// the round-robin queue of our active syncers to ensure they don't overlap and
|
||||
// request the same set of channels, which significantly reduces bandwidth
|
||||
// usage.
|
||||
//
|
||||
// NOTE: This must be run as a goroutine.
|
||||
func (m *SyncManager) roundRobinHandler() {
|
||||
defer m.wg.Done()
|
||||
|
||||
defer m.cfg.ActiveSyncerTimeoutTicker.Stop()
|
||||
|
||||
var (
|
||||
// current will hold the current active syncer we're waiting for
|
||||
// to complete its state machine.
|
||||
current *GossipSyncer
|
||||
|
||||
// transitionNext will be responsible for containing the signal
|
||||
// of when the current active syncer has completed its state
|
||||
// machine. This signal allows us to transition the next pending
|
||||
// active syncer, if any.
|
||||
transitionNext chan struct{}
|
||||
)
|
||||
|
||||
// transitionNextSyncer is a helper closure that we'll use to transition
|
||||
// the next syncer queued up. If there aren't any, this will act as a
|
||||
// NOP.
|
||||
transitionNextSyncer := func() {
|
||||
m.Lock()
|
||||
current = m.nextPendingActiveSyncer()
|
||||
m.Unlock()
|
||||
for current != nil {
|
||||
// We'll avoid performing the transition with the lock
|
||||
// as it can potentially stall the SyncManager due to
|
||||
// the syncTransitionTimeout.
|
||||
err := m.transitionPassiveSyncer(current)
|
||||
// If we timed out attempting to transition the syncer,
|
||||
// we'll re-queue it to retry at a later time and move
|
||||
// on to the next.
|
||||
if err == ErrSyncTransitionTimeout {
|
||||
log.Debugf("Timed out attempting to "+
|
||||
"transition pending active "+
|
||||
"GossipSyncer(%x)", current.cfg.peerPub)
|
||||
|
||||
m.Lock()
|
||||
m.queueActiveSyncer(current)
|
||||
current = m.nextPendingActiveSyncer()
|
||||
m.Unlock()
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("Unable to transition pending "+
|
||||
"active GossipSyncer(%x): %v",
|
||||
current.cfg.peerPub, err)
|
||||
|
||||
m.Lock()
|
||||
current = m.nextPendingActiveSyncer()
|
||||
m.Unlock()
|
||||
continue
|
||||
}
|
||||
|
||||
// The transition succeeded, so we'll set our signal to
|
||||
// know when we should attempt to transition the next
|
||||
// pending active syncer in our queue.
|
||||
transitionNext = current.ResetSyncedSignal()
|
||||
m.cfg.ActiveSyncerTimeoutTicker.Resume()
|
||||
return
|
||||
}
|
||||
|
||||
transitionNext = nil
|
||||
m.cfg.ActiveSyncerTimeoutTicker.Pause()
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
// A new active syncer signal has been received, which indicates
|
||||
// a new pending active syncer has been added to our queue.
|
||||
// We'll only attempt to transition it now if we're not already
|
||||
// in the middle of transitioning another one. We do this to
|
||||
// ensure we don't overlap when requesting channels from
|
||||
// different peers.
|
||||
case <-m.newActiveSyncers:
|
||||
if current == nil {
|
||||
transitionNextSyncer()
|
||||
}
|
||||
|
||||
// A stale active syncer has been received, so we'll need to
|
||||
// remove them from our queue. If we are currently waiting for
|
||||
// its state machine to complete, we'll move on to the next
|
||||
// active syncer in the queue.
|
||||
case staleActiveSyncer := <-m.staleActiveSyncers:
|
||||
s := staleActiveSyncer.syncer
|
||||
|
||||
m.Lock()
|
||||
// If the syncer has transitioned from an ActiveSync
|
||||
// type, rather than disconnecting, we'll include it in
|
||||
// the set of inactive syncers.
|
||||
if staleActiveSyncer.transitioned {
|
||||
m.inactiveSyncers[s.cfg.peerPub] = s
|
||||
}
|
||||
|
||||
// Remove the internal active syncer references for this
|
||||
// peer.
|
||||
delete(m.pendingActiveSyncers, s.cfg.peerPub)
|
||||
delete(m.activeSyncers, s.cfg.peerPub)
|
||||
|
||||
// We'll then attempt to find a passive syncer that can
|
||||
// replace the stale active syncer.
|
||||
newActiveSyncer := m.chooseRandomSyncer(nil, false)
|
||||
if newActiveSyncer != nil {
|
||||
m.queueActiveSyncer(newActiveSyncer)
|
||||
}
|
||||
m.Unlock()
|
||||
|
||||
// Signal to the caller that they can now proceed since
|
||||
// the SyncManager's state correctly reflects the
|
||||
// stale active syncer.
|
||||
close(staleActiveSyncer.done)
|
||||
|
||||
// If we're not currently waiting for an active syncer
|
||||
// to reach its terminal state, or if we are but we are
|
||||
// currently waiting for the peer being
|
||||
// disconnected/transitioned, then we'll move on to the
|
||||
// next active syncer in our queue.
|
||||
if current == nil || (current != nil &&
|
||||
current.cfg.peerPub == s.cfg.peerPub) {
|
||||
transitionNextSyncer()
|
||||
}
|
||||
|
||||
// Our current active syncer has reached its terminal
|
||||
// chansSynced state, so we'll proceed to transitioning the next
|
||||
// pending active syncer if there is one.
|
||||
case <-transitionNext:
|
||||
transitionNextSyncer()
|
||||
|
||||
// We've timed out waiting for the current active syncer to
|
||||
// reach its terminal chansSynced state, so we'll just
|
||||
// move on to the next and avoid retrying as its already been
|
||||
// transitioned.
|
||||
case <-m.cfg.ActiveSyncerTimeoutTicker.Ticks():
|
||||
log.Warnf("Timed out waiting for GossipSyncer(%x) to "+
|
||||
"be fully synced", current.cfg.peerPub)
|
||||
transitionNextSyncer()
|
||||
|
||||
case <-m.quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// queueActiveSyncer queues the given pending active gossip syncer to the end of
|
||||
// the round-robin queue.
|
||||
func (m *SyncManager) queueActiveSyncer(s *GossipSyncer) {
|
||||
log.Debugf("Queueing next pending active GossipSyncer(%x)",
|
||||
s.cfg.peerPub)
|
||||
|
||||
delete(m.inactiveSyncers, s.cfg.peerPub)
|
||||
m.pendingActiveSyncers[s.cfg.peerPub] = s
|
||||
m.pendingActiveSyncerQueue.PushBack(s)
|
||||
}
|
||||
|
||||
// nextPendingActiveSyncer returns the next active syncer pending to be
|
||||
// transitioned. If there aren't any, then `nil` is returned.
|
||||
func (m *SyncManager) nextPendingActiveSyncer() *GossipSyncer {
|
||||
next := m.pendingActiveSyncerQueue.Front()
|
||||
for next != nil {
|
||||
s := m.pendingActiveSyncerQueue.Remove(next).(*GossipSyncer)
|
||||
|
||||
// If the next pending active syncer is no longer in our lookup
|
||||
// map, then the corresponding peer has disconnected, so we'll
|
||||
// skip them.
|
||||
if _, ok := m.pendingActiveSyncers[s.cfg.peerPub]; !ok {
|
||||
next = m.pendingActiveSyncerQueue.Front()
|
||||
continue
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// rotateActiveSyncerCandidate rotates a single active syncer. In order to
|
||||
// achieve this, the active syncer must be in a chansSynced state in order to
|
||||
// process the sync transition.
|
||||
func (m *SyncManager) rotateActiveSyncerCandidate() {
|
||||
// If we don't have a candidate to rotate with, we can return early.
|
||||
m.Lock()
|
||||
candidate := m.chooseRandomSyncer(nil, false)
|
||||
if candidate == nil {
|
||||
m.Unlock()
|
||||
log.Debug("No eligible candidate to rotate active syncer")
|
||||
return
|
||||
}
|
||||
|
||||
// We'll choose an active syncer at random that's within a chansSynced
|
||||
// state to rotate.
|
||||
var activeSyncer *GossipSyncer
|
||||
for _, s := range m.activeSyncers {
|
||||
// The active syncer must be in a chansSynced state in order to
|
||||
// process sync transitions.
|
||||
if s.syncState() != chansSynced {
|
||||
continue
|
||||
}
|
||||
|
||||
activeSyncer = s
|
||||
break
|
||||
}
|
||||
m.Unlock()
|
||||
|
||||
// If we couldn't find an eligible one, we can return early.
|
||||
if activeSyncer == nil {
|
||||
log.Debug("No eligible active syncer to rotate")
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, we'll attempt to transition each syncer to their
|
||||
// respective new sync type. We'll avoid performing the transition with
|
||||
// the lock as it can potentially stall the SyncManager due to the
|
||||
// syncTransitionTimeout.
|
||||
if err := m.transitionActiveSyncer(activeSyncer); err != nil {
|
||||
log.Errorf("Unable to transition active "+
|
||||
"GossipSyncer(%x): %v", activeSyncer.cfg.peerPub, err)
|
||||
return
|
||||
}
|
||||
|
||||
m.Lock()
|
||||
m.queueActiveSyncer(candidate)
|
||||
m.Unlock()
|
||||
|
||||
m.signalNewActiveSyncer()
|
||||
}
|
||||
|
||||
// transitionActiveSyncer transitions an active syncer to a passive one.
|
||||
func (m *SyncManager) transitionActiveSyncer(s *GossipSyncer) error {
|
||||
log.Debugf("Transitioning active GossipSyncer(%x) to passive",
|
||||
s.cfg.peerPub)
|
||||
|
||||
if err := s.ProcessSyncTransition(PassiveSync); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.signalStaleActiveSyncer(s, true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// transitionPassiveSyncer transitions a passive syncer to an active one.
|
||||
func (m *SyncManager) transitionPassiveSyncer(s *GossipSyncer) error {
|
||||
log.Debugf("Transitioning passive GossipSyncer(%x) to active",
|
||||
s.cfg.peerPub)
|
||||
|
||||
if err := s.ProcessSyncTransition(ActiveSync); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Lock()
|
||||
m.activeSyncers[s.cfg.peerPub] = s
|
||||
delete(m.pendingActiveSyncers, s.cfg.peerPub)
|
||||
m.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// forceHistoricalSync chooses a syncer with a remote peer at random and forces
|
||||
// a historical sync with it.
|
||||
func (m *SyncManager) forceHistoricalSync() {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
// We'll choose a random peer with whom we can perform a historical sync
|
||||
// with. We'll set useActive to true to make sure we can still do one if
|
||||
// we don't happen to have any non-active syncers.
|
||||
candidatesChosen := make(map[routing.Vertex]struct{})
|
||||
s := m.chooseRandomSyncer(candidatesChosen, true)
|
||||
for s != nil {
|
||||
// Blacklist the candidate to ensure it's not chosen again.
|
||||
candidatesChosen[s.cfg.peerPub] = struct{}{}
|
||||
|
||||
err := s.historicalSync()
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Errorf("Unable to perform historical sync with "+
|
||||
"GossipSyncer(%x): %v", s.cfg.peerPub, err)
|
||||
|
||||
s = m.chooseRandomSyncer(candidatesChosen, true)
|
||||
}
|
||||
}
|
||||
|
||||
// chooseRandomSyncer returns a random non-active syncer that's eligible for a
|
||||
// sync transition. A blacklist can be used to skip any previously chosen
|
||||
// candidates. The useActive boolean can be used to also filter active syncers.
|
||||
//
|
||||
// NOTE: It's possible for a nil value to be returned if there are no eligible
|
||||
// candidate syncers.
|
||||
//
|
||||
// NOTE: This method must be called with the syncersMtx lock held.
|
||||
func (m *SyncManager) chooseRandomSyncer(blacklist map[routing.Vertex]struct{},
|
||||
useActive bool) *GossipSyncer {
|
||||
|
||||
eligible := func(s *GossipSyncer) bool {
|
||||
// Skip any syncers that exist within the blacklist.
|
||||
if blacklist != nil {
|
||||
if _, ok := blacklist[s.cfg.peerPub]; ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Only syncers in a chansSynced state are viable for sync
|
||||
// transitions, so skip any that aren't.
|
||||
return s.syncState() == chansSynced
|
||||
}
|
||||
|
||||
for _, s := range m.inactiveSyncers {
|
||||
if !eligible(s) {
|
||||
continue
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
if useActive {
|
||||
for _, s := range m.activeSyncers {
|
||||
if !eligible(s) {
|
||||
continue
|
||||
}
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitSyncState is called by outside sub-systems when a connection is
|
||||
// established to a new peer that understands how to perform channel range
|
||||
// queries. We'll allocate a new GossipSyncer for it, and start any goroutines
|
||||
// needed to handle new queries. The first GossipSyncer registered with the
|
||||
// SyncManager will attempt a historical sync to ensure we have as much of the
|
||||
// public channel graph as possible.
|
||||
//
|
||||
// TODO(wilmer): Only mark as ActiveSync if this isn't a channel peer.
|
||||
func (m *SyncManager) InitSyncState(peer lnpeer.Peer) {
|
||||
// If we already have a syncer, then we'll exit early as we don't want
|
||||
// to override it.
|
||||
nodeID := routing.Vertex(peer.PubKey())
|
||||
if _, ok := m.GossipSyncer(nodeID); ok {
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("Creating new GossipSyncer for peer=%x", nodeID[:])
|
||||
|
||||
encoding := lnwire.EncodingSortedPlain
|
||||
s := newGossipSyncer(gossipSyncerCfg{
|
||||
chainHash: m.cfg.ChainHash,
|
||||
peerPub: nodeID,
|
||||
channelSeries: m.cfg.ChanSeries,
|
||||
encodingType: encoding,
|
||||
chunkSize: encodingTypeToChunkSize[encoding],
|
||||
sendToPeer: func(msgs ...lnwire.Message) error {
|
||||
return peer.SendMessage(false, msgs...)
|
||||
},
|
||||
})
|
||||
|
||||
// Gossip syncers are initialized by default as passive and in a
|
||||
// chansSynced state so that they can reply to any peer queries or
|
||||
// handle any sync transitions.
|
||||
s.setSyncType(PassiveSync)
|
||||
s.setSyncState(chansSynced)
|
||||
s.Start()
|
||||
|
||||
m.Lock()
|
||||
m.inactiveSyncers[nodeID] = s
|
||||
|
||||
// We'll force a historical sync with the first peer we connect to
|
||||
// ensure we get as much of the graph as possible.
|
||||
var err error
|
||||
m.historicalSync.Do(func() {
|
||||
log.Infof("Attempting historical sync with GossipSyncer(%x)",
|
||||
s.cfg.peerPub)
|
||||
|
||||
err = s.historicalSync()
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Unable to perform historical sync with "+
|
||||
"GossipSyncer(%x): %v", s.cfg.peerPub, err)
|
||||
|
||||
// Reset historicalSync to ensure it is tried again with a
|
||||
// different peer.
|
||||
m.historicalSync = sync.Once{}
|
||||
}
|
||||
|
||||
// If we've yet to reach our desired number of active syncers, then
|
||||
// we'll use this one.
|
||||
numActiveSyncers := len(m.activeSyncers) + len(m.pendingActiveSyncers)
|
||||
if numActiveSyncers < m.cfg.NumActiveSyncers {
|
||||
m.queueActiveSyncer(s)
|
||||
m.Unlock()
|
||||
m.signalNewActiveSyncer()
|
||||
return
|
||||
}
|
||||
m.Unlock()
|
||||
}
|
||||
|
||||
// PruneSyncState is called by outside sub-systems once a peer that we were
|
||||
// previously connected to has been disconnected. In this case we can stop the
|
||||
// existing GossipSyncer assigned to the peer and free up resources.
|
||||
func (m *SyncManager) PruneSyncState(peer routing.Vertex) {
|
||||
s, ok := m.GossipSyncer(peer)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("Removing GossipSyncer for peer=%v", peer)
|
||||
|
||||
// We'll start by stopping the GossipSyncer for the disconnected peer.
|
||||
s.Stop()
|
||||
|
||||
// If it's a non-active syncer, then we can just exit now.
|
||||
m.Lock()
|
||||
if _, ok := m.inactiveSyncers[s.cfg.peerPub]; ok {
|
||||
delete(m.inactiveSyncers, s.cfg.peerPub)
|
||||
m.Unlock()
|
||||
return
|
||||
}
|
||||
m.Unlock()
|
||||
|
||||
// Otherwise, we'll need to dequeue it from our pending active syncers
|
||||
// queue and find a new one to replace it, if any.
|
||||
m.signalStaleActiveSyncer(s, false)
|
||||
}
|
||||
|
||||
// GossipSyncer returns the associated gossip syncer of a peer. The boolean
|
||||
// returned signals whether there exists a gossip syncer for the peer.
|
||||
func (m *SyncManager) GossipSyncer(peer routing.Vertex) (*GossipSyncer, bool) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.gossipSyncer(peer)
|
||||
}
|
||||
|
||||
// gossipSyncer returns the associated gossip syncer of a peer. The boolean
|
||||
// returned signals whether there exists a gossip syncer for the peer.
|
||||
func (m *SyncManager) gossipSyncer(peer routing.Vertex) (*GossipSyncer, bool) {
|
||||
syncer, ok := m.inactiveSyncers[peer]
|
||||
if ok {
|
||||
return syncer, true
|
||||
}
|
||||
syncer, ok = m.pendingActiveSyncers[peer]
|
||||
if ok {
|
||||
return syncer, true
|
||||
}
|
||||
syncer, ok = m.activeSyncers[peer]
|
||||
if ok {
|
||||
return syncer, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// GossipSyncers returns all of the currently initialized gossip syncers.
|
||||
func (m *SyncManager) GossipSyncers() map[routing.Vertex]*GossipSyncer {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
numSyncers := len(m.inactiveSyncers) + len(m.activeSyncers) +
|
||||
len(m.inactiveSyncers)
|
||||
syncers := make(map[routing.Vertex]*GossipSyncer, numSyncers)
|
||||
|
||||
for _, syncer := range m.inactiveSyncers {
|
||||
syncers[syncer.cfg.peerPub] = syncer
|
||||
}
|
||||
for _, syncer := range m.pendingActiveSyncers {
|
||||
syncers[syncer.cfg.peerPub] = syncer
|
||||
}
|
||||
for _, syncer := range m.activeSyncers {
|
||||
syncers[syncer.cfg.peerPub] = syncer
|
||||
}
|
||||
|
||||
return syncers
|
||||
}
|
549
discovery/sync_manager_test.go
Normal file
549
discovery/sync_manager_test.go
Normal file
@ -0,0 +1,549 @@
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
)
|
||||
|
||||
// randPeer creates a random peer.
|
||||
func randPeer(t *testing.T, quit chan struct{}) *mockPeer {
|
||||
t.Helper()
|
||||
|
||||
return &mockPeer{
|
||||
pk: randPubKey(t),
|
||||
sentMsgs: make(chan lnwire.Message),
|
||||
quit: quit,
|
||||
}
|
||||
}
|
||||
|
||||
// newTestSyncManager creates a new test SyncManager using mock implementations
|
||||
// of its dependencies.
|
||||
func newTestSyncManager(numActiveSyncers int) *SyncManager {
|
||||
hID := lnwire.ShortChannelID{BlockHeight: latestKnownHeight}
|
||||
return newSyncManager(&SyncManagerCfg{
|
||||
ChanSeries: newMockChannelGraphTimeSeries(hID),
|
||||
RotateTicker: ticker.NewForce(DefaultSyncerRotationInterval),
|
||||
HistoricalSyncTicker: ticker.NewForce(DefaultHistoricalSyncInterval),
|
||||
ActiveSyncerTimeoutTicker: ticker.NewForce(DefaultActiveSyncerTimeout),
|
||||
NumActiveSyncers: numActiveSyncers,
|
||||
})
|
||||
}
|
||||
|
||||
// TestSyncManagerNumActiveSyncers ensures that we are unable to have more than
|
||||
// NumActiveSyncers active syncers.
|
||||
func TestSyncManagerNumActiveSyncers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We'll start by creating our test sync manager which will hold up to
|
||||
// 3 active syncers.
|
||||
const numActiveSyncers = 3
|
||||
const numSyncers = numActiveSyncers + 1
|
||||
|
||||
syncMgr := newTestSyncManager(numActiveSyncers)
|
||||
syncMgr.Start()
|
||||
defer syncMgr.Stop()
|
||||
|
||||
// We'll go ahead and create our syncers. We'll gather the ones which
|
||||
// should be active and passive to check them later on.
|
||||
for i := 0; i < numActiveSyncers; i++ {
|
||||
peer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(peer)
|
||||
|
||||
// The first syncer registered always attempts a historical
|
||||
// sync.
|
||||
if i == 0 {
|
||||
assertTransitionToChansSynced(t, syncMgr, peer, true)
|
||||
}
|
||||
|
||||
assertPassiveSyncerTransition(t, syncMgr, peer)
|
||||
assertSyncerStatus(t, syncMgr, peer, chansSynced, ActiveSync)
|
||||
}
|
||||
|
||||
for i := 0; i < numSyncers-numActiveSyncers; i++ {
|
||||
peer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(peer)
|
||||
assertSyncerStatus(t, syncMgr, peer, chansSynced, PassiveSync)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSyncManagerNewActiveSyncerAfterDisconnect ensures that we can regain an
|
||||
// active syncer after losing one due to the peer disconnecting.
|
||||
func TestSyncManagerNewActiveSyncerAfterDisconnect(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We'll create our test sync manager to only have one active syncer.
|
||||
syncMgr := newTestSyncManager(1)
|
||||
syncMgr.Start()
|
||||
defer syncMgr.Stop()
|
||||
|
||||
// peer1 will represent an active syncer that performs a historical
|
||||
// sync since it is the first registered peer with the SyncManager.
|
||||
peer1 := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(peer1)
|
||||
assertTransitionToChansSynced(t, syncMgr, peer1, true)
|
||||
assertPassiveSyncerTransition(t, syncMgr, peer1)
|
||||
|
||||
// It will then be torn down to simulate a disconnection. Since there
|
||||
// are no other candidate syncers available, the active syncer won't be
|
||||
// replaced.
|
||||
syncMgr.PruneSyncState(peer1.PubKey())
|
||||
|
||||
// Then, we'll start our active syncer again, but this time we'll also
|
||||
// have a passive syncer available to replace the active syncer after
|
||||
// the peer disconnects.
|
||||
syncMgr.InitSyncState(peer1)
|
||||
assertPassiveSyncerTransition(t, syncMgr, peer1)
|
||||
|
||||
// Create our second peer, which should be initialized as a passive
|
||||
// syncer.
|
||||
peer2 := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(peer2)
|
||||
assertSyncerStatus(t, syncMgr, peer2, chansSynced, PassiveSync)
|
||||
|
||||
// Disconnect our active syncer, which should trigger the SyncManager to
|
||||
// replace it with our passive syncer.
|
||||
syncMgr.PruneSyncState(peer1.PubKey())
|
||||
assertPassiveSyncerTransition(t, syncMgr, peer2)
|
||||
}
|
||||
|
||||
// TestSyncManagerRotateActiveSyncerCandidate tests that we can successfully
|
||||
// rotate our active syncers after a certain interval.
|
||||
func TestSyncManagerRotateActiveSyncerCandidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We'll create our sync manager with three active syncers.
|
||||
syncMgr := newTestSyncManager(1)
|
||||
syncMgr.Start()
|
||||
defer syncMgr.Stop()
|
||||
|
||||
// The first syncer registered always performs a historical sync.
|
||||
activeSyncPeer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(activeSyncPeer)
|
||||
assertTransitionToChansSynced(t, syncMgr, activeSyncPeer, true)
|
||||
assertPassiveSyncerTransition(t, syncMgr, activeSyncPeer)
|
||||
|
||||
// We'll send a tick to force a rotation. Since there aren't any
|
||||
// candidates, none of the active syncers will be rotated.
|
||||
syncMgr.cfg.RotateTicker.(*ticker.Force).Force <- time.Time{}
|
||||
assertNoMsgSent(t, activeSyncPeer)
|
||||
assertSyncerStatus(t, syncMgr, activeSyncPeer, chansSynced, ActiveSync)
|
||||
|
||||
// We'll then go ahead and add a passive syncer.
|
||||
passiveSyncPeer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(passiveSyncPeer)
|
||||
assertSyncerStatus(t, syncMgr, passiveSyncPeer, chansSynced, PassiveSync)
|
||||
|
||||
// We'll force another rotation - this time, since we have a passive
|
||||
// syncer available, they should be rotated.
|
||||
syncMgr.cfg.RotateTicker.(*ticker.Force).Force <- time.Time{}
|
||||
|
||||
// The transition from an active syncer to a passive syncer causes the
|
||||
// peer to send out a new GossipTimestampRange in the past so that they
|
||||
// don't receive new graph updates.
|
||||
assertActiveSyncerTransition(t, syncMgr, activeSyncPeer)
|
||||
|
||||
// The transition from a passive syncer to an active syncer causes the
|
||||
// peer to send a new GossipTimestampRange with the current timestamp to
|
||||
// signal that they would like to receive new graph updates from their
|
||||
// peers. This will also cause the gossip syncer to redo its state
|
||||
// machine, starting from its initial syncingChans state. We'll then
|
||||
// need to transition it to its final chansSynced state to ensure the
|
||||
// next syncer is properly started in the round-robin.
|
||||
assertPassiveSyncerTransition(t, syncMgr, passiveSyncPeer)
|
||||
}
|
||||
|
||||
// TestSyncManagerHistoricalSync ensures that we only attempt a single
|
||||
// historical sync during the SyncManager's startup, and that we can routinely
|
||||
// force historical syncs whenever the HistoricalSyncTicker fires.
|
||||
func TestSyncManagerHistoricalSync(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
syncMgr := newTestSyncManager(0)
|
||||
syncMgr.Start()
|
||||
defer syncMgr.Stop()
|
||||
|
||||
// We should expect to see a QueryChannelRange message with a
|
||||
// FirstBlockHeight of the genesis block, signaling that a historical
|
||||
// sync is being attempted.
|
||||
peer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(peer)
|
||||
assertMsgSent(t, peer, &lnwire.QueryChannelRange{
|
||||
FirstBlockHeight: 0,
|
||||
NumBlocks: math.MaxUint32,
|
||||
})
|
||||
|
||||
// If an additional peer connects, then a historical sync should not be
|
||||
// attempted again.
|
||||
extraPeer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(extraPeer)
|
||||
assertNoMsgSent(t, extraPeer)
|
||||
|
||||
// Then, we'll send a tick to force a historical sync. This should
|
||||
// trigger the extra peer to also perform a historical sync since the
|
||||
// first peer is not eligible due to not being in a chansSynced state.
|
||||
syncMgr.cfg.HistoricalSyncTicker.(*ticker.Force).Force <- time.Time{}
|
||||
assertMsgSent(t, extraPeer, &lnwire.QueryChannelRange{
|
||||
FirstBlockHeight: 0,
|
||||
NumBlocks: math.MaxUint32,
|
||||
})
|
||||
}
|
||||
|
||||
// TestSyncManagerRoundRobinQueue ensures that any subsequent active syncers can
|
||||
// only be started after the previous one has completed its state machine.
|
||||
func TestSyncManagerRoundRobinQueue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const numActiveSyncers = 3
|
||||
|
||||
// We'll start by creating our sync manager with support for three
|
||||
// active syncers.
|
||||
syncMgr := newTestSyncManager(numActiveSyncers)
|
||||
syncMgr.Start()
|
||||
defer syncMgr.Stop()
|
||||
|
||||
peers := make([]*mockPeer, 0, numActiveSyncers)
|
||||
|
||||
// The first syncer registered always attempts a historical sync.
|
||||
firstPeer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(firstPeer)
|
||||
peers = append(peers, firstPeer)
|
||||
assertTransitionToChansSynced(t, syncMgr, firstPeer, true)
|
||||
|
||||
// After completing the historical sync, a sync transition to ActiveSync
|
||||
// should happen. It should transition immediately since it has no
|
||||
// dependents.
|
||||
assertActiveGossipTimestampRange(t, firstPeer)
|
||||
|
||||
// We'll create the remaining numActiveSyncers. These will be queued in
|
||||
// the round robin since the first syncer has yet to reach chansSynced.
|
||||
queuedPeers := make([]*mockPeer, 0, numActiveSyncers-1)
|
||||
for i := 0; i < numActiveSyncers-1; i++ {
|
||||
peer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(peer)
|
||||
peers = append(peers, peer)
|
||||
queuedPeers = append(queuedPeers, peer)
|
||||
}
|
||||
|
||||
// Ensure they cannot transition without sending a GossipTimestampRange
|
||||
// message first.
|
||||
for _, peer := range queuedPeers {
|
||||
assertNoMsgSent(t, peer)
|
||||
}
|
||||
|
||||
// Transition the first syncer to chansSynced, which should allow the
|
||||
// second to transition next.
|
||||
assertTransitionToChansSynced(t, syncMgr, firstPeer, false)
|
||||
|
||||
// assertSyncerTransitioned ensures the target peer's syncer is the only
|
||||
// that has transitioned.
|
||||
assertSyncerTransitioned := func(target *mockPeer) {
|
||||
t.Helper()
|
||||
|
||||
for _, peer := range peers {
|
||||
if peer.PubKey() != target.PubKey() {
|
||||
assertNoMsgSent(t, peer)
|
||||
continue
|
||||
}
|
||||
|
||||
assertActiveGossipTimestampRange(t, target)
|
||||
}
|
||||
}
|
||||
|
||||
// For each queued syncer, we'll ensure they have transitioned to an
|
||||
// ActiveSync type and reached their final chansSynced state to allow
|
||||
// the next one to transition.
|
||||
for _, peer := range queuedPeers {
|
||||
assertSyncerTransitioned(peer)
|
||||
assertTransitionToChansSynced(t, syncMgr, peer, false)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSyncManagerRoundRobinTimeout ensures that if we timeout while waiting for
|
||||
// an active syncer to reach its final chansSynced state, then we will go on to
|
||||
// start the next.
|
||||
func TestSyncManagerRoundRobinTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create our sync manager with support for two active syncers.
|
||||
syncMgr := newTestSyncManager(2)
|
||||
syncMgr.Start()
|
||||
defer syncMgr.Stop()
|
||||
|
||||
// peer1 will be the first peer we start, which will time out and cause
|
||||
// peer2 to start.
|
||||
peer1 := randPeer(t, syncMgr.quit)
|
||||
peer2 := randPeer(t, syncMgr.quit)
|
||||
|
||||
// The first syncer registered always attempts a historical sync.
|
||||
syncMgr.InitSyncState(peer1)
|
||||
assertTransitionToChansSynced(t, syncMgr, peer1, true)
|
||||
|
||||
// We assume the syncer for peer1 has transitioned once we see it send a
|
||||
// lnwire.GossipTimestampRange message.
|
||||
assertActiveGossipTimestampRange(t, peer1)
|
||||
|
||||
// We'll then create the syncer for peer2. This should cause it to be
|
||||
// queued so that it starts once the syncer for peer1 is done.
|
||||
syncMgr.InitSyncState(peer2)
|
||||
assertNoMsgSent(t, peer2)
|
||||
|
||||
// Send a force tick to pretend the sync manager has timed out waiting
|
||||
// for peer1's syncer to reach chansSynced.
|
||||
syncMgr.cfg.ActiveSyncerTimeoutTicker.(*ticker.Force).Force <- time.Time{}
|
||||
|
||||
// Finally, ensure that the syncer for peer2 has transitioned.
|
||||
assertActiveGossipTimestampRange(t, peer2)
|
||||
}
|
||||
|
||||
// TestSyncManagerRoundRobinStaleSyncer ensures that any stale active syncers we
|
||||
// are currently waiting for or are queued up to start are properly removed and
|
||||
// stopped.
|
||||
func TestSyncManagerRoundRobinStaleSyncer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const numActiveSyncers = 4
|
||||
|
||||
// We'll create and start our sync manager with some active syncers.
|
||||
syncMgr := newTestSyncManager(numActiveSyncers)
|
||||
syncMgr.Start()
|
||||
defer syncMgr.Stop()
|
||||
|
||||
peers := make([]*mockPeer, 0, numActiveSyncers)
|
||||
|
||||
// The first syncer registered always attempts a historical sync.
|
||||
firstPeer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(firstPeer)
|
||||
peers = append(peers, firstPeer)
|
||||
assertTransitionToChansSynced(t, syncMgr, firstPeer, true)
|
||||
|
||||
// After completing the historical sync, a sync transition to ActiveSync
|
||||
// should happen. It should transition immediately since it has no
|
||||
// dependents.
|
||||
assertActiveGossipTimestampRange(t, firstPeer)
|
||||
assertMsgSent(t, firstPeer, &lnwire.QueryChannelRange{
|
||||
FirstBlockHeight: startHeight,
|
||||
NumBlocks: math.MaxUint32 - startHeight,
|
||||
})
|
||||
|
||||
// We'll create the remaining numActiveSyncers. These will be queued in
|
||||
// the round robin since the first syncer has yet to reach chansSynced.
|
||||
queuedPeers := make([]*mockPeer, 0, numActiveSyncers-1)
|
||||
for i := 0; i < numActiveSyncers-1; i++ {
|
||||
peer := randPeer(t, syncMgr.quit)
|
||||
syncMgr.InitSyncState(peer)
|
||||
peers = append(peers, peer)
|
||||
queuedPeers = append(queuedPeers, peer)
|
||||
}
|
||||
|
||||
// Ensure they cannot transition without sending a GossipTimestampRange
|
||||
// message first.
|
||||
for _, peer := range queuedPeers {
|
||||
assertNoMsgSent(t, peer)
|
||||
}
|
||||
|
||||
// assertSyncerTransitioned ensures the target peer's syncer is the only
|
||||
// that has transitioned.
|
||||
assertSyncerTransitioned := func(target *mockPeer) {
|
||||
t.Helper()
|
||||
|
||||
for _, peer := range peers {
|
||||
if peer.PubKey() != target.PubKey() {
|
||||
assertNoMsgSent(t, peer)
|
||||
continue
|
||||
}
|
||||
|
||||
assertPassiveSyncerTransition(t, syncMgr, target)
|
||||
}
|
||||
}
|
||||
|
||||
// We'll then remove the syncers in the middle to cover the case where
|
||||
// they are queued up in the sync manager's pending list.
|
||||
for i, peer := range peers {
|
||||
if i == 0 || i == len(peers)-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
syncMgr.PruneSyncState(peer.PubKey())
|
||||
}
|
||||
|
||||
// We'll then remove the syncer we are currently waiting for. This
|
||||
// should prompt the last syncer to start since it is the only one left
|
||||
// pending. We'll do this in a goroutine since the peer behind the new
|
||||
// active syncer will need to send out its new GossipTimestampRange.
|
||||
go syncMgr.PruneSyncState(peers[0].PubKey())
|
||||
assertSyncerTransitioned(peers[len(peers)-1])
|
||||
}
|
||||
|
||||
// assertNoMsgSent is a helper function that ensures a peer hasn't sent any
|
||||
// messages.
|
||||
func assertNoMsgSent(t *testing.T, peer *mockPeer) {
|
||||
t.Helper()
|
||||
|
||||
select {
|
||||
case msg := <-peer.sentMsgs:
|
||||
t.Fatalf("peer %x sent unexpected message %v", peer.PubKey(),
|
||||
spew.Sdump(msg))
|
||||
case <-time.After(time.Second):
|
||||
}
|
||||
}
|
||||
|
||||
// assertMsgSent asserts that the peer has sent the given message.
|
||||
func assertMsgSent(t *testing.T, peer *mockPeer, msg lnwire.Message) {
|
||||
t.Helper()
|
||||
|
||||
var msgSent lnwire.Message
|
||||
select {
|
||||
case msgSent = <-peer.sentMsgs:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("expected peer %x to send %T message", peer.PubKey(),
|
||||
msg)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(msgSent, msg) {
|
||||
t.Fatalf("expected peer %x to send message: %v\ngot: %v",
|
||||
peer.PubKey(), spew.Sdump(msg), spew.Sdump(msgSent))
|
||||
}
|
||||
}
|
||||
|
||||
// assertActiveGossipTimestampRange is a helper function that ensures a peer has
|
||||
// sent a lnwire.GossipTimestampRange message indicating that it would like to
|
||||
// receive new graph updates.
|
||||
func assertActiveGossipTimestampRange(t *testing.T, peer *mockPeer) {
|
||||
t.Helper()
|
||||
|
||||
var msgSent lnwire.Message
|
||||
select {
|
||||
case msgSent = <-peer.sentMsgs:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("expected peer %x to send lnwire.GossipTimestampRange "+
|
||||
"message", peer.PubKey())
|
||||
}
|
||||
|
||||
msg, ok := msgSent.(*lnwire.GossipTimestampRange)
|
||||
if !ok {
|
||||
t.Fatalf("expected peer %x to send %T message", peer.PubKey(),
|
||||
msg)
|
||||
}
|
||||
if msg.FirstTimestamp == 0 {
|
||||
t.Fatalf("expected *lnwire.GossipTimestampRange message with " +
|
||||
"non-zero FirstTimestamp")
|
||||
}
|
||||
if msg.TimestampRange == 0 {
|
||||
t.Fatalf("expected *lnwire.GossipTimestampRange message with " +
|
||||
"non-zero TimestampRange")
|
||||
}
|
||||
}
|
||||
|
||||
// assertSyncerStatus asserts that the gossip syncer for the given peer matches
|
||||
// the expected sync state and type.
|
||||
func assertSyncerStatus(t *testing.T, syncMgr *SyncManager, peer *mockPeer,
|
||||
syncState syncerState, syncType SyncerType) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
s, ok := syncMgr.GossipSyncer(peer.PubKey())
|
||||
if !ok {
|
||||
t.Fatalf("gossip syncer for peer %x not found", peer.PubKey())
|
||||
}
|
||||
|
||||
// We'll check the status of our syncer within a WaitPredicate as some
|
||||
// sync transitions might cause this to be racy.
|
||||
err := lntest.WaitNoError(func() error {
|
||||
state := s.syncState()
|
||||
if s.syncState() != syncState {
|
||||
return fmt.Errorf("expected syncState %v for peer "+
|
||||
"%x, got %v", syncState, peer.PubKey(), state)
|
||||
}
|
||||
|
||||
typ := s.SyncType()
|
||||
if s.SyncType() != syncType {
|
||||
return fmt.Errorf("expected syncType %v for peer "+
|
||||
"%x, got %v", syncType, peer.PubKey(), typ)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// assertTransitionToChansSynced asserts the transition of an ActiveSync
|
||||
// GossipSyncer to its final chansSynced state.
|
||||
func assertTransitionToChansSynced(t *testing.T, syncMgr *SyncManager,
|
||||
peer *mockPeer, historicalSync bool) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
s, ok := syncMgr.GossipSyncer(peer.PubKey())
|
||||
if !ok {
|
||||
t.Fatalf("gossip syncer for peer %x not found", peer.PubKey())
|
||||
}
|
||||
|
||||
firstBlockHeight := uint32(startHeight)
|
||||
if historicalSync {
|
||||
firstBlockHeight = 0
|
||||
}
|
||||
assertMsgSent(t, peer, &lnwire.QueryChannelRange{
|
||||
FirstBlockHeight: firstBlockHeight,
|
||||
NumBlocks: math.MaxUint32 - firstBlockHeight,
|
||||
})
|
||||
|
||||
s.ProcessQueryMsg(&lnwire.ReplyChannelRange{Complete: 1}, nil)
|
||||
|
||||
chanSeries := syncMgr.cfg.ChanSeries.(*mockChannelGraphTimeSeries)
|
||||
|
||||
select {
|
||||
case <-chanSeries.filterReq:
|
||||
chanSeries.filterResp <- nil
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("expected to receive FilterKnownChanIDs request")
|
||||
}
|
||||
|
||||
err := lntest.WaitNoError(func() error {
|
||||
state := syncerState(atomic.LoadUint32(&s.state))
|
||||
if state != chansSynced {
|
||||
return fmt.Errorf("expected syncerState %v, got %v",
|
||||
chansSynced, state)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// assertPassiveSyncerTransition asserts that a gossip syncer goes through all
|
||||
// of its expected steps when transitioning from passive to active.
|
||||
func assertPassiveSyncerTransition(t *testing.T, syncMgr *SyncManager,
|
||||
peer *mockPeer) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
assertActiveGossipTimestampRange(t, peer)
|
||||
assertTransitionToChansSynced(t, syncMgr, peer, false)
|
||||
}
|
||||
|
||||
// assertActiveSyncerTransition asserts that a gossip syncer goes through all of
|
||||
// its expected steps when transitioning from active to passive.
|
||||
func assertActiveSyncerTransition(t *testing.T, syncMgr *SyncManager,
|
||||
peer *mockPeer) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
assertMsgSent(t, peer, &lnwire.GossipTimestampRange{
|
||||
FirstTimestamp: uint32(zeroTimestamp.Unix()),
|
||||
TimestampRange: 0,
|
||||
})
|
||||
assertSyncerStatus(t, syncMgr, peer, chansSynced, PassiveSync)
|
||||
}
|
@ -13,18 +13,51 @@ import (
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
// syncerState is an enum that represents the current state of the
|
||||
// gossipSyncer. As the syncer is a state machine, we'll gate our actions
|
||||
// based off of the current state and the next incoming message.
|
||||
// SyncerType encapsulates the different types of syncing mechanisms for a
|
||||
// gossip syncer.
|
||||
type SyncerType uint8
|
||||
|
||||
const (
|
||||
// ActiveSync denotes that a gossip syncer should exercise its default
|
||||
// behavior. This includes reconciling the set of missing graph updates
|
||||
// with the remote peer _and_ receiving new updates from them.
|
||||
ActiveSync SyncerType = iota
|
||||
|
||||
// PassiveSync denotes that a gossip syncer:
|
||||
//
|
||||
// 1. Should not attempt to query the remote peer for graph updates.
|
||||
// 2. Should respond to queries from the remote peer.
|
||||
// 3. Should not receive new updates from the remote peer.
|
||||
//
|
||||
// They are started in a chansSynced state in order to accomplish their
|
||||
// responsibilities above.
|
||||
PassiveSync
|
||||
)
|
||||
|
||||
// String returns a human readable string describing the target SyncerType.
|
||||
func (t SyncerType) String() string {
|
||||
switch t {
|
||||
case ActiveSync:
|
||||
return "ActiveSync"
|
||||
case PassiveSync:
|
||||
return "PassiveSync"
|
||||
default:
|
||||
return fmt.Sprintf("unknown sync type %d", t)
|
||||
}
|
||||
}
|
||||
|
||||
// syncerState is an enum that represents the current state of the GossipSyncer.
|
||||
// As the syncer is a state machine, we'll gate our actions based off of the
|
||||
// current state and the next incoming message.
|
||||
type syncerState uint32
|
||||
|
||||
const (
|
||||
// syncingChans is the default state of the gossipSyncer. We start in
|
||||
// syncingChans is the default state of the GossipSyncer. We start in
|
||||
// this state when a new peer first connects and we don't yet know if
|
||||
// we're fully synchronized.
|
||||
syncingChans syncerState = iota
|
||||
|
||||
// waitingQueryRangeReply is the second main phase of the gossipSyncer.
|
||||
// waitingQueryRangeReply is the second main phase of the GossipSyncer.
|
||||
// We enter this state after we send out our first QueryChannelRange
|
||||
// reply. We'll stay in this state until the remote party sends us a
|
||||
// ReplyShortChanIDsEnd message that indicates they've responded to our
|
||||
@ -33,19 +66,19 @@ const (
|
||||
// chan ID's to us.
|
||||
waitingQueryRangeReply
|
||||
|
||||
// queryNewChannels is the third main phase of the gossipSyncer. In
|
||||
// queryNewChannels is the third main phase of the GossipSyncer. In
|
||||
// this phase we'll send out all of our QueryShortChanIDs messages in
|
||||
// response to the new channels that we don't yet know about.
|
||||
queryNewChannels
|
||||
|
||||
// waitingQueryChanReply is the fourth main phase of the gossipSyncer.
|
||||
// waitingQueryChanReply is the fourth main phase of the GossipSyncer.
|
||||
// We enter this phase once we've sent off a query chink to the remote
|
||||
// peer. We'll stay in this phase until we receive a
|
||||
// ReplyShortChanIDsEnd message which indicates that the remote party
|
||||
// has responded to all of our requests.
|
||||
waitingQueryChanReply
|
||||
|
||||
// chansSynced is the terminal stage of the gossipSyncer. Once we enter
|
||||
// chansSynced is the terminal stage of the GossipSyncer. Once we enter
|
||||
// this phase, we'll send out our update horizon, which filters out the
|
||||
// set of channel updates that we're interested in. In this state,
|
||||
// we'll be able to accept any outgoing messages from the
|
||||
@ -54,17 +87,6 @@ const (
|
||||
chansSynced
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultMaxUndelayedQueryReplies specifies how many gossip queries we
|
||||
// will respond to immediately before starting to delay responses.
|
||||
DefaultMaxUndelayedQueryReplies = 10
|
||||
|
||||
// DefaultDelayedQueryReplyInterval is the length of time we will wait
|
||||
// before responding to gossip queries after replying to
|
||||
// maxUndelayedQueryReplies queries.
|
||||
DefaultDelayedQueryReplyInterval = 5 * time.Second
|
||||
)
|
||||
|
||||
// String returns a human readable string describing the target syncerState.
|
||||
func (s syncerState) String() string {
|
||||
switch s {
|
||||
@ -88,6 +110,26 @@ func (s syncerState) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultMaxUndelayedQueryReplies specifies how many gossip queries we
|
||||
// will respond to immediately before starting to delay responses.
|
||||
DefaultMaxUndelayedQueryReplies = 10
|
||||
|
||||
// DefaultDelayedQueryReplyInterval is the length of time we will wait
|
||||
// before responding to gossip queries after replying to
|
||||
// maxUndelayedQueryReplies queries.
|
||||
DefaultDelayedQueryReplyInterval = 5 * time.Second
|
||||
|
||||
// chanRangeQueryBuffer is the number of blocks back that we'll go when
|
||||
// asking the remote peer for their any channels they know of beyond
|
||||
// our highest known channel ID.
|
||||
chanRangeQueryBuffer = 144
|
||||
|
||||
// syncTransitionTimeout is the default timeout in which we'll wait up
|
||||
// to when attempting to perform a sync transition.
|
||||
syncTransitionTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
// encodingTypeToChunkSize maps an encoding type, to the max number of
|
||||
// short chan ID's using the encoding type that we can fit into a
|
||||
@ -98,21 +140,33 @@ var (
|
||||
|
||||
// ErrGossipSyncerExiting signals that the syncer has been killed.
|
||||
ErrGossipSyncerExiting = errors.New("gossip syncer exiting")
|
||||
|
||||
// ErrSyncTransitionTimeout is an error returned when we've timed out
|
||||
// attempting to perform a sync transition.
|
||||
ErrSyncTransitionTimeout = errors.New("timed out attempting to " +
|
||||
"transition sync type")
|
||||
|
||||
// zeroTimestamp is the timestamp we'll use when we want to indicate to
|
||||
// peers that we do not want to receive any new graph updates.
|
||||
zeroTimestamp time.Time
|
||||
)
|
||||
|
||||
const (
|
||||
// chanRangeQueryBuffer is the number of blocks back that we'll go when
|
||||
// asking the remote peer for their any channels they know of beyond
|
||||
// our highest known channel ID.
|
||||
chanRangeQueryBuffer = 144
|
||||
)
|
||||
// syncTransitionReq encapsulates a request for a gossip syncer sync transition.
|
||||
type syncTransitionReq struct {
|
||||
newSyncType SyncerType
|
||||
errChan chan error
|
||||
}
|
||||
|
||||
// gossipSyncerCfg is a struct that packages all the information a gossipSyncer
|
||||
// gossipSyncerCfg is a struct that packages all the information a GossipSyncer
|
||||
// needs to carry out its duties.
|
||||
type gossipSyncerCfg struct {
|
||||
// chainHash is the chain that this syncer is responsible for.
|
||||
chainHash chainhash.Hash
|
||||
|
||||
// peerPub is the public key of the peer we're syncing with, serialized
|
||||
// in compressed format.
|
||||
peerPub [33]byte
|
||||
|
||||
// syncChanUpdates is a bool that indicates if we should request a
|
||||
// continual channel update stream or not.
|
||||
syncChanUpdates bool
|
||||
@ -144,18 +198,27 @@ type gossipSyncerCfg struct {
|
||||
delayedQueryReplyInterval time.Duration
|
||||
}
|
||||
|
||||
// gossipSyncer is a struct that handles synchronizing the channel graph state
|
||||
// with a remote peer. The gossipSyncer implements a state machine that will
|
||||
// GossipSyncer is a struct that handles synchronizing the channel graph state
|
||||
// with a remote peer. The GossipSyncer implements a state machine that will
|
||||
// progressively ensure we're synchronized with the channel state of the remote
|
||||
// node. Once both nodes have been synchronized, we'll use an update filter to
|
||||
// filter out which messages should be sent to a remote peer based on their
|
||||
// update horizon. If the update horizon isn't specified, then we won't send
|
||||
// them any channel updates at all.
|
||||
//
|
||||
// TODO(roasbeef): modify to only sync from one peer at a time?
|
||||
type gossipSyncer struct {
|
||||
started uint32
|
||||
stopped uint32
|
||||
type GossipSyncer struct {
|
||||
started sync.Once
|
||||
stopped sync.Once
|
||||
|
||||
// state is the current state of the GossipSyncer.
|
||||
//
|
||||
// NOTE: This variable MUST be used atomically.
|
||||
state uint32
|
||||
|
||||
// syncType denotes the SyncerType the gossip syncer is currently
|
||||
// exercising.
|
||||
//
|
||||
// NOTE: This variable MUST be used atomically.
|
||||
syncType uint32
|
||||
|
||||
// remoteUpdateHorizon is the update horizon of the remote peer. We'll
|
||||
// use this to properly filter out any messages.
|
||||
@ -165,10 +228,25 @@ type gossipSyncer struct {
|
||||
// determine if we've already sent out our update.
|
||||
localUpdateHorizon *lnwire.GossipTimestampRange
|
||||
|
||||
// state is the current state of the gossipSyncer.
|
||||
//
|
||||
// NOTE: This variable MUST be used atomically.
|
||||
state uint32
|
||||
// syncTransitions is a channel through which new sync type transition
|
||||
// requests will be sent through. These requests should only be handled
|
||||
// when the gossip syncer is in a chansSynced state to ensure its state
|
||||
// machine behaves as expected.
|
||||
syncTransitionReqs chan *syncTransitionReq
|
||||
|
||||
// historicalSyncReqs is a channel that serves as a signal for the
|
||||
// gossip syncer to perform a historical sync. Theese can only be done
|
||||
// once the gossip syncer is in a chansSynced state to ensure its state
|
||||
// machine behaves as expected.
|
||||
historicalSyncReqs chan struct{}
|
||||
|
||||
// genHistoricalChanRangeQuery when true signals to the gossip syncer
|
||||
// that it should request the remote peer for all of its known channel
|
||||
// IDs starting from the genesis block of the chain. This can only
|
||||
// happen if the gossip syncer receives a request to attempt a
|
||||
// historical sync. It can be unset if the syncer ever transitions from
|
||||
// PassiveSync to ActiveSync.
|
||||
genHistoricalChanRangeQuery bool
|
||||
|
||||
// gossipMsgs is a channel that all messages from the target peer will
|
||||
// be sent over.
|
||||
@ -183,10 +261,6 @@ type gossipSyncer struct {
|
||||
// state.
|
||||
newChansToQuery []lnwire.ShortChannelID
|
||||
|
||||
// peerPub is the public key of the peer we're syncing with, serialized
|
||||
// in compressed format.
|
||||
peerPub [33]byte
|
||||
|
||||
cfg gossipSyncerCfg
|
||||
|
||||
// rateLimiter dictates the frequency with which we will reply to gossip
|
||||
@ -195,15 +269,19 @@ type gossipSyncer struct {
|
||||
// number of queries.
|
||||
rateLimiter *rate.Limiter
|
||||
|
||||
// syncedSignal is a channel that, if set, will be closed when the
|
||||
// GossipSyncer reaches its terminal chansSynced state.
|
||||
syncedSignal chan struct{}
|
||||
|
||||
sync.Mutex
|
||||
|
||||
quit chan struct{}
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// newGossiperSyncer returns a new instance of the gossipSyncer populated using
|
||||
// newGossipSyncer returns a new instance of the GossipSyncer populated using
|
||||
// the passed config.
|
||||
func newGossiperSyncer(cfg gossipSyncerCfg) *gossipSyncer {
|
||||
func newGossipSyncer(cfg gossipSyncerCfg) *GossipSyncer {
|
||||
// If no parameter was specified for max undelayed query replies, set it
|
||||
// to the default of 5 queries.
|
||||
if cfg.maxUndelayedQueryReplies <= 0 {
|
||||
@ -225,57 +303,48 @@ func newGossiperSyncer(cfg gossipSyncerCfg) *gossipSyncer {
|
||||
interval, cfg.maxUndelayedQueryReplies,
|
||||
)
|
||||
|
||||
return &gossipSyncer{
|
||||
cfg: cfg,
|
||||
rateLimiter: rateLimiter,
|
||||
gossipMsgs: make(chan lnwire.Message, 100),
|
||||
quit: make(chan struct{}),
|
||||
return &GossipSyncer{
|
||||
cfg: cfg,
|
||||
rateLimiter: rateLimiter,
|
||||
syncTransitionReqs: make(chan *syncTransitionReq),
|
||||
historicalSyncReqs: make(chan struct{}),
|
||||
gossipMsgs: make(chan lnwire.Message, 100),
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts the gossipSyncer and any goroutines that it needs to carry out
|
||||
// Start starts the GossipSyncer and any goroutines that it needs to carry out
|
||||
// its duties.
|
||||
func (g *gossipSyncer) Start() error {
|
||||
if !atomic.CompareAndSwapUint32(&g.started, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
func (g *GossipSyncer) Start() {
|
||||
g.started.Do(func() {
|
||||
log.Debugf("Starting GossipSyncer(%x)", g.cfg.peerPub[:])
|
||||
|
||||
log.Debugf("Starting gossipSyncer(%x)", g.peerPub[:])
|
||||
|
||||
g.wg.Add(1)
|
||||
go g.channelGraphSyncer()
|
||||
|
||||
return nil
|
||||
g.wg.Add(1)
|
||||
go g.channelGraphSyncer()
|
||||
})
|
||||
}
|
||||
|
||||
// Stop signals the gossipSyncer for a graceful exit, then waits until it has
|
||||
// Stop signals the GossipSyncer for a graceful exit, then waits until it has
|
||||
// exited.
|
||||
func (g *gossipSyncer) Stop() error {
|
||||
if !atomic.CompareAndSwapUint32(&g.stopped, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
|
||||
close(g.quit)
|
||||
|
||||
g.wg.Wait()
|
||||
|
||||
return nil
|
||||
func (g *GossipSyncer) Stop() {
|
||||
g.stopped.Do(func() {
|
||||
close(g.quit)
|
||||
g.wg.Wait()
|
||||
})
|
||||
}
|
||||
|
||||
// channelGraphSyncer is the main goroutine responsible for ensuring that we
|
||||
// properly channel graph state with the remote peer, and also that we only
|
||||
// send them messages which actually pass their defined update horizon.
|
||||
func (g *gossipSyncer) channelGraphSyncer() {
|
||||
func (g *GossipSyncer) channelGraphSyncer() {
|
||||
defer g.wg.Done()
|
||||
|
||||
// TODO(roasbeef): also add ability to force transition back to syncing
|
||||
// chans
|
||||
// * needed if we want to sync chan state very few blocks?
|
||||
|
||||
for {
|
||||
state := atomic.LoadUint32(&g.state)
|
||||
log.Debugf("gossipSyncer(%x): state=%v", g.peerPub[:],
|
||||
syncerState(state))
|
||||
state := g.syncState()
|
||||
syncType := g.SyncType()
|
||||
|
||||
log.Debugf("GossipSyncer(%x): state=%v, type=%v",
|
||||
g.cfg.peerPub[:], state, syncType)
|
||||
|
||||
switch syncerState(state) {
|
||||
// When we're in this state, we're trying to synchronize our
|
||||
@ -286,7 +355,9 @@ func (g *gossipSyncer) channelGraphSyncer() {
|
||||
case syncingChans:
|
||||
// If we're in this state, then we'll send the remote
|
||||
// peer our opening QueryChannelRange message.
|
||||
queryRangeMsg, err := g.genChanRangeQuery()
|
||||
queryRangeMsg, err := g.genChanRangeQuery(
|
||||
g.genHistoricalChanRangeQuery,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("unable to gen chan range "+
|
||||
"query: %v", err)
|
||||
@ -302,7 +373,7 @@ func (g *gossipSyncer) channelGraphSyncer() {
|
||||
|
||||
// With the message sent successfully, we'll transition
|
||||
// into the next state where we wait for their reply.
|
||||
atomic.StoreUint32(&g.state, uint32(waitingQueryRangeReply))
|
||||
g.setSyncState(waitingQueryRangeReply)
|
||||
|
||||
// In this state, we've sent out our initial channel range
|
||||
// query and are waiting for the final response from the remote
|
||||
@ -359,13 +430,13 @@ func (g *gossipSyncer) channelGraphSyncer() {
|
||||
// If this wasn't our last query, then we'll need to
|
||||
// transition to our waiting state.
|
||||
if !done {
|
||||
atomic.StoreUint32(&g.state, uint32(waitingQueryChanReply))
|
||||
g.setSyncState(waitingQueryChanReply)
|
||||
continue
|
||||
}
|
||||
|
||||
// If we're fully synchronized, then we can transition
|
||||
// to our terminal state.
|
||||
atomic.StoreUint32(&g.state, uint32(chansSynced))
|
||||
g.setSyncState(chansSynced)
|
||||
|
||||
// In this state, we've just sent off a new query for channels
|
||||
// that we don't yet know of. We'll remain in this state until
|
||||
@ -382,7 +453,7 @@ func (g *gossipSyncer) channelGraphSyncer() {
|
||||
// state to send of the remaining query chunks.
|
||||
_, ok := msg.(*lnwire.ReplyShortChanIDsEnd)
|
||||
if ok {
|
||||
atomic.StoreUint32(&g.state, uint32(queryNewChannels))
|
||||
g.setSyncState(queryNewChannels)
|
||||
continue
|
||||
}
|
||||
|
||||
@ -401,35 +472,30 @@ func (g *gossipSyncer) channelGraphSyncer() {
|
||||
// This is our final terminal state where we'll only reply to
|
||||
// any further queries by the remote peer.
|
||||
case chansSynced:
|
||||
g.Lock()
|
||||
if g.syncedSignal != nil {
|
||||
close(g.syncedSignal)
|
||||
g.syncedSignal = nil
|
||||
}
|
||||
g.Unlock()
|
||||
|
||||
// If we haven't yet sent out our update horizon, and
|
||||
// we want to receive real-time channel updates, we'll
|
||||
// do so now.
|
||||
if g.localUpdateHorizon == nil && g.cfg.syncChanUpdates {
|
||||
// TODO(roasbeef): query DB for most recent
|
||||
// update?
|
||||
|
||||
// We'll give an hours room in our update
|
||||
// horizon to ensure we don't miss any newer
|
||||
// items.
|
||||
updateHorizon := time.Now().Add(-time.Hour * 1)
|
||||
log.Infof("gossipSyncer(%x): applying "+
|
||||
"gossipFilter(start=%v)", g.peerPub[:],
|
||||
updateHorizon)
|
||||
|
||||
g.localUpdateHorizon = &lnwire.GossipTimestampRange{
|
||||
ChainHash: g.cfg.chainHash,
|
||||
FirstTimestamp: uint32(updateHorizon.Unix()),
|
||||
TimestampRange: math.MaxUint32,
|
||||
}
|
||||
err := g.cfg.sendToPeer(g.localUpdateHorizon)
|
||||
if g.localUpdateHorizon == nil && syncType == ActiveSync {
|
||||
err := g.sendGossipTimestampRange(
|
||||
time.Now(), math.MaxUint32,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("unable to send update "+
|
||||
"horizon: %v", err)
|
||||
log.Errorf("Unable to send update "+
|
||||
"horizon to %x: %v",
|
||||
g.cfg.peerPub, err)
|
||||
}
|
||||
}
|
||||
|
||||
// With our horizon set, we'll simply reply to any new
|
||||
// message and exit if needed.
|
||||
// messages or process any state transitions and exit if
|
||||
// needed.
|
||||
select {
|
||||
case msg := <-g.gossipMsgs:
|
||||
err := g.replyPeerQueries(msg)
|
||||
@ -438,6 +504,12 @@ func (g *gossipSyncer) channelGraphSyncer() {
|
||||
"query: %v", err)
|
||||
}
|
||||
|
||||
case req := <-g.syncTransitionReqs:
|
||||
req.errChan <- g.handleSyncTransition(req)
|
||||
|
||||
case <-g.historicalSyncReqs:
|
||||
g.handleHistoricalSync()
|
||||
|
||||
case <-g.quit:
|
||||
return
|
||||
}
|
||||
@ -445,19 +517,50 @@ func (g *gossipSyncer) channelGraphSyncer() {
|
||||
}
|
||||
}
|
||||
|
||||
// sendGossipTimestampRange constructs and sets a GossipTimestampRange for the
|
||||
// syncer and sends it to the remote peer.
|
||||
func (g *GossipSyncer) sendGossipTimestampRange(firstTimestamp time.Time,
|
||||
timestampRange uint32) error {
|
||||
|
||||
endTimestamp := firstTimestamp.Add(
|
||||
time.Duration(timestampRange) * time.Second,
|
||||
)
|
||||
|
||||
log.Infof("GossipSyncer(%x): applying gossipFilter(start=%v, end=%v)",
|
||||
g.cfg.peerPub[:], firstTimestamp, endTimestamp)
|
||||
|
||||
localUpdateHorizon := &lnwire.GossipTimestampRange{
|
||||
ChainHash: g.cfg.chainHash,
|
||||
FirstTimestamp: uint32(firstTimestamp.Unix()),
|
||||
TimestampRange: timestampRange,
|
||||
}
|
||||
|
||||
if err := g.cfg.sendToPeer(localUpdateHorizon); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if firstTimestamp == zeroTimestamp && timestampRange == 0 {
|
||||
g.localUpdateHorizon = nil
|
||||
} else {
|
||||
g.localUpdateHorizon = localUpdateHorizon
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// synchronizeChanIDs is called by the channelGraphSyncer when we need to query
|
||||
// the remote peer for its known set of channel IDs within a particular block
|
||||
// range. This method will be called continually until the entire range has
|
||||
// been queried for with a response received. We'll chunk our requests as
|
||||
// required to ensure they fit into a single message. We may re-renter this
|
||||
// state in the case that chunking is required.
|
||||
func (g *gossipSyncer) synchronizeChanIDs() (bool, error) {
|
||||
func (g *GossipSyncer) synchronizeChanIDs() (bool, error) {
|
||||
// If we're in this state yet there are no more new channels to query
|
||||
// for, then we'll transition to our final synced state and return true
|
||||
// to signal that we're fully synchronized.
|
||||
if len(g.newChansToQuery) == 0 {
|
||||
log.Infof("gossipSyncer(%x): no more chans to query",
|
||||
g.peerPub[:])
|
||||
log.Infof("GossipSyncer(%x): no more chans to query",
|
||||
g.cfg.peerPub[:])
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@ -479,8 +582,8 @@ func (g *gossipSyncer) synchronizeChanIDs() (bool, error) {
|
||||
g.newChansToQuery = g.newChansToQuery[g.cfg.chunkSize:]
|
||||
}
|
||||
|
||||
log.Infof("gossipSyncer(%x): querying for %v new channels",
|
||||
g.peerPub[:], len(queryChunk))
|
||||
log.Infof("GossipSyncer(%x): querying for %v new channels",
|
||||
g.cfg.peerPub[:], len(queryChunk))
|
||||
|
||||
// With our chunk obtained, we'll send over our next query, then return
|
||||
// false indicating that we're net yet fully synced.
|
||||
@ -493,16 +596,16 @@ func (g *gossipSyncer) synchronizeChanIDs() (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// processChanRangeReply is called each time the gossipSyncer receives a new
|
||||
// processChanRangeReply is called each time the GossipSyncer receives a new
|
||||
// reply to the initial range query to discover new channels that it didn't
|
||||
// previously know of.
|
||||
func (g *gossipSyncer) processChanRangeReply(msg *lnwire.ReplyChannelRange) error {
|
||||
func (g *GossipSyncer) processChanRangeReply(msg *lnwire.ReplyChannelRange) error {
|
||||
g.bufferedChanRangeReplies = append(
|
||||
g.bufferedChanRangeReplies, msg.ShortChanIDs...,
|
||||
)
|
||||
|
||||
log.Infof("gossipSyncer(%x): buffering chan range reply of size=%v",
|
||||
g.peerPub[:], len(msg.ShortChanIDs))
|
||||
log.Infof("GossipSyncer(%x): buffering chan range reply of size=%v",
|
||||
g.cfg.peerPub[:], len(msg.ShortChanIDs))
|
||||
|
||||
// If this isn't the last response, then we can exit as we've already
|
||||
// buffered the latest portion of the streaming reply.
|
||||
@ -510,8 +613,8 @@ func (g *gossipSyncer) processChanRangeReply(msg *lnwire.ReplyChannelRange) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Infof("gossipSyncer(%x): filtering through %v chans", g.peerPub[:],
|
||||
len(g.bufferedChanRangeReplies))
|
||||
log.Infof("GossipSyncer(%x): filtering through %v chans",
|
||||
g.cfg.peerPub[:], len(g.bufferedChanRangeReplies))
|
||||
|
||||
// Otherwise, this is the final response, so we'll now check to see
|
||||
// which channels they know of that we don't.
|
||||
@ -530,28 +633,31 @@ func (g *gossipSyncer) processChanRangeReply(msg *lnwire.ReplyChannelRange) erro
|
||||
// If there aren't any channels that we don't know of, then we can
|
||||
// switch straight to our terminal state.
|
||||
if len(newChans) == 0 {
|
||||
log.Infof("gossipSyncer(%x): remote peer has no new chans",
|
||||
g.peerPub[:])
|
||||
log.Infof("GossipSyncer(%x): remote peer has no new chans",
|
||||
g.cfg.peerPub[:])
|
||||
|
||||
atomic.StoreUint32(&g.state, uint32(chansSynced))
|
||||
g.setSyncState(chansSynced)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise, we'll set the set of channels that we need to query for
|
||||
// the next state, and also transition our state.
|
||||
g.newChansToQuery = newChans
|
||||
atomic.StoreUint32(&g.state, uint32(queryNewChannels))
|
||||
g.setSyncState(queryNewChannels)
|
||||
|
||||
log.Infof("gossipSyncer(%x): starting query for %v new chans",
|
||||
g.peerPub[:], len(newChans))
|
||||
log.Infof("GossipSyncer(%x): starting query for %v new chans",
|
||||
g.cfg.peerPub[:], len(newChans))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// genChanRangeQuery generates the initial message we'll send to the remote
|
||||
// party when we're kicking off the channel graph synchronization upon
|
||||
// connection.
|
||||
func (g *gossipSyncer) genChanRangeQuery() (*lnwire.QueryChannelRange, error) {
|
||||
// connection. The historicalQuery boolean can be used to generate a query from
|
||||
// the genesis block of the chain.
|
||||
func (g *GossipSyncer) genChanRangeQuery(
|
||||
historicalQuery bool) (*lnwire.QueryChannelRange, error) {
|
||||
|
||||
// First, we'll query our channel graph time series for its highest
|
||||
// known channel ID.
|
||||
newestChan, err := g.cfg.channelSeries.HighestChanID(g.cfg.chainHash)
|
||||
@ -559,23 +665,23 @@ func (g *gossipSyncer) genChanRangeQuery() (*lnwire.QueryChannelRange, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Once we have the chan ID of the newest, we'll obtain the block
|
||||
// height of the channel, then subtract our default horizon to ensure
|
||||
// we don't miss any channels. By default, we go back 1 day from the
|
||||
// newest channel.
|
||||
// Once we have the chan ID of the newest, we'll obtain the block height
|
||||
// of the channel, then subtract our default horizon to ensure we don't
|
||||
// miss any channels. By default, we go back 1 day from the newest
|
||||
// channel, unless we're attempting a historical sync, where we'll
|
||||
// actually start from the genesis block instead.
|
||||
var startHeight uint32
|
||||
switch {
|
||||
case newestChan.BlockHeight <= chanRangeQueryBuffer:
|
||||
case historicalQuery:
|
||||
fallthrough
|
||||
case newestChan.BlockHeight == 0:
|
||||
case newestChan.BlockHeight <= chanRangeQueryBuffer:
|
||||
startHeight = 0
|
||||
|
||||
default:
|
||||
startHeight = uint32(newestChan.BlockHeight - chanRangeQueryBuffer)
|
||||
}
|
||||
|
||||
log.Infof("gossipSyncer(%x): requesting new chans from height=%v "+
|
||||
"and %v blocks after", g.peerPub[:], startHeight,
|
||||
log.Infof("GossipSyncer(%x): requesting new chans from height=%v "+
|
||||
"and %v blocks after", g.cfg.peerPub[:], startHeight,
|
||||
math.MaxUint32-startHeight)
|
||||
|
||||
// Finally, we'll craft the channel range query, using our starting
|
||||
@ -590,7 +696,7 @@ func (g *gossipSyncer) genChanRangeQuery() (*lnwire.QueryChannelRange, error) {
|
||||
|
||||
// replyPeerQueries is called in response to any query by the remote peer.
|
||||
// We'll examine our state and send back our best response.
|
||||
func (g *gossipSyncer) replyPeerQueries(msg lnwire.Message) error {
|
||||
func (g *GossipSyncer) replyPeerQueries(msg lnwire.Message) error {
|
||||
reservation := g.rateLimiter.Reserve()
|
||||
delay := reservation.Delay()
|
||||
|
||||
@ -598,8 +704,8 @@ func (g *gossipSyncer) replyPeerQueries(msg lnwire.Message) error {
|
||||
// responses back to the remote peer. This can help prevent DOS attacks
|
||||
// where the remote peer spams us endlessly.
|
||||
if delay > 0 {
|
||||
log.Infof("gossipSyncer(%x): rate limiting gossip replies, "+
|
||||
"responding in %s", g.peerPub[:], delay)
|
||||
log.Infof("GossipSyncer(%x): rate limiting gossip replies, "+
|
||||
"responding in %s", g.cfg.peerPub[:], delay)
|
||||
|
||||
select {
|
||||
case <-time.After(delay):
|
||||
@ -630,9 +736,9 @@ func (g *gossipSyncer) replyPeerQueries(msg lnwire.Message) error {
|
||||
// meet the channel range, then chunk our responses to the remote node. We also
|
||||
// ensure that our final fragment carries the "complete" bit to indicate the
|
||||
// end of our streaming response.
|
||||
func (g *gossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) error {
|
||||
log.Infof("gossipSyncer(%x): filtering chan range: start_height=%v, "+
|
||||
"num_blocks=%v", g.peerPub[:], query.FirstBlockHeight,
|
||||
func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) error {
|
||||
log.Infof("GossipSyncer(%x): filtering chan range: start_height=%v, "+
|
||||
"num_blocks=%v", g.cfg.peerPub[:], query.FirstBlockHeight,
|
||||
query.NumBlocks)
|
||||
|
||||
// Next, we'll consult the time series to obtain the set of known
|
||||
@ -666,16 +772,16 @@ func (g *gossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
||||
if isFinalChunk {
|
||||
channelChunk = channelRange[numChansSent:]
|
||||
|
||||
log.Infof("gossipSyncer(%x): sending final chan "+
|
||||
"range chunk, size=%v", g.peerPub[:], len(channelChunk))
|
||||
|
||||
log.Infof("GossipSyncer(%x): sending final chan "+
|
||||
"range chunk, size=%v", g.cfg.peerPub[:],
|
||||
len(channelChunk))
|
||||
} else {
|
||||
// Otherwise, we'll only send off a fragment exactly
|
||||
// sized to the proper chunk size.
|
||||
channelChunk = channelRange[numChansSent : numChansSent+g.cfg.chunkSize]
|
||||
|
||||
log.Infof("gossipSyncer(%x): sending range chunk of "+
|
||||
"size=%v", g.peerPub[:], len(channelChunk))
|
||||
log.Infof("GossipSyncer(%x): sending range chunk of "+
|
||||
"size=%v", g.cfg.peerPub[:], len(channelChunk))
|
||||
}
|
||||
|
||||
// With our chunk assembled, we'll now send to the remote peer
|
||||
@ -707,7 +813,7 @@ func (g *gossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
||||
// node for information concerning a set of short channel ID's. Our response
|
||||
// will be sent in a streaming chunked manner to ensure that we remain below
|
||||
// the current transport level message size.
|
||||
func (g *gossipSyncer) replyShortChanIDs(query *lnwire.QueryShortChanIDs) error {
|
||||
func (g *GossipSyncer) replyShortChanIDs(query *lnwire.QueryShortChanIDs) error {
|
||||
// Before responding, we'll check to ensure that the remote peer is
|
||||
// querying for the same chain that we're on. If not, we'll send back a
|
||||
// response with a complete value of zero to indicate we're on a
|
||||
@ -724,13 +830,13 @@ func (g *gossipSyncer) replyShortChanIDs(query *lnwire.QueryShortChanIDs) error
|
||||
}
|
||||
|
||||
if len(query.ShortChanIDs) == 0 {
|
||||
log.Infof("gossipSyncer(%x): ignoring query for blank short chan ID's",
|
||||
g.peerPub[:])
|
||||
log.Infof("GossipSyncer(%x): ignoring query for blank short chan ID's",
|
||||
g.cfg.peerPub[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Infof("gossipSyncer(%x): fetching chan anns for %v chans",
|
||||
g.peerPub[:], len(query.ShortChanIDs))
|
||||
log.Infof("GossipSyncer(%x): fetching chan anns for %v chans",
|
||||
g.cfg.peerPub[:], len(query.ShortChanIDs))
|
||||
|
||||
// Now that we know we're on the same chain, we'll query the channel
|
||||
// time series for the set of messages that we know of which satisfies
|
||||
@ -766,7 +872,7 @@ func (g *gossipSyncer) replyShortChanIDs(query *lnwire.QueryShortChanIDs) error
|
||||
// ApplyGossipFilter applies a gossiper filter sent by the remote node to the
|
||||
// state machine. Once applied, we'll ensure that we don't forward any messages
|
||||
// to the peer that aren't within the time range of the filter.
|
||||
func (g *gossipSyncer) ApplyGossipFilter(filter *lnwire.GossipTimestampRange) error {
|
||||
func (g *GossipSyncer) ApplyGossipFilter(filter *lnwire.GossipTimestampRange) error {
|
||||
g.Lock()
|
||||
|
||||
g.remoteUpdateHorizon = filter
|
||||
@ -787,8 +893,8 @@ func (g *gossipSyncer) ApplyGossipFilter(filter *lnwire.GossipTimestampRange) er
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("gossipSyncer(%x): applying new update horizon: start=%v, "+
|
||||
"end=%v, backlog_size=%v", g.peerPub[:], startTime, endTime,
|
||||
log.Infof("GossipSyncer(%x): applying new update horizon: start=%v, "+
|
||||
"end=%v, backlog_size=%v", g.cfg.peerPub[:], startTime, endTime,
|
||||
len(newUpdatestoSend))
|
||||
|
||||
// If we don't have any to send, then we can return early.
|
||||
@ -813,17 +919,19 @@ func (g *gossipSyncer) ApplyGossipFilter(filter *lnwire.GossipTimestampRange) er
|
||||
// FilterGossipMsgs takes a set of gossip messages, and only send it to a peer
|
||||
// iff the message is within the bounds of their set gossip filter. If the peer
|
||||
// doesn't have a gossip filter set, then no messages will be forwarded.
|
||||
func (g *gossipSyncer) FilterGossipMsgs(msgs ...msgWithSenders) {
|
||||
func (g *GossipSyncer) FilterGossipMsgs(msgs ...msgWithSenders) {
|
||||
// If the peer doesn't have an update horizon set, then we won't send
|
||||
// it any new update messages.
|
||||
if g.remoteUpdateHorizon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// If we've been signalled to exit, or are exiting, then we'll stop
|
||||
// If we've been signaled to exit, or are exiting, then we'll stop
|
||||
// short.
|
||||
if atomic.LoadUint32(&g.stopped) == 1 {
|
||||
select {
|
||||
case <-g.quit:
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
// TODO(roasbeef): need to ensure that peer still online...send msg to
|
||||
@ -858,7 +966,8 @@ func (g *gossipSyncer) FilterGossipMsgs(msgs ...msgWithSenders) {
|
||||
|
||||
passesFilter := func(timeStamp uint32) bool {
|
||||
t := time.Unix(int64(timeStamp), 0)
|
||||
return t.After(startTime) && t.Before(endTime)
|
||||
return t.Equal(startTime) ||
|
||||
(t.After(startTime) && t.Before(endTime))
|
||||
}
|
||||
|
||||
msgsToSend := make([]lnwire.Message, 0, len(msgs))
|
||||
@ -866,7 +975,7 @@ func (g *gossipSyncer) FilterGossipMsgs(msgs ...msgWithSenders) {
|
||||
// If the target peer is the peer that sent us this message,
|
||||
// then we'll exit early as we don't need to filter this
|
||||
// message.
|
||||
if _, ok := msg.senders[g.peerPub]; ok {
|
||||
if _, ok := msg.senders[g.cfg.peerPub]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -920,8 +1029,8 @@ func (g *gossipSyncer) FilterGossipMsgs(msgs ...msgWithSenders) {
|
||||
}
|
||||
}
|
||||
|
||||
log.Tracef("gossipSyncer(%x): filtered gossip msgs: set=%v, sent=%v",
|
||||
g.peerPub[:], len(msgs), len(msgsToSend))
|
||||
log.Tracef("GossipSyncer(%x): filtered gossip msgs: set=%v, sent=%v",
|
||||
g.cfg.peerPub[:], len(msgs), len(msgsToSend))
|
||||
|
||||
if len(msgsToSend) == 0 {
|
||||
return
|
||||
@ -932,7 +1041,7 @@ func (g *gossipSyncer) FilterGossipMsgs(msgs ...msgWithSenders) {
|
||||
|
||||
// ProcessQueryMsg is used by outside callers to pass new channel time series
|
||||
// queries to the internal processing goroutine.
|
||||
func (g *gossipSyncer) ProcessQueryMsg(msg lnwire.Message, peerQuit <-chan struct{}) {
|
||||
func (g *GossipSyncer) ProcessQueryMsg(msg lnwire.Message, peerQuit <-chan struct{}) {
|
||||
select {
|
||||
case g.gossipMsgs <- msg:
|
||||
case <-peerQuit:
|
||||
@ -940,7 +1049,149 @@ func (g *gossipSyncer) ProcessQueryMsg(msg lnwire.Message, peerQuit <-chan struc
|
||||
}
|
||||
}
|
||||
|
||||
// SyncerState returns the current syncerState of the target gossipSyncer.
|
||||
func (g *gossipSyncer) SyncState() syncerState {
|
||||
// setSyncState sets the gossip syncer's state to the given state.
|
||||
func (g *GossipSyncer) setSyncState(state syncerState) {
|
||||
atomic.StoreUint32(&g.state, uint32(state))
|
||||
}
|
||||
|
||||
// syncState returns the current syncerState of the target GossipSyncer.
|
||||
func (g *GossipSyncer) syncState() syncerState {
|
||||
return syncerState(atomic.LoadUint32(&g.state))
|
||||
}
|
||||
|
||||
// ResetSyncedSignal returns a channel that will be closed in order to serve as
|
||||
// a signal for when the GossipSyncer has reached its chansSynced state.
|
||||
func (g *GossipSyncer) ResetSyncedSignal() chan struct{} {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
syncedSignal := make(chan struct{})
|
||||
|
||||
syncState := syncerState(atomic.LoadUint32(&g.state))
|
||||
if syncState == chansSynced {
|
||||
close(syncedSignal)
|
||||
return syncedSignal
|
||||
}
|
||||
|
||||
g.syncedSignal = syncedSignal
|
||||
return g.syncedSignal
|
||||
}
|
||||
|
||||
// ProcessSyncTransition sends a request to the gossip syncer to transition its
|
||||
// sync type to a new one.
|
||||
//
|
||||
// NOTE: This can only be done once the gossip syncer has reached its final
|
||||
// chansSynced state.
|
||||
func (g *GossipSyncer) ProcessSyncTransition(newSyncType SyncerType) error {
|
||||
errChan := make(chan error, 1)
|
||||
select {
|
||||
case g.syncTransitionReqs <- &syncTransitionReq{
|
||||
newSyncType: newSyncType,
|
||||
errChan: errChan,
|
||||
}:
|
||||
case <-time.After(syncTransitionTimeout):
|
||||
return ErrSyncTransitionTimeout
|
||||
case <-g.quit:
|
||||
return ErrGossipSyncerExiting
|
||||
}
|
||||
|
||||
select {
|
||||
case err := <-errChan:
|
||||
return err
|
||||
case <-g.quit:
|
||||
return ErrGossipSyncerExiting
|
||||
}
|
||||
}
|
||||
|
||||
// handleSyncTransition handles a new sync type transition request.
|
||||
//
|
||||
// NOTE: The gossip syncer might have another sync state as a result of this
|
||||
// transition.
|
||||
func (g *GossipSyncer) handleSyncTransition(req *syncTransitionReq) error {
|
||||
// Return early from any NOP sync transitions.
|
||||
syncType := g.SyncType()
|
||||
if syncType == req.newSyncType {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debugf("GossipSyncer(%x): transitioning from %v to %v",
|
||||
g.cfg.peerPub, syncType, req.newSyncType)
|
||||
|
||||
var (
|
||||
firstTimestamp time.Time
|
||||
timestampRange uint32
|
||||
newState syncerState
|
||||
)
|
||||
|
||||
switch req.newSyncType {
|
||||
// If an active sync has been requested, then we should resume receiving
|
||||
// new graph updates from the remote peer.
|
||||
case ActiveSync:
|
||||
firstTimestamp = time.Now()
|
||||
timestampRange = math.MaxUint32
|
||||
newState = syncingChans
|
||||
|
||||
// We'll set genHistoricalChanRangeQuery to false since in order
|
||||
// to not perform another historical sync if we previously have.
|
||||
g.genHistoricalChanRangeQuery = false
|
||||
|
||||
// If a PassiveSync transition has been requested, then we should no
|
||||
// longer receive any new updates from the remote peer. We can do this
|
||||
// by setting our update horizon to a range in the past ensuring no
|
||||
// graph updates match the timestamp range.
|
||||
case PassiveSync:
|
||||
firstTimestamp = zeroTimestamp
|
||||
timestampRange = 0
|
||||
newState = chansSynced
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unhandled sync transition %v",
|
||||
req.newSyncType)
|
||||
}
|
||||
|
||||
err := g.sendGossipTimestampRange(firstTimestamp, timestampRange)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to send local update horizon: %v", err)
|
||||
}
|
||||
|
||||
g.setSyncState(newState)
|
||||
g.setSyncType(req.newSyncType)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// setSyncType sets the gossip syncer's sync type to the given type.
|
||||
func (g *GossipSyncer) setSyncType(syncType SyncerType) {
|
||||
atomic.StoreUint32(&g.syncType, uint32(syncType))
|
||||
}
|
||||
|
||||
// SyncType returns the current SyncerType of the target GossipSyncer.
|
||||
func (g *GossipSyncer) SyncType() SyncerType {
|
||||
return SyncerType(atomic.LoadUint32(&g.syncType))
|
||||
}
|
||||
|
||||
// historicalSync sends a request to the gossip syncer to perofmr a historical
|
||||
// sync.
|
||||
//
|
||||
// NOTE: This can only be done once the gossip syncer has reached its final
|
||||
// chansSynced state.
|
||||
func (g *GossipSyncer) historicalSync() error {
|
||||
select {
|
||||
case g.historicalSyncReqs <- struct{}{}:
|
||||
return nil
|
||||
case <-time.After(syncTransitionTimeout):
|
||||
return ErrSyncTransitionTimeout
|
||||
case <-g.quit:
|
||||
return ErrGossiperShuttingDown
|
||||
}
|
||||
}
|
||||
|
||||
// handleHistoricalSync handles a request to the gossip syncer to perform a
|
||||
// historical sync.
|
||||
func (g *GossipSyncer) handleHistoricalSync() {
|
||||
// We'll go back to our initial syncingChans state in order to request
|
||||
// the remote peer to give us all of the channel IDs they know of
|
||||
// starting from the genesis block.
|
||||
g.genHistoricalChanRangeQuery = true
|
||||
g.setSyncState(syncingChans)
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultEncoding = lnwire.EncodingSortedPlain
|
||||
defaultEncoding = lnwire.EncodingSortedPlain
|
||||
latestKnownHeight = 1337
|
||||
startHeight = latestKnownHeight - chanRangeQueryBuffer
|
||||
)
|
||||
|
||||
var (
|
||||
@ -116,21 +118,20 @@ var _ ChannelGraphTimeSeries = (*mockChannelGraphTimeSeries)(nil)
|
||||
|
||||
func newTestSyncer(hID lnwire.ShortChannelID,
|
||||
encodingType lnwire.ShortChanIDEncoding, chunkSize int32,
|
||||
) (chan []lnwire.Message, *gossipSyncer, *mockChannelGraphTimeSeries) {
|
||||
) (chan []lnwire.Message, *GossipSyncer, *mockChannelGraphTimeSeries) {
|
||||
|
||||
msgChan := make(chan []lnwire.Message, 20)
|
||||
cfg := gossipSyncerCfg{
|
||||
syncChanUpdates: true,
|
||||
channelSeries: newMockChannelGraphTimeSeries(hID),
|
||||
encodingType: encodingType,
|
||||
chunkSize: chunkSize,
|
||||
channelSeries: newMockChannelGraphTimeSeries(hID),
|
||||
encodingType: encodingType,
|
||||
chunkSize: chunkSize,
|
||||
sendToPeer: func(msgs ...lnwire.Message) error {
|
||||
msgChan <- msgs
|
||||
return nil
|
||||
},
|
||||
delayedQueryReplyInterval: 2 * time.Second,
|
||||
}
|
||||
syncer := newGossiperSyncer(cfg)
|
||||
syncer := newGossipSyncer(cfg)
|
||||
|
||||
return msgChan, syncer, cfg.channelSeries.(*mockChannelGraphTimeSeries)
|
||||
}
|
||||
@ -140,7 +141,7 @@ func newTestSyncer(hID lnwire.ShortChannelID,
|
||||
func TestGossipSyncerFilterGossipMsgsNoHorizon(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
msgChan, syncer, _ := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding,
|
||||
@ -185,7 +186,7 @@ func unixStamp(a int64) uint32 {
|
||||
func TestGossipSyncerFilterGossipMsgsAllInMemory(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
msgChan, syncer, chanSeries := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding,
|
||||
@ -315,7 +316,7 @@ func TestGossipSyncerFilterGossipMsgsAllInMemory(t *testing.T) {
|
||||
func TestGossipSyncerApplyGossipFilter(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
msgChan, syncer, chanSeries := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding,
|
||||
@ -413,7 +414,7 @@ func TestGossipSyncerApplyGossipFilter(t *testing.T) {
|
||||
func TestGossipSyncerReplyShortChanIDsWrongChainHash(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
msgChan, syncer, _ := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding,
|
||||
@ -464,7 +465,7 @@ func TestGossipSyncerReplyShortChanIDsWrongChainHash(t *testing.T) {
|
||||
func TestGossipSyncerReplyShortChanIDs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
msgChan, syncer, chanSeries := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding,
|
||||
@ -718,7 +719,7 @@ func TestGossipSyncerReplyChanRangeQueryNoNewChans(t *testing.T) {
|
||||
func TestGossipSyncerGenChanRangeQuery(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
const startingHeight = 200
|
||||
_, syncer, _ := newTestSyncer(
|
||||
@ -729,7 +730,7 @@ func TestGossipSyncerGenChanRangeQuery(t *testing.T) {
|
||||
// If we now ask the syncer to generate an initial range query, it
|
||||
// should return a start height that's back chanRangeQueryBuffer
|
||||
// blocks.
|
||||
rangeQuery, err := syncer.genChanRangeQuery()
|
||||
rangeQuery, err := syncer.genChanRangeQuery(false)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to resp: %v", err)
|
||||
}
|
||||
@ -742,7 +743,22 @@ func TestGossipSyncerGenChanRangeQuery(t *testing.T) {
|
||||
}
|
||||
if rangeQuery.NumBlocks != math.MaxUint32-firstHeight {
|
||||
t.Fatalf("wrong num blocks: expected %v, got %v",
|
||||
rangeQuery.NumBlocks, math.MaxUint32-firstHeight)
|
||||
math.MaxUint32-firstHeight, rangeQuery.NumBlocks)
|
||||
}
|
||||
|
||||
// Generating a historical range query should result in a start height
|
||||
// of 0.
|
||||
rangeQuery, err = syncer.genChanRangeQuery(true)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to resp: %v", err)
|
||||
}
|
||||
if rangeQuery.FirstBlockHeight != 0 {
|
||||
t.Fatalf("incorrect chan range query: expected %v, %v", 0,
|
||||
rangeQuery.FirstBlockHeight)
|
||||
}
|
||||
if rangeQuery.NumBlocks != math.MaxUint32 {
|
||||
t.Fatalf("wrong num blocks: expected %v, got %v",
|
||||
math.MaxUint32, rangeQuery.NumBlocks)
|
||||
}
|
||||
}
|
||||
|
||||
@ -753,7 +769,7 @@ func TestGossipSyncerGenChanRangeQuery(t *testing.T) {
|
||||
func TestGossipSyncerProcessChanRangeReply(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
_, syncer, chanSeries := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding, defaultChunkSize,
|
||||
@ -827,7 +843,7 @@ func TestGossipSyncerProcessChanRangeReply(t *testing.T) {
|
||||
t.Fatalf("unable to process reply: %v", err)
|
||||
}
|
||||
|
||||
if syncer.SyncState() != queryNewChannels {
|
||||
if syncer.syncState() != queryNewChannels {
|
||||
t.Fatalf("wrong state: expected %v instead got %v",
|
||||
queryNewChannels, syncer.state)
|
||||
}
|
||||
@ -860,7 +876,7 @@ func TestGossipSyncerProcessChanRangeReply(t *testing.T) {
|
||||
t.Fatalf("unable to process reply: %v", err)
|
||||
}
|
||||
|
||||
if syncer.SyncState() != chansSynced {
|
||||
if syncer.syncState() != chansSynced {
|
||||
t.Fatalf("wrong state: expected %v instead got %v",
|
||||
chansSynced, syncer.state)
|
||||
}
|
||||
@ -878,7 +894,7 @@ func TestGossipSyncerSynchronizeChanIDs(t *testing.T) {
|
||||
// queries: two full chunks, and one lingering chunk.
|
||||
const chunkSize = 2
|
||||
|
||||
// First, we'll create a gossipSyncer instance with a canned sendToPeer
|
||||
// First, we'll create a GossipSyncer instance with a canned sendToPeer
|
||||
// message to allow us to intercept their potential sends.
|
||||
msgChan, syncer, _ := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding, chunkSize,
|
||||
@ -997,7 +1013,7 @@ func TestGossipSyncerDelayDOS(t *testing.T) {
|
||||
const numDelayedQueries = 2
|
||||
const delayTolerance = time.Millisecond * 200
|
||||
|
||||
// First, we'll create two gossipSyncer instances with a canned
|
||||
// First, we'll create two GossipSyncer instances with a canned
|
||||
// sendToPeer message to allow us to intercept their potential sends.
|
||||
startHeight := lnwire.ShortChannelID{
|
||||
BlockHeight: 1144,
|
||||
@ -1390,7 +1406,7 @@ func TestGossipSyncerRoutineSync(t *testing.T) {
|
||||
// queries: two full chunks, and one lingering chunk.
|
||||
const chunkSize = 2
|
||||
|
||||
// First, we'll create two gossipSyncer instances with a canned
|
||||
// First, we'll create two GossipSyncer instances with a canned
|
||||
// sendToPeer message to allow us to intercept their potential sends.
|
||||
startHeight := lnwire.ShortChannelID{
|
||||
BlockHeight: 1144,
|
||||
@ -1730,7 +1746,7 @@ func TestGossipSyncerAlreadySynced(t *testing.T) {
|
||||
// queries: two full chunks, and one lingering chunk.
|
||||
const chunkSize = 2
|
||||
|
||||
// First, we'll create two gossipSyncer instances with a canned
|
||||
// First, we'll create two GossipSyncer instances with a canned
|
||||
// sendToPeer message to allow us to intercept their potential sends.
|
||||
startHeight := lnwire.ShortChannelID{
|
||||
BlockHeight: 1144,
|
||||
@ -1941,3 +1957,236 @@ func TestGossipSyncerAlreadySynced(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestGossipSyncerSyncTransitions ensures that the gossip syncer properly
|
||||
// carries out its duties when accepting a new sync transition request.
|
||||
func TestGossipSyncerSyncTransitions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assertMsgSent := func(t *testing.T, msgChan chan []lnwire.Message,
|
||||
msg lnwire.Message) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
var msgSent lnwire.Message
|
||||
select {
|
||||
case msgs := <-msgChan:
|
||||
if len(msgs) != 1 {
|
||||
t.Fatal("expected to send a single message at "+
|
||||
"a time, got %d", len(msgs))
|
||||
}
|
||||
msgSent = msgs[0]
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("expected to send %T message", msg)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(msgSent, msg) {
|
||||
t.Fatalf("expected to send message: %v\ngot: %v",
|
||||
spew.Sdump(msg), spew.Sdump(msgSent))
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
entrySyncType SyncerType
|
||||
finalSyncType SyncerType
|
||||
assert func(t *testing.T, msgChan chan []lnwire.Message,
|
||||
syncer *GossipSyncer)
|
||||
}{
|
||||
{
|
||||
name: "active to passive",
|
||||
entrySyncType: ActiveSync,
|
||||
finalSyncType: PassiveSync,
|
||||
assert: func(t *testing.T, msgChan chan []lnwire.Message,
|
||||
g *GossipSyncer) {
|
||||
|
||||
// When transitioning from active to passive, we
|
||||
// should expect to see a new local update
|
||||
// horizon sent to the remote peer indicating
|
||||
// that it would not like to receive any future
|
||||
// updates.
|
||||
assertMsgSent(t, msgChan, &lnwire.GossipTimestampRange{
|
||||
FirstTimestamp: uint32(zeroTimestamp.Unix()),
|
||||
TimestampRange: 0,
|
||||
})
|
||||
|
||||
syncState := g.syncState()
|
||||
if syncState != chansSynced {
|
||||
t.Fatalf("expected syncerState %v, "+
|
||||
"got %v", chansSynced,
|
||||
syncState)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "passive to active",
|
||||
entrySyncType: PassiveSync,
|
||||
finalSyncType: ActiveSync,
|
||||
assert: func(t *testing.T, msgChan chan []lnwire.Message,
|
||||
g *GossipSyncer) {
|
||||
|
||||
// When transitioning from historical to active,
|
||||
// we should expect to see a new local update
|
||||
// horizon sent to the remote peer indicating
|
||||
// that it would like to receive any future
|
||||
// updates.
|
||||
firstTimestamp := uint32(time.Now().Unix())
|
||||
assertMsgSent(t, msgChan, &lnwire.GossipTimestampRange{
|
||||
FirstTimestamp: firstTimestamp,
|
||||
TimestampRange: math.MaxUint32,
|
||||
})
|
||||
|
||||
// The local update horizon should be followed
|
||||
// by a QueryChannelRange message sent to the
|
||||
// remote peer requesting all channels it
|
||||
// knows of from the highest height the syncer
|
||||
// knows of.
|
||||
assertMsgSent(t, msgChan, &lnwire.QueryChannelRange{
|
||||
FirstBlockHeight: startHeight,
|
||||
NumBlocks: math.MaxUint32 - startHeight,
|
||||
})
|
||||
|
||||
syncState := g.syncState()
|
||||
if syncState != waitingQueryRangeReply {
|
||||
t.Fatalf("expected syncerState %v, "+
|
||||
"got %v", waitingQueryRangeReply,
|
||||
syncState)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We'll start each test by creating our syncer. We'll
|
||||
// initialize it with a state of chansSynced, as that's
|
||||
// the only time when it can process sync transitions.
|
||||
msgChan, syncer, _ := newTestSyncer(
|
||||
lnwire.ShortChannelID{
|
||||
BlockHeight: latestKnownHeight,
|
||||
},
|
||||
defaultEncoding, defaultChunkSize,
|
||||
)
|
||||
syncer.setSyncState(chansSynced)
|
||||
|
||||
// We'll set the initial syncType to what the test
|
||||
// demands.
|
||||
syncer.setSyncType(test.entrySyncType)
|
||||
|
||||
// We'll then start the syncer in order to process the
|
||||
// request.
|
||||
syncer.Start()
|
||||
defer syncer.Stop()
|
||||
|
||||
syncer.ProcessSyncTransition(test.finalSyncType)
|
||||
|
||||
// The syncer should now have the expected final
|
||||
// SyncerType that the test expects.
|
||||
syncType := syncer.SyncType()
|
||||
if syncType != test.finalSyncType {
|
||||
t.Fatalf("expected syncType %v, got %v",
|
||||
test.finalSyncType, syncType)
|
||||
}
|
||||
|
||||
// Finally, we'll run a set of assertions for each test
|
||||
// to ensure the syncer performed its expected duties
|
||||
// after processing its sync transition.
|
||||
test.assert(t, msgChan, syncer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestGossipSyncerHistoricalSync tests that a gossip syncer can perform a
|
||||
// historical sync with the remote peer.
|
||||
func TestGossipSyncerHistoricalSync(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We'll create a new gossip syncer and manually override its state to
|
||||
// chansSynced. This is necessary as the syncer can only process
|
||||
// historical sync requests in this state.
|
||||
msgChan, syncer, _ := newTestSyncer(
|
||||
lnwire.ShortChannelID{BlockHeight: latestKnownHeight},
|
||||
defaultEncoding, defaultChunkSize,
|
||||
)
|
||||
syncer.setSyncType(PassiveSync)
|
||||
syncer.setSyncState(chansSynced)
|
||||
|
||||
syncer.Start()
|
||||
defer syncer.Stop()
|
||||
|
||||
syncer.historicalSync()
|
||||
|
||||
// We should expect to see a single lnwire.QueryChannelRange message be
|
||||
// sent to the remote peer with a FirstBlockHeight of 0.
|
||||
expectedMsg := &lnwire.QueryChannelRange{
|
||||
FirstBlockHeight: 0,
|
||||
NumBlocks: math.MaxUint32,
|
||||
}
|
||||
|
||||
select {
|
||||
case msgs := <-msgChan:
|
||||
if len(msgs) != 1 {
|
||||
t.Fatalf("expected to send a single "+
|
||||
"lnwire.QueryChannelRange message, got %d",
|
||||
len(msgs))
|
||||
}
|
||||
if !reflect.DeepEqual(msgs[0], expectedMsg) {
|
||||
t.Fatalf("expected to send message: %v\ngot: %v",
|
||||
spew.Sdump(expectedMsg), spew.Sdump(msgs[0]))
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("expected to send a lnwire.QueryChannelRange message")
|
||||
}
|
||||
}
|
||||
|
||||
// TestGossipSyncerSyncedSignal ensures that we receive a signal when a gossip
|
||||
// syncer reaches its terminal chansSynced state.
|
||||
func TestGossipSyncerSyncedSignal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We'll create a new gossip syncer and manually override its state to
|
||||
// chansSynced.
|
||||
_, syncer, _ := newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding,
|
||||
defaultChunkSize,
|
||||
)
|
||||
syncer.setSyncState(chansSynced)
|
||||
|
||||
// We'll go ahead and request a signal to be notified of when it reaches
|
||||
// this state.
|
||||
signalChan := syncer.ResetSyncedSignal()
|
||||
|
||||
// Starting the gossip syncer should cause the signal to be delivered.
|
||||
syncer.Start()
|
||||
|
||||
select {
|
||||
case <-signalChan:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("expected to receive chansSynced signal")
|
||||
}
|
||||
|
||||
syncer.Stop()
|
||||
|
||||
// We'll try this again, but this time we'll request the signal after
|
||||
// the syncer is active and has already reached its chansSynced state.
|
||||
_, syncer, _ = newTestSyncer(
|
||||
lnwire.NewShortChanIDFromInt(10), defaultEncoding,
|
||||
defaultChunkSize,
|
||||
)
|
||||
|
||||
syncer.setSyncState(chansSynced)
|
||||
|
||||
syncer.Start()
|
||||
defer syncer.Stop()
|
||||
|
||||
signalChan = syncer.ResetSyncedSignal()
|
||||
|
||||
// The signal should be delivered immediately.
|
||||
select {
|
||||
case <-signalChan:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("expected to receive chansSynced signal")
|
||||
}
|
||||
}
|
||||
|
1294
lnrpc/rpc.pb.go
1294
lnrpc/rpc.pb.go
@ -55,7 +55,7 @@ func (x AddressType) String() string {
|
||||
return proto.EnumName(AddressType_name, int32(x))
|
||||
}
|
||||
func (AddressType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{0}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{0}
|
||||
}
|
||||
|
||||
type ChannelCloseSummary_ClosureType int32
|
||||
@ -90,7 +90,39 @@ func (x ChannelCloseSummary_ClosureType) String() string {
|
||||
return proto.EnumName(ChannelCloseSummary_ClosureType_name, int32(x))
|
||||
}
|
||||
func (ChannelCloseSummary_ClosureType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{41, 0}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{41, 0}
|
||||
}
|
||||
|
||||
type Peer_SyncType int32
|
||||
|
||||
const (
|
||||
// *
|
||||
// Denotes that we cannot determine the peer's current sync type.
|
||||
Peer_UNKNOWN_SYNC Peer_SyncType = 0
|
||||
// *
|
||||
// Denotes that we are actively receiving new graph updates from the peer.
|
||||
Peer_ACTIVE_SYNC Peer_SyncType = 1
|
||||
// *
|
||||
// Denotes that we are not receiving new graph updates from the peer.
|
||||
Peer_PASSIVE_SYNC Peer_SyncType = 2
|
||||
)
|
||||
|
||||
var Peer_SyncType_name = map[int32]string{
|
||||
0: "UNKNOWN_SYNC",
|
||||
1: "ACTIVE_SYNC",
|
||||
2: "PASSIVE_SYNC",
|
||||
}
|
||||
var Peer_SyncType_value = map[string]int32{
|
||||
"UNKNOWN_SYNC": 0,
|
||||
"ACTIVE_SYNC": 1,
|
||||
"PASSIVE_SYNC": 2,
|
||||
}
|
||||
|
||||
func (x Peer_SyncType) String() string {
|
||||
return proto.EnumName(Peer_SyncType_name, int32(x))
|
||||
}
|
||||
func (Peer_SyncType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{44, 0}
|
||||
}
|
||||
|
||||
type ChannelEventUpdate_UpdateType int32
|
||||
@ -119,7 +151,7 @@ func (x ChannelEventUpdate_UpdateType) String() string {
|
||||
return proto.EnumName(ChannelEventUpdate_UpdateType_name, int32(x))
|
||||
}
|
||||
func (ChannelEventUpdate_UpdateType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{62, 0}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{62, 0}
|
||||
}
|
||||
|
||||
type Invoice_InvoiceState int32
|
||||
@ -148,7 +180,7 @@ func (x Invoice_InvoiceState) String() string {
|
||||
return proto.EnumName(Invoice_InvoiceState_name, int32(x))
|
||||
}
|
||||
func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{92, 0}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{92, 0}
|
||||
}
|
||||
|
||||
type GenSeedRequest struct {
|
||||
@ -169,7 +201,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_e15c66dc1b25da1b, []int{0}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{0}
|
||||
}
|
||||
func (m *GenSeedRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GenSeedRequest.Unmarshal(m, b)
|
||||
@ -224,7 +256,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_e15c66dc1b25da1b, []int{1}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{1}
|
||||
}
|
||||
func (m *GenSeedResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GenSeedResponse.Unmarshal(m, b)
|
||||
@ -297,7 +329,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_e15c66dc1b25da1b, []int{2}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{2}
|
||||
}
|
||||
func (m *InitWalletRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InitWalletRequest.Unmarshal(m, b)
|
||||
@ -362,7 +394,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_e15c66dc1b25da1b, []int{3}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{3}
|
||||
}
|
||||
func (m *InitWalletResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InitWalletResponse.Unmarshal(m, b)
|
||||
@ -412,7 +444,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_e15c66dc1b25da1b, []int{4}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{4}
|
||||
}
|
||||
func (m *UnlockWalletRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UnlockWalletRequest.Unmarshal(m, b)
|
||||
@ -463,7 +495,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_e15c66dc1b25da1b, []int{5}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{5}
|
||||
}
|
||||
func (m *UnlockWalletResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UnlockWalletResponse.Unmarshal(m, b)
|
||||
@ -501,7 +533,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_e15c66dc1b25da1b, []int{6}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{6}
|
||||
}
|
||||
func (m *ChangePasswordRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChangePasswordRequest.Unmarshal(m, b)
|
||||
@ -545,7 +577,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_e15c66dc1b25da1b, []int{7}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{7}
|
||||
}
|
||||
func (m *ChangePasswordResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChangePasswordResponse.Unmarshal(m, b)
|
||||
@ -587,7 +619,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_e15c66dc1b25da1b, []int{8}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{8}
|
||||
}
|
||||
func (m *Utxo) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Utxo.Unmarshal(m, b)
|
||||
@ -675,7 +707,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_e15c66dc1b25da1b, []int{9}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{9}
|
||||
}
|
||||
func (m *Transaction) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Transaction.Unmarshal(m, b)
|
||||
@ -761,7 +793,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_e15c66dc1b25da1b, []int{10}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{10}
|
||||
}
|
||||
func (m *GetTransactionsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetTransactionsRequest.Unmarshal(m, b)
|
||||
@ -793,7 +825,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_e15c66dc1b25da1b, []int{11}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{11}
|
||||
}
|
||||
func (m *TransactionDetails) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_TransactionDetails.Unmarshal(m, b)
|
||||
@ -834,7 +866,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_e15c66dc1b25da1b, []int{12}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{12}
|
||||
}
|
||||
func (m *FeeLimit) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FeeLimit.Unmarshal(m, b)
|
||||
@ -998,7 +1030,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_e15c66dc1b25da1b, []int{13}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{13}
|
||||
}
|
||||
func (m *SendRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendRequest.Unmarshal(m, b)
|
||||
@ -1102,7 +1134,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_e15c66dc1b25da1b, []int{14}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{14}
|
||||
}
|
||||
func (m *SendResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendResponse.Unmarshal(m, b)
|
||||
@ -1172,7 +1204,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_e15c66dc1b25da1b, []int{15}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{15}
|
||||
}
|
||||
func (m *SendToRouteRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendToRouteRequest.Unmarshal(m, b)
|
||||
@ -1237,7 +1269,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_e15c66dc1b25da1b, []int{16}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{16}
|
||||
}
|
||||
func (m *ChannelPoint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelPoint.Unmarshal(m, b)
|
||||
@ -1383,7 +1415,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_e15c66dc1b25da1b, []int{17}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{17}
|
||||
}
|
||||
func (m *OutPoint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_OutPoint.Unmarshal(m, b)
|
||||
@ -1438,7 +1470,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_e15c66dc1b25da1b, []int{18}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{18}
|
||||
}
|
||||
func (m *LightningAddress) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LightningAddress.Unmarshal(m, b)
|
||||
@ -1486,7 +1518,7 @@ func (m *EstimateFeeRequest) Reset() { *m = EstimateFeeRequest{} }
|
||||
func (m *EstimateFeeRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EstimateFeeRequest) ProtoMessage() {}
|
||||
func (*EstimateFeeRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{19}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{19}
|
||||
}
|
||||
func (m *EstimateFeeRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EstimateFeeRequest.Unmarshal(m, b)
|
||||
@ -1534,7 +1566,7 @@ func (m *EstimateFeeResponse) Reset() { *m = EstimateFeeResponse{} }
|
||||
func (m *EstimateFeeResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EstimateFeeResponse) ProtoMessage() {}
|
||||
func (*EstimateFeeResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{20}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{20}
|
||||
}
|
||||
func (m *EstimateFeeResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EstimateFeeResponse.Unmarshal(m, b)
|
||||
@ -1584,7 +1616,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_e15c66dc1b25da1b, []int{21}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{21}
|
||||
}
|
||||
func (m *SendManyRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendManyRequest.Unmarshal(m, b)
|
||||
@ -1637,7 +1669,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_e15c66dc1b25da1b, []int{22}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{22}
|
||||
}
|
||||
func (m *SendManyResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendManyResponse.Unmarshal(m, b)
|
||||
@ -1687,7 +1719,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_e15c66dc1b25da1b, []int{23}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{23}
|
||||
}
|
||||
func (m *SendCoinsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendCoinsRequest.Unmarshal(m, b)
|
||||
@ -1754,7 +1786,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_e15c66dc1b25da1b, []int{24}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{24}
|
||||
}
|
||||
func (m *SendCoinsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendCoinsResponse.Unmarshal(m, b)
|
||||
@ -1795,7 +1827,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_e15c66dc1b25da1b, []int{25}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{25}
|
||||
}
|
||||
func (m *ListUnspentRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListUnspentRequest.Unmarshal(m, b)
|
||||
@ -1841,7 +1873,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_e15c66dc1b25da1b, []int{26}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{26}
|
||||
}
|
||||
func (m *ListUnspentResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListUnspentResponse.Unmarshal(m, b)
|
||||
@ -1880,7 +1912,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_e15c66dc1b25da1b, []int{27}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{27}
|
||||
}
|
||||
func (m *NewAddressRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NewAddressRequest.Unmarshal(m, b)
|
||||
@ -1919,7 +1951,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_e15c66dc1b25da1b, []int{28}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{28}
|
||||
}
|
||||
func (m *NewAddressResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NewAddressResponse.Unmarshal(m, b)
|
||||
@ -1958,7 +1990,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_e15c66dc1b25da1b, []int{29}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{29}
|
||||
}
|
||||
func (m *SignMessageRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignMessageRequest.Unmarshal(m, b)
|
||||
@ -1997,7 +2029,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_e15c66dc1b25da1b, []int{30}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{30}
|
||||
}
|
||||
func (m *SignMessageResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignMessageResponse.Unmarshal(m, b)
|
||||
@ -2038,7 +2070,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_e15c66dc1b25da1b, []int{31}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{31}
|
||||
}
|
||||
func (m *VerifyMessageRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VerifyMessageRequest.Unmarshal(m, b)
|
||||
@ -2086,7 +2118,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_e15c66dc1b25da1b, []int{32}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{32}
|
||||
}
|
||||
func (m *VerifyMessageResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VerifyMessageResponse.Unmarshal(m, b)
|
||||
@ -2135,7 +2167,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_e15c66dc1b25da1b, []int{33}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{33}
|
||||
}
|
||||
func (m *ConnectPeerRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConnectPeerRequest.Unmarshal(m, b)
|
||||
@ -2179,7 +2211,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_e15c66dc1b25da1b, []int{34}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{34}
|
||||
}
|
||||
func (m *ConnectPeerResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConnectPeerResponse.Unmarshal(m, b)
|
||||
@ -2211,7 +2243,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_e15c66dc1b25da1b, []int{35}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{35}
|
||||
}
|
||||
func (m *DisconnectPeerRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DisconnectPeerRequest.Unmarshal(m, b)
|
||||
@ -2248,7 +2280,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_e15c66dc1b25da1b, []int{36}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{36}
|
||||
}
|
||||
func (m *DisconnectPeerResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DisconnectPeerResponse.Unmarshal(m, b)
|
||||
@ -2282,7 +2314,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_e15c66dc1b25da1b, []int{37}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{37}
|
||||
}
|
||||
func (m *HTLC) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_HTLC.Unmarshal(m, b)
|
||||
@ -2397,7 +2429,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_e15c66dc1b25da1b, []int{38}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{38}
|
||||
}
|
||||
func (m *Channel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Channel.Unmarshal(m, b)
|
||||
@ -2564,7 +2596,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_e15c66dc1b25da1b, []int{39}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{39}
|
||||
}
|
||||
func (m *ListChannelsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListChannelsRequest.Unmarshal(m, b)
|
||||
@ -2624,7 +2656,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_e15c66dc1b25da1b, []int{40}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{40}
|
||||
}
|
||||
func (m *ListChannelsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListChannelsResponse.Unmarshal(m, b)
|
||||
@ -2681,7 +2713,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_e15c66dc1b25da1b, []int{41}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{41}
|
||||
}
|
||||
func (m *ChannelCloseSummary) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelCloseSummary.Unmarshal(m, b)
|
||||
@ -2787,7 +2819,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_e15c66dc1b25da1b, []int{42}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{42}
|
||||
}
|
||||
func (m *ClosedChannelsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ClosedChannelsRequest.Unmarshal(m, b)
|
||||
@ -2860,7 +2892,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_e15c66dc1b25da1b, []int{43}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{43}
|
||||
}
|
||||
func (m *ClosedChannelsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ClosedChannelsResponse.Unmarshal(m, b)
|
||||
@ -2903,17 +2935,19 @@ type Peer struct {
|
||||
// / A channel is inbound if the counterparty initiated the channel
|
||||
Inbound bool `protobuf:"varint,8,opt,name=inbound,proto3" json:"inbound,omitempty"`
|
||||
// / Ping time to this peer
|
||||
PingTime int64 `protobuf:"varint,9,opt,name=ping_time,proto3" json:"ping_time,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
PingTime int64 `protobuf:"varint,9,opt,name=ping_time,proto3" json:"ping_time,omitempty"`
|
||||
// The type of sync we are currently performing with this peer.
|
||||
SyncType Peer_SyncType `protobuf:"varint,10,opt,name=sync_type,proto3,enum=lnrpc.Peer_SyncType" json:"sync_type,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
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_e15c66dc1b25da1b, []int{44}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{44}
|
||||
}
|
||||
func (m *Peer) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Peer.Unmarshal(m, b)
|
||||
@ -2989,6 +3023,13 @@ func (m *Peer) GetPingTime() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Peer) GetSyncType() Peer_SyncType {
|
||||
if m != nil {
|
||||
return m.SyncType
|
||||
}
|
||||
return Peer_UNKNOWN_SYNC
|
||||
}
|
||||
|
||||
type ListPeersRequest struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@ -2999,7 +3040,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_e15c66dc1b25da1b, []int{45}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{45}
|
||||
}
|
||||
func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPeersRequest.Unmarshal(m, b)
|
||||
@ -3031,7 +3072,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_e15c66dc1b25da1b, []int{46}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{46}
|
||||
}
|
||||
func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPeersResponse.Unmarshal(m, b)
|
||||
@ -3068,7 +3109,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_e15c66dc1b25da1b, []int{47}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{47}
|
||||
}
|
||||
func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetInfoRequest.Unmarshal(m, b)
|
||||
@ -3128,7 +3169,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_e15c66dc1b25da1b, []int{48}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{48}
|
||||
}
|
||||
func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetInfoResponse.Unmarshal(m, b)
|
||||
@ -3261,7 +3302,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_e15c66dc1b25da1b, []int{49}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{49}
|
||||
}
|
||||
func (m *Chain) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Chain.Unmarshal(m, b)
|
||||
@ -3308,7 +3349,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_e15c66dc1b25da1b, []int{50}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{50}
|
||||
}
|
||||
func (m *ConfirmationUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConfirmationUpdate.Unmarshal(m, b)
|
||||
@ -3360,7 +3401,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_e15c66dc1b25da1b, []int{51}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{51}
|
||||
}
|
||||
func (m *ChannelOpenUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelOpenUpdate.Unmarshal(m, b)
|
||||
@ -3399,7 +3440,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_e15c66dc1b25da1b, []int{52}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{52}
|
||||
}
|
||||
func (m *ChannelCloseUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelCloseUpdate.Unmarshal(m, b)
|
||||
@ -3454,7 +3495,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_e15c66dc1b25da1b, []int{53}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{53}
|
||||
}
|
||||
func (m *CloseChannelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CloseChannelRequest.Unmarshal(m, b)
|
||||
@ -3516,7 +3557,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_e15c66dc1b25da1b, []int{54}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{54}
|
||||
}
|
||||
func (m *CloseStatusUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CloseStatusUpdate.Unmarshal(m, b)
|
||||
@ -3659,7 +3700,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_e15c66dc1b25da1b, []int{55}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{55}
|
||||
}
|
||||
func (m *PendingUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingUpdate.Unmarshal(m, b)
|
||||
@ -3725,7 +3766,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_e15c66dc1b25da1b, []int{56}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{56}
|
||||
}
|
||||
func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_OpenChannelRequest.Unmarshal(m, b)
|
||||
@ -3836,7 +3877,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_e15c66dc1b25da1b, []int{57}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{57}
|
||||
}
|
||||
func (m *OpenStatusUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_OpenStatusUpdate.Unmarshal(m, b)
|
||||
@ -3992,7 +4033,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_e15c66dc1b25da1b, []int{58}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{58}
|
||||
}
|
||||
func (m *PendingHTLC) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingHTLC.Unmarshal(m, b)
|
||||
@ -4064,7 +4105,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_e15c66dc1b25da1b, []int{59}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{59}
|
||||
}
|
||||
func (m *PendingChannelsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsRequest.Unmarshal(m, b)
|
||||
@ -4104,7 +4145,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_e15c66dc1b25da1b, []int{60}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{60}
|
||||
}
|
||||
func (m *PendingChannelsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse.Unmarshal(m, b)
|
||||
@ -4176,7 +4217,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_e15c66dc1b25da1b, []int{60, 0}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{60, 0}
|
||||
}
|
||||
func (m *PendingChannelsResponse_PendingChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_PendingChannel.Unmarshal(m, b)
|
||||
@ -4263,7 +4304,7 @@ func (m *PendingChannelsResponse_PendingOpenChannel) String() string {
|
||||
}
|
||||
func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_PendingOpenChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{60, 1}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{60, 1}
|
||||
}
|
||||
func (m *PendingChannelsResponse_PendingOpenChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_PendingOpenChannel.Unmarshal(m, b)
|
||||
@ -4336,7 +4377,7 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) String() string {
|
||||
}
|
||||
func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_WaitingCloseChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{60, 2}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{60, 2}
|
||||
}
|
||||
func (m *PendingChannelsResponse_WaitingCloseChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_WaitingCloseChannel.Unmarshal(m, b)
|
||||
@ -4384,7 +4425,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_e15c66dc1b25da1b, []int{60, 3}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{60, 3}
|
||||
}
|
||||
func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_ClosedChannel.Unmarshal(m, b)
|
||||
@ -4448,7 +4489,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string {
|
||||
}
|
||||
func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{60, 4}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{60, 4}
|
||||
}
|
||||
func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_ForceClosedChannel.Unmarshal(m, b)
|
||||
@ -4527,7 +4568,7 @@ func (m *ChannelEventSubscription) Reset() { *m = ChannelEventSubscripti
|
||||
func (m *ChannelEventSubscription) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelEventSubscription) ProtoMessage() {}
|
||||
func (*ChannelEventSubscription) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{61}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{61}
|
||||
}
|
||||
func (m *ChannelEventSubscription) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEventSubscription.Unmarshal(m, b)
|
||||
@ -4564,7 +4605,7 @@ 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_e15c66dc1b25da1b, []int{62}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{62}
|
||||
}
|
||||
func (m *ChannelEventUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEventUpdate.Unmarshal(m, b)
|
||||
@ -4776,7 +4817,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_e15c66dc1b25da1b, []int{63}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{63}
|
||||
}
|
||||
func (m *WalletBalanceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_WalletBalanceRequest.Unmarshal(m, b)
|
||||
@ -4812,7 +4853,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_e15c66dc1b25da1b, []int{64}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{64}
|
||||
}
|
||||
func (m *WalletBalanceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_WalletBalanceResponse.Unmarshal(m, b)
|
||||
@ -4863,7 +4904,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_e15c66dc1b25da1b, []int{65}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{65}
|
||||
}
|
||||
func (m *ChannelBalanceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelBalanceRequest.Unmarshal(m, b)
|
||||
@ -4897,7 +4938,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_e15c66dc1b25da1b, []int{66}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{66}
|
||||
}
|
||||
func (m *ChannelBalanceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelBalanceResponse.Unmarshal(m, b)
|
||||
@ -4967,7 +5008,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_e15c66dc1b25da1b, []int{67}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{67}
|
||||
}
|
||||
func (m *QueryRoutesRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_QueryRoutesRequest.Unmarshal(m, b)
|
||||
@ -5062,7 +5103,7 @@ func (m *EdgeLocator) Reset() { *m = EdgeLocator{} }
|
||||
func (m *EdgeLocator) String() string { return proto.CompactTextString(m) }
|
||||
func (*EdgeLocator) ProtoMessage() {}
|
||||
func (*EdgeLocator) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{68}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{68}
|
||||
}
|
||||
func (m *EdgeLocator) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EdgeLocator.Unmarshal(m, b)
|
||||
@ -5107,7 +5148,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_e15c66dc1b25da1b, []int{69}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{69}
|
||||
}
|
||||
func (m *QueryRoutesResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_QueryRoutesResponse.Unmarshal(m, b)
|
||||
@ -5159,7 +5200,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_e15c66dc1b25da1b, []int{70}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{70}
|
||||
}
|
||||
func (m *Hop) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Hop.Unmarshal(m, b)
|
||||
@ -5280,7 +5321,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_e15c66dc1b25da1b, []int{71}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{71}
|
||||
}
|
||||
func (m *Route) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Route.Unmarshal(m, b)
|
||||
@ -5356,7 +5397,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_e15c66dc1b25da1b, []int{72}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{72}
|
||||
}
|
||||
func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeInfoRequest.Unmarshal(m, b)
|
||||
@ -5401,7 +5442,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_e15c66dc1b25da1b, []int{73}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{73}
|
||||
}
|
||||
func (m *NodeInfo) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeInfo.Unmarshal(m, b)
|
||||
@ -5462,7 +5503,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_e15c66dc1b25da1b, []int{74}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{74}
|
||||
}
|
||||
func (m *LightningNode) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LightningNode.Unmarshal(m, b)
|
||||
@ -5529,7 +5570,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_e15c66dc1b25da1b, []int{75}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{75}
|
||||
}
|
||||
func (m *NodeAddress) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeAddress.Unmarshal(m, b)
|
||||
@ -5579,7 +5620,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_e15c66dc1b25da1b, []int{76}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{76}
|
||||
}
|
||||
func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RoutingPolicy.Unmarshal(m, b)
|
||||
@ -5669,7 +5710,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_e15c66dc1b25da1b, []int{77}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{77}
|
||||
}
|
||||
func (m *ChannelEdge) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEdge.Unmarshal(m, b)
|
||||
@ -5760,7 +5801,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_e15c66dc1b25da1b, []int{78}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{78}
|
||||
}
|
||||
func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelGraphRequest.Unmarshal(m, b)
|
||||
@ -5802,7 +5843,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_e15c66dc1b25da1b, []int{79}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{79}
|
||||
}
|
||||
func (m *ChannelGraph) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelGraph.Unmarshal(m, b)
|
||||
@ -5851,7 +5892,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_e15c66dc1b25da1b, []int{80}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{80}
|
||||
}
|
||||
func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChanInfoRequest.Unmarshal(m, b)
|
||||
@ -5888,7 +5929,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_e15c66dc1b25da1b, []int{81}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{81}
|
||||
}
|
||||
func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NetworkInfoRequest.Unmarshal(m, b)
|
||||
@ -5928,7 +5969,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_e15c66dc1b25da1b, []int{82}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{82}
|
||||
}
|
||||
func (m *NetworkInfo) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NetworkInfo.Unmarshal(m, b)
|
||||
@ -6028,7 +6069,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_e15c66dc1b25da1b, []int{83}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{83}
|
||||
}
|
||||
func (m *StopRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StopRequest.Unmarshal(m, b)
|
||||
@ -6058,7 +6099,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_e15c66dc1b25da1b, []int{84}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{84}
|
||||
}
|
||||
func (m *StopResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StopResponse.Unmarshal(m, b)
|
||||
@ -6088,7 +6129,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_e15c66dc1b25da1b, []int{85}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{85}
|
||||
}
|
||||
func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GraphTopologySubscription.Unmarshal(m, b)
|
||||
@ -6121,7 +6162,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_e15c66dc1b25da1b, []int{86}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{86}
|
||||
}
|
||||
func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GraphTopologyUpdate.Unmarshal(m, b)
|
||||
@ -6176,7 +6217,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_e15c66dc1b25da1b, []int{87}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{87}
|
||||
}
|
||||
func (m *NodeUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeUpdate.Unmarshal(m, b)
|
||||
@ -6244,7 +6285,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_e15c66dc1b25da1b, []int{88}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{88}
|
||||
}
|
||||
func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEdgeUpdate.Unmarshal(m, b)
|
||||
@ -6324,7 +6365,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_e15c66dc1b25da1b, []int{89}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{89}
|
||||
}
|
||||
func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ClosedChannelUpdate.Unmarshal(m, b)
|
||||
@ -6394,7 +6435,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_e15c66dc1b25da1b, []int{90}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{90}
|
||||
}
|
||||
func (m *HopHint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_HopHint.Unmarshal(m, b)
|
||||
@ -6463,7 +6504,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_e15c66dc1b25da1b, []int{91}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{91}
|
||||
}
|
||||
func (m *RouteHint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RouteHint.Unmarshal(m, b)
|
||||
@ -6578,7 +6619,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_e15c66dc1b25da1b, []int{92}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{92}
|
||||
}
|
||||
func (m *Invoice) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Invoice.Unmarshal(m, b)
|
||||
@ -6770,7 +6811,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_e15c66dc1b25da1b, []int{93}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{93}
|
||||
}
|
||||
func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AddInvoiceResponse.Unmarshal(m, b)
|
||||
@ -6827,7 +6868,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_e15c66dc1b25da1b, []int{94}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{94}
|
||||
}
|
||||
func (m *PaymentHash) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PaymentHash.Unmarshal(m, b)
|
||||
@ -6883,7 +6924,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_e15c66dc1b25da1b, []int{95}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{95}
|
||||
}
|
||||
func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListInvoiceRequest.Unmarshal(m, b)
|
||||
@ -6953,7 +6994,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_e15c66dc1b25da1b, []int{96}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{96}
|
||||
}
|
||||
func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListInvoiceResponse.Unmarshal(m, b)
|
||||
@ -7016,7 +7057,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_e15c66dc1b25da1b, []int{97}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{97}
|
||||
}
|
||||
func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InvoiceSubscription.Unmarshal(m, b)
|
||||
@ -7076,7 +7117,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_e15c66dc1b25da1b, []int{98}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{98}
|
||||
}
|
||||
func (m *Payment) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Payment.Unmarshal(m, b)
|
||||
@ -7163,7 +7204,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_e15c66dc1b25da1b, []int{99}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{99}
|
||||
}
|
||||
func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPaymentsRequest.Unmarshal(m, b)
|
||||
@ -7195,7 +7236,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_e15c66dc1b25da1b, []int{100}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{100}
|
||||
}
|
||||
func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPaymentsResponse.Unmarshal(m, b)
|
||||
@ -7232,7 +7273,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_e15c66dc1b25da1b, []int{101}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{101}
|
||||
}
|
||||
func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DeleteAllPaymentsRequest.Unmarshal(m, b)
|
||||
@ -7262,7 +7303,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_e15c66dc1b25da1b, []int{102}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{102}
|
||||
}
|
||||
func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DeleteAllPaymentsResponse.Unmarshal(m, b)
|
||||
@ -7293,7 +7334,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_e15c66dc1b25da1b, []int{103}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{103}
|
||||
}
|
||||
func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AbandonChannelRequest.Unmarshal(m, b)
|
||||
@ -7330,7 +7371,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_e15c66dc1b25da1b, []int{104}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{104}
|
||||
}
|
||||
func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AbandonChannelResponse.Unmarshal(m, b)
|
||||
@ -7362,7 +7403,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_e15c66dc1b25da1b, []int{105}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{105}
|
||||
}
|
||||
func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DebugLevelRequest.Unmarshal(m, b)
|
||||
@ -7407,7 +7448,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_e15c66dc1b25da1b, []int{106}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{106}
|
||||
}
|
||||
func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DebugLevelResponse.Unmarshal(m, b)
|
||||
@ -7446,7 +7487,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_e15c66dc1b25da1b, []int{107}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{107}
|
||||
}
|
||||
func (m *PayReqString) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PayReqString.Unmarshal(m, b)
|
||||
@ -7493,7 +7534,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_e15c66dc1b25da1b, []int{108}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{108}
|
||||
}
|
||||
func (m *PayReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PayReq.Unmarshal(m, b)
|
||||
@ -7593,7 +7634,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_e15c66dc1b25da1b, []int{109}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{109}
|
||||
}
|
||||
func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FeeReportRequest.Unmarshal(m, b)
|
||||
@ -7631,7 +7672,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_e15c66dc1b25da1b, []int{110}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{110}
|
||||
}
|
||||
func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelFeeReport.Unmarshal(m, b)
|
||||
@ -7697,7 +7738,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_e15c66dc1b25da1b, []int{111}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{111}
|
||||
}
|
||||
func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FeeReportResponse.Unmarshal(m, b)
|
||||
@ -7765,7 +7806,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_e15c66dc1b25da1b, []int{112}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{112}
|
||||
}
|
||||
func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PolicyUpdateRequest.Unmarshal(m, b)
|
||||
@ -7926,7 +7967,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_e15c66dc1b25da1b, []int{113}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{113}
|
||||
}
|
||||
func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PolicyUpdateResponse.Unmarshal(m, b)
|
||||
@ -7964,7 +8005,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_e15c66dc1b25da1b, []int{114}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{114}
|
||||
}
|
||||
func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ForwardingHistoryRequest.Unmarshal(m, b)
|
||||
@ -8036,7 +8077,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_e15c66dc1b25da1b, []int{115}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{115}
|
||||
}
|
||||
func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ForwardingEvent.Unmarshal(m, b)
|
||||
@ -8119,7 +8160,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_e15c66dc1b25da1b, []int{116}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{116}
|
||||
}
|
||||
func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ForwardingHistoryResponse.Unmarshal(m, b)
|
||||
@ -8165,7 +8206,7 @@ func (m *ExportChannelBackupRequest) Reset() { *m = ExportChannelBackupR
|
||||
func (m *ExportChannelBackupRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExportChannelBackupRequest) ProtoMessage() {}
|
||||
func (*ExportChannelBackupRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{117}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{117}
|
||||
}
|
||||
func (m *ExportChannelBackupRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ExportChannelBackupRequest.Unmarshal(m, b)
|
||||
@ -8210,7 +8251,7 @@ func (m *ChannelBackup) Reset() { *m = ChannelBackup{} }
|
||||
func (m *ChannelBackup) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelBackup) ProtoMessage() {}
|
||||
func (*ChannelBackup) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{118}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{118}
|
||||
}
|
||||
func (m *ChannelBackup) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelBackup.Unmarshal(m, b)
|
||||
@ -8262,7 +8303,7 @@ func (m *MultiChanBackup) Reset() { *m = MultiChanBackup{} }
|
||||
func (m *MultiChanBackup) String() string { return proto.CompactTextString(m) }
|
||||
func (*MultiChanBackup) ProtoMessage() {}
|
||||
func (*MultiChanBackup) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{119}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{119}
|
||||
}
|
||||
func (m *MultiChanBackup) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_MultiChanBackup.Unmarshal(m, b)
|
||||
@ -8306,7 +8347,7 @@ func (m *ChanBackupExportRequest) Reset() { *m = ChanBackupExportRequest
|
||||
func (m *ChanBackupExportRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChanBackupExportRequest) ProtoMessage() {}
|
||||
func (*ChanBackupExportRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{120}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{120}
|
||||
}
|
||||
func (m *ChanBackupExportRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChanBackupExportRequest.Unmarshal(m, b)
|
||||
@ -8344,7 +8385,7 @@ func (m *ChanBackupSnapshot) Reset() { *m = ChanBackupSnapshot{} }
|
||||
func (m *ChanBackupSnapshot) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChanBackupSnapshot) ProtoMessage() {}
|
||||
func (*ChanBackupSnapshot) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{121}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{121}
|
||||
}
|
||||
func (m *ChanBackupSnapshot) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChanBackupSnapshot.Unmarshal(m, b)
|
||||
@ -8391,7 +8432,7 @@ func (m *ChannelBackups) Reset() { *m = ChannelBackups{} }
|
||||
func (m *ChannelBackups) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelBackups) ProtoMessage() {}
|
||||
func (*ChannelBackups) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{122}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{122}
|
||||
}
|
||||
func (m *ChannelBackups) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelBackups.Unmarshal(m, b)
|
||||
@ -8432,7 +8473,7 @@ func (m *RestoreChanBackupRequest) Reset() { *m = RestoreChanBackupReque
|
||||
func (m *RestoreChanBackupRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RestoreChanBackupRequest) ProtoMessage() {}
|
||||
func (*RestoreChanBackupRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{123}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{123}
|
||||
}
|
||||
func (m *RestoreChanBackupRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RestoreChanBackupRequest.Unmarshal(m, b)
|
||||
@ -8569,7 +8610,7 @@ func (m *RestoreBackupResponse) Reset() { *m = RestoreBackupResponse{} }
|
||||
func (m *RestoreBackupResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RestoreBackupResponse) ProtoMessage() {}
|
||||
func (*RestoreBackupResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{124}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{124}
|
||||
}
|
||||
func (m *RestoreBackupResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RestoreBackupResponse.Unmarshal(m, b)
|
||||
@ -8599,7 +8640,7 @@ func (m *ChannelBackupSubscription) Reset() { *m = ChannelBackupSubscrip
|
||||
func (m *ChannelBackupSubscription) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelBackupSubscription) ProtoMessage() {}
|
||||
func (*ChannelBackupSubscription) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{125}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{125}
|
||||
}
|
||||
func (m *ChannelBackupSubscription) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelBackupSubscription.Unmarshal(m, b)
|
||||
@ -8631,7 +8672,7 @@ func (m *VerifyChanBackupResponse) Reset() { *m = VerifyChanBackupRespon
|
||||
func (m *VerifyChanBackupResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*VerifyChanBackupResponse) ProtoMessage() {}
|
||||
func (*VerifyChanBackupResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_e15c66dc1b25da1b, []int{126}
|
||||
return fileDescriptor_rpc_854431eb46daab93, []int{126}
|
||||
}
|
||||
func (m *VerifyChanBackupResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VerifyChanBackupResponse.Unmarshal(m, b)
|
||||
@ -8802,6 +8843,7 @@ func init() {
|
||||
proto.RegisterType((*VerifyChanBackupResponse)(nil), "lnrpc.VerifyChanBackupResponse")
|
||||
proto.RegisterEnum("lnrpc.AddressType", AddressType_name, AddressType_value)
|
||||
proto.RegisterEnum("lnrpc.ChannelCloseSummary_ClosureType", ChannelCloseSummary_ClosureType_name, ChannelCloseSummary_ClosureType_value)
|
||||
proto.RegisterEnum("lnrpc.Peer_SyncType", Peer_SyncType_name, Peer_SyncType_value)
|
||||
proto.RegisterEnum("lnrpc.ChannelEventUpdate_UpdateType", ChannelEventUpdate_UpdateType_name, ChannelEventUpdate_UpdateType_value)
|
||||
proto.RegisterEnum("lnrpc.Invoice_InvoiceState", Invoice_InvoiceState_name, Invoice_InvoiceState_value)
|
||||
}
|
||||
@ -11438,489 +11480,493 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{
|
||||
Metadata: "rpc.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_e15c66dc1b25da1b) }
|
||||
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_854431eb46daab93) }
|
||||
|
||||
var fileDescriptor_rpc_e15c66dc1b25da1b = []byte{
|
||||
// 7696 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7c, 0x5d, 0x6c, 0x1c, 0xc9,
|
||||
0x79, 0xa0, 0x7a, 0x7e, 0xc8, 0x99, 0x6f, 0x86, 0xc3, 0x61, 0xf1, 0x6f, 0x34, 0xd2, 0x6a, 0xb9,
|
||||
0x6d, 0x59, 0xa2, 0xb9, 0x7b, 0xa2, 0x56, 0xb6, 0xd7, 0xf2, 0xea, 0x7c, 0x77, 0xfc, 0x93, 0x28,
|
||||
0x9b, 0x4b, 0xd1, 0x4d, 0xc9, 0x3a, 0xaf, 0x7d, 0x18, 0x37, 0x67, 0x8a, 0xc3, 0x5e, 0xcd, 0x74,
|
||||
0xcf, 0x76, 0xf7, 0x90, 0xa2, 0xf7, 0x74, 0x38, 0x1c, 0x0e, 0x49, 0x10, 0x24, 0x08, 0x9c, 0x20,
|
||||
0x41, 0x1c, 0x24, 0x08, 0x60, 0x07, 0x48, 0x8c, 0x3c, 0xe5, 0xc1, 0x41, 0x80, 0xc4, 0x79, 0x0d,
|
||||
0x60, 0x20, 0x08, 0x02, 0x3f, 0x06, 0x08, 0x10, 0x24, 0x2f, 0x49, 0x1e, 0x82, 0x04, 0xc8, 0x63,
|
||||
0x80, 0xa0, 0xbe, 0xfa, 0xe9, 0xaa, 0xee, 0x1e, 0x51, 0x6b, 0x3b, 0x79, 0x9a, 0xa9, 0xaf, 0xbe,
|
||||
0xae, 0xdf, 0xef, 0xbf, 0xbe, 0x2a, 0xa8, 0x86, 0xa3, 0xee, 0xad, 0x51, 0x18, 0xc4, 0x01, 0x29,
|
||||
0x0f, 0xfc, 0x70, 0xd4, 0x6d, 0x5f, 0xed, 0x07, 0x41, 0x7f, 0x40, 0xd7, 0xdd, 0x91, 0xb7, 0xee,
|
||||
0xfa, 0x7e, 0x10, 0xbb, 0xb1, 0x17, 0xf8, 0x11, 0x47, 0xb2, 0xbf, 0x01, 0x8d, 0x07, 0xd4, 0x3f,
|
||||
0xa4, 0xb4, 0xe7, 0xd0, 0x0f, 0xc7, 0x34, 0x8a, 0xc9, 0x9b, 0x30, 0xe7, 0xd2, 0x6f, 0x52, 0xda,
|
||||
0xeb, 0x8c, 0xdc, 0x28, 0x1a, 0x9d, 0x84, 0x6e, 0x44, 0x5b, 0xd6, 0x8a, 0xb5, 0x5a, 0x77, 0x9a,
|
||||
0xbc, 0xe2, 0x40, 0xc1, 0xc9, 0x1b, 0x50, 0x8f, 0x18, 0x2a, 0xf5, 0xe3, 0x30, 0x18, 0x9d, 0xb7,
|
||||
0x0a, 0x88, 0x57, 0x63, 0xb0, 0x1d, 0x0e, 0xb2, 0x07, 0x30, 0xab, 0x7a, 0x88, 0x46, 0x81, 0x1f,
|
||||
0x51, 0x72, 0x1b, 0x16, 0xba, 0xde, 0xe8, 0x84, 0x86, 0x1d, 0xfc, 0x78, 0xe8, 0xd3, 0x61, 0xe0,
|
||||
0x7b, 0xdd, 0x96, 0xb5, 0x52, 0x5c, 0xad, 0x3a, 0x84, 0xd7, 0xb1, 0x2f, 0xde, 0x13, 0x35, 0xe4,
|
||||
0x26, 0xcc, 0x52, 0x9f, 0xc3, 0x69, 0x0f, 0xbf, 0x12, 0x5d, 0x35, 0x12, 0x30, 0xfb, 0xc0, 0xfe,
|
||||
0xb9, 0x02, 0xcc, 0x3d, 0xf4, 0xbd, 0xf8, 0xa9, 0x3b, 0x18, 0xd0, 0x58, 0xce, 0xe9, 0x26, 0xcc,
|
||||
0x9e, 0x21, 0x00, 0xe7, 0x74, 0x16, 0x84, 0x3d, 0x31, 0xa3, 0x06, 0x07, 0x1f, 0x08, 0xe8, 0xc4,
|
||||
0x91, 0x15, 0x26, 0x8e, 0x2c, 0x77, 0xb9, 0x8a, 0x13, 0x96, 0xeb, 0x26, 0xcc, 0x86, 0xb4, 0x1b,
|
||||
0x9c, 0xd2, 0xf0, 0xbc, 0x73, 0xe6, 0xf9, 0xbd, 0xe0, 0xac, 0x55, 0x5a, 0xb1, 0x56, 0xcb, 0x4e,
|
||||
0x43, 0x82, 0x9f, 0x22, 0x94, 0x6c, 0xc2, 0x6c, 0xf7, 0xc4, 0xf5, 0x7d, 0x3a, 0xe8, 0x1c, 0xb9,
|
||||
0xdd, 0x67, 0xe3, 0x51, 0xd4, 0x2a, 0xaf, 0x58, 0xab, 0xb5, 0x3b, 0x97, 0x6f, 0xe1, 0xae, 0xde,
|
||||
0xda, 0x3a, 0x71, 0xfd, 0x4d, 0xac, 0x39, 0xf4, 0xdd, 0x51, 0x74, 0x12, 0xc4, 0x4e, 0x43, 0x7c,
|
||||
0xc1, 0xc1, 0x91, 0xbd, 0x00, 0x44, 0x5f, 0x09, 0xbe, 0xf6, 0xf6, 0xef, 0x5b, 0x30, 0xff, 0xc4,
|
||||
0x1f, 0x04, 0xdd, 0x67, 0x3f, 0xe6, 0x12, 0xe5, 0xcc, 0xa1, 0xf0, 0xaa, 0x73, 0x28, 0x7e, 0xdc,
|
||||
0x39, 0x2c, 0xc1, 0x82, 0x39, 0x58, 0x31, 0x0b, 0x0a, 0x8b, 0xec, 0xeb, 0x3e, 0x95, 0xc3, 0x92,
|
||||
0xd3, 0xf8, 0x14, 0x34, 0xbb, 0xe3, 0x30, 0xa4, 0x7e, 0x66, 0x1e, 0xb3, 0x02, 0xae, 0x26, 0xf2,
|
||||
0x06, 0xd4, 0x7d, 0x7a, 0x96, 0xa0, 0x09, 0xda, 0xf5, 0xe9, 0x99, 0x44, 0xb1, 0x5b, 0xb0, 0x94,
|
||||
0xee, 0x46, 0x0c, 0xe0, 0x6f, 0x2c, 0x28, 0x3d, 0x89, 0x9f, 0x07, 0xe4, 0x16, 0x94, 0xe2, 0xf3,
|
||||
0x11, 0xe7, 0x90, 0xc6, 0x1d, 0x22, 0xa6, 0xb6, 0xd1, 0xeb, 0x85, 0x34, 0x8a, 0x1e, 0x9f, 0x8f,
|
||||
0xa8, 0x53, 0x77, 0x79, 0xa1, 0xc3, 0xf0, 0x48, 0x0b, 0xa6, 0x45, 0x19, 0x3b, 0xac, 0x3a, 0xb2,
|
||||
0x48, 0xae, 0x01, 0xb8, 0xc3, 0x60, 0xec, 0xc7, 0x9d, 0xc8, 0x8d, 0x71, 0xa9, 0x8a, 0x8e, 0x06,
|
||||
0x21, 0x57, 0xa1, 0x3a, 0x7a, 0xd6, 0x89, 0xba, 0xa1, 0x37, 0x8a, 0x91, 0x6c, 0xaa, 0x4e, 0x02,
|
||||
0x20, 0x6f, 0x42, 0x25, 0x18, 0xc7, 0xa3, 0xc0, 0xf3, 0x63, 0x41, 0x2a, 0xb3, 0x62, 0x2c, 0x8f,
|
||||
0xc6, 0xf1, 0x01, 0x03, 0x3b, 0x0a, 0x81, 0x5c, 0x87, 0x99, 0x6e, 0xe0, 0x1f, 0x7b, 0xe1, 0x90,
|
||||
0x0b, 0x83, 0xd6, 0x14, 0xf6, 0x66, 0x02, 0xed, 0x6f, 0x17, 0xa0, 0xf6, 0x38, 0x74, 0xfd, 0xc8,
|
||||
0xed, 0x32, 0x00, 0x1b, 0x7a, 0xfc, 0xbc, 0x73, 0xe2, 0x46, 0x27, 0x38, 0xdb, 0xaa, 0x23, 0x8b,
|
||||
0x64, 0x09, 0xa6, 0xf8, 0x40, 0x71, 0x4e, 0x45, 0x47, 0x94, 0xc8, 0x5b, 0x30, 0xe7, 0x8f, 0x87,
|
||||
0x1d, 0xb3, 0xaf, 0x22, 0x52, 0x4b, 0xb6, 0x82, 0x2d, 0xc0, 0x11, 0xdb, 0x6b, 0xde, 0x05, 0x9f,
|
||||
0xa1, 0x06, 0x21, 0x36, 0xd4, 0x45, 0x89, 0x7a, 0xfd, 0x13, 0x3e, 0xcd, 0xb2, 0x63, 0xc0, 0x58,
|
||||
0x1b, 0xb1, 0x37, 0xa4, 0x9d, 0x28, 0x76, 0x87, 0x23, 0x31, 0x2d, 0x0d, 0x82, 0xf5, 0x41, 0xec,
|
||||
0x0e, 0x3a, 0xc7, 0x94, 0x46, 0xad, 0x69, 0x51, 0xaf, 0x20, 0xe4, 0x06, 0x34, 0x7a, 0x34, 0x8a,
|
||||
0x3b, 0x62, 0x53, 0x68, 0xd4, 0xaa, 0x20, 0xeb, 0xa7, 0xa0, 0x8c, 0x32, 0x1e, 0xd0, 0x58, 0x5b,
|
||||
0x9d, 0x48, 0x50, 0xa0, 0xbd, 0x07, 0x44, 0x03, 0x6f, 0xd3, 0xd8, 0xf5, 0x06, 0x11, 0x79, 0x07,
|
||||
0xea, 0xb1, 0x86, 0x8c, 0xa2, 0xae, 0xa6, 0xc8, 0x45, 0xfb, 0xc0, 0x31, 0xf0, 0xec, 0x07, 0x50,
|
||||
0xb9, 0x4f, 0xe9, 0x9e, 0x37, 0xf4, 0x62, 0xb2, 0x04, 0xe5, 0x63, 0xef, 0x39, 0xe5, 0x04, 0x5d,
|
||||
0xdc, 0xbd, 0xe4, 0xf0, 0x22, 0x69, 0xc3, 0xf4, 0x88, 0x86, 0x5d, 0x2a, 0x97, 0x7f, 0xf7, 0x92,
|
||||
0x23, 0x01, 0x9b, 0xd3, 0x50, 0x1e, 0xb0, 0x8f, 0xed, 0x7f, 0x2e, 0x40, 0xed, 0x90, 0xfa, 0x8a,
|
||||
0x51, 0x08, 0x94, 0xd8, 0x94, 0x04, 0x73, 0xe0, 0x7f, 0xf2, 0x3a, 0xd4, 0x70, 0x9a, 0x51, 0x1c,
|
||||
0x7a, 0x7e, 0x5f, 0xd0, 0x27, 0x30, 0xd0, 0x21, 0x42, 0x48, 0x13, 0x8a, 0xee, 0x50, 0xd2, 0x26,
|
||||
0xfb, 0xcb, 0x98, 0x68, 0xe4, 0x9e, 0x0f, 0x19, 0xbf, 0xa9, 0x5d, 0xab, 0x3b, 0x35, 0x01, 0xdb,
|
||||
0x65, 0xdb, 0x76, 0x0b, 0xe6, 0x75, 0x14, 0xd9, 0x7a, 0x19, 0x5b, 0x9f, 0xd3, 0x30, 0x45, 0x27,
|
||||
0x37, 0x61, 0x56, 0xe2, 0x87, 0x7c, 0xb0, 0xb8, 0x8f, 0x55, 0xa7, 0x21, 0xc0, 0x72, 0x0a, 0xab,
|
||||
0xd0, 0x3c, 0xf6, 0x7c, 0x77, 0xd0, 0xe9, 0x0e, 0xe2, 0xd3, 0x4e, 0x8f, 0x0e, 0x62, 0x17, 0x77,
|
||||
0xb4, 0xec, 0x34, 0x10, 0xbe, 0x35, 0x88, 0x4f, 0xb7, 0x19, 0x94, 0xbc, 0x05, 0xd5, 0x63, 0x4a,
|
||||
0x3b, 0xb8, 0x12, 0xad, 0x8a, 0xc1, 0x1d, 0x72, 0x75, 0x9d, 0xca, 0xb1, 0x5c, 0xe7, 0x55, 0x68,
|
||||
0x06, 0xe3, 0xb8, 0x1f, 0x78, 0x7e, 0xbf, 0xc3, 0xe4, 0x51, 0xc7, 0xeb, 0xb5, 0xaa, 0x2b, 0xd6,
|
||||
0x6a, 0xc9, 0x69, 0x48, 0x38, 0x93, 0x0a, 0x0f, 0x7b, 0xe4, 0x35, 0x00, 0xec, 0x9b, 0x37, 0x0c,
|
||||
0x2b, 0xd6, 0xea, 0x8c, 0x53, 0x65, 0x10, 0x6c, 0xc8, 0xfe, 0x23, 0x0b, 0xea, 0x7c, 0xcd, 0x85,
|
||||
0xe2, 0xbb, 0x0e, 0x33, 0x72, 0x6a, 0x34, 0x0c, 0x83, 0x50, 0xf0, 0x91, 0x09, 0x24, 0x6b, 0xd0,
|
||||
0x94, 0x80, 0x51, 0x48, 0xbd, 0xa1, 0xdb, 0xa7, 0x42, 0x38, 0x65, 0xe0, 0xe4, 0x4e, 0xd2, 0x62,
|
||||
0x18, 0x8c, 0x63, 0x2a, 0x44, 0x6c, 0x5d, 0xcc, 0xce, 0x61, 0x30, 0xc7, 0x44, 0x61, 0x7c, 0x94,
|
||||
0xb3, 0x67, 0x06, 0xcc, 0xfe, 0xbe, 0x05, 0x84, 0x0d, 0xfd, 0x71, 0xc0, 0x9b, 0x10, 0x4b, 0x9e,
|
||||
0xde, 0x6e, 0xeb, 0x95, 0xb7, 0xbb, 0x30, 0x69, 0xbb, 0x57, 0x61, 0x0a, 0x87, 0xc5, 0x04, 0x43,
|
||||
0x31, 0x3d, 0xf4, 0xcd, 0x42, 0xcb, 0x72, 0x44, 0x3d, 0xb1, 0xa1, 0xcc, 0xe7, 0x58, 0xca, 0x99,
|
||||
0x23, 0xaf, 0xb2, 0xbf, 0x63, 0x41, 0x7d, 0x8b, 0xeb, 0x10, 0x14, 0x7a, 0xe4, 0x36, 0x90, 0xe3,
|
||||
0xb1, 0xdf, 0x63, 0x7b, 0x19, 0x3f, 0xf7, 0x7a, 0x9d, 0xa3, 0x73, 0xd6, 0x15, 0x8e, 0x7b, 0xf7,
|
||||
0x92, 0x93, 0x53, 0x47, 0xde, 0x82, 0xa6, 0x01, 0x8d, 0xe2, 0x90, 0x8f, 0x7e, 0xf7, 0x92, 0x93,
|
||||
0xa9, 0x61, 0x8b, 0xc9, 0xc4, 0xea, 0x38, 0xee, 0x78, 0x7e, 0x8f, 0x3e, 0xc7, 0xf5, 0x9f, 0x71,
|
||||
0x0c, 0xd8, 0x66, 0x03, 0xea, 0xfa, 0x77, 0xf6, 0x07, 0x50, 0x91, 0x42, 0x19, 0x05, 0x52, 0x6a,
|
||||
0x5c, 0x8e, 0x06, 0x21, 0x6d, 0xa8, 0x98, 0xa3, 0x70, 0x2a, 0x1f, 0xa7, 0x6f, 0xfb, 0xbf, 0x41,
|
||||
0x73, 0x8f, 0x49, 0x46, 0xdf, 0xf3, 0xfb, 0x42, 0x2b, 0x31, 0x71, 0x3d, 0x1a, 0x1f, 0x3d, 0xa3,
|
||||
0xe7, 0x82, 0xfe, 0x44, 0x89, 0xc9, 0x84, 0x93, 0x20, 0x8a, 0x45, 0x3f, 0xf8, 0xdf, 0xfe, 0x33,
|
||||
0x0b, 0xc8, 0x4e, 0x14, 0x7b, 0x43, 0x37, 0xa6, 0xf7, 0xa9, 0x22, 0x84, 0x47, 0x50, 0x67, 0xad,
|
||||
0x3d, 0x0e, 0x36, 0xb8, 0xdc, 0xe7, 0xf2, 0xec, 0x4d, 0xb1, 0x25, 0xd9, 0x0f, 0x6e, 0xe9, 0xd8,
|
||||
0xcc, 0x34, 0x3c, 0x77, 0x8c, 0x06, 0x98, 0xec, 0x89, 0xdd, 0xb0, 0x4f, 0x63, 0x54, 0x0a, 0xc2,
|
||||
0xa4, 0x00, 0x0e, 0xda, 0x0a, 0xfc, 0xe3, 0xf6, 0x7f, 0x87, 0xb9, 0x4c, 0x1b, 0x4c, 0x20, 0x25,
|
||||
0xd3, 0x60, 0x7f, 0xc9, 0x02, 0x94, 0x4f, 0xdd, 0xc1, 0x98, 0x0a, 0x4d, 0xc4, 0x0b, 0xef, 0x16,
|
||||
0xee, 0x5a, 0x76, 0x17, 0xe6, 0x8d, 0x71, 0x09, 0x9e, 0x6c, 0xc1, 0x34, 0x93, 0x0d, 0x4c, 0xe7,
|
||||
0xa2, 0x5c, 0x75, 0x64, 0x91, 0xdc, 0x81, 0x85, 0x63, 0x4a, 0x43, 0x37, 0xc6, 0x62, 0x67, 0x44,
|
||||
0x43, 0xdc, 0x13, 0xd1, 0x72, 0x6e, 0x9d, 0xfd, 0xb7, 0x16, 0xcc, 0x32, 0xbe, 0x79, 0xcf, 0xf5,
|
||||
0xcf, 0xe5, 0x5a, 0xed, 0xe5, 0xae, 0xd5, 0xaa, 0x58, 0xab, 0x14, 0xf6, 0xc7, 0x5d, 0xa8, 0x62,
|
||||
0x7a, 0xa1, 0xc8, 0x0a, 0xd4, 0x8d, 0xe1, 0x96, 0xb9, 0x92, 0x8b, 0xdc, 0xf8, 0x80, 0x86, 0x9b,
|
||||
0xe7, 0x31, 0xfd, 0xc9, 0x97, 0xf2, 0x06, 0x34, 0x93, 0x61, 0x8b, 0x75, 0x24, 0x50, 0x62, 0x84,
|
||||
0x29, 0x1a, 0xc0, 0xff, 0xf6, 0x6f, 0x5a, 0x1c, 0x71, 0x2b, 0xf0, 0x94, 0x82, 0x64, 0x88, 0x4c,
|
||||
0x8f, 0x4a, 0x44, 0xf6, 0x7f, 0xa2, 0x01, 0xf1, 0x93, 0x4f, 0x96, 0x5c, 0x86, 0x4a, 0x44, 0xfd,
|
||||
0x5e, 0xc7, 0x1d, 0x0c, 0x50, 0x8f, 0x54, 0x9c, 0x69, 0x56, 0xde, 0x18, 0x0c, 0xec, 0x9b, 0x30,
|
||||
0xa7, 0x8d, 0xee, 0x25, 0xf3, 0xd8, 0x07, 0xb2, 0xe7, 0x45, 0xf1, 0x13, 0x3f, 0x1a, 0x69, 0xfa,
|
||||
0xe7, 0x0a, 0x54, 0x87, 0x9e, 0x8f, 0x23, 0xe3, 0x9c, 0x5b, 0x76, 0x2a, 0x43, 0xcf, 0x67, 0xe3,
|
||||
0x8a, 0xb0, 0xd2, 0x7d, 0x2e, 0x2a, 0x0b, 0xa2, 0xd2, 0x7d, 0x8e, 0x95, 0xf6, 0x5d, 0x98, 0x37,
|
||||
0xda, 0x13, 0x5d, 0xbf, 0x01, 0xe5, 0x71, 0xfc, 0x3c, 0x90, 0xd6, 0x41, 0x4d, 0x50, 0x08, 0xb3,
|
||||
0x33, 0x1d, 0x5e, 0x63, 0xdf, 0x83, 0xb9, 0x7d, 0x7a, 0x26, 0x18, 0x59, 0x0e, 0xe4, 0xc6, 0x85,
|
||||
0x36, 0x28, 0xd6, 0xdb, 0xb7, 0x80, 0xe8, 0x1f, 0x27, 0x0c, 0x20, 0x2d, 0x52, 0xcb, 0xb0, 0x48,
|
||||
0xed, 0x1b, 0x40, 0x0e, 0xbd, 0xbe, 0xff, 0x1e, 0x8d, 0x22, 0xb7, 0xaf, 0x58, 0xbf, 0x09, 0xc5,
|
||||
0x61, 0xd4, 0x17, 0xa2, 0x8a, 0xfd, 0xb5, 0x3f, 0x0d, 0xf3, 0x06, 0x9e, 0x68, 0xf8, 0x2a, 0x54,
|
||||
0x23, 0xaf, 0xef, 0xbb, 0xf1, 0x38, 0xa4, 0xa2, 0xe9, 0x04, 0x60, 0xdf, 0x87, 0x85, 0xaf, 0xd0,
|
||||
0xd0, 0x3b, 0x3e, 0xbf, 0xa8, 0x79, 0xb3, 0x9d, 0x42, 0xba, 0x9d, 0x1d, 0x58, 0x4c, 0xb5, 0x23,
|
||||
0xba, 0xe7, 0xe4, 0x2b, 0x76, 0xb2, 0xe2, 0xf0, 0x82, 0x26, 0xfb, 0x0a, 0xba, 0xec, 0xb3, 0x9f,
|
||||
0x00, 0xd9, 0x0a, 0x7c, 0x9f, 0x76, 0xe3, 0x03, 0x4a, 0xc3, 0xc4, 0x19, 0x4e, 0x68, 0xb5, 0x76,
|
||||
0x67, 0x59, 0xac, 0x6c, 0x5a, 0xa0, 0x0a, 0x22, 0x26, 0x50, 0x1a, 0xd1, 0x70, 0x88, 0x0d, 0x57,
|
||||
0x1c, 0xfc, 0x6f, 0x2f, 0xc2, 0xbc, 0xd1, 0xac, 0x70, 0x1f, 0xde, 0x86, 0xc5, 0x6d, 0x2f, 0xea,
|
||||
0x66, 0x3b, 0x6c, 0xc1, 0xf4, 0x68, 0x7c, 0xd4, 0x49, 0x38, 0x51, 0x16, 0x99, 0xc5, 0x99, 0xfe,
|
||||
0x44, 0x34, 0xf6, 0x33, 0x16, 0x94, 0x76, 0x1f, 0xef, 0x6d, 0x31, 0x5d, 0xe1, 0xf9, 0xdd, 0x60,
|
||||
0xc8, 0xf4, 0x2d, 0x9f, 0xb4, 0x2a, 0x4f, 0xe4, 0xb0, 0xab, 0x50, 0x45, 0x35, 0xcd, 0x8c, 0x68,
|
||||
0xe1, 0xb7, 0x26, 0x00, 0x66, 0xc0, 0xd3, 0xe7, 0x23, 0x2f, 0x44, 0x0b, 0x5d, 0xda, 0xdd, 0x25,
|
||||
0x54, 0x33, 0xd9, 0x0a, 0xfb, 0x87, 0x65, 0x98, 0x16, 0xca, 0x17, 0xfb, 0xeb, 0xc6, 0xde, 0x29,
|
||||
0x15, 0x23, 0x11, 0x25, 0x66, 0x02, 0x85, 0x74, 0x18, 0xc4, 0xb4, 0x63, 0x6c, 0x83, 0x09, 0x44,
|
||||
0x07, 0x45, 0xf8, 0x8e, 0xdc, 0xa5, 0x29, 0x72, 0x2c, 0x03, 0xc8, 0x16, 0x4b, 0xda, 0x67, 0x25,
|
||||
0xb4, 0xcf, 0x64, 0x91, 0xad, 0x44, 0xd7, 0x1d, 0xb9, 0x5d, 0x2f, 0x3e, 0x17, 0x22, 0x41, 0x95,
|
||||
0x59, 0xdb, 0x83, 0xa0, 0xeb, 0x32, 0xaf, 0x74, 0xe0, 0xfa, 0x5d, 0x2a, 0x9d, 0x1f, 0x03, 0xc8,
|
||||
0x1c, 0x01, 0x31, 0x24, 0x89, 0xc6, 0x9d, 0x85, 0x14, 0x94, 0xe9, 0xef, 0x6e, 0x30, 0x1c, 0x7a,
|
||||
0x31, 0xf3, 0x1f, 0xd0, 0xb6, 0x2c, 0x3a, 0x1a, 0x84, 0xbb, 0x5a, 0x58, 0x3a, 0xe3, 0xab, 0x57,
|
||||
0x95, 0xae, 0x96, 0x06, 0x64, 0xad, 0x30, 0xad, 0xc3, 0xc4, 0xd8, 0xb3, 0x33, 0x34, 0x24, 0x8b,
|
||||
0x8e, 0x06, 0x61, 0xfb, 0x30, 0xf6, 0x23, 0x1a, 0xc7, 0x03, 0xda, 0x53, 0x03, 0xaa, 0x21, 0x5a,
|
||||
0xb6, 0x82, 0xdc, 0x86, 0x79, 0xee, 0xd2, 0x44, 0x6e, 0x1c, 0x44, 0x27, 0x5e, 0xd4, 0x89, 0x98,
|
||||
0x73, 0x50, 0x47, 0xfc, 0xbc, 0x2a, 0x72, 0x17, 0x96, 0x53, 0xe0, 0x90, 0x76, 0xa9, 0x77, 0x4a,
|
||||
0x7b, 0xad, 0x19, 0xfc, 0x6a, 0x52, 0x35, 0x59, 0x81, 0x1a, 0xf3, 0xe4, 0xc6, 0xa3, 0x9e, 0xcb,
|
||||
0x0c, 0x98, 0x06, 0xee, 0x83, 0x0e, 0x22, 0x6f, 0xc3, 0xcc, 0x88, 0x72, 0xeb, 0xe7, 0x24, 0x1e,
|
||||
0x74, 0xa3, 0xd6, 0xac, 0x21, 0xdd, 0x18, 0xe5, 0x3a, 0x26, 0x06, 0x23, 0xca, 0x6e, 0x84, 0x26,
|
||||
0xbd, 0x7b, 0xde, 0x6a, 0x0a, 0xb3, 0x5a, 0x02, 0x90, 0x47, 0x42, 0xef, 0xd4, 0x8d, 0x69, 0x6b,
|
||||
0x8e, 0x0b, 0x74, 0x51, 0x64, 0xdf, 0x79, 0xbe, 0x17, 0x7b, 0x6e, 0x1c, 0x84, 0x2d, 0x82, 0x75,
|
||||
0x09, 0x80, 0x2d, 0x22, 0xd2, 0x47, 0x14, 0xbb, 0xf1, 0x38, 0xea, 0x1c, 0x0f, 0xdc, 0x7e, 0xd4,
|
||||
0x9a, 0xe7, 0x76, 0x69, 0xa6, 0xc2, 0xfe, 0x6d, 0x8b, 0x0b, 0x69, 0x41, 0xd0, 0x4a, 0xd8, 0xbe,
|
||||
0x0e, 0x35, 0x4e, 0xca, 0x9d, 0xc0, 0x1f, 0x9c, 0x0b, 0xea, 0x06, 0x0e, 0x7a, 0xe4, 0x0f, 0xce,
|
||||
0xc9, 0x27, 0x60, 0xc6, 0xf3, 0x75, 0x14, 0x2e, 0x0f, 0xea, 0x12, 0x88, 0x48, 0xaf, 0x43, 0x6d,
|
||||
0x34, 0x3e, 0x1a, 0x78, 0x5d, 0x8e, 0x52, 0xe4, 0xad, 0x70, 0x10, 0x22, 0x30, 0x4b, 0x9b, 0xcf,
|
||||
0x8a, 0x63, 0x94, 0x10, 0xa3, 0x26, 0x60, 0x0c, 0xc5, 0xde, 0x84, 0x05, 0x73, 0x80, 0x42, 0xf0,
|
||||
0xad, 0x41, 0x45, 0xf0, 0x49, 0xd4, 0xaa, 0xe1, 0x5a, 0x37, 0xb4, 0x88, 0x8b, 0x4f, 0x07, 0x8e,
|
||||
0xaa, 0xb7, 0xff, 0xb0, 0x04, 0xf3, 0x02, 0xba, 0x35, 0x08, 0x22, 0x7a, 0x38, 0x1e, 0x0e, 0xdd,
|
||||
0x30, 0x87, 0x01, 0xad, 0x0b, 0x18, 0xb0, 0x60, 0x32, 0x20, 0x63, 0x8b, 0x13, 0xd7, 0xf3, 0xb9,
|
||||
0x9b, 0xc0, 0xb9, 0x57, 0x83, 0x90, 0x55, 0x98, 0xed, 0x0e, 0x82, 0x88, 0x9b, 0xc4, 0xba, 0xc3,
|
||||
0x9f, 0x06, 0x67, 0x05, 0x46, 0x39, 0x4f, 0x60, 0xe8, 0x0c, 0x3f, 0x95, 0x62, 0x78, 0x1b, 0xea,
|
||||
0xac, 0x51, 0x2a, 0xe5, 0xd7, 0x34, 0x37, 0x93, 0x75, 0x18, 0x1b, 0x4f, 0x9a, 0xbd, 0x38, 0x2f,
|
||||
0xcf, 0xe6, 0x31, 0x97, 0x37, 0xa4, 0x28, 0x1f, 0x35, 0xec, 0xaa, 0x60, 0xae, 0x6c, 0x15, 0xb9,
|
||||
0xcf, 0xbc, 0x44, 0xd6, 0x17, 0x2a, 0x69, 0x40, 0x25, 0x7d, 0xc3, 0xdc, 0x11, 0x7d, 0xed, 0x6f,
|
||||
0xb1, 0xc2, 0x38, 0xa4, 0xa8, 0xb8, 0xb5, 0x2f, 0xed, 0x9f, 0xb7, 0xa0, 0xa6, 0xd5, 0x91, 0x45,
|
||||
0x98, 0xdb, 0x7a, 0xf4, 0xe8, 0x60, 0xc7, 0xd9, 0x78, 0xfc, 0xf0, 0x2b, 0x3b, 0x9d, 0xad, 0xbd,
|
||||
0x47, 0x87, 0x3b, 0xcd, 0x4b, 0x0c, 0xbc, 0xf7, 0x68, 0x6b, 0x63, 0xaf, 0x73, 0xff, 0x91, 0xb3,
|
||||
0x25, 0xc1, 0x16, 0x59, 0x02, 0xe2, 0xec, 0xbc, 0xf7, 0xe8, 0xf1, 0x8e, 0x01, 0x2f, 0x90, 0x26,
|
||||
0xd4, 0x37, 0x9d, 0x9d, 0x8d, 0xad, 0x5d, 0x01, 0x29, 0x92, 0x05, 0x68, 0xde, 0x7f, 0xb2, 0xbf,
|
||||
0xfd, 0x70, 0xff, 0x41, 0x67, 0x6b, 0x63, 0x7f, 0x6b, 0x67, 0x6f, 0x67, 0xbb, 0x59, 0x22, 0x33,
|
||||
0x50, 0xdd, 0xd8, 0xdc, 0xd8, 0xdf, 0x7e, 0xb4, 0xbf, 0xb3, 0xdd, 0x2c, 0xdb, 0x7f, 0x6d, 0xc1,
|
||||
0x22, 0x8e, 0xba, 0x97, 0x66, 0x90, 0x15, 0xa8, 0x75, 0x83, 0x60, 0xc4, 0x8c, 0xe3, 0x44, 0xfc,
|
||||
0xeb, 0x20, 0x46, 0xfc, 0x5c, 0xd8, 0x1e, 0x07, 0x61, 0x97, 0x0a, 0xfe, 0x00, 0x04, 0xdd, 0x67,
|
||||
0x10, 0x46, 0xfc, 0x62, 0x7b, 0x39, 0x06, 0x67, 0x8f, 0x1a, 0x87, 0x71, 0x94, 0x25, 0x98, 0x3a,
|
||||
0x0a, 0xa9, 0xdb, 0x3d, 0x11, 0x9c, 0x21, 0x4a, 0xe4, 0x53, 0x89, 0xf7, 0xd6, 0x65, 0xab, 0x3f,
|
||||
0xa0, 0x3d, 0xa4, 0x98, 0x8a, 0x33, 0x2b, 0xe0, 0x5b, 0x02, 0xcc, 0xa4, 0x85, 0x7b, 0xe4, 0xfa,
|
||||
0xbd, 0xc0, 0xa7, 0x3d, 0x61, 0x1a, 0x26, 0x00, 0xfb, 0x00, 0x96, 0xd2, 0xf3, 0x13, 0xfc, 0xf5,
|
||||
0x8e, 0xc6, 0x5f, 0xdc, 0x52, 0x6b, 0x4f, 0xde, 0x4d, 0x8d, 0xd7, 0xfe, 0xc1, 0x82, 0x12, 0x53,
|
||||
0xdc, 0x93, 0x95, 0xbc, 0x6e, 0x8b, 0x15, 0x33, 0xd1, 0x41, 0x74, 0x08, 0xb9, 0x28, 0xe7, 0xea,
|
||||
0x4e, 0x83, 0x24, 0xf5, 0x21, 0xed, 0x9e, 0xe2, 0x8c, 0x55, 0x3d, 0x83, 0x30, 0x06, 0x61, 0x86,
|
||||
0x32, 0x7e, 0x2d, 0x18, 0x44, 0x96, 0x65, 0x1d, 0x7e, 0x39, 0x9d, 0xd4, 0xe1, 0x77, 0x2d, 0x98,
|
||||
0xf6, 0xfc, 0xa3, 0x60, 0xec, 0xf7, 0x90, 0x21, 0x2a, 0x8e, 0x2c, 0x62, 0x3c, 0x12, 0x19, 0xd5,
|
||||
0x1b, 0x4a, 0xf2, 0x4f, 0x00, 0x36, 0x61, 0x7e, 0x67, 0x84, 0x86, 0x8a, 0x0a, 0x8d, 0xbd, 0x03,
|
||||
0x73, 0x1a, 0x2c, 0x31, 0x7a, 0x47, 0x0c, 0x90, 0x32, 0x7a, 0xd1, 0xc2, 0xe1, 0x35, 0x76, 0x13,
|
||||
0x1a, 0x0f, 0x68, 0xfc, 0xd0, 0x3f, 0x0e, 0x64, 0x4b, 0xbf, 0x5b, 0x82, 0x59, 0x05, 0x12, 0x0d,
|
||||
0xad, 0xc2, 0xac, 0xd7, 0xa3, 0x7e, 0xec, 0xc5, 0xe7, 0x1d, 0xc3, 0xbd, 0x4d, 0x83, 0x99, 0x65,
|
||||
0xe8, 0x0e, 0x3c, 0x57, 0x46, 0x60, 0x79, 0x81, 0xb9, 0x7b, 0x4c, 0x6d, 0x49, 0x4d, 0xa4, 0xb6,
|
||||
0x98, 0x7b, 0xd5, 0xb9, 0x75, 0x4c, 0x18, 0x30, 0xb8, 0x90, 0xf6, 0xea, 0x13, 0x6e, 0x21, 0xe5,
|
||||
0x55, 0xb1, 0x55, 0xe3, 0x2d, 0xb1, 0x29, 0x97, 0xb9, 0x6a, 0x53, 0x80, 0x4c, 0x88, 0x73, 0x8a,
|
||||
0x8b, 0xaa, 0x74, 0x88, 0x53, 0x0b, 0x93, 0x56, 0x32, 0x61, 0x52, 0x26, 0xca, 0xce, 0xfd, 0x2e,
|
||||
0xed, 0x75, 0xe2, 0xa0, 0x83, 0x22, 0x17, 0x77, 0xa7, 0xe2, 0xa4, 0xc1, 0xe4, 0x2a, 0x4c, 0xc7,
|
||||
0x34, 0x8a, 0x7d, 0xca, 0x63, 0x57, 0x15, 0x8c, 0xb6, 0x48, 0x10, 0x33, 0x67, 0xc7, 0xa1, 0x17,
|
||||
0xb5, 0xea, 0x18, 0x00, 0xc5, 0xff, 0xe4, 0x33, 0xb0, 0x78, 0x44, 0xa3, 0xb8, 0x73, 0x42, 0xdd,
|
||||
0x1e, 0x0d, 0x71, 0xa7, 0x79, 0xa4, 0x95, 0x5b, 0x09, 0xf9, 0x95, 0x8c, 0x86, 0x4e, 0x69, 0x18,
|
||||
0x79, 0x81, 0x8f, 0xf6, 0x41, 0xd5, 0x91, 0x45, 0xd6, 0x1e, 0x9b, 0xbc, 0xd2, 0x97, 0x6a, 0x05,
|
||||
0x67, 0x71, 0xe2, 0xf9, 0x95, 0xe4, 0x3a, 0x4c, 0xe1, 0x04, 0xa2, 0x56, 0xd3, 0x08, 0x19, 0x6d,
|
||||
0x31, 0xa0, 0x23, 0xea, 0xbe, 0x58, 0xaa, 0xd4, 0x9a, 0x75, 0xfb, 0x73, 0x50, 0x46, 0x30, 0xdb,
|
||||
0x74, 0xbe, 0x18, 0x9c, 0x28, 0x78, 0x81, 0x0d, 0xcd, 0xa7, 0xf1, 0x59, 0x10, 0x3e, 0x93, 0xe1,
|
||||
0x78, 0x51, 0xb4, 0xbf, 0x89, 0x0e, 0x81, 0x0a, 0x4f, 0x3f, 0x41, 0x6b, 0x86, 0xb9, 0x75, 0x7c,
|
||||
0xa9, 0xa3, 0x13, 0x57, 0xf8, 0x28, 0x15, 0x04, 0x1c, 0x9e, 0xb8, 0x4c, 0x6c, 0x19, 0xbb, 0xc7,
|
||||
0xdd, 0xbe, 0x1a, 0xc2, 0x76, 0xf9, 0xe6, 0x5d, 0x87, 0x86, 0x0c, 0x7c, 0x47, 0x9d, 0x01, 0x3d,
|
||||
0x8e, 0x65, 0xd0, 0xc6, 0x1f, 0x0f, 0xd1, 0x37, 0xdc, 0xa3, 0xc7, 0xb1, 0xbd, 0x0f, 0x73, 0x42,
|
||||
0x94, 0x3c, 0x1a, 0x51, 0xd9, 0xf5, 0xe7, 0xf3, 0x54, 0x72, 0xed, 0xce, 0xbc, 0x29, 0x7b, 0x78,
|
||||
0xa8, 0xdf, 0xc4, 0xb4, 0x1d, 0x20, 0xba, 0x68, 0x12, 0x0d, 0x0a, 0xbd, 0x28, 0xc3, 0x52, 0x62,
|
||||
0x3a, 0x06, 0x8c, 0xad, 0x4f, 0x34, 0xee, 0x76, 0xe5, 0x71, 0x05, 0x73, 0x9e, 0x79, 0xd1, 0xfe,
|
||||
0x3d, 0x0b, 0xe6, 0xb1, 0x35, 0x69, 0x54, 0x08, 0xf1, 0x7f, 0xf7, 0x63, 0x0c, 0xb3, 0xde, 0xd5,
|
||||
0x43, 0x75, 0x0b, 0x50, 0xd6, 0x15, 0x02, 0x2f, 0x7c, 0xfc, 0x10, 0x40, 0x29, 0x1d, 0x02, 0xb0,
|
||||
0x7f, 0xdd, 0x82, 0x39, 0x2e, 0x93, 0xd1, 0xc0, 0x13, 0xd3, 0xff, 0xaf, 0x30, 0xc3, 0x95, 0xab,
|
||||
0xe0, 0x6a, 0x31, 0xd0, 0x05, 0x25, 0x80, 0x10, 0xca, 0x91, 0x77, 0x2f, 0x39, 0x26, 0x32, 0xb9,
|
||||
0x87, 0x06, 0x8e, 0xdf, 0x41, 0x68, 0xce, 0xc1, 0x96, 0xb9, 0xd6, 0xbb, 0x97, 0x1c, 0x0d, 0x7d,
|
||||
0xb3, 0x02, 0x53, 0xdc, 0x3a, 0xb6, 0x1f, 0xc0, 0x8c, 0xd1, 0x91, 0x11, 0x7e, 0xa8, 0xf3, 0xf0,
|
||||
0x43, 0x26, 0xce, 0x57, 0xc8, 0x89, 0xf3, 0xfd, 0x41, 0x11, 0x08, 0x23, 0x96, 0xd4, 0x6e, 0x30,
|
||||
0xf3, 0x3c, 0xe8, 0x19, 0xce, 0x56, 0xdd, 0xd1, 0x41, 0xe4, 0x16, 0x10, 0xad, 0x28, 0xc3, 0xb5,
|
||||
0x5c, 0xfb, 0xe4, 0xd4, 0x30, 0x31, 0x29, 0x94, 0xb7, 0x50, 0xb3, 0xc2, 0xad, 0xe4, 0xcb, 0x9e,
|
||||
0x5b, 0xc7, 0x14, 0xcc, 0x68, 0x1c, 0x9d, 0x60, 0x90, 0x4d, 0xb8, 0x63, 0xb2, 0x9c, 0xde, 0xdf,
|
||||
0xa9, 0x0b, 0xf7, 0x77, 0x3a, 0x13, 0xe2, 0xd1, 0x1c, 0x82, 0x8a, 0xe9, 0x10, 0x5c, 0x87, 0x99,
|
||||
0x21, 0x33, 0x39, 0xe3, 0x41, 0xb7, 0x33, 0x64, 0xbd, 0x0b, 0xef, 0xcb, 0x00, 0x92, 0x35, 0x68,
|
||||
0x0a, 0x73, 0x23, 0xf1, 0x3a, 0x78, 0x30, 0x3f, 0x03, 0x67, 0xf2, 0x3b, 0x09, 0xfa, 0xd4, 0x70,
|
||||
0xb0, 0x09, 0x80, 0xb9, 0x18, 0x11, 0xa3, 0x90, 0xce, 0xd8, 0x17, 0x67, 0x5b, 0xb4, 0x87, 0x7e,
|
||||
0x57, 0xc5, 0xc9, 0x56, 0xd8, 0xbf, 0x6c, 0x41, 0x93, 0xed, 0x99, 0x41, 0x96, 0xef, 0x02, 0x72,
|
||||
0xc5, 0x2b, 0x52, 0xa5, 0x81, 0x4b, 0xee, 0x42, 0x15, 0xcb, 0xc1, 0x88, 0xfa, 0x82, 0x26, 0x5b,
|
||||
0x26, 0x4d, 0x26, 0xf2, 0x64, 0xf7, 0x92, 0x93, 0x20, 0x6b, 0x14, 0xf9, 0x17, 0x16, 0xd4, 0x44,
|
||||
0x2f, 0x3f, 0x76, 0x50, 0xa1, 0xad, 0x1d, 0x46, 0x72, 0x4a, 0x4a, 0xce, 0x1e, 0x57, 0x61, 0x76,
|
||||
0xe8, 0xc6, 0xe3, 0x90, 0xe9, 0x63, 0x23, 0xa0, 0x90, 0x06, 0x33, 0xe5, 0x8a, 0xa2, 0x33, 0xea,
|
||||
0xc4, 0xde, 0xa0, 0x23, 0x6b, 0xc5, 0xb1, 0x5f, 0x5e, 0x15, 0x93, 0x20, 0x51, 0xec, 0xf6, 0xa9,
|
||||
0xd0, 0x9b, 0xbc, 0x60, 0xb7, 0x60, 0x49, 0x4c, 0x28, 0x65, 0xaa, 0xda, 0x3f, 0xa8, 0xc3, 0x72,
|
||||
0xa6, 0x4a, 0x25, 0x29, 0x08, 0x4f, 0x79, 0xe0, 0x0d, 0x8f, 0x02, 0x65, 0xe7, 0x5b, 0xba, 0x13,
|
||||
0x6d, 0x54, 0x91, 0x3e, 0x2c, 0x4a, 0x03, 0x81, 0xad, 0x69, 0xa2, 0xcc, 0x0a, 0xa8, 0xa5, 0xde,
|
||||
0x36, 0xb7, 0x30, 0xdd, 0xa1, 0x84, 0xeb, 0x4c, 0x9c, 0xdf, 0x1e, 0x39, 0x81, 0x96, 0xb2, 0x44,
|
||||
0x84, 0xb0, 0xd6, 0xac, 0x15, 0xd6, 0xd7, 0x5b, 0x17, 0xf4, 0x65, 0x58, 0xb6, 0xce, 0xc4, 0xd6,
|
||||
0xc8, 0x39, 0x5c, 0x93, 0x75, 0x28, 0x8d, 0xb3, 0xfd, 0x95, 0x5e, 0x69, 0x6e, 0x68, 0xb3, 0x9b,
|
||||
0x9d, 0x5e, 0xd0, 0x30, 0xf9, 0x00, 0x96, 0xce, 0x5c, 0x2f, 0x96, 0xc3, 0xd2, 0x6c, 0x83, 0x32,
|
||||
0x76, 0x79, 0xe7, 0x82, 0x2e, 0x9f, 0xf2, 0x8f, 0x0d, 0x15, 0x35, 0xa1, 0xc5, 0xf6, 0x0f, 0x2d,
|
||||
0x68, 0x98, 0xed, 0x30, 0x32, 0x15, 0xbc, 0x2f, 0x65, 0xa0, 0xb4, 0x26, 0x53, 0xe0, 0xac, 0xab,
|
||||
0x5c, 0xc8, 0x73, 0x95, 0x75, 0x07, 0xb5, 0x78, 0x51, 0x44, 0xaa, 0xf4, 0x6a, 0x11, 0xa9, 0x72,
|
||||
0x5e, 0x44, 0xaa, 0xfd, 0xaf, 0x16, 0x90, 0x2c, 0x2d, 0x91, 0x07, 0xdc, 0x57, 0xf7, 0xe9, 0x40,
|
||||
0x88, 0x94, 0xff, 0xf2, 0x6a, 0xf4, 0x28, 0xd7, 0x4e, 0x7e, 0xcd, 0x18, 0x43, 0x3f, 0xb7, 0xd7,
|
||||
0x8d, 0x9d, 0x19, 0x27, 0xaf, 0x2a, 0x15, 0x23, 0x2b, 0x5d, 0x1c, 0x23, 0x2b, 0x5f, 0x1c, 0x23,
|
||||
0x9b, 0x4a, 0xc7, 0xc8, 0xda, 0xff, 0xdf, 0x82, 0xf9, 0x9c, 0x4d, 0xff, 0xe9, 0x4d, 0x9c, 0x6d,
|
||||
0x93, 0x21, 0x0b, 0x0a, 0x62, 0x9b, 0x74, 0x60, 0xfb, 0x7f, 0xc3, 0x8c, 0x41, 0xe8, 0x3f, 0xbd,
|
||||
0xfe, 0xd3, 0xf6, 0x1a, 0xa7, 0x33, 0x03, 0xd6, 0xfe, 0xc7, 0x02, 0x90, 0x2c, 0xb3, 0xfd, 0xa7,
|
||||
0x8e, 0x21, 0xbb, 0x4e, 0xc5, 0x9c, 0x75, 0xfa, 0x0f, 0xd5, 0x03, 0x6f, 0xc1, 0x9c, 0x48, 0x46,
|
||||
0xd2, 0x22, 0x34, 0x9c, 0x62, 0xb2, 0x15, 0xcc, 0x62, 0x35, 0x03, 0x94, 0x15, 0x23, 0x39, 0x43,
|
||||
0x53, 0x86, 0xa9, 0x38, 0xa5, 0xdd, 0x86, 0x96, 0x58, 0xa1, 0x9d, 0x53, 0xea, 0xc7, 0x87, 0xe3,
|
||||
0x23, 0x9e, 0x8d, 0xe3, 0x05, 0xbe, 0xfd, 0xfd, 0xa2, 0x32, 0xba, 0xb1, 0x52, 0xa8, 0xf7, 0xcf,
|
||||
0x40, 0x5d, 0x17, 0xe6, 0x62, 0x3b, 0x52, 0x01, 0x3a, 0xa6, 0xd8, 0x75, 0x2c, 0xb2, 0x0d, 0x0d,
|
||||
0x14, 0x59, 0x3d, 0xf5, 0x5d, 0x01, 0xbf, 0x7b, 0x49, 0xe0, 0x61, 0xf7, 0x92, 0x93, 0xfa, 0x86,
|
||||
0x7c, 0x01, 0x1a, 0xa6, 0x2b, 0x25, 0x6c, 0x84, 0x3c, 0xdb, 0x9c, 0x7d, 0x6e, 0x22, 0x93, 0x0d,
|
||||
0x68, 0xa6, 0x7d, 0x31, 0x71, 0x14, 0x3f, 0xa1, 0x81, 0x0c, 0x3a, 0xb9, 0x2b, 0x4e, 0xaa, 0xca,
|
||||
0x18, 0x04, 0xbb, 0x6e, 0x7e, 0xa6, 0x2d, 0xd3, 0x2d, 0xfe, 0xa3, 0x9d, 0x5d, 0x7d, 0x1d, 0x20,
|
||||
0x81, 0x91, 0x26, 0xd4, 0x1f, 0x1d, 0xec, 0xec, 0x77, 0xb6, 0x76, 0x37, 0xf6, 0xf7, 0x77, 0xf6,
|
||||
0x9a, 0x97, 0x08, 0x81, 0x06, 0xc6, 0xaf, 0xb6, 0x15, 0xcc, 0x62, 0xb0, 0x8d, 0x2d, 0x1e, 0x1b,
|
||||
0x13, 0xb0, 0x02, 0x59, 0x80, 0xe6, 0xc3, 0xfd, 0x14, 0xb4, 0xb8, 0x59, 0x55, 0xfc, 0x61, 0x2f,
|
||||
0xc1, 0x02, 0x4f, 0x36, 0xdb, 0xe4, 0xe4, 0x21, 0x6d, 0x85, 0xdf, 0xb2, 0x60, 0x31, 0x55, 0x91,
|
||||
0x64, 0x75, 0x70, 0x73, 0xc0, 0xb4, 0x11, 0x4c, 0x20, 0x46, 0x9f, 0xa5, 0xe5, 0x97, 0x92, 0x20,
|
||||
0xd9, 0x0a, 0x46, 0xf3, 0x9a, 0xa5, 0x98, 0xe2, 0xa4, 0xbc, 0x2a, 0x7b, 0x99, 0xa7, 0xc4, 0x61,
|
||||
0xf2, 0x9c, 0x31, 0xf0, 0x63, 0x9e, 0xc4, 0xa6, 0x57, 0x24, 0x27, 0x7f, 0xe6, 0x90, 0x65, 0x91,
|
||||
0x19, 0xf9, 0x86, 0xe9, 0x61, 0x8e, 0x37, 0xb7, 0xce, 0xfe, 0xd3, 0x02, 0x90, 0x2f, 0x8f, 0x69,
|
||||
0x78, 0x8e, 0x09, 0x19, 0x2a, 0x1c, 0xb8, 0x9c, 0x0e, 0x76, 0x4d, 0x8d, 0xc6, 0x47, 0x5f, 0xa2,
|
||||
0xe7, 0x32, 0x99, 0xa8, 0xa0, 0x27, 0x13, 0x01, 0x73, 0x8e, 0x55, 0x3a, 0x88, 0xb5, 0x5a, 0xc6,
|
||||
0x90, 0x44, 0xd5, 0x1f, 0x0f, 0x79, 0xa3, 0xb9, 0x39, 0x3f, 0xa5, 0x8b, 0x73, 0x7e, 0xca, 0x17,
|
||||
0xe5, 0xfc, 0x7c, 0x02, 0x66, 0xbc, 0xbe, 0x1f, 0x30, 0xb1, 0xc0, 0x14, 0x7b, 0xd4, 0x9a, 0x5a,
|
||||
0x29, 0x32, 0x67, 0x58, 0x00, 0xf7, 0x19, 0x8c, 0x7c, 0x2e, 0x41, 0xa2, 0xbd, 0x3e, 0xe6, 0x8f,
|
||||
0xe9, 0x82, 0x62, 0xa7, 0xd7, 0xa7, 0x7b, 0x41, 0xd7, 0x8d, 0x83, 0x50, 0x7d, 0xc8, 0x60, 0x11,
|
||||
0xf3, 0xfa, 0xa3, 0x60, 0xcc, 0xcc, 0x1c, 0xb9, 0x14, 0x3c, 0x6c, 0x53, 0xe7, 0xd0, 0x03, 0x5c,
|
||||
0x10, 0xfb, 0xab, 0x50, 0xd3, 0x9a, 0xc0, 0xe4, 0x22, 0x61, 0x42, 0x08, 0x7f, 0xb0, 0xc4, 0x2d,
|
||||
0x76, 0x9f, 0x0e, 0x1e, 0xf6, 0xc8, 0x9b, 0x30, 0xd7, 0xf3, 0x42, 0x8a, 0x79, 0x62, 0x9d, 0x90,
|
||||
0x9e, 0xd2, 0x30, 0x92, 0x9e, 0x73, 0x53, 0x55, 0x38, 0x1c, 0x6e, 0xdf, 0x83, 0x79, 0x63, 0x6b,
|
||||
0x14, 0xe5, 0xca, 0xdc, 0x1b, 0x2b, 0x9b, 0x7b, 0x23, 0xf3, 0x6e, 0xec, 0x9f, 0x2d, 0x40, 0x71,
|
||||
0x37, 0x18, 0xe9, 0xd1, 0x7e, 0xcb, 0x8c, 0xf6, 0x0b, 0x13, 0xa8, 0xa3, 0x2c, 0x1c, 0xa1, 0x19,
|
||||
0x0d, 0x20, 0x59, 0x83, 0x86, 0x3b, 0x8c, 0x3b, 0x71, 0xc0, 0x4c, 0xbe, 0x33, 0x37, 0xec, 0x71,
|
||||
0x72, 0xc6, 0x2d, 0x4e, 0xd5, 0x90, 0x05, 0x28, 0x2a, 0x5b, 0x01, 0x11, 0x58, 0x91, 0xf9, 0x1b,
|
||||
0x78, 0xea, 0x78, 0x2e, 0x22, 0x67, 0xa2, 0xc4, 0xb8, 0xc5, 0xfc, 0x9e, 0x3b, 0x7b, 0x5c, 0xe2,
|
||||
0xe7, 0x55, 0x31, 0x73, 0x8c, 0x51, 0x07, 0xa2, 0x89, 0x90, 0xa7, 0x2c, 0xeb, 0xe1, 0xd9, 0x8a,
|
||||
0x79, 0x06, 0xfb, 0xf7, 0x16, 0x94, 0x71, 0x6d, 0x98, 0xf6, 0xe2, 0xec, 0xad, 0x02, 0xfe, 0xb8,
|
||||
0x26, 0x33, 0x4e, 0x1a, 0x4c, 0x6c, 0x23, 0xe3, 0xb0, 0xa0, 0x26, 0xa4, 0x67, 0x1d, 0xae, 0x40,
|
||||
0x95, 0x97, 0x54, 0x76, 0x1d, 0xa7, 0x7b, 0x05, 0x24, 0xd7, 0xa0, 0x74, 0x12, 0x8c, 0xa4, 0xb9,
|
||||
0x0d, 0xf2, 0xec, 0x2c, 0x18, 0x39, 0x08, 0x4f, 0xc6, 0xc3, 0xda, 0xe3, 0xd3, 0xe2, 0x46, 0x54,
|
||||
0x1a, 0xcc, 0xcc, 0x48, 0xd5, 0xac, 0xbe, 0x4c, 0x29, 0xa8, 0xbd, 0x06, 0xb3, 0x8c, 0xea, 0xb5,
|
||||
0xa8, 0xeb, 0x44, 0x56, 0xb6, 0xff, 0xaf, 0x05, 0x15, 0x89, 0x4c, 0x56, 0xa1, 0xc4, 0x58, 0x28,
|
||||
0xe5, 0xb8, 0xaa, 0x33, 0x73, 0x86, 0xe7, 0x20, 0x06, 0x33, 0x26, 0x30, 0x18, 0x96, 0xf8, 0x49,
|
||||
0x32, 0x14, 0x96, 0xb8, 0x01, 0x6a, 0xb8, 0x29, 0xeb, 0x39, 0x05, 0xb5, 0xbf, 0x67, 0xc1, 0x8c,
|
||||
0xd1, 0x07, 0x59, 0x81, 0xda, 0xc0, 0x8d, 0x62, 0x71, 0x0e, 0x29, 0xb6, 0x47, 0x07, 0xe9, 0x1b,
|
||||
0x5d, 0x30, 0xe3, 0xf0, 0x2a, 0x42, 0x5c, 0xd4, 0x23, 0xc4, 0xb7, 0xa1, 0x9a, 0xe4, 0x85, 0x96,
|
||||
0x0c, 0xde, 0x67, 0x3d, 0xca, 0x6c, 0x80, 0x04, 0x09, 0x83, 0x8e, 0xc1, 0x20, 0x08, 0xc5, 0xa1,
|
||||
0x15, 0x2f, 0xd8, 0xf7, 0xa0, 0xa6, 0xe1, 0xeb, 0x31, 0x48, 0xcb, 0x88, 0x41, 0xaa, 0x54, 0x99,
|
||||
0x42, 0x92, 0x2a, 0x63, 0xff, 0x93, 0x05, 0x33, 0x8c, 0x06, 0x3d, 0xbf, 0x7f, 0x10, 0x0c, 0xbc,
|
||||
0xee, 0x39, 0xee, 0xbd, 0x24, 0x37, 0x21, 0x12, 0x25, 0x2d, 0x9a, 0x60, 0x46, 0xf5, 0x32, 0xf2,
|
||||
0x21, 0x58, 0x54, 0x95, 0x19, 0x0f, 0x33, 0x0e, 0x38, 0x72, 0x23, 0xc1, 0x16, 0xc2, 0x6a, 0x33,
|
||||
0x80, 0x8c, 0xd3, 0x18, 0x00, 0x13, 0x9f, 0x86, 0xde, 0x60, 0xe0, 0x71, 0x5c, 0x6e, 0xd3, 0xe7,
|
||||
0x55, 0xb1, 0x3e, 0x7b, 0x5e, 0xe4, 0x1e, 0x25, 0x07, 0x31, 0xaa, 0x8c, 0xe1, 0x19, 0xf7, 0xb9,
|
||||
0x16, 0x9e, 0x99, 0x42, 0xb9, 0x62, 0x02, 0xed, 0x3f, 0x2e, 0x40, 0x4d, 0x9a, 0x08, 0xbd, 0x3e,
|
||||
0x15, 0x67, 0x8b, 0xa6, 0x60, 0xd4, 0x20, 0xb2, 0xde, 0xf0, 0xc6, 0x34, 0x48, 0x9a, 0x30, 0x8a,
|
||||
0x59, 0xc2, 0xb8, 0x0a, 0x55, 0x46, 0xa0, 0x6f, 0xa3, 0xdb, 0x27, 0x52, 0xad, 0x15, 0x40, 0xd6,
|
||||
0xde, 0xc1, 0xda, 0x72, 0x52, 0x8b, 0x80, 0x97, 0x9e, 0x44, 0xde, 0x85, 0xba, 0x68, 0x06, 0x77,
|
||||
0x0e, 0x25, 0x4f, 0xc2, 0x22, 0xc6, 0xae, 0x3a, 0x06, 0xa6, 0xfc, 0xf2, 0x8e, 0xfc, 0xb2, 0x72,
|
||||
0xd1, 0x97, 0x12, 0xd3, 0x7e, 0xa0, 0x0e, 0x78, 0x1f, 0x84, 0xee, 0xe8, 0x44, 0xf2, 0xf2, 0x6d,
|
||||
0x98, 0xf7, 0xfc, 0xee, 0x60, 0xdc, 0xa3, 0x9d, 0xb1, 0xef, 0xfa, 0x7e, 0x30, 0xf6, 0xbb, 0x54,
|
||||
0xe6, 0xca, 0xe4, 0x55, 0xd9, 0x3d, 0x95, 0x59, 0x89, 0x0d, 0x91, 0x35, 0x28, 0x73, 0x55, 0xc9,
|
||||
0x75, 0x47, 0x3e, 0xa3, 0x73, 0x14, 0xb2, 0x0a, 0x65, 0xae, 0x31, 0x0b, 0x06, 0xd7, 0x68, 0xbb,
|
||||
0xea, 0x70, 0x04, 0x26, 0x76, 0x30, 0xb9, 0xd6, 0x14, 0x3b, 0xa6, 0xde, 0x99, 0xea, 0x62, 0xfa,
|
||||
0xad, 0xbd, 0x00, 0x64, 0x9f, 0x73, 0x8a, 0x7e, 0x36, 0xf4, 0x83, 0x22, 0xd4, 0x34, 0x30, 0x93,
|
||||
0x20, 0x7d, 0x36, 0xe0, 0x4e, 0xcf, 0x73, 0x87, 0x34, 0xa6, 0xa1, 0xe0, 0x8e, 0x14, 0x94, 0xe1,
|
||||
0xb9, 0xa7, 0xfd, 0x4e, 0x30, 0x8e, 0x3b, 0x3d, 0xda, 0x0f, 0x29, 0xd7, 0xa6, 0x4c, 0x35, 0x19,
|
||||
0x50, 0x86, 0xc7, 0xe8, 0x53, 0xc3, 0xe3, 0x14, 0x94, 0x82, 0xca, 0x93, 0x1e, 0xbe, 0x46, 0xa5,
|
||||
0xe4, 0xa4, 0x87, 0xaf, 0x48, 0x5a, 0xf6, 0x95, 0x73, 0x64, 0xdf, 0x3b, 0xb0, 0xc4, 0xa5, 0x9c,
|
||||
0x90, 0x07, 0x9d, 0x14, 0x61, 0x4d, 0xa8, 0x25, 0x6b, 0xd0, 0x64, 0x63, 0x96, 0x2c, 0x11, 0x79,
|
||||
0xdf, 0xe4, 0x51, 0x53, 0xcb, 0xc9, 0xc0, 0x19, 0x2e, 0x86, 0x2f, 0x75, 0x5c, 0x7e, 0xf2, 0x9d,
|
||||
0x81, 0x23, 0xae, 0xfb, 0xdc, 0xc4, 0xad, 0x0a, 0xdc, 0x14, 0x9c, 0xdc, 0x85, 0xe5, 0x21, 0xed,
|
||||
0x79, 0xae, 0xd9, 0x04, 0x46, 0x80, 0x79, 0x7a, 0xcb, 0xa4, 0x6a, 0x7b, 0x06, 0x6a, 0x87, 0x71,
|
||||
0x30, 0x92, 0xdb, 0xd9, 0x80, 0x3a, 0x2f, 0x8a, 0x6c, 0xa7, 0x2b, 0x70, 0x19, 0xe9, 0xef, 0x71,
|
||||
0x30, 0x0a, 0x06, 0x41, 0xff, 0xdc, 0x70, 0xba, 0xfe, 0xdc, 0x82, 0x79, 0xa3, 0x36, 0xf1, 0xba,
|
||||
0x30, 0x5e, 0x23, 0xd3, 0x54, 0x38, 0xc9, 0xce, 0x69, 0xc2, 0x9b, 0x23, 0xf2, 0xd0, 0xf8, 0x13,
|
||||
0x91, 0xb9, 0xb2, 0x91, 0xdc, 0x60, 0x91, 0x1f, 0x72, 0xfa, 0x6d, 0x65, 0xe9, 0x57, 0x7c, 0x2f,
|
||||
0x2f, 0xb0, 0xc8, 0x26, 0xbe, 0x20, 0x72, 0x0f, 0xb8, 0x13, 0x26, 0xc3, 0x73, 0xca, 0x6d, 0xd3,
|
||||
0x9d, 0x74, 0x39, 0x82, 0xae, 0x02, 0x46, 0xf6, 0x2f, 0x58, 0x00, 0xc9, 0xe8, 0xf0, 0xc4, 0x5a,
|
||||
0x29, 0x20, 0x7e, 0x5b, 0x4a, 0x53, 0x36, 0x6f, 0x40, 0x5d, 0x9d, 0x74, 0x26, 0x3a, 0xad, 0x26,
|
||||
0x61, 0xcc, 0xe6, 0xbe, 0x09, 0xb3, 0xfd, 0x41, 0x70, 0x84, 0x06, 0x01, 0xa6, 0xcf, 0x45, 0x22,
|
||||
0xe7, 0xab, 0xc1, 0xc1, 0xf7, 0x05, 0x34, 0x51, 0x80, 0x25, 0x4d, 0x01, 0xda, 0xbf, 0x58, 0x50,
|
||||
0x07, 0x53, 0xc9, 0x9c, 0x27, 0xf2, 0x27, 0xb9, 0x93, 0x11, 0xc4, 0x13, 0xce, 0x81, 0xd0, 0xac,
|
||||
0x3d, 0xb8, 0x30, 0x4e, 0x76, 0x0f, 0x1a, 0x21, 0x97, 0x74, 0x52, 0x0c, 0x96, 0x5e, 0x22, 0x06,
|
||||
0x67, 0x42, 0x43, 0x4b, 0x7e, 0x0a, 0x9a, 0x6e, 0xef, 0x94, 0x86, 0xb1, 0x87, 0x91, 0x0a, 0x34,
|
||||
0x51, 0xb8, 0xf0, 0x9e, 0xd5, 0xe0, 0x68, 0x39, 0xdc, 0x84, 0x59, 0x91, 0x67, 0xa7, 0x30, 0xc5,
|
||||
0x0d, 0x84, 0x04, 0xcc, 0x10, 0xed, 0xef, 0xca, 0x33, 0x30, 0x73, 0x0f, 0x27, 0xaf, 0x88, 0x3e,
|
||||
0xbb, 0x42, 0x6a, 0x76, 0x9f, 0x10, 0xe7, 0x51, 0x3d, 0x19, 0x0e, 0x29, 0x6a, 0x79, 0x2a, 0x3d,
|
||||
0x71, 0x7e, 0x68, 0x2e, 0x69, 0xe9, 0x55, 0x96, 0xd4, 0xfe, 0x91, 0x05, 0xd3, 0xbb, 0xc1, 0x68,
|
||||
0x57, 0x64, 0xec, 0x20, 0x23, 0xa8, 0x04, 0x57, 0x59, 0x7c, 0x49, 0x2e, 0x4f, 0xae, 0x65, 0x30,
|
||||
0x93, 0xb6, 0x0c, 0xfe, 0x07, 0x5c, 0xc1, 0x60, 0x5c, 0x18, 0x8c, 0x82, 0x90, 0x31, 0xa3, 0x3b,
|
||||
0xe0, 0x66, 0x40, 0xe0, 0xc7, 0x27, 0x52, 0x00, 0xbe, 0x0c, 0x05, 0x3d, 0x64, 0xe6, 0xd5, 0x71,
|
||||
0xa3, 0x5e, 0x58, 0x32, 0x5c, 0x2e, 0x66, 0x2b, 0xec, 0xcf, 0x43, 0x15, 0x4d, 0x71, 0x9c, 0xd6,
|
||||
0x5b, 0x50, 0x3d, 0x09, 0x46, 0x9d, 0x13, 0xcf, 0x8f, 0x25, 0x73, 0x37, 0x12, 0x1b, 0x79, 0x17,
|
||||
0x17, 0x44, 0x21, 0xd8, 0xbf, 0x3a, 0x05, 0xd3, 0x0f, 0xfd, 0xd3, 0xc0, 0xeb, 0xe2, 0x79, 0xdb,
|
||||
0x90, 0x0e, 0x03, 0x99, 0xee, 0xcb, 0xfe, 0x93, 0xab, 0x30, 0x8d, 0xf9, 0x6d, 0x23, 0x4e, 0xb4,
|
||||
0x75, 0x7e, 0x2e, 0x2e, 0x40, 0xcc, 0xbc, 0x08, 0x93, 0x8b, 0x19, 0x9c, 0x7d, 0x34, 0x08, 0x73,
|
||||
0x52, 0x42, 0xfd, 0x62, 0x85, 0x28, 0x25, 0xe9, 0xd4, 0x65, 0x2d, 0x9d, 0x9a, 0xf5, 0x25, 0x32,
|
||||
0x8c, 0x78, 0x0a, 0x0a, 0xef, 0x4b, 0x80, 0xd0, 0xb1, 0x0a, 0x29, 0x0f, 0xa6, 0xa2, 0xb1, 0x32,
|
||||
0x2d, 0x1c, 0x2b, 0x1d, 0xc8, 0x0c, 0x1a, 0xfe, 0x01, 0xc7, 0xe1, 0xe2, 0x5b, 0x07, 0x31, 0x13,
|
||||
0x31, 0x7d, 0xa7, 0xa6, 0xca, 0x69, 0x3f, 0x05, 0x66, 0x32, 0xbe, 0x47, 0x95, 0x40, 0xe5, 0xf3,
|
||||
0x00, 0x7e, 0xf9, 0x24, 0x0d, 0xd7, 0xdc, 0x31, 0x9e, 0x8a, 0x28, 0xdd, 0x31, 0x46, 0x30, 0xee,
|
||||
0x60, 0x70, 0xe4, 0x76, 0x9f, 0xe1, 0x95, 0x29, 0x3c, 0x01, 0xab, 0x3a, 0x26, 0x10, 0xf3, 0x84,
|
||||
0x92, 0x5d, 0xc5, 0x0c, 0x82, 0x92, 0xa3, 0x83, 0xc8, 0x1d, 0xa8, 0xa1, 0x0b, 0x2a, 0xf6, 0xb5,
|
||||
0x81, 0xfb, 0xda, 0xd4, 0x7d, 0x54, 0xdc, 0x59, 0x1d, 0x49, 0x3f, 0x0b, 0x9c, 0xcd, 0x24, 0x07,
|
||||
0xba, 0xbd, 0x9e, 0x38, 0x42, 0x6d, 0x72, 0x77, 0x5a, 0x01, 0x98, 0x3e, 0x16, 0x0b, 0xc6, 0x11,
|
||||
0xe6, 0x10, 0xc1, 0x80, 0x91, 0x6b, 0x50, 0x61, 0xee, 0xd1, 0xc8, 0xf5, 0x7a, 0x98, 0x5d, 0xc8,
|
||||
0xbd, 0x34, 0x05, 0x63, 0x6d, 0xc8, 0xff, 0xa8, 0xe8, 0xe6, 0x71, 0x55, 0x0c, 0x18, 0x5b, 0x1b,
|
||||
0x55, 0x46, 0x66, 0x5a, 0xe0, 0x3b, 0x6a, 0x00, 0xc9, 0xdb, 0x78, 0x90, 0x15, 0xd3, 0xd6, 0x22,
|
||||
0x06, 0xca, 0xae, 0x88, 0x39, 0x0b, 0xa2, 0x95, 0xbf, 0x87, 0x0c, 0xc5, 0xe1, 0x98, 0xf6, 0x06,
|
||||
0xd4, 0x75, 0x30, 0xa9, 0x40, 0xe9, 0xd1, 0xc1, 0xce, 0x7e, 0xf3, 0x12, 0xa9, 0xc1, 0xf4, 0xe1,
|
||||
0xce, 0xe3, 0xc7, 0x7b, 0x3b, 0xdb, 0x4d, 0x8b, 0xd4, 0xa1, 0xa2, 0x92, 0xba, 0x0a, 0xac, 0xb4,
|
||||
0xb1, 0xb5, 0xb5, 0x73, 0xf0, 0x78, 0x67, 0xbb, 0x59, 0xb4, 0x63, 0x20, 0x1b, 0xbd, 0x9e, 0x68,
|
||||
0x45, 0x05, 0x09, 0x12, 0x7a, 0xb6, 0x0c, 0x7a, 0xce, 0xa1, 0xa9, 0x42, 0x3e, 0x4d, 0xbd, 0x74,
|
||||
0xe5, 0xed, 0x1d, 0xa8, 0x1d, 0x68, 0xf7, 0x87, 0x90, 0xbd, 0xe4, 0xcd, 0x21, 0xc1, 0x96, 0x1a,
|
||||
0x44, 0x1b, 0x4e, 0x41, 0x1f, 0x8e, 0xfd, 0x3b, 0x16, 0x4f, 0xd2, 0x57, 0xc3, 0xe7, 0x7d, 0xdb,
|
||||
0x50, 0x57, 0xd1, 0xaa, 0x24, 0x5f, 0xd3, 0x80, 0x31, 0x1c, 0x1c, 0x4a, 0x27, 0x38, 0x3e, 0x8e,
|
||||
0xa8, 0xcc, 0xae, 0x32, 0x60, 0x8c, 0x2f, 0x98, 0x6d, 0xc6, 0xec, 0x1c, 0x8f, 0xf7, 0x10, 0x89,
|
||||
0x2c, 0xab, 0x0c, 0x9c, 0x49, 0x79, 0x11, 0x90, 0x91, 0x79, 0x65, 0xaa, 0xac, 0xd2, 0x4a, 0xd3,
|
||||
0xab, 0xbc, 0x06, 0x15, 0xd5, 0xae, 0x29, 0xc0, 0x24, 0xa6, 0xaa, 0x67, 0x82, 0x12, 0xbd, 0x15,
|
||||
0x63, 0xd0, 0x5c, 0x68, 0x67, 0x2b, 0xc8, 0x2d, 0x20, 0xc7, 0x5e, 0x98, 0x46, 0x2f, 0x22, 0x7a,
|
||||
0x4e, 0x8d, 0xfd, 0x14, 0xe6, 0x25, 0x21, 0x69, 0xa6, 0x95, 0xb9, 0x89, 0xd6, 0x45, 0xec, 0x53,
|
||||
0xc8, 0xb2, 0x8f, 0xfd, 0x6f, 0x16, 0x4c, 0x8b, 0x9d, 0xce, 0xdc, 0x41, 0xe3, 0xfb, 0x6c, 0xc0,
|
||||
0x48, 0xcb, 0xb8, 0x7f, 0x82, 0xbc, 0x26, 0x84, 0x66, 0x46, 0x2c, 0x16, 0xf3, 0xc4, 0x22, 0x81,
|
||||
0xd2, 0xc8, 0x8d, 0x4f, 0xd0, 0x53, 0xaf, 0x3a, 0xf8, 0x9f, 0x34, 0x79, 0x5c, 0x89, 0x8b, 0x60,
|
||||
0x8c, 0x29, 0xe5, 0xdd, 0xb6, 0xe3, 0xda, 0x3e, 0x7b, 0xdb, 0xee, 0x2a, 0x54, 0x71, 0x00, 0x9d,
|
||||
0x24, 0x6c, 0x94, 0x00, 0x18, 0xe5, 0xf2, 0x02, 0xf2, 0xb5, 0x48, 0x05, 0x4f, 0x20, 0xf6, 0x22,
|
||||
0xdf, 0x79, 0xb1, 0x04, 0xea, 0x10, 0x5a, 0xa4, 0xf1, 0x26, 0xe0, 0x84, 0x22, 0xc4, 0x00, 0xd2,
|
||||
0x14, 0x21, 0x50, 0x1d, 0x55, 0x6f, 0xb7, 0xa1, 0xb5, 0x4d, 0x07, 0x34, 0xa6, 0x1b, 0x83, 0x41,
|
||||
0xba, 0xfd, 0x2b, 0x70, 0x39, 0xa7, 0x4e, 0x58, 0xd3, 0x5f, 0x86, 0xc5, 0x0d, 0x9e, 0xf2, 0xf8,
|
||||
0xd3, 0x4a, 0xe3, 0xb1, 0x5b, 0xb0, 0x94, 0x6e, 0x52, 0x74, 0x76, 0x1f, 0xe6, 0xb6, 0xe9, 0xd1,
|
||||
0xb8, 0xbf, 0x47, 0x4f, 0x93, 0x8e, 0x08, 0x94, 0xa2, 0x93, 0xe0, 0x4c, 0x30, 0x26, 0xfe, 0x27,
|
||||
0xaf, 0x01, 0x0c, 0x18, 0x4e, 0x27, 0x1a, 0xd1, 0xae, 0xbc, 0xf2, 0x81, 0x90, 0xc3, 0x11, 0xed,
|
||||
0xda, 0xef, 0x00, 0xd1, 0xdb, 0x11, 0xeb, 0xc5, 0xb4, 0xe0, 0xf8, 0xa8, 0x13, 0x9d, 0x47, 0x31,
|
||||
0x1d, 0xca, 0xbb, 0x2c, 0x3a, 0xc8, 0xbe, 0x09, 0xf5, 0x03, 0xf7, 0xdc, 0xa1, 0x1f, 0x8a, 0xab,
|
||||
0x87, 0xcb, 0x30, 0x3d, 0x72, 0xcf, 0x99, 0x98, 0x52, 0xf1, 0x2c, 0xac, 0xb6, 0xff, 0xa5, 0x00,
|
||||
0x53, 0x1c, 0x93, 0xb5, 0xda, 0xa3, 0x51, 0xec, 0xf9, 0x48, 0x58, 0xb2, 0x55, 0x0d, 0x94, 0x21,
|
||||
0xe5, 0x42, 0x0e, 0x29, 0x0b, 0x6f, 0x4f, 0xa6, 0xcf, 0x0b, 0x7a, 0x35, 0x60, 0x8c, 0xb8, 0x92,
|
||||
0x7c, 0x3a, 0x1e, 0x50, 0x49, 0x00, 0xa9, 0xd0, 0x67, 0xa2, 0x6b, 0xf9, 0xf8, 0x24, 0x97, 0x0a,
|
||||
0xca, 0xd5, 0x41, 0xb9, 0x1a, 0x7d, 0x9a, 0x13, 0x78, 0x46, 0xa3, 0x67, 0x34, 0x77, 0xe5, 0x15,
|
||||
0x34, 0x37, 0x77, 0x01, 0x5f, 0xa6, 0xb9, 0xe1, 0x15, 0x34, 0xb7, 0x4d, 0xa0, 0x89, 0xf7, 0xf2,
|
||||
0x98, 0x6d, 0x28, 0x69, 0xf7, 0xdb, 0x16, 0x34, 0x05, 0x15, 0xa9, 0x3a, 0xf2, 0x86, 0x61, 0x03,
|
||||
0xe7, 0x26, 0xa6, 0x5f, 0x87, 0x19, 0xb4, 0x4c, 0x55, 0x8c, 0x57, 0x04, 0xa4, 0x0d, 0x20, 0x9b,
|
||||
0x87, 0x3c, 0x3f, 0x1e, 0x7a, 0x03, 0xb1, 0x29, 0x3a, 0x48, 0x86, 0x89, 0x43, 0x57, 0xe4, 0x95,
|
||||
0x59, 0x8e, 0x2a, 0xdb, 0x7f, 0x62, 0xc1, 0x9c, 0x36, 0x60, 0x41, 0x85, 0xf7, 0x40, 0x72, 0x03,
|
||||
0x0f, 0xf8, 0x72, 0xce, 0x5d, 0x36, 0xd9, 0x26, 0xf9, 0xcc, 0x40, 0xc6, 0xcd, 0x74, 0xcf, 0x71,
|
||||
0x80, 0xd1, 0x78, 0x28, 0x84, 0xa8, 0x0e, 0x62, 0x84, 0x74, 0x46, 0xe9, 0x33, 0x85, 0xc2, 0xc5,
|
||||
0xb8, 0x01, 0xc3, 0xa8, 0x1a, 0xb3, 0xa8, 0x15, 0x52, 0x49, 0x44, 0xd5, 0x74, 0xa0, 0xfd, 0x57,
|
||||
0x16, 0xcc, 0x73, 0xd7, 0x48, 0x38, 0x9e, 0xea, 0x06, 0xd2, 0x14, 0xf7, 0x05, 0x39, 0x47, 0xee,
|
||||
0x5e, 0x72, 0x44, 0x99, 0x7c, 0xf6, 0x15, 0xdd, 0x39, 0x95, 0xec, 0x36, 0x61, 0x2f, 0x8a, 0x79,
|
||||
0x7b, 0xf1, 0x92, 0x95, 0xce, 0x0b, 0x70, 0x96, 0x73, 0x03, 0x9c, 0x9b, 0xd3, 0x50, 0x8e, 0xba,
|
||||
0xc1, 0x88, 0xda, 0x4b, 0xb0, 0x60, 0x4e, 0x4e, 0x88, 0xa0, 0xef, 0x58, 0xd0, 0xba, 0xcf, 0x0f,
|
||||
0x02, 0x3c, 0xbf, 0xbf, 0xeb, 0x45, 0x71, 0x10, 0xaa, 0x8b, 0x9a, 0xd7, 0x00, 0xa2, 0xd8, 0x0d,
|
||||
0x63, 0x9e, 0xd2, 0x2c, 0x02, 0x8b, 0x09, 0x84, 0x8d, 0x91, 0xfa, 0x3d, 0x5e, 0xcb, 0xf7, 0x46,
|
||||
0x95, 0x33, 0x36, 0x84, 0x70, 0xde, 0x0c, 0x4d, 0x7c, 0x83, 0x27, 0x7f, 0x32, 0x5b, 0x81, 0x9e,
|
||||
0xa2, 0x5c, 0xe7, 0x5e, 0x51, 0x0a, 0x6a, 0xff, 0xa5, 0x05, 0xb3, 0xc9, 0x20, 0xf1, 0x58, 0xd4,
|
||||
0x94, 0x0e, 0x42, 0xfd, 0x26, 0xd2, 0x41, 0x86, 0x3c, 0x3d, 0xa6, 0x8f, 0xc5, 0xd8, 0x34, 0x08,
|
||||
0x72, 0xac, 0x28, 0x05, 0x63, 0x69, 0xe0, 0xe8, 0x20, 0x9e, 0xca, 0xc5, 0x2c, 0x01, 0x61, 0xd5,
|
||||
0x88, 0x12, 0x66, 0xa4, 0x0f, 0x63, 0xfc, 0x8a, 0x07, 0x67, 0x65, 0x51, 0xaa, 0xd2, 0x69, 0x84,
|
||||
0xa2, 0x2a, 0xd5, 0x0f, 0x55, 0x2a, 0x7c, 0x7d, 0x64, 0xd9, 0xfe, 0x25, 0x0b, 0x2e, 0xe7, 0x2c,
|
||||
0xbc, 0xe0, 0x9a, 0x6d, 0x98, 0x3b, 0x56, 0x95, 0x72, 0x71, 0x38, 0xeb, 0x2c, 0xc9, 0x43, 0x3b,
|
||||
0x73, 0x41, 0x9c, 0xec, 0x07, 0xca, 0x2e, 0xe2, 0xcb, 0x6d, 0x24, 0x4b, 0x66, 0x2b, 0xec, 0x03,
|
||||
0x68, 0xef, 0x3c, 0x67, 0x4c, 0xb8, 0xa5, 0xbf, 0x39, 0x22, 0x69, 0xe1, 0x4e, 0x46, 0xc8, 0x5c,
|
||||
0xec, 0x68, 0x1f, 0xc3, 0x8c, 0xd1, 0x16, 0xf9, 0xf4, 0xab, 0x36, 0x92, 0x0a, 0x4f, 0x63, 0x89,
|
||||
0x3f, 0x9a, 0x22, 0x53, 0x36, 0x35, 0x90, 0x7d, 0x0a, 0xb3, 0xef, 0x8d, 0x07, 0xb1, 0x97, 0x3c,
|
||||
0xa0, 0x42, 0x3e, 0x2b, 0x3e, 0xc2, 0x26, 0xe4, 0xd2, 0xe5, 0x76, 0xa5, 0xe3, 0xb1, 0x15, 0x1b,
|
||||
0xb2, 0x96, 0x3a, 0xd9, 0x1e, 0xb3, 0x15, 0xf6, 0x65, 0x58, 0x4e, 0xba, 0xe4, 0x6b, 0x27, 0x05,
|
||||
0xf5, 0x77, 0x2d, 0x9e, 0xed, 0x60, 0xbe, 0xe7, 0x42, 0x1e, 0xc0, 0x7c, 0xe4, 0xf9, 0xfd, 0x01,
|
||||
0xd5, 0xdb, 0x89, 0xc4, 0x4a, 0x2c, 0x9a, 0xc3, 0x13, 0x6f, 0xbe, 0x38, 0x79, 0x5f, 0x30, 0x02,
|
||||
0xc9, 0x1f, 0x68, 0x42, 0x20, 0xa9, 0x25, 0xc9, 0x9b, 0xc0, 0x17, 0xa1, 0x61, 0x76, 0x46, 0xee,
|
||||
0x8a, 0x6c, 0xcb, 0x64, 0x64, 0x7a, 0x2c, 0xdb, 0xa4, 0x0c, 0x03, 0xd3, 0xfe, 0x96, 0x05, 0x2d,
|
||||
0x87, 0x32, 0x32, 0xa6, 0x5a, 0xa7, 0x82, 0x7a, 0xee, 0x65, 0x9a, 0x9d, 0x3c, 0x61, 0x95, 0xc5,
|
||||
0x29, 0xe7, 0x7a, 0x6b, 0xe2, 0xa6, 0xec, 0x5e, 0xca, 0x99, 0xd5, 0x66, 0x05, 0xa6, 0xc4, 0xfc,
|
||||
0x96, 0x61, 0x51, 0x0c, 0x49, 0x0e, 0x27, 0x09, 0x9a, 0x1a, 0x9d, 0x1a, 0x41, 0xd3, 0x23, 0x68,
|
||||
0xf1, 0x1b, 0xb4, 0xfa, 0x3c, 0x92, 0xdc, 0x06, 0xbe, 0x1d, 0x51, 0x47, 0xbf, 0x4c, 0x6b, 0x02,
|
||||
0x19, 0xc9, 0xf2, 0x61, 0x71, 0x1c, 0x7e, 0x0a, 0xad, 0x83, 0xd6, 0x5e, 0x40, 0x4d, 0xbb, 0x8f,
|
||||
0x4c, 0x96, 0x61, 0xfe, 0xe9, 0xc3, 0xc7, 0xfb, 0x3b, 0x87, 0x87, 0x9d, 0x83, 0x27, 0x9b, 0x5f,
|
||||
0xda, 0xf9, 0x6a, 0x67, 0x77, 0xe3, 0x70, 0xb7, 0x79, 0x89, 0x2c, 0x01, 0xd9, 0xdf, 0x39, 0x7c,
|
||||
0xbc, 0xb3, 0x6d, 0xc0, 0x2d, 0x72, 0x0d, 0xda, 0x4f, 0xf6, 0x9f, 0x1c, 0xee, 0x6c, 0x77, 0xf2,
|
||||
0xbe, 0x2b, 0x90, 0xd7, 0xe0, 0xb2, 0xa8, 0xcf, 0xf9, 0xbc, 0x78, 0xe7, 0x5b, 0x45, 0x68, 0xf0,
|
||||
0xe4, 0x0d, 0xfe, 0x9c, 0x10, 0x0d, 0xc9, 0x7b, 0x30, 0x2d, 0xde, 0xa5, 0x22, 0x72, 0x5f, 0xcc,
|
||||
0x97, 0xb0, 0xda, 0x4b, 0x69, 0xb0, 0x58, 0xcc, 0xf9, 0xff, 0xf7, 0xa3, 0xbf, 0xfb, 0x95, 0xc2,
|
||||
0x0c, 0xa9, 0xad, 0x9f, 0xbe, 0xbd, 0xde, 0xa7, 0x7e, 0xc4, 0xda, 0xf8, 0x3a, 0x40, 0xf2, 0xda,
|
||||
0x12, 0x69, 0x29, 0xdf, 0x2d, 0xf5, 0x14, 0x55, 0xfb, 0x72, 0x4e, 0x8d, 0x68, 0xf7, 0x32, 0xb6,
|
||||
0x3b, 0x6f, 0x37, 0x58, 0xbb, 0x9e, 0xef, 0xc5, 0xfc, 0xe5, 0xa5, 0x77, 0xad, 0x35, 0xd2, 0x83,
|
||||
0xba, 0xfe, 0x0e, 0x12, 0x91, 0x01, 0xe4, 0x9c, 0x97, 0x9c, 0xda, 0x57, 0x72, 0xeb, 0x24, 0x21,
|
||||
0x60, 0x1f, 0x8b, 0x76, 0x93, 0xf5, 0x31, 0x46, 0x8c, 0xa4, 0x97, 0x01, 0x67, 0x8f, 0xe4, 0xb9,
|
||||
0x23, 0x72, 0x55, 0xa3, 0xd8, 0xcc, 0x63, 0x4b, 0xed, 0xd7, 0x26, 0xd4, 0x8a, 0xbe, 0x5e, 0xc3,
|
||||
0xbe, 0x96, 0x6d, 0xc2, 0xfa, 0xea, 0x22, 0x8e, 0x7c, 0x6c, 0xe9, 0x5d, 0x6b, 0xed, 0xce, 0xaf,
|
||||
0xdd, 0x80, 0xaa, 0x3a, 0x2c, 0x22, 0x1f, 0xc0, 0x8c, 0x91, 0x5d, 0x43, 0xe4, 0x34, 0xf2, 0x92,
|
||||
0x71, 0xda, 0x57, 0xf3, 0x2b, 0x45, 0xc7, 0xd7, 0xb0, 0xe3, 0x16, 0x59, 0x62, 0x1d, 0x8b, 0xf4,
|
||||
0x94, 0x75, 0xcc, 0x13, 0xe3, 0x97, 0x3e, 0x9e, 0x69, 0x62, 0x80, 0x77, 0x76, 0x35, 0xcd, 0x99,
|
||||
0x46, 0x6f, 0xaf, 0x4d, 0xa8, 0x15, 0xdd, 0x5d, 0xc5, 0xee, 0x96, 0xc8, 0x82, 0xde, 0x9d, 0x3a,
|
||||
0xc4, 0xa1, 0x78, 0x53, 0x49, 0x7f, 0x29, 0x88, 0xbc, 0xa6, 0x08, 0x2b, 0xef, 0x05, 0x21, 0x45,
|
||||
0x22, 0xd9, 0x67, 0x84, 0xec, 0x16, 0x76, 0x45, 0x08, 0x6e, 0x9f, 0xfe, 0x50, 0x10, 0x39, 0x82,
|
||||
0x9a, 0xf6, 0xba, 0x05, 0xb9, 0x3c, 0xf1, 0x25, 0x8e, 0x76, 0x3b, 0xaf, 0x2a, 0x6f, 0x2a, 0x7a,
|
||||
0xfb, 0xeb, 0x4c, 0xbf, 0x7f, 0x0d, 0xaa, 0xea, 0xbd, 0x04, 0xb2, 0xac, 0xbd, 0x5f, 0xa1, 0xbf,
|
||||
0xef, 0xd0, 0x6e, 0x65, 0x2b, 0xf2, 0x88, 0x4f, 0x6f, 0x9d, 0x11, 0xdf, 0x53, 0xa8, 0x69, 0x6f,
|
||||
0x22, 0xa8, 0x09, 0x64, 0xdf, 0x5d, 0x50, 0x13, 0xc8, 0x79, 0x42, 0xc1, 0x9e, 0xc3, 0x2e, 0x6a,
|
||||
0xa4, 0x8a, 0xf4, 0x1d, 0x3f, 0x0f, 0x22, 0xb2, 0x07, 0x8b, 0x42, 0xdc, 0x1d, 0xd1, 0x8f, 0xb3,
|
||||
0x0d, 0x39, 0x8f, 0x33, 0xdd, 0xb6, 0xc8, 0x3d, 0xa8, 0xc8, 0xa7, 0x2f, 0xc8, 0x52, 0xfe, 0x13,
|
||||
0x1e, 0xed, 0xe5, 0x0c, 0x5c, 0x48, 0xd3, 0xaf, 0x02, 0x24, 0x0f, 0x30, 0x28, 0x21, 0x91, 0x79,
|
||||
0xd0, 0x41, 0x51, 0x40, 0xf6, 0xb5, 0x06, 0x7b, 0x09, 0x27, 0xd8, 0x24, 0x28, 0x24, 0x7c, 0x7a,
|
||||
0x26, 0xef, 0x07, 0x7e, 0x03, 0x6a, 0xda, 0x1b, 0x0c, 0x6a, 0xf9, 0xb2, 0xef, 0x37, 0xa8, 0xe5,
|
||||
0xcb, 0x79, 0xb2, 0xc1, 0x6e, 0x63, 0xeb, 0x0b, 0xf6, 0x2c, 0x6b, 0x3d, 0xf2, 0xfa, 0xfe, 0x90,
|
||||
0x23, 0xb0, 0x0d, 0x3a, 0x81, 0x19, 0xe3, 0xa1, 0x05, 0xc5, 0xa1, 0x79, 0xcf, 0x38, 0x28, 0x0e,
|
||||
0xcd, 0x7d, 0x9b, 0x41, 0xd2, 0x99, 0x3d, 0xc7, 0xfa, 0x39, 0x45, 0x14, 0xad, 0xa7, 0xf7, 0xa1,
|
||||
0xa6, 0x3d, 0x9a, 0xa0, 0xe6, 0x92, 0x7d, 0x9f, 0x41, 0xcd, 0x25, 0xef, 0x8d, 0x85, 0x05, 0xec,
|
||||
0xa3, 0x61, 0x23, 0x29, 0xe0, 0xf5, 0x3a, 0xd6, 0xf6, 0x07, 0xd0, 0x30, 0x9f, 0x51, 0x50, 0xbc,
|
||||
0x9f, 0xfb, 0x20, 0x83, 0xe2, 0xfd, 0x09, 0x6f, 0x2f, 0x08, 0x92, 0x5e, 0x9b, 0x57, 0x9d, 0xac,
|
||||
0x7f, 0x24, 0x92, 0x48, 0x5e, 0x90, 0x2f, 0x33, 0x01, 0x27, 0xee, 0x3b, 0x92, 0x65, 0x8d, 0x6a,
|
||||
0xf5, 0x5b, 0x91, 0x8a, 0x5f, 0x32, 0x57, 0x23, 0x4d, 0x62, 0xe6, 0x17, 0x04, 0x51, 0x6b, 0xe1,
|
||||
0xbd, 0x47, 0x4d, 0x6b, 0xe9, 0x57, 0x23, 0x35, 0xad, 0x65, 0x5c, 0x8f, 0x4c, 0x6b, 0xad, 0xd8,
|
||||
0x63, 0x6d, 0xf8, 0x30, 0x9b, 0xca, 0x00, 0x56, 0x5c, 0x91, 0x7f, 0x65, 0xa2, 0x7d, 0xed, 0xe5,
|
||||
0x89, 0xc3, 0xa6, 0x04, 0x91, 0x42, 0x70, 0x5d, 0x5e, 0x50, 0xf9, 0x5f, 0x50, 0xd7, 0xaf, 0xac,
|
||||
0x13, 0x9d, 0x95, 0xd3, 0x3d, 0x5d, 0xc9, 0xad, 0x33, 0x37, 0x97, 0xd4, 0xf5, 0x6e, 0xc8, 0x57,
|
||||
0x60, 0x49, 0xb1, 0xba, 0x9e, 0x54, 0x1a, 0x91, 0xd7, 0x73, 0x52, 0x4d, 0x75, 0x23, 0xa8, 0x7d,
|
||||
0x79, 0x62, 0x2e, 0xea, 0x6d, 0x8b, 0x11, 0x8d, 0x79, 0x17, 0x38, 0x51, 0x18, 0x79, 0x57, 0xa0,
|
||||
0x13, 0x85, 0x91, 0x7b, 0x81, 0x58, 0x12, 0x0d, 0x99, 0x37, 0xd6, 0x88, 0x9f, 0xf3, 0x91, 0xf7,
|
||||
0x61, 0x56, 0x4b, 0xdb, 0x3f, 0x3c, 0xf7, 0xbb, 0x8a, 0x01, 0xb2, 0xf7, 0xbb, 0xda, 0x79, 0x26,
|
||||
0xbe, 0xbd, 0x8c, 0xed, 0xcf, 0xd9, 0xc6, 0xe2, 0x30, 0xe2, 0xdf, 0x82, 0x9a, 0x7e, 0x25, 0xe0,
|
||||
0x25, 0xed, 0x2e, 0x6b, 0x55, 0xfa, 0xf5, 0xa4, 0xdb, 0x16, 0xf9, 0x0d, 0x0b, 0xea, 0x46, 0x82,
|
||||
0xbd, 0x71, 0x9a, 0x9d, 0x6a, 0xa7, 0xa5, 0xd7, 0xe9, 0x0d, 0xd9, 0x0e, 0x0e, 0x72, 0x6f, 0xed,
|
||||
0x8b, 0xc6, 0x22, 0x7c, 0x64, 0xc4, 0x71, 0x6e, 0xa5, 0x9f, 0xdb, 0x7a, 0x91, 0x46, 0xd0, 0xef,
|
||||
0xc0, 0xbd, 0xb8, 0x6d, 0x91, 0xef, 0x59, 0xd0, 0x30, 0xa3, 0x8f, 0x6a, 0xab, 0x72, 0xe3, 0x9c,
|
||||
0x6a, 0xab, 0x26, 0x84, 0x2c, 0xdf, 0xc7, 0x51, 0x3e, 0x5e, 0x73, 0x8c, 0x51, 0x8a, 0x5b, 0xe2,
|
||||
0x3f, 0xd9, 0x68, 0xc9, 0xbb, 0xfc, 0x45, 0x3e, 0x19, 0x12, 0x27, 0x9a, 0xd6, 0x48, 0x6f, 0xaf,
|
||||
0xfe, 0x8a, 0xdc, 0xaa, 0x75, 0xdb, 0x22, 0xdf, 0xe0, 0xcf, 0x4c, 0x89, 0x6f, 0x91, 0x4a, 0x5e,
|
||||
0xf5, 0x7b, 0xfb, 0x3a, 0xce, 0xe9, 0x9a, 0x7d, 0xd9, 0x98, 0x53, 0x5a, 0x1f, 0x6f, 0xf0, 0xd1,
|
||||
0x89, 0x07, 0xe0, 0x12, 0x85, 0x92, 0x79, 0x14, 0x6e, 0xf2, 0x20, 0x87, 0x7c, 0x90, 0x02, 0xdd,
|
||||
0x20, 0xe5, 0x57, 0x6c, 0xc6, 0x5e, 0xc3, 0xb1, 0x5e, 0xb7, 0x5f, 0x9f, 0x38, 0xd6, 0x75, 0x8c,
|
||||
0x21, 0xb2, 0x11, 0x1f, 0x00, 0x24, 0xc7, 0x57, 0x24, 0x75, 0x7c, 0xa2, 0x18, 0x3c, 0x7b, 0xc2,
|
||||
0x65, 0xf2, 0x8b, 0x3c, 0x65, 0x61, 0x2d, 0x7e, 0x8d, 0x8b, 0xab, 0x87, 0xf2, 0xe0, 0x45, 0x37,
|
||||
0x4a, 0xcc, 0x73, 0x26, 0xc3, 0x28, 0x49, 0xb7, 0x6f, 0x08, 0x2b, 0x75, 0x8a, 0xf3, 0x04, 0x66,
|
||||
0xf6, 0x82, 0xe0, 0xd9, 0x78, 0xa4, 0x8e, 0xa2, 0xcd, 0xf0, 0xfe, 0xae, 0x1b, 0x9d, 0xb4, 0x53,
|
||||
0xb3, 0xb0, 0x57, 0xb0, 0xa9, 0x36, 0x69, 0x69, 0x4d, 0xad, 0x7f, 0x94, 0x1c, 0x8f, 0xbd, 0x20,
|
||||
0x2e, 0xcc, 0x29, 0x19, 0xa8, 0x06, 0xde, 0x36, 0x9b, 0x31, 0x24, 0x5f, 0xba, 0x0b, 0xc3, 0x7a,
|
||||
0x96, 0xa3, 0x5d, 0x8f, 0x64, 0x9b, 0xb7, 0x2d, 0x72, 0x00, 0xf5, 0x6d, 0xda, 0x0d, 0x7a, 0x54,
|
||||
0xc4, 0xc8, 0xe7, 0x93, 0x81, 0xab, 0xe0, 0x7a, 0x7b, 0xc6, 0x00, 0x9a, 0x7a, 0x61, 0xe4, 0x9e,
|
||||
0x87, 0xf4, 0xc3, 0xf5, 0x8f, 0x44, 0xf4, 0xfd, 0x85, 0xd4, 0x0b, 0xf2, 0x78, 0xc2, 0xd0, 0x0b,
|
||||
0xa9, 0xf3, 0x0c, 0x43, 0x2f, 0x64, 0xce, 0x33, 0x8c, 0xa5, 0x96, 0xc7, 0x23, 0x64, 0x00, 0x73,
|
||||
0x99, 0x23, 0x10, 0xa5, 0x12, 0x26, 0x1d, 0x9c, 0xb4, 0x57, 0x26, 0x23, 0x98, 0xbd, 0xad, 0x99,
|
||||
0xbd, 0x1d, 0xc2, 0xcc, 0x36, 0xe5, 0x8b, 0xc5, 0x33, 0xe5, 0x52, 0xb7, 0x34, 0xf4, 0x3c, 0xbc,
|
||||
0xb4, 0x00, 0xc7, 0x3a, 0x53, 0xf1, 0x63, 0x9a, 0x1a, 0xf9, 0x1a, 0xd4, 0x1e, 0xd0, 0x58, 0xa6,
|
||||
0xc6, 0x29, 0xd3, 0x33, 0x95, 0x2b, 0xd7, 0xce, 0xc9, 0xac, 0x33, 0x69, 0x06, 0x5b, 0x5b, 0xa7,
|
||||
0xbd, 0x3e, 0xe5, 0xc2, 0xa9, 0xe3, 0xf5, 0x5e, 0x90, 0xff, 0x89, 0x8d, 0xab, 0x0c, 0xde, 0x25,
|
||||
0x2d, 0x2f, 0x4a, 0x6f, 0x7c, 0x36, 0x05, 0xcf, 0x6b, 0xd9, 0x0f, 0x7a, 0x54, 0x33, 0x81, 0x7c,
|
||||
0xa8, 0x69, 0x89, 0xe7, 0x8a, 0x81, 0xb2, 0xf7, 0x04, 0x14, 0x03, 0xe5, 0xe4, 0xa9, 0xdb, 0xab,
|
||||
0xd8, 0x8f, 0x4d, 0x56, 0x92, 0x7e, 0x78, 0x6e, 0x7a, 0xd2, 0xd3, 0xfa, 0x47, 0xee, 0x30, 0x7e,
|
||||
0x41, 0x9e, 0xe2, 0x53, 0x11, 0x7a, 0xfa, 0x5f, 0x62, 0x4b, 0xa7, 0x33, 0x05, 0xd5, 0x62, 0x69,
|
||||
0x55, 0xa6, 0x7d, 0xcd, 0xbb, 0x42, 0x4b, 0xe9, 0xb3, 0x00, 0x87, 0x71, 0x30, 0xda, 0x76, 0xe9,
|
||||
0x30, 0xf0, 0x13, 0x59, 0x9b, 0x24, 0xaa, 0x25, 0xf2, 0x4b, 0xcb, 0x56, 0x23, 0x4f, 0x35, 0xe7,
|
||||
0xc3, 0xc8, 0x9e, 0x94, 0xc4, 0x35, 0x31, 0x97, 0x4d, 0x2d, 0x48, 0x4e, 0x3e, 0xdb, 0x6d, 0x8b,
|
||||
0x6c, 0x00, 0x24, 0x67, 0x60, 0xca, 0x95, 0xc8, 0x1c, 0xaf, 0x29, 0xb1, 0x97, 0x73, 0x60, 0x76,
|
||||
0x00, 0xd5, 0xe4, 0x50, 0x65, 0x39, 0xb9, 0x1b, 0x61, 0x1c, 0xc1, 0x28, 0x0d, 0x9e, 0x39, 0xea,
|
||||
0xb0, 0x9b, 0xb8, 0x54, 0x40, 0x2a, 0x6c, 0xa9, 0xf0, 0xfc, 0xc2, 0x83, 0x79, 0x3e, 0x40, 0x65,
|
||||
0x8e, 0x60, 0xea, 0x95, 0x9c, 0x49, 0xce, 0x71, 0x83, 0xe2, 0xe6, 0xdc, 0x68, 0xbd, 0x11, 0x11,
|
||||
0x61, 0xd4, 0xca, 0xd3, 0xbe, 0x98, 0x68, 0x1e, 0xc2, 0x5c, 0x26, 0x9c, 0xac, 0x58, 0x7a, 0x52,
|
||||
0x84, 0x5f, 0xb1, 0xf4, 0xc4, 0x48, 0xb4, 0xbd, 0x88, 0x5d, 0xce, 0xda, 0x80, 0x1e, 0xd0, 0x99,
|
||||
0x17, 0x77, 0x4f, 0x58, 0x77, 0xdf, 0xb5, 0x60, 0x3e, 0x27, 0x5a, 0x4c, 0xde, 0x90, 0xce, 0xf4,
|
||||
0xc4, 0x48, 0x72, 0x3b, 0x37, 0x98, 0x68, 0x1f, 0x62, 0x3f, 0xef, 0x91, 0x2f, 0x19, 0x8a, 0x8d,
|
||||
0xc7, 0xf1, 0x04, 0x67, 0xbe, 0xd4, 0xa8, 0xc8, 0xb5, 0x28, 0x3e, 0x84, 0x65, 0x3e, 0x90, 0x8d,
|
||||
0xc1, 0x20, 0x15, 0xe8, 0xbc, 0x96, 0x79, 0x74, 0xdb, 0x08, 0xe0, 0xb6, 0x27, 0x3f, 0xca, 0x3d,
|
||||
0xc1, 0x5c, 0xe5, 0x43, 0x25, 0x63, 0x68, 0xa6, 0x83, 0x87, 0x64, 0x72, 0x5b, 0xed, 0xd7, 0x0d,
|
||||
0xb7, 0x30, 0x1b, 0x70, 0xb4, 0x3f, 0x89, 0x9d, 0xbd, 0x6e, 0xb7, 0xf3, 0xd6, 0x85, 0x7b, 0x8a,
|
||||
0x6c, 0x3f, 0xfe, 0x8f, 0x8a, 0x74, 0xa6, 0xe6, 0x29, 0x3b, 0x98, 0x14, 0x9a, 0x55, 0x8e, 0x69,
|
||||
0x7e, 0xa0, 0xf4, 0x06, 0x76, 0xbf, 0x62, 0x5f, 0xc9, 0xeb, 0x3e, 0xe4, 0x9f, 0x70, 0x17, 0x75,
|
||||
0x39, 0xcd, 0xd7, 0x72, 0x04, 0x2b, 0x79, 0xfb, 0x3d, 0xd1, 0xd7, 0x48, 0xad, 0xf5, 0xa5, 0xdb,
|
||||
0xd6, 0xe6, 0xcd, 0xf7, 0x3f, 0xd9, 0xf7, 0xe2, 0x93, 0xf1, 0xd1, 0xad, 0x6e, 0x30, 0x5c, 0x1f,
|
||||
0xc8, 0x10, 0x99, 0x48, 0xf3, 0x5d, 0x1f, 0xf8, 0xbd, 0x75, 0xfc, 0xfe, 0x68, 0x0a, 0xdf, 0xf0,
|
||||
0xff, 0xf4, 0xbf, 0x07, 0x00, 0x00, 0xff, 0xff, 0x5d, 0xb7, 0x1a, 0xb7, 0xf5, 0x5f, 0x00, 0x00,
|
||||
var fileDescriptor_rpc_854431eb46daab93 = []byte{
|
||||
// 7755 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x24, 0xd9,
|
||||
0x59, 0xb0, 0xab, 0x2f, 0x76, 0xf7, 0xd7, 0x6d, 0xbb, 0x7d, 0x7c, 0xeb, 0xe9, 0x99, 0x9d, 0xf5,
|
||||
0x56, 0x26, 0x33, 0x8e, 0x77, 0xff, 0xf1, 0xec, 0x24, 0xd9, 0x4c, 0x76, 0xfe, 0xfc, 0xf9, 0x7d,
|
||||
0x9b, 0xf1, 0x64, 0xbd, 0x1e, 0xa7, 0x3c, 0x93, 0xf9, 0x77, 0x93, 0x5f, 0x9d, 0x72, 0xf7, 0x71,
|
||||
0xbb, 0x76, 0xba, 0xab, 0x7a, 0xab, 0xaa, 0xed, 0x71, 0x96, 0x41, 0x08, 0x21, 0x40, 0x08, 0x84,
|
||||
0x02, 0x02, 0x11, 0x04, 0x42, 0x4a, 0x90, 0x20, 0xe2, 0x89, 0x87, 0x20, 0x24, 0x08, 0xaf, 0x48,
|
||||
0x91, 0x10, 0x42, 0x79, 0x44, 0x02, 0x21, 0x78, 0x41, 0x3c, 0x20, 0x90, 0x78, 0x44, 0x42, 0xe7,
|
||||
0x3b, 0x97, 0x3a, 0xa7, 0xaa, 0x7a, 0x3c, 0x9b, 0x04, 0x9e, 0xdc, 0xe7, 0x3b, 0x5f, 0x9d, 0xeb,
|
||||
0x77, 0x3f, 0xdf, 0x39, 0x86, 0x6a, 0x38, 0xec, 0xdc, 0x1c, 0x86, 0x41, 0x1c, 0x90, 0x72, 0xdf,
|
||||
0x0f, 0x87, 0x9d, 0xd6, 0x95, 0x5e, 0x10, 0xf4, 0xfa, 0x74, 0xdd, 0x1d, 0x7a, 0xeb, 0xae, 0xef,
|
||||
0x07, 0xb1, 0x1b, 0x7b, 0x81, 0x1f, 0x71, 0x24, 0xfb, 0xeb, 0x30, 0x73, 0x9f, 0xfa, 0x87, 0x94,
|
||||
0x76, 0x1d, 0xfa, 0xe1, 0x88, 0x46, 0x31, 0x79, 0x1d, 0xe6, 0x5c, 0xfa, 0x0d, 0x4a, 0xbb, 0xed,
|
||||
0xa1, 0x1b, 0x45, 0xc3, 0x93, 0xd0, 0x8d, 0x68, 0xd3, 0x5a, 0xb1, 0x56, 0xeb, 0x4e, 0x83, 0x57,
|
||||
0x1c, 0x28, 0x38, 0x79, 0x0d, 0xea, 0x11, 0x43, 0xa5, 0x7e, 0x1c, 0x06, 0xc3, 0xf3, 0x66, 0x01,
|
||||
0xf1, 0x6a, 0x0c, 0xb6, 0xc3, 0x41, 0x76, 0x1f, 0x66, 0x55, 0x0f, 0xd1, 0x30, 0xf0, 0x23, 0x4a,
|
||||
0x6e, 0xc1, 0x42, 0xc7, 0x1b, 0x9e, 0xd0, 0xb0, 0x8d, 0x1f, 0x0f, 0x7c, 0x3a, 0x08, 0x7c, 0xaf,
|
||||
0xd3, 0xb4, 0x56, 0x8a, 0xab, 0x55, 0x87, 0xf0, 0x3a, 0xf6, 0xc5, 0xbb, 0xa2, 0x86, 0xdc, 0x80,
|
||||
0x59, 0xea, 0x73, 0x38, 0xed, 0xe2, 0x57, 0xa2, 0xab, 0x99, 0x04, 0xcc, 0x3e, 0xb0, 0x7f, 0xb1,
|
||||
0x00, 0x73, 0x0f, 0x7c, 0x2f, 0x7e, 0xe2, 0xf6, 0xfb, 0x34, 0x96, 0x73, 0xba, 0x01, 0xb3, 0x67,
|
||||
0x08, 0xc0, 0x39, 0x9d, 0x05, 0x61, 0x57, 0xcc, 0x68, 0x86, 0x83, 0x0f, 0x04, 0x74, 0xec, 0xc8,
|
||||
0x0a, 0x63, 0x47, 0x96, 0xbb, 0x5c, 0xc5, 0x31, 0xcb, 0x75, 0x03, 0x66, 0x43, 0xda, 0x09, 0x4e,
|
||||
0x69, 0x78, 0xde, 0x3e, 0xf3, 0xfc, 0x6e, 0x70, 0xd6, 0x2c, 0xad, 0x58, 0xab, 0x65, 0x67, 0x46,
|
||||
0x82, 0x9f, 0x20, 0x94, 0x6c, 0xc2, 0x6c, 0xe7, 0xc4, 0xf5, 0x7d, 0xda, 0x6f, 0x1f, 0xb9, 0x9d,
|
||||
0xa7, 0xa3, 0x61, 0xd4, 0x2c, 0xaf, 0x58, 0xab, 0xb5, 0xdb, 0x97, 0x6e, 0xe2, 0xae, 0xde, 0xdc,
|
||||
0x3a, 0x71, 0xfd, 0x4d, 0xac, 0x39, 0xf4, 0xdd, 0x61, 0x74, 0x12, 0xc4, 0xce, 0x8c, 0xf8, 0x82,
|
||||
0x83, 0x23, 0x7b, 0x01, 0x88, 0xbe, 0x12, 0x7c, 0xed, 0xed, 0x3f, 0xb2, 0x60, 0xfe, 0xb1, 0xdf,
|
||||
0x0f, 0x3a, 0x4f, 0x7f, 0xc4, 0x25, 0xca, 0x99, 0x43, 0xe1, 0x65, 0xe7, 0x50, 0xfc, 0xb8, 0x73,
|
||||
0x58, 0x82, 0x05, 0x73, 0xb0, 0x62, 0x16, 0x14, 0x16, 0xd9, 0xd7, 0x3d, 0x2a, 0x87, 0x25, 0xa7,
|
||||
0xf1, 0x29, 0x68, 0x74, 0x46, 0x61, 0x48, 0xfd, 0xcc, 0x3c, 0x66, 0x05, 0x5c, 0x4d, 0xe4, 0x35,
|
||||
0xa8, 0xfb, 0xf4, 0x2c, 0x41, 0x13, 0xb4, 0xeb, 0xd3, 0x33, 0x89, 0x62, 0x37, 0x61, 0x29, 0xdd,
|
||||
0x8d, 0x18, 0xc0, 0x3f, 0x58, 0x50, 0x7a, 0x1c, 0x3f, 0x0b, 0xc8, 0x4d, 0x28, 0xc5, 0xe7, 0x43,
|
||||
0xce, 0x21, 0x33, 0xb7, 0x89, 0x98, 0xda, 0x46, 0xb7, 0x1b, 0xd2, 0x28, 0x7a, 0x74, 0x3e, 0xa4,
|
||||
0x4e, 0xdd, 0xe5, 0x85, 0x36, 0xc3, 0x23, 0x4d, 0x98, 0x12, 0x65, 0xec, 0xb0, 0xea, 0xc8, 0x22,
|
||||
0xb9, 0x0a, 0xe0, 0x0e, 0x82, 0x91, 0x1f, 0xb7, 0x23, 0x37, 0xc6, 0xa5, 0x2a, 0x3a, 0x1a, 0x84,
|
||||
0x5c, 0x81, 0xea, 0xf0, 0x69, 0x3b, 0xea, 0x84, 0xde, 0x30, 0x46, 0xb2, 0xa9, 0x3a, 0x09, 0x80,
|
||||
0xbc, 0x0e, 0x95, 0x60, 0x14, 0x0f, 0x03, 0xcf, 0x8f, 0x05, 0xa9, 0xcc, 0x8a, 0xb1, 0x3c, 0x1c,
|
||||
0xc5, 0x07, 0x0c, 0xec, 0x28, 0x04, 0x72, 0x0d, 0xa6, 0x3b, 0x81, 0x7f, 0xec, 0x85, 0x03, 0x2e,
|
||||
0x0c, 0x9a, 0x93, 0xd8, 0x9b, 0x09, 0xb4, 0xbf, 0x55, 0x80, 0xda, 0xa3, 0xd0, 0xf5, 0x23, 0xb7,
|
||||
0xc3, 0x00, 0x6c, 0xe8, 0xf1, 0xb3, 0xf6, 0x89, 0x1b, 0x9d, 0xe0, 0x6c, 0xab, 0x8e, 0x2c, 0x92,
|
||||
0x25, 0x98, 0xe4, 0x03, 0xc5, 0x39, 0x15, 0x1d, 0x51, 0x22, 0x6f, 0xc0, 0x9c, 0x3f, 0x1a, 0xb4,
|
||||
0xcd, 0xbe, 0x8a, 0x48, 0x2d, 0xd9, 0x0a, 0xb6, 0x00, 0x47, 0x6c, 0xaf, 0x79, 0x17, 0x7c, 0x86,
|
||||
0x1a, 0x84, 0xd8, 0x50, 0x17, 0x25, 0xea, 0xf5, 0x4e, 0xf8, 0x34, 0xcb, 0x8e, 0x01, 0x63, 0x6d,
|
||||
0xc4, 0xde, 0x80, 0xb6, 0xa3, 0xd8, 0x1d, 0x0c, 0xc5, 0xb4, 0x34, 0x08, 0xd6, 0x07, 0xb1, 0xdb,
|
||||
0x6f, 0x1f, 0x53, 0x1a, 0x35, 0xa7, 0x44, 0xbd, 0x82, 0x90, 0xeb, 0x30, 0xd3, 0xa5, 0x51, 0xdc,
|
||||
0x16, 0x9b, 0x42, 0xa3, 0x66, 0x05, 0x59, 0x3f, 0x05, 0x65, 0x94, 0x71, 0x9f, 0xc6, 0xda, 0xea,
|
||||
0x44, 0x82, 0x02, 0xed, 0x3d, 0x20, 0x1a, 0x78, 0x9b, 0xc6, 0xae, 0xd7, 0x8f, 0xc8, 0x5b, 0x50,
|
||||
0x8f, 0x35, 0x64, 0x14, 0x75, 0x35, 0x45, 0x2e, 0xda, 0x07, 0x8e, 0x81, 0x67, 0xdf, 0x87, 0xca,
|
||||
0x3d, 0x4a, 0xf7, 0xbc, 0x81, 0x17, 0x93, 0x25, 0x28, 0x1f, 0x7b, 0xcf, 0x28, 0x27, 0xe8, 0xe2,
|
||||
0xee, 0x84, 0xc3, 0x8b, 0xa4, 0x05, 0x53, 0x43, 0x1a, 0x76, 0xa8, 0x5c, 0xfe, 0xdd, 0x09, 0x47,
|
||||
0x02, 0x36, 0xa7, 0xa0, 0xdc, 0x67, 0x1f, 0xdb, 0xff, 0x56, 0x80, 0xda, 0x21, 0xf5, 0x15, 0xa3,
|
||||
0x10, 0x28, 0xb1, 0x29, 0x09, 0xe6, 0xc0, 0xdf, 0xe4, 0x55, 0xa8, 0xe1, 0x34, 0xa3, 0x38, 0xf4,
|
||||
0xfc, 0x9e, 0xa0, 0x4f, 0x60, 0xa0, 0x43, 0x84, 0x90, 0x06, 0x14, 0xdd, 0x81, 0xa4, 0x4d, 0xf6,
|
||||
0x93, 0x31, 0xd1, 0xd0, 0x3d, 0x1f, 0x30, 0x7e, 0x53, 0xbb, 0x56, 0x77, 0x6a, 0x02, 0xb6, 0xcb,
|
||||
0xb6, 0xed, 0x26, 0xcc, 0xeb, 0x28, 0xb2, 0xf5, 0x32, 0xb6, 0x3e, 0xa7, 0x61, 0x8a, 0x4e, 0x6e,
|
||||
0xc0, 0xac, 0xc4, 0x0f, 0xf9, 0x60, 0x71, 0x1f, 0xab, 0xce, 0x8c, 0x00, 0xcb, 0x29, 0xac, 0x42,
|
||||
0xe3, 0xd8, 0xf3, 0xdd, 0x7e, 0xbb, 0xd3, 0x8f, 0x4f, 0xdb, 0x5d, 0xda, 0x8f, 0x5d, 0xdc, 0xd1,
|
||||
0xb2, 0x33, 0x83, 0xf0, 0xad, 0x7e, 0x7c, 0xba, 0xcd, 0xa0, 0xe4, 0x0d, 0xa8, 0x1e, 0x53, 0xda,
|
||||
0xc6, 0x95, 0x68, 0x56, 0x0c, 0xee, 0x90, 0xab, 0xeb, 0x54, 0x8e, 0xe5, 0x3a, 0xaf, 0x42, 0x23,
|
||||
0x18, 0xc5, 0xbd, 0xc0, 0xf3, 0x7b, 0x6d, 0x26, 0x8f, 0xda, 0x5e, 0xb7, 0x59, 0x5d, 0xb1, 0x56,
|
||||
0x4b, 0xce, 0x8c, 0x84, 0x33, 0xa9, 0xf0, 0xa0, 0x4b, 0x5e, 0x01, 0xc0, 0xbe, 0x79, 0xc3, 0xb0,
|
||||
0x62, 0xad, 0x4e, 0x3b, 0x55, 0x06, 0xc1, 0x86, 0xec, 0x3f, 0xb5, 0xa0, 0xce, 0xd7, 0x5c, 0x28,
|
||||
0xbe, 0x6b, 0x30, 0x2d, 0xa7, 0x46, 0xc3, 0x30, 0x08, 0x05, 0x1f, 0x99, 0x40, 0xb2, 0x06, 0x0d,
|
||||
0x09, 0x18, 0x86, 0xd4, 0x1b, 0xb8, 0x3d, 0x2a, 0x84, 0x53, 0x06, 0x4e, 0x6e, 0x27, 0x2d, 0x86,
|
||||
0xc1, 0x28, 0xa6, 0x42, 0xc4, 0xd6, 0xc5, 0xec, 0x1c, 0x06, 0x73, 0x4c, 0x14, 0xc6, 0x47, 0x39,
|
||||
0x7b, 0x66, 0xc0, 0xec, 0xef, 0x59, 0x40, 0xd8, 0xd0, 0x1f, 0x05, 0xbc, 0x09, 0xb1, 0xe4, 0xe9,
|
||||
0xed, 0xb6, 0x5e, 0x7a, 0xbb, 0x0b, 0xe3, 0xb6, 0x7b, 0x15, 0x26, 0x71, 0x58, 0x4c, 0x30, 0x14,
|
||||
0xd3, 0x43, 0xdf, 0x2c, 0x34, 0x2d, 0x47, 0xd4, 0x13, 0x1b, 0xca, 0x7c, 0x8e, 0xa5, 0x9c, 0x39,
|
||||
0xf2, 0x2a, 0xfb, 0xdb, 0x16, 0xd4, 0xb7, 0xb8, 0x0e, 0x41, 0xa1, 0x47, 0x6e, 0x01, 0x39, 0x1e,
|
||||
0xf9, 0x5d, 0xb6, 0x97, 0xf1, 0x33, 0xaf, 0xdb, 0x3e, 0x3a, 0x67, 0x5d, 0xe1, 0xb8, 0x77, 0x27,
|
||||
0x9c, 0x9c, 0x3a, 0xf2, 0x06, 0x34, 0x0c, 0x68, 0x14, 0x87, 0x7c, 0xf4, 0xbb, 0x13, 0x4e, 0xa6,
|
||||
0x86, 0x2d, 0x26, 0x13, 0xab, 0xa3, 0xb8, 0xed, 0xf9, 0x5d, 0xfa, 0x0c, 0xd7, 0x7f, 0xda, 0x31,
|
||||
0x60, 0x9b, 0x33, 0x50, 0xd7, 0xbf, 0xb3, 0x3f, 0x80, 0x8a, 0x14, 0xca, 0x28, 0x90, 0x52, 0xe3,
|
||||
0x72, 0x34, 0x08, 0x69, 0x41, 0xc5, 0x1c, 0x85, 0x53, 0xf9, 0x38, 0x7d, 0xdb, 0xff, 0x07, 0x1a,
|
||||
0x7b, 0x4c, 0x32, 0xfa, 0x9e, 0xdf, 0x13, 0x5a, 0x89, 0x89, 0xeb, 0xe1, 0xe8, 0xe8, 0x29, 0x3d,
|
||||
0x17, 0xf4, 0x27, 0x4a, 0x4c, 0x26, 0x9c, 0x04, 0x51, 0x2c, 0xfa, 0xc1, 0xdf, 0xf6, 0x5f, 0x5a,
|
||||
0x40, 0x76, 0xa2, 0xd8, 0x1b, 0xb8, 0x31, 0xbd, 0x47, 0x15, 0x21, 0x3c, 0x84, 0x3a, 0x6b, 0xed,
|
||||
0x51, 0xb0, 0xc1, 0xe5, 0x3e, 0x97, 0x67, 0xaf, 0x8b, 0x2d, 0xc9, 0x7e, 0x70, 0x53, 0xc7, 0x66,
|
||||
0xa6, 0xe1, 0xb9, 0x63, 0x34, 0xc0, 0x64, 0x4f, 0xec, 0x86, 0x3d, 0x1a, 0xa3, 0x52, 0x10, 0x26,
|
||||
0x05, 0x70, 0xd0, 0x56, 0xe0, 0x1f, 0xb7, 0xbe, 0x08, 0x73, 0x99, 0x36, 0x98, 0x40, 0x4a, 0xa6,
|
||||
0xc1, 0x7e, 0x92, 0x05, 0x28, 0x9f, 0xba, 0xfd, 0x11, 0x15, 0x9a, 0x88, 0x17, 0xde, 0x2e, 0xdc,
|
||||
0xb1, 0xec, 0x0e, 0xcc, 0x1b, 0xe3, 0x12, 0x3c, 0xd9, 0x84, 0x29, 0x26, 0x1b, 0x98, 0xce, 0x45,
|
||||
0xb9, 0xea, 0xc8, 0x22, 0xb9, 0x0d, 0x0b, 0xc7, 0x94, 0x86, 0x6e, 0x8c, 0xc5, 0xf6, 0x90, 0x86,
|
||||
0xb8, 0x27, 0xa2, 0xe5, 0xdc, 0x3a, 0xfb, 0x1f, 0x2d, 0x98, 0x65, 0x7c, 0xf3, 0xae, 0xeb, 0x9f,
|
||||
0xcb, 0xb5, 0xda, 0xcb, 0x5d, 0xab, 0x55, 0xb1, 0x56, 0x29, 0xec, 0x8f, 0xbb, 0x50, 0xc5, 0xf4,
|
||||
0x42, 0x91, 0x15, 0xa8, 0x1b, 0xc3, 0x2d, 0x73, 0x25, 0x17, 0xb9, 0xf1, 0x01, 0x0d, 0x37, 0xcf,
|
||||
0x63, 0xfa, 0xe3, 0x2f, 0xe5, 0x75, 0x68, 0x24, 0xc3, 0x16, 0xeb, 0x48, 0xa0, 0xc4, 0x08, 0x53,
|
||||
0x34, 0x80, 0xbf, 0xed, 0xdf, 0xb1, 0x38, 0xe2, 0x56, 0xe0, 0x29, 0x05, 0xc9, 0x10, 0x99, 0x1e,
|
||||
0x95, 0x88, 0xec, 0xf7, 0x58, 0x03, 0xe2, 0xc7, 0x9f, 0x2c, 0xb9, 0x04, 0x95, 0x88, 0xfa, 0xdd,
|
||||
0xb6, 0xdb, 0xef, 0xa3, 0x1e, 0xa9, 0x38, 0x53, 0xac, 0xbc, 0xd1, 0xef, 0xdb, 0x37, 0x60, 0x4e,
|
||||
0x1b, 0xdd, 0x0b, 0xe6, 0xb1, 0x0f, 0x64, 0xcf, 0x8b, 0xe2, 0xc7, 0x7e, 0x34, 0xd4, 0xf4, 0xcf,
|
||||
0x65, 0xa8, 0x0e, 0x3c, 0x1f, 0x47, 0xc6, 0x39, 0xb7, 0xec, 0x54, 0x06, 0x9e, 0xcf, 0xc6, 0x15,
|
||||
0x61, 0xa5, 0xfb, 0x4c, 0x54, 0x16, 0x44, 0xa5, 0xfb, 0x0c, 0x2b, 0xed, 0x3b, 0x30, 0x6f, 0xb4,
|
||||
0x27, 0xba, 0x7e, 0x0d, 0xca, 0xa3, 0xf8, 0x59, 0x20, 0xad, 0x83, 0x9a, 0xa0, 0x10, 0x66, 0x67,
|
||||
0x3a, 0xbc, 0xc6, 0xbe, 0x0b, 0x73, 0xfb, 0xf4, 0x4c, 0x30, 0xb2, 0x1c, 0xc8, 0xf5, 0x0b, 0x6d,
|
||||
0x50, 0xac, 0xb7, 0x6f, 0x02, 0xd1, 0x3f, 0x4e, 0x18, 0x40, 0x5a, 0xa4, 0x96, 0x61, 0x91, 0xda,
|
||||
0xd7, 0x81, 0x1c, 0x7a, 0x3d, 0xff, 0x5d, 0x1a, 0x45, 0x6e, 0x4f, 0xb1, 0x7e, 0x03, 0x8a, 0x83,
|
||||
0xa8, 0x27, 0x44, 0x15, 0xfb, 0x69, 0x7f, 0x1a, 0xe6, 0x0d, 0x3c, 0xd1, 0xf0, 0x15, 0xa8, 0x46,
|
||||
0x5e, 0xcf, 0x77, 0xe3, 0x51, 0x48, 0x45, 0xd3, 0x09, 0xc0, 0xbe, 0x07, 0x0b, 0x5f, 0xa1, 0xa1,
|
||||
0x77, 0x7c, 0x7e, 0x51, 0xf3, 0x66, 0x3b, 0x85, 0x74, 0x3b, 0x3b, 0xb0, 0x98, 0x6a, 0x47, 0x74,
|
||||
0xcf, 0xc9, 0x57, 0xec, 0x64, 0xc5, 0xe1, 0x05, 0x4d, 0xf6, 0x15, 0x74, 0xd9, 0x67, 0x3f, 0x06,
|
||||
0xb2, 0x15, 0xf8, 0x3e, 0xed, 0xc4, 0x07, 0x94, 0x86, 0x89, 0x33, 0x9c, 0xd0, 0x6a, 0xed, 0xf6,
|
||||
0xb2, 0x58, 0xd9, 0xb4, 0x40, 0x15, 0x44, 0x4c, 0xa0, 0x34, 0xa4, 0xe1, 0x00, 0x1b, 0xae, 0x38,
|
||||
0xf8, 0xdb, 0x5e, 0x84, 0x79, 0xa3, 0x59, 0xe1, 0x3e, 0xbc, 0x09, 0x8b, 0xdb, 0x5e, 0xd4, 0xc9,
|
||||
0x76, 0xd8, 0x84, 0xa9, 0xe1, 0xe8, 0xa8, 0x9d, 0x70, 0xa2, 0x2c, 0x32, 0x8b, 0x33, 0xfd, 0x89,
|
||||
0x68, 0xec, 0xe7, 0x2d, 0x28, 0xed, 0x3e, 0xda, 0xdb, 0x62, 0xba, 0xc2, 0xf3, 0x3b, 0xc1, 0x80,
|
||||
0xe9, 0x5b, 0x3e, 0x69, 0x55, 0x1e, 0xcb, 0x61, 0x57, 0xa0, 0x8a, 0x6a, 0x9a, 0x19, 0xd1, 0xc2,
|
||||
0x6f, 0x4d, 0x00, 0xcc, 0x80, 0xa7, 0xcf, 0x86, 0x5e, 0x88, 0x16, 0xba, 0xb4, 0xbb, 0x4b, 0xa8,
|
||||
0x66, 0xb2, 0x15, 0xf6, 0x0f, 0xca, 0x30, 0x25, 0x94, 0x2f, 0xf6, 0xd7, 0x89, 0xbd, 0x53, 0x2a,
|
||||
0x46, 0x22, 0x4a, 0xcc, 0x04, 0x0a, 0xe9, 0x20, 0x88, 0x69, 0xdb, 0xd8, 0x06, 0x13, 0x88, 0x0e,
|
||||
0x8a, 0xf0, 0x1d, 0xb9, 0x4b, 0x53, 0xe4, 0x58, 0x06, 0x90, 0x2d, 0x96, 0xb4, 0xcf, 0x4a, 0x68,
|
||||
0x9f, 0xc9, 0x22, 0x5b, 0x89, 0x8e, 0x3b, 0x74, 0x3b, 0x5e, 0x7c, 0x2e, 0x44, 0x82, 0x2a, 0xb3,
|
||||
0xb6, 0xfb, 0x41, 0xc7, 0x65, 0x5e, 0x69, 0xdf, 0xf5, 0x3b, 0x54, 0x3a, 0x3f, 0x06, 0x90, 0x39,
|
||||
0x02, 0x62, 0x48, 0x12, 0x8d, 0x3b, 0x0b, 0x29, 0x28, 0xd3, 0xdf, 0x9d, 0x60, 0x30, 0xf0, 0x62,
|
||||
0xe6, 0x3f, 0xa0, 0x6d, 0x59, 0x74, 0x34, 0x08, 0x77, 0xb5, 0xb0, 0x74, 0xc6, 0x57, 0xaf, 0x2a,
|
||||
0x5d, 0x2d, 0x0d, 0xc8, 0x5a, 0x61, 0x5a, 0x87, 0x89, 0xb1, 0xa7, 0x67, 0x68, 0x48, 0x16, 0x1d,
|
||||
0x0d, 0xc2, 0xf6, 0x61, 0xe4, 0x47, 0x34, 0x8e, 0xfb, 0xb4, 0xab, 0x06, 0x54, 0x43, 0xb4, 0x6c,
|
||||
0x05, 0xb9, 0x05, 0xf3, 0xdc, 0xa5, 0x89, 0xdc, 0x38, 0x88, 0x4e, 0xbc, 0xa8, 0x1d, 0x31, 0xe7,
|
||||
0xa0, 0x8e, 0xf8, 0x79, 0x55, 0xe4, 0x0e, 0x2c, 0xa7, 0xc0, 0x21, 0xed, 0x50, 0xef, 0x94, 0x76,
|
||||
0x9b, 0xd3, 0xf8, 0xd5, 0xb8, 0x6a, 0xb2, 0x02, 0x35, 0xe6, 0xc9, 0x8d, 0x86, 0x5d, 0x97, 0x19,
|
||||
0x30, 0x33, 0xb8, 0x0f, 0x3a, 0x88, 0xbc, 0x09, 0xd3, 0x43, 0xca, 0xad, 0x9f, 0x93, 0xb8, 0xdf,
|
||||
0x89, 0x9a, 0xb3, 0x86, 0x74, 0x63, 0x94, 0xeb, 0x98, 0x18, 0x8c, 0x28, 0x3b, 0x11, 0x9a, 0xf4,
|
||||
0xee, 0x79, 0xb3, 0x21, 0xcc, 0x6a, 0x09, 0x40, 0x1e, 0x09, 0xbd, 0x53, 0x37, 0xa6, 0xcd, 0x39,
|
||||
0x2e, 0xd0, 0x45, 0x91, 0x7d, 0xe7, 0xf9, 0x5e, 0xec, 0xb9, 0x71, 0x10, 0x36, 0x09, 0xd6, 0x25,
|
||||
0x00, 0xb6, 0x88, 0x48, 0x1f, 0x51, 0xec, 0xc6, 0xa3, 0xa8, 0x7d, 0xdc, 0x77, 0x7b, 0x51, 0x73,
|
||||
0x9e, 0xdb, 0xa5, 0x99, 0x0a, 0xfb, 0xf7, 0x2c, 0x2e, 0xa4, 0x05, 0x41, 0x2b, 0x61, 0xfb, 0x2a,
|
||||
0xd4, 0x38, 0x29, 0xb7, 0x03, 0xbf, 0x7f, 0x2e, 0xa8, 0x1b, 0x38, 0xe8, 0xa1, 0xdf, 0x3f, 0x27,
|
||||
0x9f, 0x80, 0x69, 0xcf, 0xd7, 0x51, 0xb8, 0x3c, 0xa8, 0x4b, 0x20, 0x22, 0xbd, 0x0a, 0xb5, 0xe1,
|
||||
0xe8, 0xa8, 0xef, 0x75, 0x38, 0x4a, 0x91, 0xb7, 0xc2, 0x41, 0x88, 0xc0, 0x2c, 0x6d, 0x3e, 0x2b,
|
||||
0x8e, 0x51, 0x42, 0x8c, 0x9a, 0x80, 0x31, 0x14, 0x7b, 0x13, 0x16, 0xcc, 0x01, 0x0a, 0xc1, 0xb7,
|
||||
0x06, 0x15, 0xc1, 0x27, 0x51, 0xb3, 0x86, 0x6b, 0x3d, 0xa3, 0x45, 0x5c, 0x7c, 0xda, 0x77, 0x54,
|
||||
0xbd, 0xfd, 0x27, 0x25, 0x98, 0x17, 0xd0, 0xad, 0x7e, 0x10, 0xd1, 0xc3, 0xd1, 0x60, 0xe0, 0x86,
|
||||
0x39, 0x0c, 0x68, 0x5d, 0xc0, 0x80, 0x05, 0x93, 0x01, 0x19, 0x5b, 0x9c, 0xb8, 0x9e, 0xcf, 0xdd,
|
||||
0x04, 0xce, 0xbd, 0x1a, 0x84, 0xac, 0xc2, 0x6c, 0xa7, 0x1f, 0x44, 0xdc, 0x24, 0xd6, 0x1d, 0xfe,
|
||||
0x34, 0x38, 0x2b, 0x30, 0xca, 0x79, 0x02, 0x43, 0x67, 0xf8, 0xc9, 0x14, 0xc3, 0xdb, 0x50, 0x67,
|
||||
0x8d, 0x52, 0x29, 0xbf, 0xa6, 0xb8, 0x99, 0xac, 0xc3, 0xd8, 0x78, 0xd2, 0xec, 0xc5, 0x79, 0x79,
|
||||
0x36, 0x8f, 0xb9, 0xbc, 0x01, 0x45, 0xf9, 0xa8, 0x61, 0x57, 0x05, 0x73, 0x65, 0xab, 0xc8, 0x3d,
|
||||
0xe6, 0x25, 0xb2, 0xbe, 0x50, 0x49, 0x03, 0x2a, 0xe9, 0xeb, 0xe6, 0x8e, 0xe8, 0x6b, 0x7f, 0x93,
|
||||
0x15, 0x46, 0x21, 0x45, 0xc5, 0xad, 0x7d, 0x69, 0xff, 0x92, 0x05, 0x35, 0xad, 0x8e, 0x2c, 0xc2,
|
||||
0xdc, 0xd6, 0xc3, 0x87, 0x07, 0x3b, 0xce, 0xc6, 0xa3, 0x07, 0x5f, 0xd9, 0x69, 0x6f, 0xed, 0x3d,
|
||||
0x3c, 0xdc, 0x69, 0x4c, 0x30, 0xf0, 0xde, 0xc3, 0xad, 0x8d, 0xbd, 0xf6, 0xbd, 0x87, 0xce, 0x96,
|
||||
0x04, 0x5b, 0x64, 0x09, 0x88, 0xb3, 0xf3, 0xee, 0xc3, 0x47, 0x3b, 0x06, 0xbc, 0x40, 0x1a, 0x50,
|
||||
0xdf, 0x74, 0x76, 0x36, 0xb6, 0x76, 0x05, 0xa4, 0x48, 0x16, 0xa0, 0x71, 0xef, 0xf1, 0xfe, 0xf6,
|
||||
0x83, 0xfd, 0xfb, 0xed, 0xad, 0x8d, 0xfd, 0xad, 0x9d, 0xbd, 0x9d, 0xed, 0x46, 0x89, 0x4c, 0x43,
|
||||
0x75, 0x63, 0x73, 0x63, 0x7f, 0xfb, 0xe1, 0xfe, 0xce, 0x76, 0xa3, 0x6c, 0xff, 0x9d, 0x05, 0x8b,
|
||||
0x38, 0xea, 0x6e, 0x9a, 0x41, 0x56, 0xa0, 0xd6, 0x09, 0x82, 0x21, 0x33, 0x8e, 0x13, 0xf1, 0xaf,
|
||||
0x83, 0x18, 0xf1, 0x73, 0x61, 0x7b, 0x1c, 0x84, 0x1d, 0x2a, 0xf8, 0x03, 0x10, 0x74, 0x8f, 0x41,
|
||||
0x18, 0xf1, 0x8b, 0xed, 0xe5, 0x18, 0x9c, 0x3d, 0x6a, 0x1c, 0xc6, 0x51, 0x96, 0x60, 0xf2, 0x28,
|
||||
0xa4, 0x6e, 0xe7, 0x44, 0x70, 0x86, 0x28, 0x91, 0x4f, 0x25, 0xde, 0x5b, 0x87, 0xad, 0x7e, 0x9f,
|
||||
0x76, 0x91, 0x62, 0x2a, 0xce, 0xac, 0x80, 0x6f, 0x09, 0x30, 0x93, 0x16, 0xee, 0x91, 0xeb, 0x77,
|
||||
0x03, 0x9f, 0x76, 0x85, 0x69, 0x98, 0x00, 0xec, 0x03, 0x58, 0x4a, 0xcf, 0x4f, 0xf0, 0xd7, 0x5b,
|
||||
0x1a, 0x7f, 0x71, 0x4b, 0xad, 0x35, 0x7e, 0x37, 0x35, 0x5e, 0xfb, 0xfb, 0x02, 0x94, 0x98, 0xe2,
|
||||
0x1e, 0xaf, 0xe4, 0x75, 0x5b, 0xac, 0x98, 0x89, 0x0e, 0xa2, 0x43, 0xc8, 0x45, 0x39, 0x57, 0x77,
|
||||
0x1a, 0x24, 0xa9, 0x0f, 0x69, 0xe7, 0x14, 0x67, 0xac, 0xea, 0x19, 0x84, 0x31, 0x08, 0x33, 0x94,
|
||||
0xf1, 0x6b, 0xc1, 0x20, 0xb2, 0x2c, 0xeb, 0xf0, 0xcb, 0xa9, 0xa4, 0x0e, 0xbf, 0x6b, 0xc2, 0x94,
|
||||
0xe7, 0x1f, 0x05, 0x23, 0xbf, 0x8b, 0x0c, 0x51, 0x71, 0x64, 0x11, 0xe3, 0x91, 0xc8, 0xa8, 0xde,
|
||||
0x40, 0x92, 0x7f, 0x02, 0x20, 0xb7, 0xa1, 0x1a, 0x9d, 0xfb, 0x1d, 0x9d, 0xe6, 0x17, 0xc4, 0x2a,
|
||||
0xb1, 0x35, 0xb8, 0x79, 0x78, 0xee, 0x77, 0x90, 0xc2, 0x13, 0x34, 0xfb, 0x8b, 0x50, 0x91, 0x60,
|
||||
0x46, 0x96, 0x8f, 0xf7, 0xdf, 0xd9, 0x7f, 0xf8, 0x64, 0xbf, 0x7d, 0xf8, 0xde, 0xfe, 0x56, 0x63,
|
||||
0x82, 0xcc, 0x42, 0x6d, 0x63, 0x0b, 0x29, 0x1d, 0x01, 0x16, 0x43, 0x39, 0xd8, 0x38, 0x3c, 0x54,
|
||||
0x90, 0x82, 0x4d, 0x98, 0xb3, 0x1b, 0xa1, 0x75, 0xa4, 0xe2, 0x71, 0x6f, 0xc1, 0x9c, 0x06, 0x4b,
|
||||
0x2c, 0xed, 0x21, 0x03, 0xa4, 0x2c, 0x6d, 0x34, 0xab, 0x78, 0x8d, 0xdd, 0x80, 0x99, 0xfb, 0x34,
|
||||
0x7e, 0xe0, 0x1f, 0x07, 0xb2, 0xa5, 0x3f, 0x28, 0xc1, 0xac, 0x02, 0x89, 0x86, 0x56, 0x61, 0xd6,
|
||||
0xeb, 0x52, 0x3f, 0xf6, 0xe2, 0xf3, 0xb6, 0xe1, 0x53, 0xa7, 0xc1, 0xcc, 0x1c, 0x75, 0xfb, 0x9e,
|
||||
0x2b, 0xc3, 0xbe, 0xbc, 0xc0, 0x7c, 0x4c, 0xa6, 0x2b, 0xa5, 0xfa, 0x53, 0x74, 0xc5, 0x5d, 0xf9,
|
||||
0xdc, 0x3a, 0x26, 0x81, 0x18, 0x5c, 0xa8, 0x18, 0xf5, 0x09, 0x37, 0xcb, 0xf2, 0xaa, 0xd8, 0x56,
|
||||
0xf1, 0x96, 0xd8, 0x94, 0xcb, 0x5c, 0x9f, 0x2a, 0x40, 0x26, 0xae, 0x3a, 0xc9, 0xe5, 0x63, 0x3a,
|
||||
0xae, 0xaa, 0xc5, 0x66, 0x2b, 0x99, 0xd8, 0x2c, 0x93, 0x9f, 0xe7, 0x7e, 0x87, 0x76, 0xdb, 0x71,
|
||||
0xd0, 0x46, 0x39, 0x8f, 0x24, 0x51, 0x71, 0xd2, 0x60, 0x72, 0x05, 0xa6, 0x62, 0x1a, 0xc5, 0x3e,
|
||||
0xe5, 0x01, 0xb3, 0x0a, 0x86, 0x78, 0x24, 0x88, 0xd9, 0xd0, 0xa3, 0xd0, 0x8b, 0x9a, 0x75, 0x8c,
|
||||
0xba, 0xe2, 0x6f, 0xf2, 0x19, 0x58, 0x3c, 0xa2, 0x51, 0xdc, 0x3e, 0xa1, 0x6e, 0x97, 0x86, 0x48,
|
||||
0x5e, 0x3c, 0xbc, 0xcb, 0x4d, 0x93, 0xfc, 0x4a, 0x46, 0xb8, 0xa7, 0x34, 0x8c, 0xbc, 0xc0, 0x47,
|
||||
0xa3, 0xa4, 0xea, 0xc8, 0x22, 0x6b, 0x8f, 0x4d, 0x5e, 0x29, 0x69, 0xb5, 0x82, 0xb3, 0x38, 0xf1,
|
||||
0xfc, 0x4a, 0x72, 0x0d, 0x26, 0x71, 0x02, 0x51, 0xb3, 0x61, 0xc4, 0xa9, 0xb6, 0x18, 0xd0, 0x11,
|
||||
0x75, 0x5f, 0x2a, 0x55, 0x6a, 0x8d, 0xba, 0xfd, 0x39, 0x28, 0x23, 0x98, 0x6d, 0x3a, 0x5f, 0x0c,
|
||||
0x4e, 0x14, 0xbc, 0xc0, 0x86, 0xe6, 0xd3, 0xf8, 0x2c, 0x08, 0x9f, 0xca, 0x33, 0x00, 0x51, 0xb4,
|
||||
0xbf, 0x81, 0x5e, 0x88, 0x8a, 0x89, 0x3f, 0x46, 0x13, 0x8a, 0xf9, 0x92, 0x7c, 0xa9, 0xa3, 0x13,
|
||||
0x57, 0x38, 0x46, 0x15, 0x04, 0x1c, 0x9e, 0xb8, 0x4c, 0x56, 0x1a, 0xbb, 0xc7, 0x7d, 0xcd, 0x1a,
|
||||
0xc2, 0x76, 0xf9, 0xe6, 0x5d, 0x83, 0x19, 0x19, 0x6d, 0x8f, 0xda, 0x7d, 0x7a, 0x1c, 0xcb, 0x48,
|
||||
0x91, 0x3f, 0x1a, 0xa0, 0x43, 0xba, 0x47, 0x8f, 0x63, 0x7b, 0x1f, 0xe6, 0x84, 0xfc, 0x7a, 0x38,
|
||||
0xa4, 0xb2, 0xeb, 0xcf, 0xe7, 0xd9, 0x01, 0xb5, 0xdb, 0xf3, 0xa6, 0xc0, 0xe3, 0xe7, 0x0b, 0x26,
|
||||
0xa6, 0xed, 0x00, 0xd1, 0xe5, 0xa1, 0x68, 0x50, 0x28, 0x63, 0x19, 0x0b, 0x13, 0xd3, 0x31, 0x60,
|
||||
0x6c, 0x7d, 0xa2, 0x51, 0xa7, 0x23, 0xcf, 0x48, 0x98, 0xc7, 0xce, 0x8b, 0xf6, 0x1f, 0x5a, 0x30,
|
||||
0x8f, 0xad, 0x49, 0x4b, 0x46, 0xe8, 0x9c, 0x3b, 0x1f, 0x63, 0x98, 0xf5, 0x8e, 0x1e, 0x1f, 0x5c,
|
||||
0x80, 0xb2, 0xae, 0x85, 0x78, 0xe1, 0xe3, 0xc7, 0x1d, 0x4a, 0xe9, 0xb8, 0x83, 0xfd, 0x5b, 0x16,
|
||||
0xcc, 0x71, 0x45, 0x80, 0x56, 0xa5, 0x98, 0xfe, 0xff, 0x86, 0x69, 0xae, 0xd1, 0x05, 0x57, 0x8b,
|
||||
0x81, 0x26, 0xa2, 0x11, 0xa1, 0x1c, 0x79, 0x77, 0xc2, 0x31, 0x91, 0xc9, 0x5d, 0xb4, 0xaa, 0xfc,
|
||||
0x36, 0x42, 0x73, 0x4e, 0xd3, 0xcc, 0xb5, 0xde, 0x9d, 0x70, 0x34, 0xf4, 0xcd, 0x0a, 0x4c, 0x72,
|
||||
0x93, 0xdc, 0xbe, 0x0f, 0xd3, 0x46, 0x47, 0x46, 0xcc, 0xa3, 0xce, 0x63, 0x1e, 0x99, 0xe0, 0x62,
|
||||
0x21, 0x27, 0xb8, 0xf8, 0xc7, 0x45, 0x20, 0x8c, 0x58, 0x52, 0xbb, 0xc1, 0x7c, 0x82, 0xa0, 0x6b,
|
||||
0x78, 0x78, 0x75, 0x47, 0x07, 0x91, 0x9b, 0x40, 0xb4, 0xa2, 0x8c, 0x11, 0x73, 0x95, 0x97, 0x53,
|
||||
0xc3, 0xc4, 0xa4, 0xb0, 0x18, 0x84, 0x6e, 0x17, 0xbe, 0x2c, 0x5f, 0xf6, 0xdc, 0x3a, 0xa6, 0xd5,
|
||||
0x86, 0xa3, 0xe8, 0x04, 0x23, 0x7b, 0xc2, 0x07, 0x94, 0xe5, 0xf4, 0xfe, 0x4e, 0x5e, 0xb8, 0xbf,
|
||||
0x53, 0x99, 0xb8, 0x92, 0xe6, 0x85, 0x54, 0x4c, 0x2f, 0xe4, 0x1a, 0x4c, 0x0f, 0x98, 0x9d, 0x1b,
|
||||
0xf7, 0x3b, 0xed, 0x01, 0xeb, 0x5d, 0xb8, 0x7c, 0x06, 0x90, 0xac, 0x41, 0x43, 0xd8, 0x38, 0x89,
|
||||
0xab, 0xc3, 0x4f, 0x10, 0x32, 0x70, 0x26, 0xbf, 0x93, 0x48, 0x53, 0x0d, 0x07, 0x9b, 0x00, 0x98,
|
||||
0x5f, 0x13, 0x31, 0x0a, 0x69, 0x8f, 0x7c, 0x71, 0xa0, 0x46, 0xbb, 0xe8, 0xec, 0x55, 0x9c, 0x6c,
|
||||
0x85, 0xfd, 0x6b, 0x16, 0x34, 0xd8, 0x9e, 0x19, 0x64, 0xf9, 0x36, 0x20, 0x57, 0xbc, 0x24, 0x55,
|
||||
0x1a, 0xb8, 0xe4, 0x0e, 0x54, 0xb1, 0x1c, 0x0c, 0xa9, 0x2f, 0x68, 0xb2, 0x69, 0xd2, 0x64, 0x22,
|
||||
0x4f, 0x76, 0x27, 0x9c, 0x04, 0x59, 0xa3, 0xc8, 0xbf, 0xb6, 0xa0, 0x26, 0x7a, 0xf9, 0x91, 0x23,
|
||||
0x19, 0x2d, 0xed, 0x04, 0x94, 0x53, 0x52, 0x72, 0xe0, 0xb9, 0x0a, 0xb3, 0x03, 0x37, 0x1e, 0x85,
|
||||
0x4c, 0x1f, 0x1b, 0x51, 0x8c, 0x34, 0x98, 0x29, 0x57, 0x14, 0x9d, 0x51, 0x3b, 0xf6, 0xfa, 0x6d,
|
||||
0x59, 0x2b, 0xce, 0x1a, 0xf3, 0xaa, 0x98, 0x04, 0x89, 0x62, 0xb7, 0x47, 0x85, 0xde, 0xe4, 0x05,
|
||||
0xbb, 0x09, 0x4b, 0x62, 0x42, 0x29, 0xfb, 0xd8, 0xfe, 0x7e, 0x1d, 0x96, 0x33, 0x55, 0x2a, 0x33,
|
||||
0x42, 0xb8, 0xe7, 0x7d, 0x6f, 0x70, 0x14, 0x28, 0xe7, 0xc2, 0xd2, 0x3d, 0x77, 0xa3, 0x8a, 0xf4,
|
||||
0x60, 0x51, 0x1a, 0x08, 0x6c, 0x4d, 0x13, 0x65, 0x56, 0x40, 0x2d, 0xf5, 0xa6, 0xb9, 0x85, 0xe9,
|
||||
0x0e, 0x25, 0x5c, 0x67, 0xe2, 0xfc, 0xf6, 0xc8, 0x09, 0x34, 0x95, 0x25, 0x22, 0x84, 0xb5, 0x66,
|
||||
0xad, 0xb0, 0xbe, 0xde, 0xb8, 0xa0, 0x2f, 0xc3, 0x9c, 0x76, 0xc6, 0xb6, 0x46, 0xce, 0xe1, 0xaa,
|
||||
0xac, 0x43, 0x69, 0x9c, 0xed, 0xaf, 0xf4, 0x52, 0x73, 0x43, 0x47, 0xc1, 0xec, 0xf4, 0x82, 0x86,
|
||||
0xc9, 0x07, 0xb0, 0x74, 0xe6, 0x7a, 0xb1, 0x1c, 0x96, 0x66, 0x1b, 0x94, 0xb1, 0xcb, 0xdb, 0x17,
|
||||
0x74, 0xf9, 0x84, 0x7f, 0x6c, 0xa8, 0xa8, 0x31, 0x2d, 0xb6, 0x7e, 0x60, 0xc1, 0x8c, 0xd9, 0x0e,
|
||||
0x23, 0x53, 0xc1, 0xfb, 0x52, 0x06, 0x4a, 0x6b, 0x32, 0x05, 0xce, 0xfa, 0xe7, 0x85, 0x3c, 0xff,
|
||||
0x5c, 0xf7, 0x8a, 0x8b, 0x17, 0x85, 0xc1, 0x4a, 0x2f, 0x17, 0x06, 0x2b, 0xe7, 0x85, 0xc1, 0x5a,
|
||||
0xff, 0x61, 0x01, 0xc9, 0xd2, 0x12, 0xb9, 0xcf, 0x03, 0x04, 0x3e, 0xed, 0x0b, 0x91, 0xf2, 0xbf,
|
||||
0x5e, 0x8e, 0x1e, 0xe5, 0xda, 0xc9, 0xaf, 0x19, 0x63, 0xe8, 0xc9, 0x02, 0xba, 0xb1, 0x33, 0xed,
|
||||
0xe4, 0x55, 0xa5, 0x02, 0x73, 0xa5, 0x8b, 0x03, 0x73, 0xe5, 0x8b, 0x03, 0x73, 0x93, 0xe9, 0xc0,
|
||||
0x5c, 0xeb, 0xe7, 0x2c, 0x98, 0xcf, 0xd9, 0xf4, 0x9f, 0xdc, 0xc4, 0xd9, 0x36, 0x19, 0xb2, 0xa0,
|
||||
0x20, 0xb6, 0x49, 0x07, 0xb6, 0x7e, 0x0a, 0xa6, 0x0d, 0x42, 0xff, 0xc9, 0xf5, 0x9f, 0xb6, 0xd7,
|
||||
0x38, 0x9d, 0x19, 0xb0, 0xd6, 0xbf, 0x14, 0x80, 0x64, 0x99, 0xed, 0x7f, 0x74, 0x0c, 0xd9, 0x75,
|
||||
0x2a, 0xe6, 0xac, 0xd3, 0x7f, 0xab, 0x1e, 0x78, 0x03, 0xe6, 0x44, 0x06, 0x94, 0x16, 0x16, 0xe2,
|
||||
0x14, 0x93, 0xad, 0x60, 0x16, 0xab, 0x19, 0x15, 0xad, 0x18, 0x19, 0x21, 0x9a, 0x32, 0x4c, 0x05,
|
||||
0x47, 0xed, 0x16, 0x34, 0xc5, 0x0a, 0xed, 0x9c, 0x52, 0x3f, 0x3e, 0x1c, 0x1d, 0xf1, 0x14, 0x20,
|
||||
0x2f, 0xf0, 0xed, 0xef, 0x15, 0x95, 0xd1, 0x8d, 0x95, 0x42, 0xbd, 0x7f, 0x06, 0xea, 0xba, 0x30,
|
||||
0x17, 0xdb, 0x91, 0x8a, 0x0a, 0x32, 0xc5, 0xae, 0x63, 0x91, 0x6d, 0x98, 0x41, 0x91, 0xd5, 0x55,
|
||||
0xdf, 0x15, 0xf0, 0xbb, 0x17, 0x44, 0x3b, 0x76, 0x27, 0x9c, 0xd4, 0x37, 0xe4, 0x0b, 0x30, 0x63,
|
||||
0xba, 0x52, 0xc2, 0x46, 0xc8, 0xb3, 0xcd, 0xd9, 0xe7, 0x26, 0x32, 0xd9, 0x80, 0x46, 0xda, 0x17,
|
||||
0x13, 0xe7, 0xff, 0x63, 0x1a, 0xc8, 0xa0, 0x93, 0x3b, 0xe2, 0x78, 0xac, 0x8c, 0x51, 0x88, 0x6b,
|
||||
0xe6, 0x67, 0xda, 0x32, 0xdd, 0xe4, 0x7f, 0xb4, 0x03, 0xb3, 0xaf, 0x01, 0x24, 0x30, 0xd2, 0x80,
|
||||
0xfa, 0xc3, 0x83, 0x9d, 0xfd, 0xf6, 0xd6, 0xee, 0xc6, 0xfe, 0xfe, 0xce, 0x5e, 0x63, 0x82, 0x10,
|
||||
0x98, 0xc1, 0xa0, 0xd9, 0xb6, 0x82, 0x59, 0x0c, 0x26, 0xc2, 0x14, 0x12, 0x56, 0x20, 0x0b, 0xd0,
|
||||
0x78, 0xb0, 0x9f, 0x82, 0x16, 0x37, 0xab, 0x8a, 0x3f, 0xec, 0x25, 0x58, 0xe0, 0x19, 0x6e, 0x9b,
|
||||
0x9c, 0x3c, 0xa4, 0xad, 0xf0, 0xbb, 0x16, 0x2c, 0xa6, 0x2a, 0x92, 0x54, 0x12, 0x6e, 0x0e, 0x98,
|
||||
0x36, 0x82, 0x09, 0xc4, 0x90, 0xb7, 0xb4, 0xfc, 0x52, 0x12, 0x24, 0x5b, 0xc1, 0x68, 0x5e, 0xb3,
|
||||
0x14, 0x53, 0x9c, 0x94, 0x57, 0x65, 0x2f, 0xf3, 0x3c, 0x3c, 0xcc, 0xd8, 0x33, 0x06, 0x7e, 0xcc,
|
||||
0x33, 0xe7, 0xf4, 0x8a, 0xe4, 0xb8, 0xd1, 0x1c, 0xb2, 0x2c, 0x32, 0x23, 0xdf, 0x30, 0x3d, 0xcc,
|
||||
0xf1, 0xe6, 0xd6, 0xd9, 0x7f, 0x51, 0x00, 0xf2, 0xe5, 0x11, 0x0d, 0xcf, 0x31, 0x0b, 0x44, 0xc5,
|
||||
0x20, 0x97, 0xd3, 0x11, 0xb6, 0xc9, 0xe1, 0xe8, 0xe8, 0x1d, 0x7a, 0x2e, 0x33, 0x98, 0x0a, 0x7a,
|
||||
0x06, 0x13, 0x30, 0xe7, 0x58, 0xe5, 0xa0, 0x58, 0xab, 0x65, 0x0c, 0x49, 0x54, 0xfd, 0xd1, 0x80,
|
||||
0x37, 0x9a, 0x9b, 0x68, 0x54, 0xba, 0x38, 0xd1, 0xa8, 0x7c, 0x51, 0xa2, 0xd1, 0x27, 0x60, 0xda,
|
||||
0xeb, 0xf9, 0x01, 0x13, 0x0b, 0x4c, 0xb1, 0x47, 0xcd, 0xc9, 0x95, 0x22, 0x73, 0x86, 0x05, 0x70,
|
||||
0x9f, 0xc1, 0xc8, 0xe7, 0x12, 0x24, 0xda, 0xed, 0x61, 0xd2, 0x9a, 0x2e, 0x28, 0x76, 0xba, 0x3d,
|
||||
0xba, 0x17, 0x74, 0xdc, 0x38, 0x08, 0xd5, 0x87, 0x0c, 0x16, 0x31, 0xaf, 0x3f, 0x0a, 0x46, 0xcc,
|
||||
0xcc, 0x91, 0x4b, 0xc1, 0xc3, 0x36, 0x75, 0x0e, 0x3d, 0xc0, 0x05, 0xb1, 0xdf, 0x83, 0x9a, 0xd6,
|
||||
0x04, 0x66, 0x34, 0x09, 0x13, 0x42, 0xf8, 0x83, 0x25, 0x6e, 0xb1, 0xfb, 0xb4, 0xff, 0xa0, 0x4b,
|
||||
0x5e, 0x87, 0xb9, 0xae, 0x17, 0x52, 0x4c, 0x4e, 0x6b, 0x87, 0xf4, 0x94, 0x86, 0x91, 0xf4, 0x9c,
|
||||
0x1b, 0xaa, 0xc2, 0xe1, 0x70, 0xfb, 0x2e, 0xcc, 0x1b, 0x5b, 0xa3, 0x28, 0x57, 0x26, 0xfc, 0x58,
|
||||
0xd9, 0x84, 0x1f, 0x99, 0xec, 0x63, 0xff, 0x42, 0x01, 0x8a, 0xbb, 0xc1, 0x50, 0x3f, 0x62, 0xb0,
|
||||
0xcc, 0x23, 0x06, 0x61, 0x02, 0xb5, 0x95, 0x85, 0x23, 0x34, 0xa3, 0x01, 0x24, 0x6b, 0x30, 0xe3,
|
||||
0x0e, 0xe2, 0x76, 0x1c, 0x30, 0x93, 0xef, 0xcc, 0x0d, 0xbb, 0x9c, 0x9c, 0x71, 0x8b, 0x53, 0x35,
|
||||
0x64, 0x01, 0x8a, 0xca, 0x56, 0x40, 0x04, 0x56, 0x64, 0xfe, 0x06, 0x1e, 0x75, 0x9e, 0x8b, 0xc8,
|
||||
0x99, 0x28, 0x31, 0x6e, 0x31, 0xbf, 0xe7, 0xce, 0x1e, 0x97, 0xf8, 0x79, 0x55, 0xcc, 0x1c, 0x63,
|
||||
0xd4, 0x81, 0x68, 0x22, 0xce, 0x2a, 0xcb, 0x7a, 0x4c, 0xb8, 0x62, 0x1e, 0xfc, 0xfe, 0xb3, 0x05,
|
||||
0x65, 0x5c, 0x1b, 0xa6, 0xbd, 0x38, 0x7b, 0xab, 0x53, 0x06, 0x5c, 0x93, 0x69, 0x27, 0x0d, 0x26,
|
||||
0xb6, 0x91, 0xe6, 0x58, 0x50, 0x13, 0xd2, 0x53, 0x1d, 0x57, 0xa0, 0xca, 0x4b, 0x2a, 0xa5, 0x8f,
|
||||
0xd3, 0xbd, 0x02, 0x92, 0xab, 0x50, 0x3a, 0x09, 0x86, 0xd2, 0xdc, 0x06, 0x79, 0x60, 0x17, 0x0c,
|
||||
0x1d, 0x84, 0x27, 0xe3, 0x61, 0xed, 0xf1, 0x69, 0x71, 0x23, 0x2a, 0x0d, 0x66, 0x66, 0xa4, 0x6a,
|
||||
0x56, 0x5f, 0xa6, 0x14, 0xd4, 0x5e, 0x83, 0x59, 0x46, 0xf5, 0x5a, 0xd4, 0x75, 0x2c, 0x2b, 0xdb,
|
||||
0x3f, 0x63, 0x41, 0x45, 0x22, 0x93, 0x55, 0x28, 0x31, 0x16, 0x4a, 0x39, 0xae, 0xea, 0xa0, 0x9e,
|
||||
0xe1, 0x39, 0x88, 0xc1, 0x8c, 0x09, 0x0c, 0x86, 0x25, 0x7e, 0x92, 0x0c, 0x85, 0x25, 0x6e, 0x80,
|
||||
0x1a, 0x6e, 0xca, 0x7a, 0x4e, 0x41, 0xed, 0xef, 0x5a, 0x30, 0x6d, 0xf4, 0x41, 0x56, 0xa0, 0xd6,
|
||||
0x77, 0xa3, 0x58, 0x1c, 0x7e, 0x8a, 0xed, 0xd1, 0x41, 0xfa, 0x46, 0x17, 0xcc, 0xe0, 0xbf, 0x8a,
|
||||
0x10, 0x17, 0xf5, 0x08, 0xf1, 0x2d, 0xa8, 0x26, 0xc9, 0xa8, 0x25, 0x83, 0xf7, 0x59, 0x8f, 0x32,
|
||||
0x05, 0x21, 0x41, 0xc2, 0xa0, 0x63, 0xd0, 0x0f, 0x42, 0x71, 0x52, 0xc6, 0x0b, 0xf6, 0x5d, 0xa8,
|
||||
0x69, 0xf8, 0x7a, 0x0c, 0xd2, 0x32, 0x62, 0x90, 0x2a, 0x3f, 0xa7, 0x90, 0xe4, 0xe7, 0xd8, 0xff,
|
||||
0x6a, 0xc1, 0x34, 0xa3, 0x41, 0xcf, 0xef, 0x1d, 0x04, 0x7d, 0xaf, 0x73, 0x8e, 0x7b, 0x2f, 0xc9,
|
||||
0x4d, 0x88, 0x44, 0x49, 0x8b, 0x26, 0x98, 0x51, 0xbd, 0x8c, 0x7c, 0x08, 0x16, 0x55, 0x65, 0xc6,
|
||||
0xc3, 0x8c, 0x03, 0x8e, 0xdc, 0x48, 0xb0, 0x85, 0xb0, 0xda, 0x0c, 0x20, 0xe3, 0x34, 0x06, 0xc0,
|
||||
0x6c, 0xab, 0x81, 0xd7, 0xef, 0x7b, 0x1c, 0x97, 0xdb, 0xf4, 0x79, 0x55, 0xac, 0xcf, 0xae, 0x17,
|
||||
0xb9, 0x47, 0xc9, 0xe9, 0x8f, 0x2a, 0x63, 0x78, 0xc6, 0x7d, 0xa6, 0x85, 0x67, 0x26, 0x51, 0xae,
|
||||
0x98, 0x40, 0xfb, 0xcf, 0x0a, 0x50, 0x93, 0x26, 0x42, 0xb7, 0x47, 0xc5, 0x81, 0xa6, 0x29, 0x18,
|
||||
0x35, 0x88, 0xac, 0x37, 0xbc, 0x31, 0x0d, 0x92, 0x26, 0x8c, 0x62, 0x96, 0x30, 0xae, 0x40, 0x95,
|
||||
0x11, 0xe8, 0x9b, 0xe8, 0xf6, 0x89, 0xfc, 0x6e, 0x05, 0x90, 0xb5, 0xb7, 0xb1, 0xb6, 0x9c, 0xd4,
|
||||
0x22, 0xe0, 0x85, 0xc7, 0x9f, 0x77, 0xa0, 0x2e, 0x9a, 0xc1, 0x9d, 0x43, 0xc9, 0x93, 0xb0, 0x88,
|
||||
0xb1, 0xab, 0x8e, 0x81, 0x29, 0xbf, 0xbc, 0x2d, 0xbf, 0xac, 0x5c, 0xf4, 0xa5, 0xc4, 0xb4, 0xef,
|
||||
0xab, 0x53, 0xe5, 0xfb, 0xa1, 0x3b, 0x3c, 0x91, 0xbc, 0x7c, 0x0b, 0xe6, 0x3d, 0xbf, 0xd3, 0x1f,
|
||||
0x75, 0x69, 0x7b, 0xe4, 0xbb, 0xbe, 0x1f, 0x8c, 0xfc, 0x0e, 0x95, 0x09, 0x3a, 0x79, 0x55, 0x76,
|
||||
0x57, 0xa5, 0x73, 0x62, 0x43, 0x64, 0x0d, 0xca, 0x5c, 0x55, 0x72, 0xdd, 0x91, 0xcf, 0xe8, 0x1c,
|
||||
0x85, 0xac, 0x42, 0x99, 0x6b, 0xcc, 0x82, 0xc1, 0x35, 0xda, 0xae, 0x3a, 0x1c, 0x81, 0x89, 0x1d,
|
||||
0xcc, 0xe8, 0x35, 0xc5, 0x8e, 0xa9, 0x77, 0x26, 0x3b, 0x98, 0xf3, 0x6b, 0x2f, 0x00, 0xd9, 0xe7,
|
||||
0x9c, 0xa2, 0x9f, 0x0d, 0x7d, 0xbf, 0x08, 0x35, 0x0d, 0xcc, 0x24, 0x48, 0x8f, 0x0d, 0xb8, 0xdd,
|
||||
0xf5, 0xdc, 0x01, 0x8d, 0x69, 0x28, 0xb8, 0x23, 0x05, 0x65, 0x78, 0xee, 0x69, 0xaf, 0x1d, 0x8c,
|
||||
0xe2, 0x76, 0x97, 0xf6, 0x42, 0xca, 0xb5, 0x29, 0x53, 0x4d, 0x06, 0x94, 0xe1, 0x31, 0xfa, 0xd4,
|
||||
0xf0, 0x38, 0x05, 0xa5, 0xa0, 0xf2, 0xa4, 0x87, 0xaf, 0x51, 0x29, 0x39, 0xe9, 0xe1, 0x2b, 0x92,
|
||||
0x96, 0x7d, 0xe5, 0x1c, 0xd9, 0xf7, 0x16, 0x2c, 0x71, 0x29, 0x27, 0xe4, 0x41, 0x3b, 0x45, 0x58,
|
||||
0x63, 0x6a, 0xc9, 0x1a, 0x34, 0xd8, 0x98, 0x25, 0x4b, 0x44, 0xde, 0x37, 0x78, 0xd4, 0xd4, 0x72,
|
||||
0x32, 0x70, 0x86, 0x8b, 0xe1, 0x4b, 0x1d, 0x97, 0x1f, 0xb7, 0x67, 0xe0, 0x88, 0xeb, 0x3e, 0x33,
|
||||
0x71, 0xab, 0x02, 0x37, 0x05, 0x27, 0x77, 0x60, 0x79, 0x40, 0xbb, 0x9e, 0x6b, 0x36, 0x81, 0x11,
|
||||
0x60, 0x9e, 0x53, 0x33, 0xae, 0xda, 0x9e, 0x86, 0xda, 0x61, 0x1c, 0x0c, 0xe5, 0x76, 0xce, 0x40,
|
||||
0x9d, 0x17, 0x45, 0x8a, 0xd5, 0x65, 0xb8, 0x84, 0xf4, 0xf7, 0x28, 0x18, 0x06, 0xfd, 0xa0, 0x77,
|
||||
0x6e, 0x38, 0x5d, 0x7f, 0x65, 0xc1, 0xbc, 0x51, 0x9b, 0x78, 0x5d, 0x18, 0xaf, 0x91, 0xb9, 0x31,
|
||||
0x9c, 0x64, 0xe7, 0x34, 0xe1, 0xcd, 0x11, 0x79, 0x68, 0xfc, 0xb1, 0x48, 0x97, 0xd9, 0x48, 0xae,
|
||||
0xcd, 0xc8, 0x0f, 0x39, 0xfd, 0x36, 0xb3, 0xf4, 0x2b, 0xbe, 0x97, 0xb7, 0x66, 0x64, 0x13, 0x5f,
|
||||
0x10, 0x09, 0x0f, 0xdc, 0x09, 0x93, 0xe1, 0x39, 0xe5, 0xb6, 0xe9, 0x4e, 0xba, 0x1c, 0x41, 0x47,
|
||||
0x01, 0x23, 0xfb, 0x97, 0x2d, 0x80, 0x64, 0x74, 0x78, 0x4c, 0xae, 0x14, 0x10, 0xbf, 0xa2, 0xa5,
|
||||
0x29, 0x9b, 0xd7, 0xa0, 0xae, 0x4e, 0x3a, 0x13, 0x9d, 0x56, 0x93, 0x30, 0x66, 0x73, 0xdf, 0x80,
|
||||
0xd9, 0x5e, 0x3f, 0x38, 0x42, 0x83, 0x00, 0x73, 0xf6, 0x22, 0x91, 0x68, 0x36, 0xc3, 0xc1, 0xf7,
|
||||
0x04, 0x34, 0x51, 0x80, 0x25, 0x4d, 0x01, 0xda, 0xbf, 0x52, 0x50, 0x07, 0x53, 0xc9, 0x9c, 0xc7,
|
||||
0xf2, 0x27, 0xb9, 0x9d, 0x11, 0xc4, 0x63, 0xce, 0x81, 0xd0, 0xac, 0x3d, 0xb8, 0x30, 0x4e, 0x76,
|
||||
0x17, 0x66, 0x42, 0x2e, 0xe9, 0xa4, 0x18, 0x2c, 0xbd, 0x40, 0x0c, 0x4e, 0x87, 0x86, 0x96, 0xfc,
|
||||
0x14, 0x34, 0xdc, 0xee, 0x29, 0x0d, 0x63, 0x0f, 0x23, 0x15, 0x68, 0xa2, 0x70, 0xe1, 0x3d, 0xab,
|
||||
0xc1, 0xd1, 0x72, 0xb8, 0x01, 0xb3, 0x22, 0xb9, 0x4f, 0x61, 0x8a, 0x6b, 0x0f, 0x09, 0x98, 0x21,
|
||||
0xda, 0xdf, 0x91, 0x67, 0x60, 0xe6, 0x1e, 0x8e, 0x5f, 0x11, 0x7d, 0x76, 0x85, 0xd4, 0xec, 0x3e,
|
||||
0x21, 0xce, 0xa3, 0xba, 0x32, 0x1c, 0x52, 0xd4, 0x92, 0x63, 0xba, 0xe2, 0xfc, 0xd0, 0x5c, 0xd2,
|
||||
0xd2, 0xcb, 0x2c, 0xa9, 0xfd, 0x43, 0x0b, 0xa6, 0x76, 0x83, 0xe1, 0xae, 0x48, 0x13, 0x42, 0x46,
|
||||
0x50, 0x59, 0xb5, 0xb2, 0xf8, 0x82, 0x04, 0xa2, 0x5c, 0xcb, 0x60, 0x3a, 0x6d, 0x19, 0xfc, 0x5f,
|
||||
0xb8, 0x8c, 0xc1, 0xb8, 0x30, 0x18, 0x06, 0x21, 0x63, 0x46, 0xb7, 0xcf, 0xcd, 0x80, 0xc0, 0x8f,
|
||||
0x4f, 0xa4, 0x00, 0x7c, 0x11, 0x0a, 0x7a, 0xc8, 0xcc, 0xab, 0xe3, 0x46, 0xbd, 0xb0, 0x64, 0xb8,
|
||||
0x5c, 0xcc, 0x56, 0xd8, 0x9f, 0x87, 0x2a, 0x9a, 0xe2, 0x38, 0xad, 0x37, 0xa0, 0x7a, 0x12, 0x0c,
|
||||
0xdb, 0x27, 0x9e, 0x1f, 0x4b, 0xe6, 0x9e, 0x49, 0x6c, 0xe4, 0x5d, 0x5c, 0x10, 0x85, 0x60, 0xff,
|
||||
0xc6, 0x24, 0x4c, 0x3d, 0xf0, 0x4f, 0x03, 0xaf, 0x83, 0xe7, 0x6d, 0x03, 0x3a, 0x08, 0x64, 0x8e,
|
||||
0x31, 0xfb, 0x4d, 0xae, 0xc0, 0x14, 0x26, 0xd5, 0x0d, 0x39, 0xd1, 0xd6, 0xf9, 0xb9, 0xb8, 0x00,
|
||||
0x31, 0xf3, 0x22, 0x4c, 0x6e, 0x83, 0x70, 0xf6, 0xd1, 0x20, 0xcc, 0x49, 0x09, 0xf5, 0xdb, 0x1c,
|
||||
0xa2, 0x94, 0xe4, 0x70, 0x97, 0xb5, 0x1c, 0x6e, 0xd6, 0x97, 0x48, 0x6b, 0xe2, 0x79, 0x2f, 0xbc,
|
||||
0x2f, 0x01, 0x42, 0xc7, 0x2a, 0xa4, 0x3c, 0x98, 0x8a, 0xc6, 0xca, 0x94, 0x70, 0xac, 0x74, 0x20,
|
||||
0x33, 0x68, 0xf8, 0x07, 0x1c, 0x87, 0x8b, 0x6f, 0x1d, 0xc4, 0x4c, 0xc4, 0xf4, 0x45, 0x9e, 0x2a,
|
||||
0xa7, 0xfd, 0x14, 0x98, 0xc9, 0xf8, 0x2e, 0x55, 0x02, 0x95, 0xcf, 0x03, 0xf8, 0x8d, 0x97, 0x34,
|
||||
0x5c, 0x73, 0xc7, 0x78, 0xfe, 0xa3, 0x74, 0xc7, 0x18, 0xc1, 0xb8, 0xfd, 0xfe, 0x91, 0xdb, 0x79,
|
||||
0x8a, 0xf7, 0xb4, 0xf0, 0x04, 0xac, 0xea, 0x98, 0x40, 0x4c, 0x4e, 0x4a, 0x76, 0x15, 0x33, 0x08,
|
||||
0x4a, 0x8e, 0x0e, 0x22, 0xb7, 0xa1, 0x86, 0x2e, 0xa8, 0xd8, 0xd7, 0x19, 0xdc, 0xd7, 0x86, 0xee,
|
||||
0xa3, 0xe2, 0xce, 0xea, 0x48, 0xfa, 0x59, 0xe0, 0x6c, 0x26, 0x23, 0xd1, 0xed, 0x76, 0xc5, 0x11,
|
||||
0x6a, 0x83, 0xbb, 0xd3, 0x0a, 0xc0, 0xf4, 0xb1, 0x58, 0x30, 0x8e, 0x30, 0x87, 0x08, 0x06, 0x8c,
|
||||
0x5c, 0x85, 0x0a, 0x73, 0x8f, 0x86, 0xae, 0xd7, 0xc5, 0x94, 0x46, 0xee, 0xa5, 0x29, 0x18, 0x6b,
|
||||
0x43, 0xfe, 0x46, 0x45, 0x37, 0x8f, 0xab, 0x62, 0xc0, 0xd8, 0xda, 0xa8, 0x32, 0x32, 0xd3, 0x02,
|
||||
0xdf, 0x51, 0x03, 0x48, 0xde, 0xc4, 0x83, 0xac, 0x98, 0x36, 0x17, 0x31, 0x50, 0x76, 0x59, 0xcc,
|
||||
0x59, 0x10, 0xad, 0xfc, 0x7b, 0xc8, 0x50, 0x1c, 0x8e, 0x69, 0x6f, 0x40, 0x5d, 0x07, 0x93, 0x0a,
|
||||
0x94, 0x1e, 0x1e, 0xec, 0xec, 0x37, 0x26, 0x48, 0x0d, 0xa6, 0x0e, 0x77, 0x1e, 0x3d, 0xda, 0xdb,
|
||||
0xd9, 0x6e, 0x58, 0xa4, 0x0e, 0x15, 0x95, 0x49, 0x56, 0x60, 0xa5, 0x8d, 0xad, 0xad, 0x9d, 0x83,
|
||||
0x47, 0x3b, 0xdb, 0x8d, 0xa2, 0x1d, 0x03, 0xd9, 0xe8, 0x76, 0x45, 0x2b, 0x2a, 0x48, 0x90, 0xd0,
|
||||
0xb3, 0x65, 0xd0, 0x73, 0x0e, 0x4d, 0x15, 0xf2, 0x69, 0xea, 0x85, 0x2b, 0x6f, 0xef, 0x40, 0xed,
|
||||
0x40, 0xbb, 0xb4, 0x84, 0xec, 0x25, 0xaf, 0x2b, 0x09, 0xb6, 0xd4, 0x20, 0xda, 0x70, 0x0a, 0xfa,
|
||||
0x70, 0xec, 0xdf, 0xb7, 0xf8, 0xcd, 0x00, 0x35, 0x7c, 0xde, 0xb7, 0x0d, 0x75, 0x15, 0xad, 0x4a,
|
||||
0x92, 0x44, 0x0d, 0x18, 0xc3, 0xc1, 0xa1, 0xb4, 0x83, 0xe3, 0xe3, 0x88, 0xca, 0x94, 0x2e, 0x03,
|
||||
0xc6, 0xf8, 0x82, 0xd9, 0x66, 0xcc, 0xce, 0xf1, 0x78, 0x0f, 0x91, 0x48, 0xed, 0xca, 0xc0, 0x99,
|
||||
0x94, 0x17, 0x01, 0x19, 0x99, 0xcc, 0xa6, 0xca, 0x2a, 0x97, 0x35, 0xbd, 0xca, 0x6b, 0x50, 0x51,
|
||||
0xed, 0x9a, 0x02, 0x4c, 0x62, 0xaa, 0x7a, 0x26, 0x28, 0xd1, 0x5b, 0x31, 0x06, 0xcd, 0x85, 0x76,
|
||||
0xb6, 0x82, 0xdc, 0x04, 0x72, 0xec, 0x85, 0x69, 0xf4, 0x22, 0xa2, 0xe7, 0xd4, 0xd8, 0x4f, 0x60,
|
||||
0x5e, 0x12, 0x92, 0x66, 0x5a, 0x99, 0x9b, 0x68, 0x5d, 0xc4, 0x3e, 0x85, 0x2c, 0xfb, 0xd8, 0xff,
|
||||
0x69, 0xc1, 0x94, 0xd8, 0xe9, 0xcc, 0xc5, 0x37, 0xbe, 0xcf, 0x06, 0x8c, 0x34, 0x8d, 0x4b, 0x2f,
|
||||
0xc8, 0x6b, 0x42, 0x68, 0x66, 0xc4, 0x62, 0x31, 0x4f, 0x2c, 0x12, 0x28, 0x0d, 0xdd, 0xf8, 0x04,
|
||||
0x3d, 0xf5, 0xaa, 0x83, 0xbf, 0x49, 0x83, 0xc7, 0x95, 0xb8, 0x08, 0xc6, 0x98, 0x52, 0xde, 0x15,
|
||||
0x3f, 0xae, 0xed, 0xb3, 0x57, 0xfc, 0xae, 0x40, 0x15, 0x07, 0xd0, 0x4e, 0xc2, 0x46, 0x09, 0x80,
|
||||
0x51, 0x2e, 0x2f, 0x20, 0x5f, 0x8b, 0xfc, 0xf3, 0x04, 0x62, 0x2f, 0xf2, 0x9d, 0x17, 0x4b, 0xa0,
|
||||
0x0e, 0xa1, 0x45, 0xee, 0x70, 0x02, 0x4e, 0x28, 0x42, 0x0c, 0x20, 0x4d, 0x11, 0x02, 0xd5, 0x51,
|
||||
0xf5, 0x76, 0x0b, 0x9a, 0xdb, 0xb4, 0x4f, 0x63, 0xba, 0xd1, 0xef, 0xa7, 0xdb, 0xbf, 0x0c, 0x97,
|
||||
0x72, 0xea, 0x84, 0x35, 0xfd, 0x65, 0x58, 0xdc, 0xe0, 0x79, 0x96, 0x3f, 0xa9, 0x34, 0x1e, 0xbb,
|
||||
0x09, 0x4b, 0xe9, 0x26, 0x45, 0x67, 0xf7, 0x60, 0x6e, 0x9b, 0x1e, 0x8d, 0x7a, 0x7b, 0xf4, 0x34,
|
||||
0xe9, 0x88, 0x40, 0x29, 0x3a, 0x09, 0xce, 0x04, 0x63, 0xe2, 0x6f, 0xf2, 0x0a, 0x40, 0x9f, 0xe1,
|
||||
0xb4, 0xa3, 0x21, 0xed, 0xc8, 0x7b, 0x26, 0x08, 0x39, 0x1c, 0xd2, 0x8e, 0xfd, 0x16, 0x10, 0xbd,
|
||||
0x1d, 0xb1, 0x5e, 0x4c, 0x0b, 0x8e, 0x8e, 0xda, 0xd1, 0x79, 0x14, 0xd3, 0x81, 0xbc, 0x40, 0xa3,
|
||||
0x83, 0xec, 0x1b, 0x50, 0x3f, 0x70, 0xcf, 0x1d, 0xfa, 0xa1, 0xb8, 0xef, 0xb8, 0x0c, 0x53, 0x43,
|
||||
0xf7, 0x9c, 0x89, 0x29, 0x15, 0xcf, 0xc2, 0x6a, 0xfb, 0xdf, 0x0b, 0x30, 0xc9, 0x31, 0x59, 0xab,
|
||||
0x5d, 0x1a, 0xc5, 0x9e, 0x8f, 0x84, 0x25, 0x5b, 0xd5, 0x40, 0x19, 0x52, 0x2e, 0xe4, 0x90, 0xb2,
|
||||
0xf0, 0xf6, 0x64, 0xce, 0xbe, 0xa0, 0x57, 0x03, 0xc6, 0x88, 0x2b, 0xc9, 0xa7, 0xe3, 0x01, 0x95,
|
||||
0x04, 0x90, 0x0a, 0x7d, 0x26, 0xba, 0x96, 0x8f, 0x4f, 0x72, 0xa9, 0xa0, 0x5c, 0x1d, 0x94, 0xab,
|
||||
0xd1, 0xa7, 0x38, 0x81, 0x67, 0x34, 0x7a, 0x46, 0x73, 0x57, 0x5e, 0x42, 0x73, 0x73, 0x17, 0xf0,
|
||||
0x45, 0x9a, 0x1b, 0x5e, 0x42, 0x73, 0xdb, 0x04, 0x1a, 0x78, 0x19, 0x90, 0xd9, 0x86, 0x92, 0x76,
|
||||
0xbf, 0x65, 0x41, 0x43, 0x50, 0x91, 0xaa, 0x23, 0xaf, 0x19, 0x36, 0x70, 0x6e, 0x36, 0xfc, 0x35,
|
||||
0x98, 0x46, 0xcb, 0x54, 0xc5, 0x78, 0x45, 0x40, 0xda, 0x00, 0xb2, 0x79, 0xc8, 0xf3, 0xe3, 0x81,
|
||||
0xd7, 0x17, 0x9b, 0xa2, 0x83, 0x64, 0x98, 0x38, 0x74, 0x45, 0x5e, 0x99, 0xe5, 0xa8, 0xb2, 0xfd,
|
||||
0xe7, 0x16, 0xcc, 0x69, 0x03, 0x16, 0x54, 0x78, 0x17, 0x24, 0x37, 0xf0, 0x80, 0x2f, 0xe7, 0xdc,
|
||||
0x65, 0x93, 0x6d, 0x92, 0xcf, 0x0c, 0x64, 0xdc, 0x4c, 0xf7, 0x1c, 0x07, 0x18, 0x8d, 0x06, 0x42,
|
||||
0x88, 0xea, 0x20, 0x46, 0x48, 0x67, 0x94, 0x3e, 0x55, 0x28, 0x5c, 0x8c, 0x1b, 0x30, 0x8c, 0xaa,
|
||||
0x31, 0x8b, 0x5a, 0x21, 0x95, 0x44, 0x54, 0x4d, 0x07, 0xda, 0x7f, 0x6b, 0xc1, 0x3c, 0x77, 0x8d,
|
||||
0x84, 0xe3, 0xa9, 0xae, 0x3d, 0x4d, 0x72, 0x5f, 0x90, 0x73, 0xe4, 0xee, 0x84, 0x23, 0xca, 0xe4,
|
||||
0xb3, 0x2f, 0xe9, 0xce, 0xa9, 0x64, 0xb7, 0x31, 0x7b, 0x51, 0xcc, 0xdb, 0x8b, 0x17, 0xac, 0x74,
|
||||
0x5e, 0x80, 0xb3, 0x9c, 0x1b, 0xe0, 0xdc, 0x9c, 0x82, 0x72, 0xd4, 0x09, 0x86, 0xd4, 0x5e, 0x82,
|
||||
0x05, 0x73, 0x72, 0x42, 0x04, 0x7d, 0xdb, 0x82, 0xe6, 0x3d, 0x7e, 0x10, 0xe0, 0xf9, 0xbd, 0x5d,
|
||||
0x2f, 0x8a, 0x83, 0x50, 0xdd, 0x0e, 0xbd, 0x0a, 0x10, 0xc5, 0x6e, 0x18, 0xf3, 0x3c, 0x6a, 0x11,
|
||||
0x58, 0x4c, 0x20, 0x6c, 0x8c, 0xd4, 0xef, 0xf2, 0x5a, 0xbe, 0x37, 0xaa, 0x9c, 0xb1, 0x21, 0x84,
|
||||
0xf3, 0x66, 0x68, 0xe2, 0xeb, 0x3c, 0xf9, 0x93, 0xd9, 0x0a, 0xf4, 0x14, 0xe5, 0x3a, 0xf7, 0x8a,
|
||||
0x52, 0x50, 0xfb, 0x6f, 0x2c, 0x98, 0x4d, 0x06, 0x89, 0xc7, 0xa2, 0xa6, 0x74, 0x10, 0xea, 0x37,
|
||||
0x91, 0x0e, 0x32, 0xe4, 0xe9, 0x31, 0x7d, 0x2c, 0xc6, 0xa6, 0x41, 0x90, 0x63, 0x45, 0x29, 0x18,
|
||||
0x49, 0x03, 0x47, 0x07, 0xf1, 0x54, 0x2e, 0x66, 0x09, 0x08, 0xab, 0x46, 0x94, 0x30, 0x0d, 0x7e,
|
||||
0x10, 0xe3, 0x57, 0x3c, 0x38, 0x2b, 0x8b, 0x52, 0x95, 0x4e, 0x21, 0x14, 0x55, 0xa9, 0x7e, 0xa8,
|
||||
0x52, 0xe1, 0xeb, 0x23, 0xcb, 0xf6, 0xaf, 0x5a, 0x70, 0x29, 0x67, 0xe1, 0x05, 0xd7, 0x6c, 0xc3,
|
||||
0xdc, 0xb1, 0xaa, 0x94, 0x8b, 0xc3, 0x59, 0x67, 0x49, 0x1e, 0xda, 0x99, 0x0b, 0xe2, 0x64, 0x3f,
|
||||
0x50, 0x76, 0x11, 0x5f, 0x6e, 0x23, 0x59, 0x32, 0x5b, 0x61, 0x1f, 0x40, 0x6b, 0xe7, 0x19, 0x63,
|
||||
0xc2, 0x2d, 0xfd, 0xa1, 0x13, 0x49, 0x0b, 0xb7, 0x33, 0x42, 0xe6, 0x62, 0x47, 0xfb, 0x18, 0xa6,
|
||||
0x8d, 0xb6, 0xc8, 0xa7, 0x5f, 0xb6, 0x91, 0x54, 0x78, 0x1a, 0x4b, 0xfc, 0xa5, 0x16, 0x99, 0xb2,
|
||||
0xa9, 0x81, 0xec, 0x53, 0x98, 0x7d, 0x77, 0xd4, 0x8f, 0xbd, 0xe4, 0xd5, 0x16, 0xf2, 0x59, 0xf1,
|
||||
0x11, 0x36, 0x21, 0x97, 0x2e, 0xb7, 0x2b, 0x1d, 0x8f, 0xad, 0xd8, 0x80, 0xb5, 0xd4, 0xce, 0xf6,
|
||||
0x98, 0xad, 0xb0, 0x2f, 0xc1, 0x72, 0xd2, 0x25, 0x5f, 0x3b, 0x29, 0xa8, 0xbf, 0x63, 0xf1, 0x6c,
|
||||
0x07, 0xf3, 0x11, 0x19, 0x72, 0x1f, 0xe6, 0x23, 0xcf, 0xef, 0xf5, 0xa9, 0xde, 0x4e, 0x24, 0x56,
|
||||
0x62, 0xd1, 0x1c, 0x9e, 0x78, 0x68, 0xc6, 0xc9, 0xfb, 0x82, 0x11, 0x48, 0xfe, 0x40, 0x13, 0x02,
|
||||
0x49, 0x2d, 0x49, 0xde, 0x04, 0xbe, 0x04, 0x33, 0x66, 0x67, 0xe4, 0x8e, 0xc8, 0xb6, 0x4c, 0x46,
|
||||
0xa6, 0xc7, 0xb2, 0x4d, 0xca, 0x30, 0x30, 0xed, 0x6f, 0x5a, 0xd0, 0x74, 0x28, 0x23, 0x63, 0xaa,
|
||||
0x75, 0x2a, 0xa8, 0xe7, 0x6e, 0xa6, 0xd9, 0xf1, 0x13, 0x56, 0x59, 0x9c, 0x72, 0xae, 0x37, 0xc7,
|
||||
0x6e, 0xca, 0xee, 0x44, 0xce, 0xac, 0x36, 0x2b, 0x30, 0x29, 0xe6, 0xb7, 0x0c, 0x8b, 0x62, 0x48,
|
||||
0x72, 0x38, 0x49, 0xd0, 0xd4, 0xe8, 0xd4, 0x08, 0x9a, 0x1e, 0x41, 0x93, 0x5f, 0xdb, 0xd5, 0xe7,
|
||||
0x91, 0xe4, 0x36, 0xf0, 0xed, 0x88, 0xda, 0xfa, 0x0d, 0x5e, 0x13, 0xc8, 0x48, 0x96, 0x0f, 0x8b,
|
||||
0xe3, 0xf0, 0x53, 0x68, 0x1d, 0xb4, 0xf6, 0x1c, 0x6a, 0xda, 0x25, 0x68, 0xb2, 0x0c, 0xf3, 0x4f,
|
||||
0x1e, 0x3c, 0xda, 0xdf, 0x39, 0x3c, 0x6c, 0x1f, 0x3c, 0xde, 0x7c, 0x67, 0xe7, 0xbd, 0xf6, 0xee,
|
||||
0xc6, 0xe1, 0x6e, 0x63, 0x82, 0x2c, 0x01, 0xd9, 0xdf, 0x39, 0x7c, 0xb4, 0xb3, 0x6d, 0xc0, 0x2d,
|
||||
0x72, 0x15, 0x5a, 0x8f, 0xf7, 0x1f, 0x1f, 0xee, 0x6c, 0xb7, 0xf3, 0xbe, 0x2b, 0x90, 0x57, 0xe0,
|
||||
0x92, 0xa8, 0xcf, 0xf9, 0xbc, 0x78, 0xfb, 0x9b, 0x45, 0x98, 0xe1, 0xc9, 0x1b, 0xfc, 0x0d, 0x23,
|
||||
0x1a, 0x92, 0x77, 0x61, 0x4a, 0x3c, 0x86, 0x45, 0xe4, 0xbe, 0x98, 0xcf, 0x6f, 0xb5, 0x96, 0xd2,
|
||||
0x60, 0xb1, 0x98, 0xf3, 0x3f, 0xfb, 0xc3, 0x7f, 0xfa, 0xf5, 0xc2, 0x34, 0xa9, 0xad, 0x9f, 0xbe,
|
||||
0xb9, 0xde, 0xa3, 0x7e, 0xc4, 0xda, 0xf8, 0x1a, 0x40, 0xf2, 0xc4, 0x13, 0x69, 0x2a, 0xdf, 0x2d,
|
||||
0xf5, 0xfe, 0x55, 0xeb, 0x52, 0x4e, 0x8d, 0x68, 0xf7, 0x12, 0xb6, 0x3b, 0x6f, 0xcf, 0xb0, 0x76,
|
||||
0x3d, 0xdf, 0x8b, 0xf9, 0x73, 0x4f, 0x6f, 0x5b, 0x6b, 0xa4, 0x0b, 0x75, 0xfd, 0xf1, 0x25, 0x22,
|
||||
0x03, 0xc8, 0x39, 0xcf, 0x47, 0xb5, 0x2e, 0xe7, 0xd6, 0x49, 0x42, 0xc0, 0x3e, 0x16, 0xed, 0x06,
|
||||
0xeb, 0x63, 0x84, 0x18, 0x49, 0x2f, 0x7d, 0xce, 0x1e, 0xc9, 0x1b, 0x4b, 0xe4, 0x8a, 0x46, 0xb1,
|
||||
0x99, 0x17, 0x9e, 0x5a, 0xaf, 0x8c, 0xa9, 0x15, 0x7d, 0xbd, 0x82, 0x7d, 0x2d, 0xdb, 0x84, 0xf5,
|
||||
0xd5, 0x41, 0x1c, 0xf9, 0xc2, 0xd3, 0xdb, 0xd6, 0xda, 0xed, 0xdf, 0xbc, 0x0e, 0x55, 0x75, 0x58,
|
||||
0x44, 0x3e, 0x80, 0x69, 0x23, 0xbb, 0x86, 0xc8, 0x69, 0xe4, 0x25, 0xe3, 0xb4, 0xae, 0xe4, 0x57,
|
||||
0x8a, 0x8e, 0xaf, 0x62, 0xc7, 0x4d, 0xb2, 0xc4, 0x3a, 0x16, 0xe9, 0x29, 0xeb, 0x98, 0x27, 0xc6,
|
||||
0x2f, 0x7d, 0x3c, 0xd5, 0xc4, 0x00, 0xef, 0xec, 0x4a, 0x9a, 0x33, 0x8d, 0xde, 0x5e, 0x19, 0x53,
|
||||
0x2b, 0xba, 0xbb, 0x82, 0xdd, 0x2d, 0x91, 0x05, 0xbd, 0x3b, 0x75, 0x88, 0x43, 0xf1, 0xa6, 0x92,
|
||||
0xfe, 0x3c, 0x11, 0x79, 0x45, 0x11, 0x56, 0xde, 0xb3, 0x45, 0x8a, 0x44, 0xb2, 0x6f, 0x17, 0xd9,
|
||||
0x4d, 0xec, 0x8a, 0x10, 0xdc, 0x3e, 0xfd, 0x75, 0x22, 0x72, 0x04, 0x35, 0xed, 0x49, 0x0d, 0x72,
|
||||
0x69, 0xec, 0xf3, 0x1f, 0xad, 0x56, 0x5e, 0x55, 0xde, 0x54, 0xf4, 0xf6, 0xd7, 0x99, 0x7e, 0xff,
|
||||
0x2a, 0x54, 0xd5, 0x23, 0x0d, 0x64, 0x59, 0x7b, 0x34, 0x43, 0x7f, 0x54, 0xa2, 0xd5, 0xcc, 0x56,
|
||||
0xe4, 0x11, 0x9f, 0xde, 0x3a, 0x23, 0xbe, 0x27, 0x50, 0xd3, 0x1e, 0x62, 0x50, 0x13, 0xc8, 0x3e,
|
||||
0xf6, 0xa0, 0x26, 0x90, 0xf3, 0x6e, 0x83, 0x3d, 0x87, 0x5d, 0xd4, 0x48, 0x15, 0xe9, 0x3b, 0x7e,
|
||||
0x16, 0x44, 0x64, 0x0f, 0x16, 0x85, 0xb8, 0x3b, 0xa2, 0x1f, 0x67, 0x1b, 0x72, 0x5e, 0x84, 0xba,
|
||||
0x65, 0x91, 0xbb, 0x50, 0x91, 0xef, 0x6d, 0x90, 0xa5, 0xfc, 0x77, 0x43, 0x5a, 0xcb, 0x19, 0xb8,
|
||||
0x90, 0xa6, 0xef, 0x01, 0x24, 0xaf, 0x3e, 0x28, 0x21, 0x91, 0x79, 0x45, 0x42, 0x51, 0x40, 0xf6,
|
||||
0x89, 0x08, 0x7b, 0x09, 0x27, 0xd8, 0x20, 0x28, 0x24, 0x7c, 0x7a, 0x26, 0x2f, 0x25, 0x7e, 0x1d,
|
||||
0x6a, 0xda, 0xc3, 0x0f, 0x6a, 0xf9, 0xb2, 0x8f, 0x46, 0xa8, 0xe5, 0xcb, 0x79, 0x27, 0xc2, 0x6e,
|
||||
0x61, 0xeb, 0x0b, 0xf6, 0x2c, 0x6b, 0x3d, 0xf2, 0x7a, 0xfe, 0x80, 0x23, 0xb0, 0x0d, 0x3a, 0x81,
|
||||
0x69, 0xe3, 0x75, 0x07, 0xc5, 0xa1, 0x79, 0x6f, 0x47, 0x28, 0x0e, 0xcd, 0x7d, 0x10, 0x42, 0xd2,
|
||||
0x99, 0x3d, 0xc7, 0xfa, 0x39, 0x45, 0x14, 0xad, 0xa7, 0xf7, 0xa1, 0xa6, 0xbd, 0xd4, 0xa0, 0xe6,
|
||||
0x92, 0x7d, 0x14, 0x42, 0xcd, 0x25, 0xef, 0x61, 0x87, 0x05, 0xec, 0x63, 0xc6, 0x46, 0x52, 0xc0,
|
||||
0xeb, 0x75, 0xac, 0xed, 0x0f, 0x60, 0xc6, 0x7c, 0xbb, 0x41, 0xf1, 0x7e, 0xee, 0x2b, 0x10, 0x8a,
|
||||
0xf7, 0xc7, 0x3c, 0xf8, 0x20, 0x48, 0x7a, 0x6d, 0x5e, 0x75, 0xb2, 0xfe, 0x91, 0x48, 0x22, 0x79,
|
||||
0x4e, 0xbe, 0xcc, 0x04, 0x9c, 0xb8, 0xef, 0x48, 0x96, 0x35, 0xaa, 0xd5, 0x6f, 0x45, 0x2a, 0x7e,
|
||||
0xc9, 0x5c, 0x8d, 0x34, 0x89, 0x99, 0x5f, 0x10, 0x44, 0xad, 0x85, 0xf7, 0x1e, 0x35, 0xad, 0xa5,
|
||||
0x5f, 0x8d, 0xd4, 0xb4, 0x96, 0x71, 0x3d, 0x32, 0xad, 0xb5, 0x62, 0x8f, 0xb5, 0xe1, 0xc3, 0x6c,
|
||||
0x2a, 0x03, 0x58, 0x71, 0x45, 0xfe, 0x95, 0x89, 0xd6, 0xd5, 0x17, 0x27, 0x0e, 0x9b, 0x12, 0x44,
|
||||
0x0a, 0xc1, 0x75, 0x79, 0x41, 0xe5, 0xff, 0x43, 0x5d, 0xbf, 0x27, 0x4f, 0x74, 0x56, 0x4e, 0xf7,
|
||||
0x74, 0x39, 0xb7, 0xce, 0xdc, 0x5c, 0x52, 0xd7, 0xbb, 0x21, 0x5f, 0x81, 0x25, 0xc5, 0xea, 0x7a,
|
||||
0x52, 0x69, 0x44, 0x5e, 0xcd, 0x49, 0x35, 0xd5, 0x8d, 0xa0, 0xd6, 0xa5, 0xb1, 0xb9, 0xa8, 0xb7,
|
||||
0x2c, 0x46, 0x34, 0xe6, 0x05, 0xe4, 0x44, 0x61, 0xe4, 0xdd, 0xbb, 0x4e, 0x14, 0x46, 0xee, 0xad,
|
||||
0x65, 0x49, 0x34, 0x64, 0xde, 0x58, 0x23, 0x7e, 0xce, 0x47, 0xde, 0x87, 0x59, 0x2d, 0x6d, 0xff,
|
||||
0xf0, 0xdc, 0xef, 0x28, 0x06, 0xc8, 0xde, 0xef, 0x6a, 0xe5, 0x99, 0xf8, 0xf6, 0x32, 0xb6, 0x3f,
|
||||
0x67, 0x1b, 0x8b, 0xc3, 0x88, 0x7f, 0x0b, 0x6a, 0xfa, 0x95, 0x80, 0x17, 0xb4, 0xbb, 0xac, 0x55,
|
||||
0xe9, 0xd7, 0x93, 0x6e, 0x59, 0xe4, 0xb7, 0x2d, 0xa8, 0x1b, 0x09, 0xf6, 0xc6, 0x69, 0x76, 0xaa,
|
||||
0x9d, 0xa6, 0x5e, 0xa7, 0x37, 0x64, 0x3b, 0x38, 0xc8, 0xbd, 0xb5, 0x2f, 0x19, 0x8b, 0xf0, 0x91,
|
||||
0x11, 0xc7, 0xb9, 0x99, 0x7e, 0xe3, 0xeb, 0x79, 0x1a, 0x41, 0xbf, 0x03, 0xf7, 0xfc, 0x96, 0x45,
|
||||
0xbe, 0x6b, 0xc1, 0x8c, 0x19, 0x7d, 0x54, 0x5b, 0x95, 0x1b, 0xe7, 0x54, 0x5b, 0x35, 0x26, 0x64,
|
||||
0xf9, 0x3e, 0x8e, 0xf2, 0xd1, 0x9a, 0x63, 0x8c, 0x52, 0x5c, 0x4d, 0xff, 0xf1, 0x46, 0x4b, 0xde,
|
||||
0xe6, 0xcf, 0x00, 0xca, 0x90, 0x38, 0xd1, 0xb4, 0x46, 0x7a, 0x7b, 0xf5, 0xa7, 0xeb, 0x56, 0xad,
|
||||
0x5b, 0x16, 0xf9, 0x3a, 0x7f, 0xdb, 0x4a, 0x7c, 0x8b, 0x54, 0xf2, 0xb2, 0xdf, 0xdb, 0xd7, 0x70,
|
||||
0x4e, 0x57, 0xed, 0x4b, 0xc6, 0x9c, 0xd2, 0xfa, 0x78, 0x83, 0x8f, 0x4e, 0xbc, 0x3a, 0x97, 0x28,
|
||||
0x94, 0xcc, 0x4b, 0x74, 0xe3, 0x07, 0x39, 0xe0, 0x83, 0x14, 0xe8, 0x06, 0x29, 0xbf, 0x64, 0x33,
|
||||
0xf6, 0x1a, 0x8e, 0xf5, 0x9a, 0xfd, 0xea, 0xd8, 0xb1, 0xae, 0x63, 0x0c, 0x91, 0x8d, 0xf8, 0x00,
|
||||
0x20, 0x39, 0xbe, 0x22, 0xa9, 0xe3, 0x13, 0xc5, 0xe0, 0xd9, 0x13, 0x2e, 0x93, 0x5f, 0xe4, 0x29,
|
||||
0x0b, 0x6b, 0xf1, 0xab, 0x5c, 0x5c, 0x3d, 0x90, 0x07, 0x2f, 0xba, 0x51, 0x62, 0x9e, 0x33, 0x19,
|
||||
0x46, 0x49, 0xba, 0x7d, 0x43, 0x58, 0xa9, 0x53, 0x9c, 0xc7, 0x30, 0xbd, 0x17, 0x04, 0x4f, 0x47,
|
||||
0x43, 0x75, 0x14, 0x6d, 0x86, 0xf7, 0x77, 0xdd, 0xe8, 0xa4, 0x95, 0x9a, 0x85, 0xbd, 0x82, 0x4d,
|
||||
0xb5, 0x48, 0x53, 0x6b, 0x6a, 0xfd, 0xa3, 0xe4, 0x78, 0xec, 0x39, 0x71, 0x61, 0x4e, 0xc9, 0x40,
|
||||
0x35, 0xf0, 0x96, 0xd9, 0x8c, 0x21, 0xf9, 0xd2, 0x5d, 0x18, 0xd6, 0xb3, 0x1c, 0xed, 0x7a, 0x24,
|
||||
0xdb, 0xbc, 0x65, 0x91, 0x03, 0xa8, 0x6f, 0xd3, 0x4e, 0xd0, 0xa5, 0x22, 0x46, 0x3e, 0x9f, 0x0c,
|
||||
0x5c, 0x05, 0xd7, 0x5b, 0xd3, 0x06, 0xd0, 0xd4, 0x0b, 0x43, 0xf7, 0x3c, 0xa4, 0x1f, 0xae, 0x7f,
|
||||
0x24, 0xa2, 0xef, 0xcf, 0xa5, 0x5e, 0x90, 0xc7, 0x13, 0x86, 0x5e, 0x48, 0x9d, 0x67, 0x18, 0x7a,
|
||||
0x21, 0x73, 0x9e, 0x61, 0x2c, 0xb5, 0x3c, 0x1e, 0x21, 0x7d, 0x98, 0xcb, 0x1c, 0x81, 0x28, 0x95,
|
||||
0x30, 0xee, 0xe0, 0xa4, 0xb5, 0x32, 0x1e, 0xc1, 0xec, 0x6d, 0xcd, 0xec, 0xed, 0x10, 0xa6, 0xb7,
|
||||
0x29, 0x5f, 0x2c, 0x9e, 0x29, 0x97, 0xba, 0xa5, 0xa1, 0xe7, 0xe1, 0xa5, 0x05, 0x38, 0xd6, 0x99,
|
||||
0x8a, 0x1f, 0xd3, 0xd4, 0xc8, 0x57, 0xa1, 0x76, 0x9f, 0xc6, 0x32, 0x35, 0x4e, 0x99, 0x9e, 0xa9,
|
||||
0x5c, 0xb9, 0x56, 0x4e, 0x66, 0x9d, 0x49, 0x33, 0xd8, 0xda, 0x3a, 0xed, 0xf6, 0x28, 0x17, 0x4e,
|
||||
0x6d, 0xaf, 0xfb, 0x9c, 0xfc, 0x3f, 0x6c, 0x5c, 0x65, 0xf0, 0x2e, 0x69, 0x79, 0x51, 0x7a, 0xe3,
|
||||
0xb3, 0x29, 0x78, 0x5e, 0xcb, 0x7e, 0xd0, 0xa5, 0x9a, 0x09, 0xe4, 0x43, 0x4d, 0x4b, 0x3c, 0x57,
|
||||
0x0c, 0x94, 0xbd, 0x27, 0xa0, 0x18, 0x28, 0x27, 0x4f, 0xdd, 0x5e, 0xc5, 0x7e, 0x6c, 0xb2, 0x92,
|
||||
0xf4, 0xc3, 0x73, 0xd3, 0x93, 0x9e, 0xd6, 0x3f, 0x72, 0x07, 0xf1, 0x73, 0xf2, 0x04, 0x9f, 0x8a,
|
||||
0xd0, 0xd3, 0xff, 0x12, 0x5b, 0x3a, 0x9d, 0x29, 0xa8, 0x16, 0x4b, 0xab, 0x32, 0xed, 0x6b, 0xde,
|
||||
0x15, 0x5a, 0x4a, 0x9f, 0x05, 0x38, 0x8c, 0x83, 0xe1, 0xb6, 0x4b, 0x07, 0x81, 0x9f, 0xc8, 0xda,
|
||||
0x24, 0x51, 0x2d, 0x91, 0x5f, 0x5a, 0xb6, 0x1a, 0x79, 0xa2, 0x39, 0x1f, 0x46, 0xf6, 0xa4, 0x24,
|
||||
0xae, 0xb1, 0xb9, 0x6c, 0x6a, 0x41, 0x72, 0xf2, 0xd9, 0x6e, 0x59, 0x64, 0x03, 0x20, 0x39, 0x03,
|
||||
0x53, 0xae, 0x44, 0xe6, 0x78, 0x4d, 0x89, 0xbd, 0x9c, 0x03, 0xb3, 0x03, 0xa8, 0x26, 0x87, 0x2a,
|
||||
0xcb, 0xc9, 0xdd, 0x08, 0xe3, 0x08, 0x46, 0x69, 0xf0, 0xcc, 0x51, 0x87, 0xdd, 0xc0, 0xa5, 0x02,
|
||||
0x52, 0x61, 0x4b, 0x85, 0xe7, 0x17, 0x1e, 0xcc, 0xf3, 0x01, 0x2a, 0x73, 0x04, 0x53, 0xaf, 0xe4,
|
||||
0x4c, 0x72, 0x8e, 0x1b, 0x14, 0x37, 0xe7, 0x46, 0xeb, 0x8d, 0x88, 0x08, 0xa3, 0x56, 0x9e, 0xf6,
|
||||
0xc5, 0x44, 0xf3, 0x00, 0xe6, 0x32, 0xe1, 0x64, 0xc5, 0xd2, 0xe3, 0x22, 0xfc, 0x8a, 0xa5, 0xc7,
|
||||
0x46, 0xa2, 0xed, 0x45, 0xec, 0x72, 0xd6, 0x06, 0xf4, 0x80, 0xce, 0xbc, 0xb8, 0x73, 0xc2, 0xba,
|
||||
0xfb, 0x8e, 0x05, 0xf3, 0x39, 0xd1, 0x62, 0xf2, 0x9a, 0x74, 0xa6, 0xc7, 0x46, 0x92, 0x5b, 0xb9,
|
||||
0xc1, 0x44, 0xfb, 0x10, 0xfb, 0x79, 0x97, 0xbc, 0x63, 0x28, 0x36, 0x1e, 0xc7, 0x13, 0x9c, 0xf9,
|
||||
0x42, 0xa3, 0x22, 0xd7, 0xa2, 0xf8, 0x10, 0x96, 0xf9, 0x40, 0x36, 0xfa, 0xfd, 0x54, 0xa0, 0xf3,
|
||||
0x6a, 0xe6, 0xa5, 0x6f, 0x23, 0x80, 0xdb, 0x1a, 0xff, 0x12, 0xf8, 0x18, 0x73, 0x95, 0x0f, 0x95,
|
||||
0x8c, 0xa0, 0x91, 0x0e, 0x1e, 0x92, 0xf1, 0x6d, 0xb5, 0x5e, 0x35, 0xdc, 0xc2, 0x6c, 0xc0, 0xd1,
|
||||
0xfe, 0x24, 0x76, 0xf6, 0xaa, 0xdd, 0xca, 0x5b, 0x17, 0xee, 0x29, 0xb2, 0xfd, 0xf8, 0x69, 0x15,
|
||||
0xe9, 0x4c, 0xcd, 0x53, 0x76, 0x30, 0x2e, 0x34, 0xab, 0x1c, 0xd3, 0xfc, 0x40, 0xe9, 0x75, 0xec,
|
||||
0x7e, 0xc5, 0xbe, 0x9c, 0xd7, 0x7d, 0xc8, 0x3f, 0xe1, 0x2e, 0xea, 0x72, 0x9a, 0xaf, 0xe5, 0x08,
|
||||
0x56, 0xf2, 0xf6, 0x7b, 0xac, 0xaf, 0x91, 0x5a, 0xeb, 0x89, 0x5b, 0xd6, 0xe6, 0x8d, 0xf7, 0x3f,
|
||||
0xd9, 0xf3, 0xe2, 0x93, 0xd1, 0xd1, 0xcd, 0x4e, 0x30, 0x58, 0xef, 0xcb, 0x10, 0x99, 0x48, 0xf3,
|
||||
0x5d, 0xef, 0xfb, 0xdd, 0x75, 0xfc, 0xfe, 0x68, 0x12, 0xff, 0x71, 0xc0, 0xa7, 0xff, 0x2b, 0x00,
|
||||
0x00, 0xff, 0xff, 0x1d, 0xe9, 0x2d, 0xa2, 0x6a, 0x60, 0x00, 0x00,
|
||||
}
|
||||
|
@ -1257,6 +1257,26 @@ message Peer {
|
||||
|
||||
/// Ping time to this peer
|
||||
int64 ping_time = 9 [json_name = "ping_time"];
|
||||
|
||||
enum SyncType {
|
||||
/**
|
||||
Denotes that we cannot determine the peer's current sync type.
|
||||
*/
|
||||
UNKNOWN_SYNC = 0;
|
||||
|
||||
/**
|
||||
Denotes that we are actively receiving new graph updates from the peer.
|
||||
*/
|
||||
ACTIVE_SYNC = 1;
|
||||
|
||||
/**
|
||||
Denotes that we are not receiving new graph updates from the peer.
|
||||
*/
|
||||
PASSIVE_SYNC = 2;
|
||||
}
|
||||
|
||||
// The type of sync we are currently performing with this peer.
|
||||
SyncType sync_type = 10 [json_name = "sync_type"];
|
||||
}
|
||||
|
||||
message ListPeersRequest {
|
||||
|
@ -1305,6 +1305,16 @@
|
||||
],
|
||||
"default": "OPEN"
|
||||
},
|
||||
"PeerSyncType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"UNKNOWN_SYNC",
|
||||
"ACTIVE_SYNC",
|
||||
"PASSIVE_SYNC"
|
||||
],
|
||||
"default": "UNKNOWN_SYNC",
|
||||
"description": " - UNKNOWN_SYNC: *\nDenotes that we cannot determine the peer's current sync type.\n - ACTIVE_SYNC: *\nDenotes that we are actively receiving new graph updates from the peer.\n - PASSIVE_SYNC: *\nDenotes that we are not receiving new graph updates from the peer."
|
||||
},
|
||||
"PendingChannelsResponseClosedChannel": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -2856,6 +2866,10 @@
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"title": "/ Ping time to this peer"
|
||||
},
|
||||
"sync_type": {
|
||||
"$ref": "#/definitions/PeerSyncType",
|
||||
"description": "The type of sync we are currently performing with this peer."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
15
peer.go
15
peer.go
@ -396,19 +396,16 @@ func (p *peer) initGossipSync() {
|
||||
srvrLog.Infof("Negotiated chan series queries with %x",
|
||||
p.pubKeyBytes[:])
|
||||
|
||||
// We'll only request channel updates from the remote peer if
|
||||
// its enabled in the config, or we're already getting updates
|
||||
// from enough peers.
|
||||
//
|
||||
// TODO(roasbeef): craft s.t. we only get updates from a few
|
||||
// peers
|
||||
recvUpdates := !cfg.NoChanUpdates
|
||||
|
||||
// Register the this peer's for gossip syncer with the gossiper.
|
||||
// This is blocks synchronously to ensure the gossip syncer is
|
||||
// registered with the gossiper before attempting to read
|
||||
// messages from the remote peer.
|
||||
p.server.authGossiper.InitSyncState(p, recvUpdates)
|
||||
//
|
||||
// TODO(wilmer): Only sync updates from non-channel peers. This
|
||||
// requires an improved version of the current network
|
||||
// bootstrapper to ensure we can find and connect to non-channel
|
||||
// peers.
|
||||
p.server.authGossiper.InitSyncState(p)
|
||||
|
||||
// If the remote peer has the initial sync feature bit set, then we'll
|
||||
// being the synchronization protocol to exchange authenticated channel
|
||||
|
33
rpcserver.go
33
rpcserver.go
@ -34,6 +34,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chanbackup"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channelnotifier"
|
||||
"github.com/lightningnetwork/lnd/discovery"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
@ -2012,9 +2013,36 @@ func (r *rpcServer) ListPeers(ctx context.Context,
|
||||
satRecv += int64(c.TotalMSatReceived.ToSatoshis())
|
||||
}
|
||||
|
||||
nodePub := serverPeer.addr.IdentityKey.SerializeCompressed()
|
||||
nodePub := serverPeer.PubKey()
|
||||
|
||||
// Retrieve the peer's sync type. If we don't currently have a
|
||||
// syncer for the peer, then we'll default to a passive sync.
|
||||
// This can happen if the RPC is called while a peer is
|
||||
// initializing.
|
||||
syncer, ok := r.server.authGossiper.SyncManager().GossipSyncer(
|
||||
nodePub,
|
||||
)
|
||||
|
||||
var lnrpcSyncType lnrpc.Peer_SyncType
|
||||
if !ok {
|
||||
rpcsLog.Warnf("Gossip syncer for peer=%x not found",
|
||||
nodePub)
|
||||
lnrpcSyncType = lnrpc.Peer_UNKNOWN_SYNC
|
||||
} else {
|
||||
syncType := syncer.SyncType()
|
||||
switch syncType {
|
||||
case discovery.ActiveSync:
|
||||
lnrpcSyncType = lnrpc.Peer_ACTIVE_SYNC
|
||||
case discovery.PassiveSync:
|
||||
lnrpcSyncType = lnrpc.Peer_PASSIVE_SYNC
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled sync type %v",
|
||||
syncType)
|
||||
}
|
||||
}
|
||||
|
||||
peer := &lnrpc.Peer{
|
||||
PubKey: hex.EncodeToString(nodePub),
|
||||
PubKey: hex.EncodeToString(nodePub[:]),
|
||||
Address: serverPeer.conn.RemoteAddr().String(),
|
||||
Inbound: serverPeer.inbound,
|
||||
BytesRecv: atomic.LoadUint64(&serverPeer.bytesReceived),
|
||||
@ -2022,6 +2050,7 @@ func (r *rpcServer) ListPeers(ctx context.Context,
|
||||
SatSent: satSent,
|
||||
SatRecv: satRecv,
|
||||
PingTime: serverPeer.PingTime(),
|
||||
SyncType: lnrpcSyncType,
|
||||
}
|
||||
|
||||
resp.Peers = append(resp.Peers, peer)
|
||||
|
37
server.go
37
server.go
@ -636,10 +636,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
|
||||
return nil, fmt.Errorf("can't create router: %v", err)
|
||||
}
|
||||
|
||||
chanSeries := discovery.NewChanSeries(
|
||||
s.chanDB.ChannelGraph(),
|
||||
)
|
||||
|
||||
chanSeries := discovery.NewChanSeries(s.chanDB.ChannelGraph())
|
||||
gossipMessageStore, err := discovery.NewMessageStore(s.chanDB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -650,19 +647,23 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
|
||||
}
|
||||
|
||||
s.authGossiper = discovery.New(discovery.Config{
|
||||
Router: s.chanRouter,
|
||||
Notifier: s.cc.chainNotifier,
|
||||
ChainHash: *activeNetParams.GenesisHash,
|
||||
Broadcast: s.BroadcastMessage,
|
||||
ChanSeries: chanSeries,
|
||||
NotifyWhenOnline: s.NotifyWhenOnline,
|
||||
NotifyWhenOffline: s.NotifyWhenOffline,
|
||||
ProofMatureDelta: 0,
|
||||
TrickleDelay: time.Millisecond * time.Duration(cfg.TrickleDelay),
|
||||
RetransmitDelay: time.Minute * 30,
|
||||
WaitingProofStore: waitingProofStore,
|
||||
MessageStore: gossipMessageStore,
|
||||
AnnSigner: s.nodeSigner,
|
||||
Router: s.chanRouter,
|
||||
Notifier: s.cc.chainNotifier,
|
||||
ChainHash: *activeNetParams.GenesisHash,
|
||||
Broadcast: s.BroadcastMessage,
|
||||
ChanSeries: chanSeries,
|
||||
NotifyWhenOnline: s.NotifyWhenOnline,
|
||||
NotifyWhenOffline: s.NotifyWhenOffline,
|
||||
ProofMatureDelta: 0,
|
||||
TrickleDelay: time.Millisecond * time.Duration(cfg.TrickleDelay),
|
||||
RetransmitDelay: time.Minute * 30,
|
||||
WaitingProofStore: waitingProofStore,
|
||||
MessageStore: gossipMessageStore,
|
||||
AnnSigner: s.nodeSigner,
|
||||
RotateTicker: ticker.New(discovery.DefaultSyncerRotationInterval),
|
||||
HistoricalSyncTicker: ticker.New(discovery.DefaultHistoricalSyncInterval),
|
||||
ActiveSyncerTimeoutTicker: ticker.New(discovery.DefaultActiveSyncerTimeout),
|
||||
NumActiveSyncers: cfg.NumGraphSyncPeers,
|
||||
},
|
||||
s.identityPriv.PubKey(),
|
||||
)
|
||||
@ -2622,7 +2623,7 @@ func (s *server) peerTerminationWatcher(p *peer, ready chan struct{}) {
|
||||
|
||||
// We'll also inform the gossiper that this peer is no longer active,
|
||||
// so we don't need to maintain sync state for it any longer.
|
||||
s.authGossiper.PruneSyncState(pubKey)
|
||||
s.authGossiper.PruneSyncState(p.PubKey())
|
||||
|
||||
// Tell the switch to remove all links associated with this peer.
|
||||
// Passing nil as the target link indicates that all links associated
|
||||
|
Loading…
Reference in New Issue
Block a user