lnwire: update NodeAnnouncement to handle multiple addresses

This commit modifies address handling in the NodeAnnouncement struct,
switching from net.TCPAddr to []net.Addr. This enables more flexible
address handling with multiple types and multiple addresses for each
node. This commit addresses the first part of issue #131 .
This commit is contained in:
bryanvu 2017-02-17 01:29:23 -08:00 committed by Olaoluwa Osuntokun
parent 65c15c4cb0
commit 9ffac9eae1
16 changed files with 594 additions and 397 deletions

@ -73,4 +73,8 @@ var (
// ErrNodeAliasNotFound is returned when alias for node can't be found. // ErrNodeAliasNotFound is returned when alias for node can't be found.
ErrNodeAliasNotFound = fmt.Errorf("alias for node not found") ErrNodeAliasNotFound = fmt.Errorf("alias for node not found")
// ErrUnknownAddressType is returned when a node's addressType is not
// an expected value.
ErrUnknownAddressType = fmt.Errorf("address type cannot be resolved")
) )

@ -114,6 +114,16 @@ type ChannelGraph struct {
// * LRU cache for edges? // * LRU cache for edges?
} }
// addressType specifies the network protocol and version that should be used
// when connecting to a node at a particular address.
type addressType uint8
const (
tcp4Addr addressType = 0
tcp6Addr addressType = 1
onionAddr addressType = 2
)
// ForEachChannel iterates through all the channel edges stored within the // ForEachChannel iterates through all the channel edges stored within the
// graph and invokes the passed callback for each edge. The callback takes two // graph and invokes the passed callback for each edge. The callback takes two
// edges as since this is a directed graph, both the in/out edges are visited. // edges as since this is a directed graph, both the in/out edges are visited.
@ -801,7 +811,7 @@ type LightningNode struct {
LastUpdate time.Time LastUpdate time.Time
// Address is the TCP address this node is reachable over. // Address is the TCP address this node is reachable over.
Address *net.TCPAddr Addresses []net.Addr
// PubKey is the node's long-term identity public key. This key will be // PubKey is the node's long-term identity public key. This key will be
// used to authenticated any advertisements/updates sent by the node. // used to authenticated any advertisements/updates sent by the node.
@ -1265,7 +1275,7 @@ func (c *ChannelGraph) NewChannelEdgePolicy() *ChannelEdgePolicy {
func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *LightningNode) error { func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *LightningNode) error {
var ( var (
scratch [8]byte scratch [16]byte
b bytes.Buffer b bytes.Buffer
) )
@ -1276,13 +1286,8 @@ func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *L
} }
updateUnix := uint64(node.LastUpdate.Unix()) updateUnix := uint64(node.LastUpdate.Unix())
byteOrder.PutUint64(scratch[:], updateUnix) byteOrder.PutUint64(scratch[:8], updateUnix)
if _, err := b.Write(scratch[:]); err != nil { if _, err := b.Write(scratch[:8]); err != nil {
return err
}
addrString := node.Address.String()
if err := wire.WriteVarString(&b, 0, addrString); err != nil {
return err return err
} }
@ -1304,6 +1309,41 @@ func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *L
return err return err
} }
numAddresses := uint16(len(node.Addresses))
byteOrder.PutUint16(scratch[:2], numAddresses)
if _, err := b.Write(scratch[:2]); err != nil {
return err
}
for _, address := range node.Addresses {
if address.Network() == "tcp" {
if address.(*net.TCPAddr).IP.To4() != nil {
scratch[0] = uint8(tcp4Addr)
if _, err := b.Write(scratch[:1]); err != nil {
return err
}
copy(scratch[:4], address.(*net.TCPAddr).IP.To4())
if _, err := b.Write(scratch[:4]); err != nil {
return err
}
} else {
scratch[0] = uint8(tcp6Addr)
if _, err := b.Write(scratch[:1]); err != nil {
return err
}
copy(scratch[:], address.(*net.TCPAddr).IP.To16())
if _, err := b.Write(scratch[:]); err != nil {
return err
}
}
byteOrder.PutUint16(scratch[:2],
uint16(address.(*net.TCPAddr).Port))
if _, err := b.Write(scratch[:2]); err != nil {
return err
}
}
}
return nodeBucket.Put(nodePub, b.Bytes()) return nodeBucket.Put(nodePub, b.Bytes())
} }
@ -1321,8 +1361,8 @@ func fetchLightningNode(nodeBucket *bolt.Bucket,
func deserializeLightningNode(r io.Reader) (*LightningNode, error) { func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
node := &LightningNode{} node := &LightningNode{}
var scratch [8]byte var scratch [8]byte
if _, err := r.Read(scratch[:]); err != nil { if _, err := r.Read(scratch[:]); err != nil {
return nil, err return nil, err
} }
@ -1330,19 +1370,11 @@ func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
unix := int64(byteOrder.Uint64(scratch[:])) unix := int64(byteOrder.Uint64(scratch[:]))
node.LastUpdate = time.Unix(unix, 0) node.LastUpdate = time.Unix(unix, 0)
addrString, err := wire.ReadVarString(r, 0)
if err != nil {
return nil, err
}
node.Address, err = net.ResolveTCPAddr("tcp", addrString)
if err != nil {
return nil, err
}
var pub [33]byte var pub [33]byte
if _, err := r.Read(pub[:]); err != nil { if _, err := r.Read(pub[:]); err != nil {
return nil, err return nil, err
} }
var err error
node.PubKey, err = btcec.ParsePubKey(pub[:], btcec.S256()) node.PubKey, err = btcec.ParsePubKey(pub[:], btcec.S256())
if err != nil { if err != nil {
return nil, err return nil, err
@ -1363,6 +1395,51 @@ func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
return nil, err return nil, err
} }
if _, err := r.Read(scratch[:2]); err != nil {
return nil, err
}
numAddresses := int(byteOrder.Uint16(scratch[:2]))
var addresses []net.Addr
for i := 0; i < numAddresses; i++ {
var address net.Addr
if _, err := r.Read(scratch[:1]); err != nil {
return nil, err
}
switch addressType(scratch[0]) {
case tcp4Addr:
addr := &net.TCPAddr{}
var ip [4]byte
if _, err := r.Read(ip[:]); err != nil {
return nil, err
}
addr.IP = (net.IP)(ip[:])
if _, err := r.Read(scratch[:2]); err != nil {
return nil, err
}
addr.Port = int(byteOrder.Uint16(scratch[:2]))
address = addr
case tcp6Addr:
addr := &net.TCPAddr{}
var ip [16]byte
if _, err := r.Read(ip[:]); err != nil {
return nil, err
}
addr.IP = (net.IP)(ip[:])
if _, err := r.Read(scratch[:2]); err != nil {
return nil, err
}
addr.Port = int(byteOrder.Uint16(scratch[:2]))
address = addr
default:
return nil, ErrUnknownAddressType
}
addresses = append(addresses, address)
}
node.Addresses = addresses
return node, nil return node, nil
} }

@ -21,7 +21,9 @@ import (
) )
var ( var (
testAddr, _ = net.ResolveTCPAddr("tcp", "10.0.0.1:9000") testAddr = &net.TCPAddr{IP: (net.IP)([]byte{0xA, 0x0, 0x0, 0x1}),
Port: 9000}
testAddrs = []net.Addr{testAddr}
randSource = prand.NewSource(time.Now().Unix()) randSource = prand.NewSource(time.Now().Unix())
randInts = prand.New(randSource) randInts = prand.New(randSource)
@ -44,7 +46,7 @@ func createTestVertex(db *DB) (*LightningNode, error) {
pub := priv.PubKey().SerializeCompressed() pub := priv.PubKey().SerializeCompressed()
return &LightningNode{ return &LightningNode{
LastUpdate: time.Unix(updateTime, 0), LastUpdate: time.Unix(updateTime, 0),
Address: testAddr, Addresses: testAddrs,
PubKey: priv.PubKey(), PubKey: priv.PubKey(),
Color: color.RGBA{1, 2, 3, 0}, Color: color.RGBA{1, 2, 3, 0},
Alias: "kek" + string(pub[:]), Alias: "kek" + string(pub[:]),
@ -66,7 +68,7 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
_, testPub := btcec.PrivKeyFromBytes(btcec.S256(), key[:]) _, testPub := btcec.PrivKeyFromBytes(btcec.S256(), key[:])
node := &LightningNode{ node := &LightningNode{
LastUpdate: time.Unix(1232342, 0), LastUpdate: time.Unix(1232342, 0),
Address: testAddr, Addresses: testAddrs,
PubKey: testPub, PubKey: testPub,
Color: color.RGBA{1, 2, 3, 0}, Color: color.RGBA{1, 2, 3, 0},
Alias: "kek", Alias: "kek",

@ -55,6 +55,7 @@ It has these top-level messages:
NodeInfoRequest NodeInfoRequest
NodeInfo NodeInfo
LightningNode LightningNode
NodeAddress
RoutingPolicy RoutingPolicy
ChannelEdge ChannelEdge
ChannelGraphRequest ChannelGraphRequest
@ -90,7 +91,7 @@ package lnrpc
import proto "github.com/golang/protobuf/proto" import proto "github.com/golang/protobuf/proto"
import fmt "fmt" import fmt "fmt"
import math "math" import math "math"
import _ "google.golang.org/genproto/googleapis/api/annotations" import _ "github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api"
import ( import (
context "golang.org/x/net/context" context "golang.org/x/net/context"
@ -384,7 +385,7 @@ func (m *LightningAddress) GetHost() string {
} }
type SendManyRequest struct { type SendManyRequest struct {
AddrToAmount map[string]int64 `protobuf:"bytes,1,rep,name=AddrToAmount" json:"AddrToAmount,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` AddrToAmount map[string]int64 `protobuf:"bytes,1,rep,name=AddrToAmount,json=addrToAmount" json:"AddrToAmount,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
} }
func (m *SendManyRequest) Reset() { *m = SendManyRequest{} } func (m *SendManyRequest) Reset() { *m = SendManyRequest{} }
@ -1714,10 +1715,10 @@ func (m *NodeInfo) GetTotalCapacity() int64 {
} }
type LightningNode struct { type LightningNode struct {
LastUpdate uint32 `protobuf:"varint,1,opt,name=last_update" json:"last_update,omitempty"` LastUpdate uint32 `protobuf:"varint,1,opt,name=last_update" json:"last_update,omitempty"`
PubKey string `protobuf:"bytes,2,opt,name=pub_key" json:"pub_key,omitempty"` PubKey string `protobuf:"bytes,2,opt,name=pub_key" json:"pub_key,omitempty"`
Address string `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` Alias string `protobuf:"bytes,3,opt,name=alias" json:"alias,omitempty"`
Alias string `protobuf:"bytes,4,opt,name=alias" json:"alias,omitempty"` Addresses []*NodeAddress `protobuf:"bytes,4,rep,name=addresses" json:"addresses,omitempty"`
} }
func (m *LightningNode) Reset() { *m = LightningNode{} } func (m *LightningNode) Reset() { *m = LightningNode{} }
@ -1739,16 +1740,40 @@ func (m *LightningNode) GetPubKey() string {
return "" return ""
} }
func (m *LightningNode) GetAddress() string { func (m *LightningNode) GetAlias() string {
if m != nil { if m != nil {
return m.Address return m.Alias
} }
return "" return ""
} }
func (m *LightningNode) GetAlias() string { func (m *LightningNode) GetAddresses() []*NodeAddress {
if m != nil { if m != nil {
return m.Alias return m.Addresses
}
return nil
}
type NodeAddress struct {
Network string `protobuf:"bytes,1,opt,name=network" json:"network,omitempty"`
Addr string `protobuf:"bytes,2,opt,name=addr" json:"addr,omitempty"`
}
func (m *NodeAddress) Reset() { *m = NodeAddress{} }
func (m *NodeAddress) String() string { return proto.CompactTextString(m) }
func (*NodeAddress) ProtoMessage() {}
func (*NodeAddress) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} }
func (m *NodeAddress) GetNetwork() string {
if m != nil {
return m.Network
}
return ""
}
func (m *NodeAddress) GetAddr() string {
if m != nil {
return m.Addr
} }
return "" return ""
} }
@ -1763,7 +1788,7 @@ type RoutingPolicy struct {
func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} } func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} }
func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) } func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) }
func (*RoutingPolicy) ProtoMessage() {} func (*RoutingPolicy) ProtoMessage() {}
func (*RoutingPolicy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } func (*RoutingPolicy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{47} }
func (m *RoutingPolicy) GetTimeLockDelta() uint32 { func (m *RoutingPolicy) GetTimeLockDelta() uint32 {
if m != nil { if m != nil {
@ -1807,7 +1832,7 @@ type ChannelEdge struct {
func (m *ChannelEdge) Reset() { *m = ChannelEdge{} } func (m *ChannelEdge) Reset() { *m = ChannelEdge{} }
func (m *ChannelEdge) String() string { return proto.CompactTextString(m) } func (m *ChannelEdge) String() string { return proto.CompactTextString(m) }
func (*ChannelEdge) ProtoMessage() {} func (*ChannelEdge) ProtoMessage() {}
func (*ChannelEdge) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{47} } func (*ChannelEdge) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} }
func (m *ChannelEdge) GetChannelId() uint64 { func (m *ChannelEdge) GetChannelId() uint64 {
if m != nil { if m != nil {
@ -1871,7 +1896,7 @@ type ChannelGraphRequest struct {
func (m *ChannelGraphRequest) Reset() { *m = ChannelGraphRequest{} } func (m *ChannelGraphRequest) Reset() { *m = ChannelGraphRequest{} }
func (m *ChannelGraphRequest) String() string { return proto.CompactTextString(m) } func (m *ChannelGraphRequest) String() string { return proto.CompactTextString(m) }
func (*ChannelGraphRequest) ProtoMessage() {} func (*ChannelGraphRequest) ProtoMessage() {}
func (*ChannelGraphRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } func (*ChannelGraphRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{49} }
type ChannelGraph struct { type ChannelGraph struct {
Nodes []*LightningNode `protobuf:"bytes,1,rep,name=nodes" json:"nodes,omitempty"` Nodes []*LightningNode `protobuf:"bytes,1,rep,name=nodes" json:"nodes,omitempty"`
@ -1881,7 +1906,7 @@ type ChannelGraph struct {
func (m *ChannelGraph) Reset() { *m = ChannelGraph{} } func (m *ChannelGraph) Reset() { *m = ChannelGraph{} }
func (m *ChannelGraph) String() string { return proto.CompactTextString(m) } func (m *ChannelGraph) String() string { return proto.CompactTextString(m) }
func (*ChannelGraph) ProtoMessage() {} func (*ChannelGraph) ProtoMessage() {}
func (*ChannelGraph) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{49} } func (*ChannelGraph) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{50} }
func (m *ChannelGraph) GetNodes() []*LightningNode { func (m *ChannelGraph) GetNodes() []*LightningNode {
if m != nil { if m != nil {
@ -1904,7 +1929,7 @@ type ChanInfoRequest struct {
func (m *ChanInfoRequest) Reset() { *m = ChanInfoRequest{} } func (m *ChanInfoRequest) Reset() { *m = ChanInfoRequest{} }
func (m *ChanInfoRequest) String() string { return proto.CompactTextString(m) } func (m *ChanInfoRequest) String() string { return proto.CompactTextString(m) }
func (*ChanInfoRequest) ProtoMessage() {} func (*ChanInfoRequest) ProtoMessage() {}
func (*ChanInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{50} } func (*ChanInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51} }
func (m *ChanInfoRequest) GetChanId() uint64 { func (m *ChanInfoRequest) GetChanId() uint64 {
if m != nil { if m != nil {
@ -1919,7 +1944,7 @@ type NetworkInfoRequest struct {
func (m *NetworkInfoRequest) Reset() { *m = NetworkInfoRequest{} } func (m *NetworkInfoRequest) Reset() { *m = NetworkInfoRequest{} }
func (m *NetworkInfoRequest) String() string { return proto.CompactTextString(m) } func (m *NetworkInfoRequest) String() string { return proto.CompactTextString(m) }
func (*NetworkInfoRequest) ProtoMessage() {} func (*NetworkInfoRequest) ProtoMessage() {}
func (*NetworkInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51} } func (*NetworkInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{52} }
type NetworkInfo struct { type NetworkInfo struct {
GraphDiameter uint32 `protobuf:"varint,1,opt,name=graph_diameter" json:"graph_diameter,omitempty"` GraphDiameter uint32 `protobuf:"varint,1,opt,name=graph_diameter" json:"graph_diameter,omitempty"`
@ -1936,7 +1961,7 @@ type NetworkInfo struct {
func (m *NetworkInfo) Reset() { *m = NetworkInfo{} } func (m *NetworkInfo) Reset() { *m = NetworkInfo{} }
func (m *NetworkInfo) String() string { return proto.CompactTextString(m) } func (m *NetworkInfo) String() string { return proto.CompactTextString(m) }
func (*NetworkInfo) ProtoMessage() {} func (*NetworkInfo) ProtoMessage() {}
func (*NetworkInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{52} } func (*NetworkInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{53} }
func (m *NetworkInfo) GetGraphDiameter() uint32 { func (m *NetworkInfo) GetGraphDiameter() uint32 {
if m != nil { if m != nil {
@ -2007,7 +2032,7 @@ type GraphTopologySubscription struct {
func (m *GraphTopologySubscription) Reset() { *m = GraphTopologySubscription{} } func (m *GraphTopologySubscription) Reset() { *m = GraphTopologySubscription{} }
func (m *GraphTopologySubscription) String() string { return proto.CompactTextString(m) } func (m *GraphTopologySubscription) String() string { return proto.CompactTextString(m) }
func (*GraphTopologySubscription) ProtoMessage() {} func (*GraphTopologySubscription) ProtoMessage() {}
func (*GraphTopologySubscription) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{53} } func (*GraphTopologySubscription) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{54} }
type GraphTopologyUpdate struct { type GraphTopologyUpdate struct {
NodeUpdates []*NodeUpdate `protobuf:"bytes,1,rep,name=node_updates,json=nodeUpdates" json:"node_updates,omitempty"` NodeUpdates []*NodeUpdate `protobuf:"bytes,1,rep,name=node_updates,json=nodeUpdates" json:"node_updates,omitempty"`
@ -2018,7 +2043,7 @@ type GraphTopologyUpdate struct {
func (m *GraphTopologyUpdate) Reset() { *m = GraphTopologyUpdate{} } func (m *GraphTopologyUpdate) Reset() { *m = GraphTopologyUpdate{} }
func (m *GraphTopologyUpdate) String() string { return proto.CompactTextString(m) } func (m *GraphTopologyUpdate) String() string { return proto.CompactTextString(m) }
func (*GraphTopologyUpdate) ProtoMessage() {} func (*GraphTopologyUpdate) ProtoMessage() {}
func (*GraphTopologyUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{54} } func (*GraphTopologyUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{55} }
func (m *GraphTopologyUpdate) GetNodeUpdates() []*NodeUpdate { func (m *GraphTopologyUpdate) GetNodeUpdates() []*NodeUpdate {
if m != nil { if m != nil {
@ -2051,7 +2076,7 @@ type NodeUpdate struct {
func (m *NodeUpdate) Reset() { *m = NodeUpdate{} } func (m *NodeUpdate) Reset() { *m = NodeUpdate{} }
func (m *NodeUpdate) String() string { return proto.CompactTextString(m) } func (m *NodeUpdate) String() string { return proto.CompactTextString(m) }
func (*NodeUpdate) ProtoMessage() {} func (*NodeUpdate) ProtoMessage() {}
func (*NodeUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{55} } func (*NodeUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{56} }
func (m *NodeUpdate) GetAddresses() []string { func (m *NodeUpdate) GetAddresses() []string {
if m != nil { if m != nil {
@ -2093,7 +2118,7 @@ type ChannelEdgeUpdate struct {
func (m *ChannelEdgeUpdate) Reset() { *m = ChannelEdgeUpdate{} } func (m *ChannelEdgeUpdate) Reset() { *m = ChannelEdgeUpdate{} }
func (m *ChannelEdgeUpdate) String() string { return proto.CompactTextString(m) } func (m *ChannelEdgeUpdate) String() string { return proto.CompactTextString(m) }
func (*ChannelEdgeUpdate) ProtoMessage() {} func (*ChannelEdgeUpdate) ProtoMessage() {}
func (*ChannelEdgeUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{56} } func (*ChannelEdgeUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{57} }
func (m *ChannelEdgeUpdate) GetChanId() uint64 { func (m *ChannelEdgeUpdate) GetChanId() uint64 {
if m != nil { if m != nil {
@ -2147,7 +2172,7 @@ type ClosedChannelUpdate struct {
func (m *ClosedChannelUpdate) Reset() { *m = ClosedChannelUpdate{} } func (m *ClosedChannelUpdate) Reset() { *m = ClosedChannelUpdate{} }
func (m *ClosedChannelUpdate) String() string { return proto.CompactTextString(m) } func (m *ClosedChannelUpdate) String() string { return proto.CompactTextString(m) }
func (*ClosedChannelUpdate) ProtoMessage() {} func (*ClosedChannelUpdate) ProtoMessage() {}
func (*ClosedChannelUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{57} } func (*ClosedChannelUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{58} }
func (m *ClosedChannelUpdate) GetChanId() uint64 { func (m *ClosedChannelUpdate) GetChanId() uint64 {
if m != nil { if m != nil {
@ -2184,7 +2209,7 @@ type SetAliasRequest struct {
func (m *SetAliasRequest) Reset() { *m = SetAliasRequest{} } func (m *SetAliasRequest) Reset() { *m = SetAliasRequest{} }
func (m *SetAliasRequest) String() string { return proto.CompactTextString(m) } func (m *SetAliasRequest) String() string { return proto.CompactTextString(m) }
func (*SetAliasRequest) ProtoMessage() {} func (*SetAliasRequest) ProtoMessage() {}
func (*SetAliasRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{58} } func (*SetAliasRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{59} }
func (m *SetAliasRequest) GetNewAlias() string { func (m *SetAliasRequest) GetNewAlias() string {
if m != nil { if m != nil {
@ -2199,7 +2224,7 @@ type SetAliasResponse struct {
func (m *SetAliasResponse) Reset() { *m = SetAliasResponse{} } func (m *SetAliasResponse) Reset() { *m = SetAliasResponse{} }
func (m *SetAliasResponse) String() string { return proto.CompactTextString(m) } func (m *SetAliasResponse) String() string { return proto.CompactTextString(m) }
func (*SetAliasResponse) ProtoMessage() {} func (*SetAliasResponse) ProtoMessage() {}
func (*SetAliasResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{59} } func (*SetAliasResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{60} }
type Invoice struct { type Invoice struct {
Memo string `protobuf:"bytes,1,opt,name=memo" json:"memo,omitempty"` Memo string `protobuf:"bytes,1,opt,name=memo" json:"memo,omitempty"`
@ -2216,7 +2241,7 @@ type Invoice struct {
func (m *Invoice) Reset() { *m = Invoice{} } func (m *Invoice) Reset() { *m = Invoice{} }
func (m *Invoice) String() string { return proto.CompactTextString(m) } func (m *Invoice) String() string { return proto.CompactTextString(m) }
func (*Invoice) ProtoMessage() {} func (*Invoice) ProtoMessage() {}
func (*Invoice) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{60} } func (*Invoice) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{61} }
func (m *Invoice) GetMemo() string { func (m *Invoice) GetMemo() string {
if m != nil { if m != nil {
@ -2289,7 +2314,7 @@ type AddInvoiceResponse struct {
func (m *AddInvoiceResponse) Reset() { *m = AddInvoiceResponse{} } func (m *AddInvoiceResponse) Reset() { *m = AddInvoiceResponse{} }
func (m *AddInvoiceResponse) String() string { return proto.CompactTextString(m) } func (m *AddInvoiceResponse) String() string { return proto.CompactTextString(m) }
func (*AddInvoiceResponse) ProtoMessage() {} func (*AddInvoiceResponse) ProtoMessage() {}
func (*AddInvoiceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{61} } func (*AddInvoiceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62} }
func (m *AddInvoiceResponse) GetRHash() []byte { func (m *AddInvoiceResponse) GetRHash() []byte {
if m != nil { if m != nil {
@ -2313,7 +2338,7 @@ type PaymentHash struct {
func (m *PaymentHash) Reset() { *m = PaymentHash{} } func (m *PaymentHash) Reset() { *m = PaymentHash{} }
func (m *PaymentHash) String() string { return proto.CompactTextString(m) } func (m *PaymentHash) String() string { return proto.CompactTextString(m) }
func (*PaymentHash) ProtoMessage() {} func (*PaymentHash) ProtoMessage() {}
func (*PaymentHash) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62} } func (*PaymentHash) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{63} }
func (m *PaymentHash) GetRHashStr() string { func (m *PaymentHash) GetRHashStr() string {
if m != nil { if m != nil {
@ -2336,7 +2361,7 @@ type ListInvoiceRequest struct {
func (m *ListInvoiceRequest) Reset() { *m = ListInvoiceRequest{} } func (m *ListInvoiceRequest) Reset() { *m = ListInvoiceRequest{} }
func (m *ListInvoiceRequest) String() string { return proto.CompactTextString(m) } func (m *ListInvoiceRequest) String() string { return proto.CompactTextString(m) }
func (*ListInvoiceRequest) ProtoMessage() {} func (*ListInvoiceRequest) ProtoMessage() {}
func (*ListInvoiceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{63} } func (*ListInvoiceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{64} }
func (m *ListInvoiceRequest) GetPendingOnly() bool { func (m *ListInvoiceRequest) GetPendingOnly() bool {
if m != nil { if m != nil {
@ -2352,7 +2377,7 @@ type ListInvoiceResponse struct {
func (m *ListInvoiceResponse) Reset() { *m = ListInvoiceResponse{} } func (m *ListInvoiceResponse) Reset() { *m = ListInvoiceResponse{} }
func (m *ListInvoiceResponse) String() string { return proto.CompactTextString(m) } func (m *ListInvoiceResponse) String() string { return proto.CompactTextString(m) }
func (*ListInvoiceResponse) ProtoMessage() {} func (*ListInvoiceResponse) ProtoMessage() {}
func (*ListInvoiceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{64} } func (*ListInvoiceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{65} }
func (m *ListInvoiceResponse) GetInvoices() []*Invoice { func (m *ListInvoiceResponse) GetInvoices() []*Invoice {
if m != nil { if m != nil {
@ -2367,7 +2392,7 @@ type InvoiceSubscription struct {
func (m *InvoiceSubscription) Reset() { *m = InvoiceSubscription{} } func (m *InvoiceSubscription) Reset() { *m = InvoiceSubscription{} }
func (m *InvoiceSubscription) String() string { return proto.CompactTextString(m) } func (m *InvoiceSubscription) String() string { return proto.CompactTextString(m) }
func (*InvoiceSubscription) ProtoMessage() {} func (*InvoiceSubscription) ProtoMessage() {}
func (*InvoiceSubscription) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{65} } func (*InvoiceSubscription) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{66} }
type Payment struct { type Payment struct {
PaymentHash string `protobuf:"bytes,1,opt,name=payment_hash" json:"payment_hash,omitempty"` PaymentHash string `protobuf:"bytes,1,opt,name=payment_hash" json:"payment_hash,omitempty"`
@ -2380,7 +2405,7 @@ type Payment struct {
func (m *Payment) Reset() { *m = Payment{} } func (m *Payment) Reset() { *m = Payment{} }
func (m *Payment) String() string { return proto.CompactTextString(m) } func (m *Payment) String() string { return proto.CompactTextString(m) }
func (*Payment) ProtoMessage() {} func (*Payment) ProtoMessage() {}
func (*Payment) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{66} } func (*Payment) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{67} }
func (m *Payment) GetPaymentHash() string { func (m *Payment) GetPaymentHash() string {
if m != nil { if m != nil {
@ -2423,7 +2448,7 @@ type ListPaymentsRequest struct {
func (m *ListPaymentsRequest) Reset() { *m = ListPaymentsRequest{} } func (m *ListPaymentsRequest) Reset() { *m = ListPaymentsRequest{} }
func (m *ListPaymentsRequest) String() string { return proto.CompactTextString(m) } func (m *ListPaymentsRequest) String() string { return proto.CompactTextString(m) }
func (*ListPaymentsRequest) ProtoMessage() {} func (*ListPaymentsRequest) ProtoMessage() {}
func (*ListPaymentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{67} } func (*ListPaymentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{68} }
type ListPaymentsResponse struct { type ListPaymentsResponse struct {
Payments []*Payment `protobuf:"bytes,1,rep,name=payments" json:"payments,omitempty"` Payments []*Payment `protobuf:"bytes,1,rep,name=payments" json:"payments,omitempty"`
@ -2432,7 +2457,7 @@ type ListPaymentsResponse struct {
func (m *ListPaymentsResponse) Reset() { *m = ListPaymentsResponse{} } func (m *ListPaymentsResponse) Reset() { *m = ListPaymentsResponse{} }
func (m *ListPaymentsResponse) String() string { return proto.CompactTextString(m) } func (m *ListPaymentsResponse) String() string { return proto.CompactTextString(m) }
func (*ListPaymentsResponse) ProtoMessage() {} func (*ListPaymentsResponse) ProtoMessage() {}
func (*ListPaymentsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{68} } func (*ListPaymentsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{69} }
func (m *ListPaymentsResponse) GetPayments() []*Payment { func (m *ListPaymentsResponse) GetPayments() []*Payment {
if m != nil { if m != nil {
@ -2447,7 +2472,7 @@ type DeleteAllPaymentsRequest struct {
func (m *DeleteAllPaymentsRequest) Reset() { *m = DeleteAllPaymentsRequest{} } func (m *DeleteAllPaymentsRequest) Reset() { *m = DeleteAllPaymentsRequest{} }
func (m *DeleteAllPaymentsRequest) String() string { return proto.CompactTextString(m) } func (m *DeleteAllPaymentsRequest) String() string { return proto.CompactTextString(m) }
func (*DeleteAllPaymentsRequest) ProtoMessage() {} func (*DeleteAllPaymentsRequest) ProtoMessage() {}
func (*DeleteAllPaymentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{69} } func (*DeleteAllPaymentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{70} }
type DeleteAllPaymentsResponse struct { type DeleteAllPaymentsResponse struct {
} }
@ -2455,7 +2480,7 @@ type DeleteAllPaymentsResponse struct {
func (m *DeleteAllPaymentsResponse) Reset() { *m = DeleteAllPaymentsResponse{} } func (m *DeleteAllPaymentsResponse) Reset() { *m = DeleteAllPaymentsResponse{} }
func (m *DeleteAllPaymentsResponse) String() string { return proto.CompactTextString(m) } func (m *DeleteAllPaymentsResponse) String() string { return proto.CompactTextString(m) }
func (*DeleteAllPaymentsResponse) ProtoMessage() {} func (*DeleteAllPaymentsResponse) ProtoMessage() {}
func (*DeleteAllPaymentsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{70} } func (*DeleteAllPaymentsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{71} }
type DebugLevelRequest struct { type DebugLevelRequest struct {
Show bool `protobuf:"varint,1,opt,name=show" json:"show,omitempty"` Show bool `protobuf:"varint,1,opt,name=show" json:"show,omitempty"`
@ -2465,7 +2490,7 @@ type DebugLevelRequest struct {
func (m *DebugLevelRequest) Reset() { *m = DebugLevelRequest{} } func (m *DebugLevelRequest) Reset() { *m = DebugLevelRequest{} }
func (m *DebugLevelRequest) String() string { return proto.CompactTextString(m) } func (m *DebugLevelRequest) String() string { return proto.CompactTextString(m) }
func (*DebugLevelRequest) ProtoMessage() {} func (*DebugLevelRequest) ProtoMessage() {}
func (*DebugLevelRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{71} } func (*DebugLevelRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{72} }
func (m *DebugLevelRequest) GetShow() bool { func (m *DebugLevelRequest) GetShow() bool {
if m != nil { if m != nil {
@ -2488,7 +2513,7 @@ type DebugLevelResponse struct {
func (m *DebugLevelResponse) Reset() { *m = DebugLevelResponse{} } func (m *DebugLevelResponse) Reset() { *m = DebugLevelResponse{} }
func (m *DebugLevelResponse) String() string { return proto.CompactTextString(m) } func (m *DebugLevelResponse) String() string { return proto.CompactTextString(m) }
func (*DebugLevelResponse) ProtoMessage() {} func (*DebugLevelResponse) ProtoMessage() {}
func (*DebugLevelResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{72} } func (*DebugLevelResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{73} }
func (m *DebugLevelResponse) GetSubSystems() string { func (m *DebugLevelResponse) GetSubSystems() string {
if m != nil { if m != nil {
@ -2504,7 +2529,7 @@ type PayReqString struct {
func (m *PayReqString) Reset() { *m = PayReqString{} } func (m *PayReqString) Reset() { *m = PayReqString{} }
func (m *PayReqString) String() string { return proto.CompactTextString(m) } func (m *PayReqString) String() string { return proto.CompactTextString(m) }
func (*PayReqString) ProtoMessage() {} func (*PayReqString) ProtoMessage() {}
func (*PayReqString) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{73} } func (*PayReqString) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{74} }
func (m *PayReqString) GetPayReq() string { func (m *PayReqString) GetPayReq() string {
if m != nil { if m != nil {
@ -2522,7 +2547,7 @@ type PayReq struct {
func (m *PayReq) Reset() { *m = PayReq{} } func (m *PayReq) Reset() { *m = PayReq{} }
func (m *PayReq) String() string { return proto.CompactTextString(m) } func (m *PayReq) String() string { return proto.CompactTextString(m) }
func (*PayReq) ProtoMessage() {} func (*PayReq) ProtoMessage() {}
func (*PayReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{74} } func (*PayReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{75} }
func (m *PayReq) GetDestination() string { func (m *PayReq) GetDestination() string {
if m != nil { if m != nil {
@ -2593,6 +2618,7 @@ func init() {
proto.RegisterType((*NodeInfoRequest)(nil), "lnrpc.NodeInfoRequest") proto.RegisterType((*NodeInfoRequest)(nil), "lnrpc.NodeInfoRequest")
proto.RegisterType((*NodeInfo)(nil), "lnrpc.NodeInfo") proto.RegisterType((*NodeInfo)(nil), "lnrpc.NodeInfo")
proto.RegisterType((*LightningNode)(nil), "lnrpc.LightningNode") proto.RegisterType((*LightningNode)(nil), "lnrpc.LightningNode")
proto.RegisterType((*NodeAddress)(nil), "lnrpc.NodeAddress")
proto.RegisterType((*RoutingPolicy)(nil), "lnrpc.RoutingPolicy") proto.RegisterType((*RoutingPolicy)(nil), "lnrpc.RoutingPolicy")
proto.RegisterType((*ChannelEdge)(nil), "lnrpc.ChannelEdge") proto.RegisterType((*ChannelEdge)(nil), "lnrpc.ChannelEdge")
proto.RegisterType((*ChannelGraphRequest)(nil), "lnrpc.ChannelGraphRequest") proto.RegisterType((*ChannelGraphRequest)(nil), "lnrpc.ChannelGraphRequest")
@ -3927,252 +3953,254 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("rpc.proto", fileDescriptor0) } func init() { proto.RegisterFile("rpc.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 3937 bytes of a gzipped FileDescriptorProto // 3972 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x5a, 0xcd, 0x6f, 0x1c, 0xc9, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x5a, 0xcd, 0x6f, 0x1c, 0xc9,
0x75, 0x57, 0x0f, 0x87, 0xe4, 0xcc, 0x9b, 0x19, 0x7e, 0x14, 0x29, 0x72, 0x34, 0xd2, 0xae, 0xb5, 0x75, 0x57, 0xcf, 0x0c, 0xc9, 0x99, 0x37, 0x33, 0xfc, 0x28, 0x52, 0xe4, 0x68, 0xa8, 0x5d, 0x6b,
0x65, 0x61, 0xc5, 0x30, 0x0b, 0x52, 0xcb, 0x04, 0x1b, 0x79, 0x37, 0xc9, 0x82, 0x2b, 0xd1, 0xa2, 0xcb, 0xc2, 0x8a, 0x61, 0x16, 0xa4, 0x96, 0x09, 0x36, 0xf2, 0x2a, 0xc9, 0x82, 0x2b, 0xd1, 0xa2,
0x60, 0x9a, 0xa2, 0x9b, 0xda, 0x95, 0x63, 0x23, 0x98, 0x34, 0xa7, 0x8b, 0xc3, 0xb6, 0x7a, 0xba, 0x60, 0x9a, 0xa2, 0x9b, 0xda, 0x95, 0x63, 0x23, 0x98, 0x34, 0x67, 0x8a, 0xc3, 0xb6, 0x7a, 0xba,
0x7b, 0xbb, 0x6b, 0x48, 0x8d, 0x05, 0x22, 0x81, 0xe3, 0x5b, 0x12, 0x18, 0x41, 0x80, 0x1c, 0x8d, 0x7b, 0xbb, 0x6b, 0x48, 0x8d, 0x05, 0x22, 0x81, 0xe3, 0x5b, 0x12, 0x18, 0x81, 0x81, 0x1c, 0x8d,
0x00, 0x39, 0xe7, 0x92, 0x6b, 0xfe, 0x86, 0x00, 0x06, 0x7c, 0xca, 0x21, 0xb7, 0x20, 0xf7, 0xdc, 0x00, 0x39, 0xe7, 0x92, 0x6b, 0xfe, 0x86, 0x00, 0x06, 0x7c, 0xca, 0x21, 0xb7, 0x20, 0xf7, 0xdc,
0x73, 0x08, 0x5e, 0x7d, 0x74, 0x57, 0x75, 0x37, 0x77, 0x15, 0xf8, 0x34, 0x53, 0xbf, 0x7a, 0xf5, 0x73, 0x08, 0x5e, 0x7d, 0x74, 0x57, 0x75, 0x37, 0xb5, 0x0a, 0x72, 0x9a, 0xa9, 0x5f, 0xbd, 0x7a,
0xaa, 0xea, 0xd5, 0x7b, 0xaf, 0xde, 0x7b, 0xd5, 0xd0, 0x4e, 0x93, 0xd1, 0x4e, 0x92, 0xc6, 0x3c, 0x55, 0xf5, 0xea, 0x7d, 0xd5, 0xab, 0x86, 0x56, 0x12, 0x0f, 0x77, 0xe2, 0x24, 0xe2, 0x11, 0x99,
0x26, 0xf3, 0x61, 0x94, 0x26, 0xa3, 0xc1, 0xbd, 0x71, 0x1c, 0x8f, 0x43, 0xb6, 0xeb, 0x25, 0xc1, 0x0b, 0xc2, 0x24, 0x1e, 0xf6, 0xef, 0x8e, 0xa3, 0x68, 0x1c, 0xb0, 0x5d, 0x2f, 0xf6, 0x77, 0xbd,
0xae, 0x17, 0x45, 0x31, 0xf7, 0x78, 0x10, 0x47, 0x99, 0x24, 0xa2, 0xff, 0xe3, 0x40, 0xe7, 0x65, 0x30, 0x8c, 0xb8, 0xc7, 0xfd, 0x28, 0x4c, 0x25, 0x11, 0xfd, 0x6f, 0x07, 0xda, 0x2f, 0x13, 0x2f,
0xea, 0x45, 0x99, 0x37, 0x42, 0x98, 0xf4, 0x61, 0x91, 0xbf, 0x19, 0x5e, 0x78, 0xd9, 0x45, 0xdf, 0x4c, 0xbd, 0x21, 0xc2, 0xa4, 0x07, 0x0b, 0xfc, 0xcd, 0xe0, 0xc2, 0x4b, 0x2f, 0x7a, 0xce, 0x3d,
0xb9, 0xef, 0x6c, 0xb5, 0x5d, 0xdd, 0x24, 0x1b, 0xb0, 0xe0, 0x4d, 0xe2, 0x69, 0xc4, 0xfb, 0x8d, 0x67, 0xab, 0xe5, 0xea, 0x26, 0x59, 0x87, 0x79, 0x6f, 0x12, 0x4d, 0x43, 0xde, 0xab, 0xdd, 0x73,
0xfb, 0xce, 0xd6, 0x9c, 0xab, 0x5a, 0xe4, 0x23, 0x58, 0x8d, 0xa6, 0x93, 0xe1, 0x28, 0x8e, 0xce, 0xb6, 0xea, 0xae, 0x6a, 0x91, 0x4f, 0x60, 0x25, 0x9c, 0x4e, 0x06, 0xc3, 0x28, 0x3c, 0xf7, 0x93,
0x83, 0x74, 0x22, 0x99, 0xf7, 0xe7, 0xee, 0x3b, 0x5b, 0xf3, 0x6e, 0xb5, 0x83, 0xbc, 0x0f, 0x70, 0x89, 0x64, 0xde, 0xab, 0xdf, 0x73, 0xb6, 0xe6, 0xdc, 0x72, 0x07, 0xf9, 0x10, 0xe0, 0x2c, 0x88,
0x16, 0xc6, 0xa3, 0xd7, 0x72, 0x8a, 0xa6, 0x98, 0xc2, 0x40, 0x08, 0x85, 0xae, 0x6a, 0xb1, 0x60, 0x86, 0xaf, 0xe5, 0x14, 0x0d, 0x31, 0x85, 0x81, 0x10, 0x0a, 0x1d, 0xd5, 0x62, 0xfe, 0xf8, 0x82,
0x7c, 0xc1, 0xfb, 0xf3, 0x82, 0x91, 0x85, 0x21, 0x0f, 0x1e, 0x4c, 0xd8, 0x30, 0xe3, 0xde, 0x24, 0xf7, 0xe6, 0x04, 0x23, 0x0b, 0x43, 0x1e, 0xdc, 0x9f, 0xb0, 0x41, 0xca, 0xbd, 0x49, 0xdc, 0x9b,
0xe9, 0x2f, 0x88, 0xd5, 0x18, 0x88, 0xe8, 0x8f, 0xb9, 0x17, 0x0e, 0xcf, 0x19, 0xcb, 0xfa, 0x8b, 0x17, 0xab, 0x31, 0x10, 0xd1, 0x1f, 0x71, 0x2f, 0x18, 0x9c, 0x33, 0x96, 0xf6, 0x16, 0x54, 0x7f,
0xaa, 0x3f, 0x47, 0x68, 0x1f, 0x36, 0x9e, 0x31, 0x6e, 0xec, 0x3a, 0x73, 0xd9, 0xd7, 0x53, 0x96, 0x86, 0xd0, 0x1e, 0xac, 0x3f, 0x63, 0xdc, 0xd8, 0x75, 0xea, 0xb2, 0x6f, 0xa6, 0x2c, 0xe5, 0xf4,
0x71, 0x7a, 0x04, 0xc4, 0x80, 0x9f, 0x32, 0xee, 0x05, 0x61, 0x46, 0x3e, 0x81, 0x2e, 0x37, 0x88, 0x08, 0x88, 0x01, 0x3f, 0x65, 0xdc, 0xf3, 0x83, 0x94, 0x7c, 0x06, 0x1d, 0x6e, 0x10, 0xf7, 0x9c,
0xfb, 0xce, 0xfd, 0xb9, 0xad, 0xce, 0x1e, 0xd9, 0x11, 0xf2, 0xdd, 0x31, 0x06, 0xb8, 0x16, 0x1d, 0x7b, 0xf5, 0xad, 0xf6, 0x1e, 0xd9, 0x11, 0xf2, 0xdd, 0x31, 0x06, 0xb8, 0x16, 0x1d, 0xfd, 0xad,
0xfd, 0x8d, 0x03, 0x9d, 0x53, 0x16, 0xf9, 0x8a, 0x3b, 0x21, 0xd0, 0xf4, 0x59, 0xc6, 0x85, 0x60, 0x03, 0xed, 0x53, 0x16, 0x8e, 0x14, 0x77, 0x42, 0xa0, 0x31, 0x62, 0x29, 0x17, 0x82, 0xed, 0xb8,
0xbb, 0xae, 0xf8, 0x4f, 0xbe, 0x03, 0x1d, 0xfc, 0x1d, 0x66, 0x3c, 0x0d, 0xa2, 0xb1, 0x10, 0x6d, 0xe2, 0x3f, 0xf9, 0x0e, 0xb4, 0xf1, 0x77, 0x90, 0xf2, 0xc4, 0x0f, 0xc7, 0x42, 0xb4, 0x2d, 0x17,
0xdb, 0x05, 0x84, 0x4e, 0x05, 0x42, 0x56, 0x60, 0xce, 0x9b, 0x70, 0x21, 0xd0, 0x39, 0x17, 0xff, 0x10, 0x3a, 0x15, 0x08, 0x59, 0x86, 0xba, 0x37, 0xe1, 0x42, 0xa0, 0x75, 0x17, 0xff, 0x92, 0x8f,
0x92, 0x0f, 0xa0, 0x9b, 0x78, 0xb3, 0x09, 0x8b, 0x78, 0x21, 0xc4, 0xae, 0xdb, 0x51, 0xd8, 0x21, 0xa0, 0x13, 0x7b, 0xb3, 0x09, 0x0b, 0x79, 0x2e, 0xc4, 0x8e, 0xdb, 0x56, 0xd8, 0x21, 0x4a, 0x71,
0x4a, 0x71, 0x07, 0xd6, 0x4c, 0x12, 0xcd, 0x7d, 0x5e, 0x70, 0x5f, 0x35, 0x28, 0xd5, 0x24, 0x0f, 0x07, 0x56, 0x4d, 0x12, 0xcd, 0x7d, 0x4e, 0x70, 0x5f, 0x31, 0x28, 0xd5, 0x24, 0x0f, 0x60, 0x49,
0x61, 0x59, 0xd3, 0xa7, 0x72, 0xb1, 0x42, 0xac, 0x6d, 0x77, 0x49, 0xc1, 0x5a, 0x40, 0x11, 0x74, 0xd3, 0x27, 0x72, 0xb1, 0x42, 0xac, 0x2d, 0x77, 0x51, 0xc1, 0x5a, 0x40, 0x21, 0x74, 0xe4, 0x8e,
0xe5, 0x8e, 0xb2, 0x24, 0x8e, 0x32, 0x46, 0xb6, 0x61, 0x45, 0x0f, 0x4c, 0x52, 0x16, 0x4c, 0xbc, 0xd2, 0x38, 0x0a, 0x53, 0x46, 0xb6, 0x61, 0x59, 0x0f, 0x8c, 0x13, 0xe6, 0x4f, 0xbc, 0x31, 0x53,
0x31, 0x53, 0xdb, 0xab, 0xe0, 0x64, 0x0f, 0x7a, 0xf9, 0x24, 0xf1, 0x94, 0x33, 0xb1, 0xd9, 0xce, 0xdb, 0x2b, 0xe1, 0x64, 0x0f, 0xba, 0xd9, 0x24, 0xd1, 0x94, 0x33, 0xb1, 0xd9, 0xf6, 0x5e, 0x47,
0x5e, 0x57, 0xc9, 0xd1, 0x45, 0xcc, 0xb5, 0x49, 0xe8, 0x2f, 0x1c, 0xe8, 0x3e, 0xb9, 0xf0, 0xa2, 0xc9, 0xd1, 0x45, 0xcc, 0xb5, 0x49, 0xe8, 0x2f, 0x1c, 0xe8, 0x3c, 0xb9, 0xf0, 0xc2, 0x90, 0x05,
0x88, 0x85, 0x27, 0x71, 0x10, 0x71, 0xd4, 0x8f, 0xf3, 0x69, 0xe4, 0x07, 0xd1, 0x78, 0xc8, 0xdf, 0x27, 0x91, 0x1f, 0x72, 0xd4, 0x8f, 0xf3, 0x69, 0x38, 0xf2, 0xc3, 0xf1, 0x80, 0xbf, 0xf1, 0x47,
0x04, 0xbe, 0x9a, 0xcc, 0xc2, 0x70, 0x51, 0x66, 0x1b, 0x77, 0xaf, 0x04, 0x5b, 0xc1, 0x91, 0x5f, 0x6a, 0x32, 0x0b, 0xc3, 0x45, 0x99, 0x6d, 0xdc, 0xbd, 0x12, 0x6c, 0x09, 0x47, 0x7e, 0xd1, 0x94,
0x3c, 0xe5, 0xc9, 0x94, 0x0f, 0x83, 0xc8, 0x67, 0x6f, 0x84, 0x9c, 0x7b, 0xae, 0x85, 0xd1, 0x3f, 0xc7, 0x53, 0x3e, 0xf0, 0xc3, 0x11, 0x7b, 0x23, 0xe4, 0xdc, 0x75, 0x2d, 0x8c, 0xfe, 0x29, 0x2c,
0x85, 0x95, 0x23, 0x54, 0xbc, 0x28, 0x88, 0xc6, 0xfb, 0xbe, 0x9f, 0xb2, 0x2c, 0x43, 0x6b, 0x48, 0x1f, 0xa1, 0xe2, 0x85, 0x7e, 0x38, 0xde, 0x1f, 0x8d, 0x12, 0x96, 0xa6, 0x68, 0x0d, 0xf1, 0xf4,
0xa6, 0x67, 0xaf, 0xd9, 0x4c, 0x99, 0x89, 0x6a, 0xe1, 0x19, 0x5f, 0xc4, 0x19, 0x57, 0xf3, 0x89, 0xec, 0x35, 0x9b, 0x29, 0x33, 0x51, 0x2d, 0x3c, 0xe3, 0x8b, 0x28, 0xe5, 0x6a, 0x3e, 0xf1, 0x9f,
0xff, 0xf4, 0x9f, 0x1c, 0x58, 0x46, 0xa9, 0xfd, 0xd0, 0x8b, 0x66, 0x5a, 0x17, 0x8e, 0xa0, 0x8b, 0xfe, 0xa3, 0x03, 0x4b, 0x28, 0xb5, 0x1f, 0x7a, 0xe1, 0x4c, 0xeb, 0xc2, 0x11, 0x74, 0x90, 0xd5,
0xac, 0x5e, 0xc6, 0xfb, 0xd2, 0xa6, 0xa4, 0x4e, 0x6d, 0x29, 0x59, 0x94, 0xa8, 0x77, 0x4c, 0xd2, 0xcb, 0x68, 0x5f, 0xda, 0x94, 0xd4, 0xa9, 0x2d, 0x25, 0x8b, 0x02, 0xf5, 0x8e, 0x49, 0x7a, 0x10,
0x83, 0x88, 0xa7, 0x33, 0xd7, 0x1a, 0x3d, 0xf8, 0x1c, 0x56, 0x2b, 0x24, 0xa8, 0x39, 0xc5, 0xfa, 0xf2, 0x64, 0xe6, 0x76, 0x3c, 0x03, 0xea, 0x7f, 0x01, 0x2b, 0x25, 0x12, 0xd4, 0x9c, 0x7c, 0x7d,
0xf0, 0x2f, 0x59, 0x87, 0xf9, 0x4b, 0x2f, 0x9c, 0x32, 0x65, 0xc1, 0xb2, 0xf1, 0x69, 0xe3, 0xb1, 0xf8, 0x97, 0xac, 0xc1, 0xdc, 0xa5, 0x17, 0x4c, 0x99, 0xb2, 0x60, 0xd9, 0xf8, 0xbc, 0xf6, 0xc8,
0x43, 0x3f, 0x84, 0x95, 0x62, 0x4e, 0x75, 0xb6, 0x04, 0x9a, 0xb9, 0x88, 0xdb, 0xae, 0xf8, 0x8f, 0xa1, 0x1f, 0xc3, 0x72, 0x3e, 0xa7, 0x3a, 0x5b, 0x02, 0x8d, 0x4c, 0xc4, 0x2d, 0x57, 0xfc, 0x47,
0xa2, 0x40, 0xba, 0x27, 0x71, 0x90, 0x1b, 0x0d, 0xd2, 0x79, 0xbe, 0x9f, 0x6a, 0x3a, 0xfc, 0x7f, 0x51, 0x20, 0xdd, 0x93, 0xc8, 0xcf, 0x8c, 0x06, 0xe9, 0x70, 0x31, 0x9a, 0x0e, 0xff, 0xdf, 0xe4,
0x93, 0xb3, 0xa0, 0x0f, 0x61, 0xd5, 0x18, 0xff, 0x0d, 0x13, 0xfd, 0xda, 0x81, 0xd5, 0x63, 0x76, 0x2c, 0xe8, 0x03, 0x58, 0x31, 0xc6, 0xbf, 0x63, 0xa2, 0xdf, 0x38, 0xb0, 0x72, 0xcc, 0xae, 0x94,
0xa5, 0xc4, 0xad, 0xa7, 0x7a, 0x0c, 0x4d, 0x3e, 0x4b, 0xa4, 0x8a, 0x2d, 0xed, 0x3d, 0x50, 0xd2, 0xb8, 0xf5, 0x54, 0x8f, 0xa0, 0xc1, 0x67, 0xb1, 0x54, 0xb1, 0xc5, 0xbd, 0xfb, 0x4a, 0x5a, 0x25,
0xaa, 0xd0, 0xed, 0xa8, 0xe6, 0xcb, 0x59, 0xc2, 0x5c, 0x31, 0x82, 0xbe, 0x80, 0x8e, 0x01, 0x92, 0xba, 0x1d, 0xd5, 0x7c, 0x39, 0x8b, 0x99, 0x2b, 0x46, 0xd0, 0x17, 0xd0, 0x36, 0x40, 0xb2, 0x01,
0x4d, 0x58, 0x7b, 0xf5, 0xfc, 0xe5, 0xf1, 0xc1, 0xe9, 0xe9, 0xf0, 0xe4, 0xcb, 0x2f, 0x7e, 0x70, 0xab, 0xaf, 0x9e, 0xbf, 0x3c, 0x3e, 0x38, 0x3d, 0x1d, 0x9c, 0x7c, 0xf5, 0xe5, 0x0f, 0x0e, 0xfe,
0xf0, 0x67, 0xc3, 0xc3, 0xfd, 0xd3, 0xc3, 0x95, 0x5b, 0x64, 0x03, 0xc8, 0xf1, 0xc1, 0xe9, 0xcb, 0x6c, 0x70, 0xb8, 0x7f, 0x7a, 0xb8, 0x7c, 0x8b, 0xac, 0x03, 0x39, 0x3e, 0x38, 0x7d, 0x79, 0xf0,
0x83, 0xa7, 0x16, 0xee, 0x90, 0x65, 0xe8, 0x98, 0x40, 0x83, 0x0e, 0xa0, 0x7f, 0xcc, 0xae, 0x5e, 0xd4, 0xc2, 0x1d, 0xb2, 0x04, 0x6d, 0x13, 0xa8, 0xd1, 0x3e, 0xf4, 0x8e, 0xd9, 0xd5, 0x2b, 0x9f,
0x05, 0x3c, 0x62, 0x59, 0x66, 0x4f, 0x4f, 0x77, 0x80, 0x98, 0x6b, 0x52, 0xdb, 0xec, 0xc3, 0xa2, 0x87, 0x2c, 0x4d, 0xed, 0xe9, 0xe9, 0x0e, 0x10, 0x73, 0x4d, 0x6a, 0x9b, 0x3d, 0x58, 0xf0, 0x24,
0x27, 0x21, 0xed, 0x5a, 0x55, 0x93, 0x7e, 0x09, 0xe4, 0x49, 0x1c, 0x45, 0x6c, 0xc4, 0x4f, 0x18, 0xa4, 0x5d, 0xab, 0x6a, 0xd2, 0xaf, 0x80, 0x3c, 0x89, 0xc2, 0x90, 0x0d, 0xf9, 0x09, 0x63, 0x89,
0x4b, 0xf5, 0x66, 0x7f, 0xdf, 0x90, 0x6b, 0x67, 0x6f, 0x53, 0x6d, 0xb6, 0xac, 0x89, 0x4a, 0xe0, 0xde, 0xec, 0xef, 0x1b, 0x72, 0x6d, 0xef, 0x6d, 0xa8, 0xcd, 0x16, 0x35, 0x51, 0x09, 0x9c, 0x40,
0x04, 0x9a, 0x09, 0x4b, 0x27, 0x42, 0xdc, 0x2d, 0x57, 0xfc, 0xa7, 0xbb, 0xb0, 0x66, 0xb1, 0x2d, 0x23, 0x66, 0xc9, 0x44, 0x88, 0xbb, 0xe9, 0x8a, 0xff, 0x74, 0x17, 0x56, 0x2d, 0xb6, 0xf9, 0x3a,
0xd6, 0x91, 0x30, 0x96, 0x0e, 0x95, 0xc4, 0xe7, 0x5d, 0xdd, 0xa4, 0xff, 0xea, 0x40, 0xf3, 0xf0, 0x62, 0xc6, 0x92, 0x81, 0x92, 0xf8, 0x9c, 0xab, 0x9b, 0xf4, 0x5f, 0x1c, 0x68, 0x1c, 0xbe, 0x3c,
0xe5, 0xd1, 0x13, 0x32, 0x80, 0x56, 0x10, 0x8d, 0xe2, 0x09, 0x3a, 0x0d, 0x47, 0x70, 0xcc, 0xdb, 0x7a, 0x42, 0xfa, 0xd0, 0xf4, 0xc3, 0x61, 0x34, 0x41, 0xa7, 0xe1, 0x08, 0x8e, 0x59, 0xfb, 0xc6,
0x37, 0xde, 0x03, 0xf7, 0xa0, 0x2d, 0x7c, 0x0d, 0x7a, 0x6a, 0x61, 0x46, 0x5d, 0xb7, 0x00, 0xf0, 0x38, 0x70, 0x17, 0x5a, 0xc2, 0xd7, 0xa0, 0xa7, 0x16, 0x66, 0xd4, 0x71, 0x73, 0x00, 0xa3, 0x04,
0x96, 0x60, 0x6f, 0x92, 0x20, 0x15, 0xd7, 0x80, 0x76, 0xee, 0x4d, 0x61, 0x6c, 0xd5, 0x0e, 0xb4, 0x7b, 0x13, 0xfb, 0x89, 0x08, 0x03, 0xda, 0xb9, 0x37, 0x84, 0xb1, 0x95, 0x3b, 0xd0, 0x82, 0x13,
0xe0, 0x94, 0x5d, 0xc6, 0x23, 0x09, 0xfa, 0x2c, 0xf4, 0x66, 0xc2, 0x79, 0xf5, 0xdc, 0x0a, 0x4e, 0x76, 0x19, 0x0d, 0x25, 0x38, 0x62, 0x81, 0x37, 0x13, 0xce, 0xab, 0xeb, 0x96, 0x70, 0xfa, 0x5f,
0xff, 0x7b, 0x0e, 0x7a, 0xfb, 0x23, 0x1e, 0x5c, 0x32, 0xe5, 0x28, 0xc4, 0x0a, 0x05, 0xa0, 0xd6, 0x75, 0xe8, 0xee, 0x0f, 0xb9, 0x7f, 0xc9, 0x94, 0xa3, 0x10, 0x2b, 0x14, 0x80, 0x5a, 0xbb, 0x6a,
0xae, 0x5a, 0xe4, 0x01, 0xf4, 0x52, 0x36, 0x89, 0x39, 0x1b, 0x2a, 0xd3, 0x95, 0x46, 0x6a, 0x83, 0x91, 0xfb, 0xd0, 0x4d, 0xd8, 0x24, 0xe2, 0x6c, 0xa0, 0x4c, 0x57, 0x1a, 0xa9, 0x0d, 0x22, 0xd5,
0x48, 0x35, 0x92, 0x8c, 0x86, 0x09, 0xba, 0x1c, 0xb1, 0x97, 0xb6, 0x6b, 0x83, 0x28, 0x44, 0x04, 0x50, 0x32, 0x1a, 0xc4, 0xe8, 0x72, 0xc4, 0x5e, 0x5a, 0xae, 0x0d, 0xa2, 0x10, 0x11, 0x40, 0x21,
0x50, 0x88, 0xb8, 0x8b, 0xa6, 0xab, 0x9b, 0x28, 0xbb, 0x91, 0x97, 0x78, 0xa3, 0x80, 0xcb, 0x35, 0xe2, 0x2e, 0x1a, 0xae, 0x6e, 0xa2, 0xec, 0x86, 0x5e, 0xec, 0x0d, 0x7d, 0x2e, 0xd7, 0x5c, 0x77,
0xcf, 0xb9, 0x79, 0x1b, 0x79, 0x87, 0xf1, 0xc8, 0x0b, 0x87, 0x67, 0x5e, 0xe8, 0x45, 0x23, 0xa6, 0xb3, 0x36, 0xf2, 0x0e, 0xa2, 0xa1, 0x17, 0x0c, 0xce, 0xbc, 0xc0, 0x0b, 0x87, 0x4c, 0x05, 0x2f,
0x2e, 0x2f, 0x1b, 0x24, 0x1f, 0xc2, 0x92, 0x5a, 0x92, 0x26, 0x93, 0x77, 0x58, 0x09, 0x45, 0x99, 0x1b, 0x24, 0x1f, 0xc3, 0xa2, 0x5a, 0x92, 0x26, 0x93, 0x31, 0xac, 0x80, 0xa2, 0x4c, 0xa7, 0x61,
0x4e, 0xa3, 0x8c, 0x71, 0x1e, 0x32, 0x3f, 0x27, 0x6d, 0x09, 0xd2, 0x6a, 0x07, 0x79, 0x04, 0x6b, 0xca, 0x38, 0x0f, 0xd8, 0x28, 0x23, 0x6d, 0x0a, 0xd2, 0x72, 0x07, 0x79, 0x08, 0xab, 0x32, 0x06,
0xf2, 0x0e, 0xcc, 0x3c, 0x1e, 0x67, 0x17, 0x41, 0x36, 0xcc, 0x58, 0xc4, 0xfb, 0x6d, 0x41, 0x5f, 0xa6, 0x1e, 0x8f, 0xd2, 0x0b, 0x3f, 0x1d, 0xa4, 0x2c, 0xe4, 0xbd, 0x96, 0xa0, 0xaf, 0xea, 0x22,
0xd7, 0x45, 0x1e, 0xc3, 0x66, 0x09, 0x4e, 0xd9, 0x88, 0x05, 0x97, 0xcc, 0xef, 0x83, 0x18, 0x75, 0x8f, 0x60, 0xa3, 0x00, 0x27, 0x6c, 0xc8, 0xfc, 0x4b, 0x36, 0xea, 0x81, 0x18, 0x75, 0x53, 0x37,
0x53, 0x37, 0xb9, 0x0f, 0x1d, 0xbc, 0xfa, 0xa7, 0x89, 0xef, 0x71, 0x96, 0xf5, 0x3b, 0x42, 0x42, 0xb9, 0x07, 0x6d, 0x0c, 0xfd, 0xd3, 0x78, 0xe4, 0x71, 0x96, 0xf6, 0xda, 0x42, 0x42, 0x26, 0x44,
0x26, 0x44, 0x3e, 0x86, 0x5e, 0xc2, 0xa4, 0x2f, 0xbe, 0xe0, 0xe1, 0x28, 0xeb, 0x77, 0x85, 0x03, 0x3e, 0x85, 0x6e, 0xcc, 0xa4, 0x2f, 0xbe, 0xe0, 0xc1, 0x30, 0xed, 0x75, 0x84, 0x03, 0x6c, 0x2b,
0xec, 0x28, 0x2d, 0x47, 0x2d, 0x74, 0x6d, 0x0a, 0x7a, 0x1b, 0xd6, 0x8e, 0x82, 0x8c, 0xab, 0x53, 0x2d, 0x47, 0x2d, 0x74, 0x6d, 0x0a, 0x7a, 0x1b, 0x56, 0x8f, 0xfc, 0x94, 0xab, 0x53, 0xce, 0x8c,
0xce, 0x8d, 0xed, 0x10, 0xd6, 0x6d, 0x58, 0xa9, 0xf9, 0x23, 0x68, 0xa9, 0x23, 0xc3, 0x05, 0x20, 0xed, 0x10, 0xd6, 0x6c, 0x58, 0xa9, 0xf9, 0x43, 0x68, 0xaa, 0x23, 0xc3, 0x05, 0x20, 0xf3, 0x35,
0xf3, 0x75, 0xc5, 0xdc, 0xd2, 0x16, 0x37, 0xa7, 0xa2, 0xbf, 0x6c, 0x40, 0x13, 0x2d, 0x45, 0x58, 0xc5, 0xdc, 0xd2, 0x16, 0x37, 0xa3, 0xa2, 0xbf, 0xac, 0x41, 0x03, 0x2d, 0x45, 0x58, 0xc8, 0xf4,
0xc8, 0xf4, 0x6c, 0x58, 0x78, 0x4f, 0xdd, 0x34, 0x6d, 0xa7, 0x61, 0xd9, 0x8e, 0x69, 0xdd, 0x73, 0x6c, 0x90, 0x7b, 0x4f, 0xdd, 0x34, 0x6d, 0xa7, 0x66, 0xd9, 0x8e, 0x69, 0xdd, 0x75, 0xcb, 0xba,
0x96, 0x75, 0x8b, 0x90, 0x67, 0xc6, 0x99, 0x92, 0xb7, 0xd4, 0x16, 0x03, 0x29, 0xfa, 0x53, 0x36, 0x45, 0xca, 0x33, 0xe3, 0x4c, 0xc9, 0x5b, 0x6a, 0x8b, 0x81, 0xe4, 0xfd, 0x09, 0x1b, 0x5e, 0x0a,
0xba, 0x14, 0x2a, 0x93, 0xf7, 0x23, 0x82, 0x0a, 0x95, 0x79, 0x5c, 0x8e, 0x96, 0xfa, 0x92, 0xb7, 0x95, 0xc9, 0xfa, 0x11, 0x41, 0x85, 0x4a, 0x3d, 0x2e, 0x47, 0x4b, 0x7d, 0xc9, 0xda, 0xba, 0x4f,
0x75, 0x9f, 0x18, 0xb9, 0x58, 0xf4, 0x89, 0x71, 0x7d, 0x58, 0x0c, 0xa2, 0xb3, 0x78, 0x1a, 0xf9, 0x8c, 0x5c, 0xc8, 0xfb, 0xc4, 0xb8, 0x1e, 0x2c, 0xf8, 0xe1, 0x59, 0x34, 0x0d, 0x47, 0x42, 0x29,
0x42, 0x29, 0x5a, 0xae, 0x6e, 0xa2, 0xa9, 0x26, 0xe2, 0x16, 0x0c, 0x26, 0x4c, 0x29, 0x40, 0x01, 0x9a, 0xae, 0x6e, 0xa2, 0xa9, 0xc6, 0x22, 0x0a, 0xfa, 0x13, 0xa6, 0x14, 0x20, 0x07, 0x28, 0xc1,
0x50, 0x82, 0xd7, 0x5d, 0x26, 0x7c, 0x46, 0x2e, 0xe4, 0x4f, 0x60, 0xd5, 0xc0, 0x94, 0x84, 0x3f, 0x70, 0x97, 0x0a, 0x9f, 0x91, 0x09, 0xf9, 0x33, 0x58, 0x31, 0x30, 0x25, 0xe1, 0x8f, 0x60, 0x0e,
0x80, 0x79, 0xdc, 0xbd, 0x0e, 0x88, 0xf4, 0xd9, 0x09, 0x67, 0x23, 0x7b, 0xe8, 0x0a, 0x2c, 0x3d, 0x77, 0xaf, 0x13, 0x22, 0x7d, 0x76, 0xc2, 0xd9, 0xc8, 0x1e, 0xba, 0x0c, 0x8b, 0xcf, 0x18, 0x7f,
0x63, 0xfc, 0x79, 0x74, 0x1e, 0x6b, 0x4e, 0xff, 0xd9, 0x80, 0xe5, 0x1c, 0x52, 0x8c, 0xb6, 0x60, 0x1e, 0x9e, 0x47, 0x9a, 0xd3, 0x7f, 0xd4, 0x60, 0x29, 0x83, 0x14, 0xa3, 0x2d, 0x58, 0xf2, 0x47,
0x39, 0xf0, 0x59, 0xc4, 0x03, 0x3e, 0x1b, 0x5a, 0xb7, 0x6a, 0x19, 0xc6, 0x1b, 0xcc, 0x0b, 0x03, 0x2c, 0xe4, 0x3e, 0x9f, 0x0d, 0xac, 0xa8, 0x5a, 0x84, 0x31, 0x82, 0x79, 0x81, 0xef, 0xa5, 0xca,
0x2f, 0x53, 0xa6, 0x2b, 0x1b, 0x64, 0x0f, 0xd6, 0x51, 0xb7, 0xb4, 0xba, 0xe4, 0xc7, 0x2e, 0x2f, 0x74, 0x65, 0x83, 0xec, 0xc1, 0x1a, 0xea, 0x96, 0x56, 0x97, 0xec, 0xd8, 0x65, 0x30, 0xaf, 0xec,
0xf3, 0xda, 0x3e, 0x34, 0x07, 0xc4, 0xa5, 0x6b, 0x28, 0x86, 0x48, 0x97, 0x54, 0xd7, 0x85, 0x52, 0x43, 0x73, 0x40, 0x5c, 0xba, 0x86, 0x7c, 0x88, 0x74, 0x49, 0x55, 0x5d, 0x28, 0x35, 0xc9, 0x09,
0x93, 0x9c, 0x70, 0xcb, 0xd2, 0x1b, 0x15, 0x40, 0x25, 0x70, 0x5d, 0x90, 0x81, 0x44, 0x39, 0x70, 0xb7, 0x2c, 0xbd, 0x51, 0x0e, 0x94, 0x12, 0xd7, 0x79, 0x99, 0x48, 0x14, 0x13, 0x57, 0x23, 0xf9,
0x35, 0x82, 0xdf, 0x56, 0x25, 0xf8, 0xdd, 0x82, 0xe5, 0x6c, 0x16, 0x8d, 0x98, 0x3f, 0xe4, 0x31, 0x6d, 0x96, 0x92, 0xdf, 0x2d, 0x58, 0x4a, 0x67, 0xe1, 0x90, 0x8d, 0x06, 0x3c, 0xc2, 0x79, 0xfd,
0xce, 0x1b, 0x44, 0xe2, 0x74, 0x5a, 0x6e, 0x19, 0x16, 0x61, 0x3a, 0xcb, 0x78, 0xc4, 0xb8, 0x30, 0x50, 0x9c, 0x4e, 0xd3, 0x2d, 0xc2, 0x22, 0x4d, 0x67, 0x29, 0x0f, 0x19, 0x17, 0xa6, 0xd8, 0x74,
0xc5, 0x96, 0xab, 0x9b, 0xf4, 0xe7, 0xe2, 0x2e, 0xc9, 0x23, 0xee, 0x2f, 0x85, 0xbd, 0x91, 0xbb, 0x75, 0x93, 0xfe, 0x5c, 0xc4, 0x92, 0x2c, 0xe3, 0xfe, 0x4a, 0xd8, 0x1b, 0xd9, 0x84, 0x96, 0x9c,
0xd0, 0x96, 0xf3, 0x64, 0x17, 0x9e, 0x8a, 0x99, 0x5a, 0x02, 0x38, 0xbd, 0xf0, 0x30, 0xa0, 0xb4, 0x27, 0xbd, 0xf0, 0x54, 0xce, 0xd4, 0x14, 0xc0, 0xe9, 0x85, 0x87, 0x09, 0xa5, 0xb5, 0x74, 0xa9,
0x96, 0x2e, 0x35, 0xbb, 0x23, 0xb0, 0x43, 0xb9, 0xf2, 0x07, 0xb0, 0xa4, 0x63, 0xf9, 0x6c, 0x18, 0xd9, 0x6d, 0x81, 0x1d, 0xca, 0x95, 0xdf, 0x87, 0x45, 0x9d, 0xcb, 0xa7, 0x83, 0x80, 0x9d, 0x73,
0xb2, 0x73, 0xae, 0x03, 0xa5, 0x68, 0x3a, 0xc1, 0xe9, 0xb2, 0x23, 0x76, 0xce, 0xe9, 0x31, 0xac, 0x9d, 0x28, 0x85, 0xd3, 0x09, 0x4e, 0x97, 0x1e, 0xb1, 0x73, 0x4e, 0x8f, 0x61, 0x45, 0x59, 0xd5,
0x2a, 0xab, 0x7a, 0x91, 0x30, 0x3d, 0xf5, 0xf7, 0xca, 0xfe, 0x54, 0xde, 0x67, 0x6b, 0x4a, 0x5b, 0x8b, 0x98, 0xe9, 0xa9, 0xbf, 0x57, 0xf4, 0xa7, 0x32, 0x9e, 0xad, 0x2a, 0x6d, 0x31, 0xb3, 0xbb,
0xcc, 0xe8, 0xae, 0xe4, 0x64, 0xa9, 0x0b, 0x44, 0x75, 0x3f, 0x09, 0xe3, 0x8c, 0x29, 0x86, 0x14, 0x82, 0x93, 0xa5, 0x2e, 0x10, 0xd5, 0xfd, 0x24, 0x88, 0x52, 0xa6, 0x18, 0x52, 0xe8, 0x0c, 0x83,
0xba, 0xa3, 0x30, 0xce, 0xca, 0x21, 0xa0, 0x89, 0xa1, 0x7c, 0xb2, 0xe9, 0x68, 0x84, 0xd6, 0x28, 0x28, 0x2d, 0xa6, 0x80, 0x26, 0x86, 0xf2, 0x49, 0xa7, 0xc3, 0x21, 0x5a, 0xa3, 0x8c, 0x88, 0xba,
0x6f, 0x44, 0xdd, 0xa4, 0xbf, 0x74, 0x60, 0x4d, 0x70, 0xd3, 0xf6, 0x9f, 0x87, 0x16, 0xef, 0xbe, 0x49, 0x7f, 0xe9, 0xc0, 0xaa, 0xe0, 0xa6, 0xed, 0x3f, 0x4b, 0x2d, 0xde, 0x7f, 0x99, 0x9d, 0xa1,
0xcc, 0xee, 0xc8, 0x0c, 0x49, 0xdf, 0x53, 0xe9, 0x48, 0x18, 0x4c, 0x02, 0x7d, 0x29, 0xb6, 0x11, 0x99, 0x92, 0x7e, 0xa0, 0xae, 0x23, 0x81, 0x3f, 0xf1, 0x75, 0x50, 0x6c, 0x21, 0x72, 0x84, 0x00,
0x39, 0x42, 0x00, 0x55, 0xf6, 0x3c, 0x4e, 0x47, 0x4c, 0x48, 0xac, 0xe5, 0xca, 0x06, 0xfd, 0x0f, 0xaa, 0xec, 0x79, 0x94, 0x0c, 0x99, 0x90, 0x58, 0xd3, 0x95, 0x0d, 0xfa, 0xef, 0x0e, 0xac, 0x88,
0x07, 0x56, 0xc5, 0x32, 0x4e, 0xb9, 0xc7, 0xa7, 0x99, 0xda, 0xda, 0x1f, 0x43, 0x0f, 0xb7, 0xc1, 0x65, 0x9c, 0x72, 0x8f, 0x4f, 0x53, 0xb5, 0xb5, 0x3f, 0x86, 0x2e, 0x6e, 0x83, 0x69, 0x75, 0x55,
0xb4, 0xba, 0xaa, 0x45, 0xac, 0xe7, 0x96, 0x25, 0x50, 0x49, 0x7c, 0x78, 0xcb, 0xb5, 0x89, 0xc9, 0x8b, 0x58, 0xcb, 0x2c, 0x4b, 0xa0, 0x92, 0xf8, 0xf0, 0x96, 0x6b, 0x13, 0x93, 0x2f, 0xa0, 0x63,
0xe7, 0xd0, 0x35, 0x93, 0x2d, 0x15, 0x5f, 0xdf, 0xd1, 0x3b, 0xa8, 0x68, 0xc5, 0xe1, 0x2d, 0xd7, 0x5e, 0xb6, 0x54, 0x7e, 0x7d, 0x47, 0xef, 0xa0, 0xa4, 0x15, 0x87, 0xb7, 0x5c, 0x6b, 0x00, 0x79,
0x1a, 0x40, 0x3e, 0x03, 0x10, 0xb7, 0x98, 0x60, 0x2b, 0xd6, 0x6b, 0x0c, 0xaf, 0x1c, 0xc4, 0xe1, 0x0c, 0x20, 0xa2, 0x98, 0x60, 0x2b, 0xd6, 0x6b, 0x0c, 0x2f, 0x1d, 0xc4, 0xe1, 0x2d, 0xd7, 0x20,
0x2d, 0xd7, 0x20, 0xff, 0xa2, 0x05, 0x0b, 0xd2, 0xb9, 0xd3, 0x67, 0xd0, 0xb3, 0x56, 0x6a, 0x05, 0xff, 0xb2, 0x09, 0xf3, 0xd2, 0xb9, 0xd3, 0x67, 0xd0, 0xb5, 0x56, 0x6a, 0x25, 0x78, 0x1d, 0x99,
0x78, 0x5d, 0x19, 0xe0, 0x55, 0x02, 0xef, 0x46, 0x4d, 0xe0, 0xfd, 0xbf, 0x0e, 0x10, 0xd4, 0xa4, 0xe0, 0x95, 0x12, 0xef, 0x5a, 0x45, 0xe2, 0xfd, 0x3f, 0x0e, 0x10, 0xd4, 0xa4, 0xc2, 0x51, 0x7d,
0xd2, 0x51, 0x7d, 0x08, 0x4b, 0xdc, 0x4b, 0xc7, 0x8c, 0x0f, 0xed, 0x38, 0xa6, 0x84, 0x8a, 0x5b, 0x0c, 0x8b, 0xdc, 0x4b, 0xc6, 0x8c, 0x0f, 0xec, 0x3c, 0xa6, 0x80, 0x8a, 0x28, 0x14, 0x8d, 0xac,
0x28, 0xf6, 0xad, 0xdb, 0xbe, 0xeb, 0x9a, 0x10, 0xd9, 0x01, 0x62, 0x34, 0x75, 0x9a, 0x24, 0xfd, 0x68, 0xdf, 0x71, 0x4d, 0x88, 0xec, 0x00, 0x31, 0x9a, 0xfa, 0x9a, 0x24, 0xfd, 0x77, 0x45, 0x0f,
0x77, 0x4d, 0x0f, 0x3a, 0x1a, 0x79, 0x55, 0xeb, 0x3c, 0x42, 0x45, 0x42, 0x4d, 0x71, 0xe8, 0xb5, 0x3a, 0x1a, 0x19, 0xaa, 0xf5, 0x3d, 0x42, 0x65, 0x42, 0x0d, 0x71, 0xe8, 0x95, 0x7d, 0xe8, 0xa2,
0x7d, 0xe8, 0xa2, 0x93, 0x29, 0xe6, 0x60, 0x1e, 0xd7, 0xf1, 0x80, 0x6e, 0x6b, 0x97, 0x22, 0xcc, 0xe3, 0x29, 0xde, 0xc1, 0x3c, 0xae, 0xf3, 0x01, 0xdd, 0xd6, 0x2e, 0x45, 0x98, 0x95, 0xf2, 0x18,
0x4a, 0x79, 0x8c, 0x02, 0xa0, 0xbf, 0x75, 0x60, 0x05, 0xb7, 0x6f, 0xa9, 0xc8, 0xa7, 0x20, 0xb4, 0x39, 0x40, 0x7f, 0xe7, 0xc0, 0x32, 0x6e, 0xdf, 0x52, 0x91, 0xcf, 0x41, 0x68, 0xdf, 0x7b, 0x6a,
0xef, 0x1d, 0x35, 0xc4, 0xa2, 0xfd, 0xdd, 0x15, 0xe4, 0x31, 0xb4, 0x05, 0xc3, 0x38, 0x61, 0x91, 0x88, 0x45, 0xfb, 0xff, 0x57, 0x90, 0x47, 0xd0, 0x12, 0x0c, 0xa3, 0x98, 0x85, 0x4a, 0x3f, 0x7a,
0xd2, 0x8f, 0xbe, 0xad, 0x1f, 0x85, 0xe1, 0x1f, 0xde, 0x72, 0x0b, 0x62, 0x43, 0x3b, 0x0e, 0xe0, 0xb6, 0x7e, 0xe4, 0x86, 0x7f, 0x78, 0xcb, 0xcd, 0x89, 0x0d, 0xed, 0x38, 0x80, 0xdb, 0x6a, 0x95,
0xb6, 0x5a, 0x65, 0xe9, 0x58, 0x3f, 0x82, 0x85, 0x4c, 0xec, 0x54, 0x85, 0xf7, 0xeb, 0x36, 0x67, 0x85, 0x63, 0xfd, 0x04, 0xe6, 0x53, 0xb1, 0x53, 0x95, 0xde, 0xaf, 0xd9, 0x9c, 0xa5, 0x14, 0x5c,
0x29, 0x05, 0x57, 0xd1, 0xd0, 0xbf, 0x99, 0x83, 0x8d, 0x32, 0x1f, 0x75, 0x9d, 0xfc, 0x18, 0x56, 0x45, 0x43, 0xff, 0xa6, 0x0e, 0xeb, 0x45, 0x3e, 0x2a, 0x9c, 0xfc, 0x18, 0x96, 0x4b, 0xa1, 0x40,
0x2a, 0x57, 0x81, 0xbc, 0xa2, 0x3e, 0xb2, 0xc5, 0x54, 0x1a, 0x58, 0x86, 0x2b, 0x5c, 0x06, 0xff, 0x86, 0xa8, 0x4f, 0x6c, 0x31, 0x15, 0x06, 0x16, 0xe1, 0x12, 0x97, 0xfe, 0x3f, 0xd4, 0x60, 0xd1,
0xd8, 0x80, 0x25, 0x9b, 0x08, 0xf5, 0x38, 0xbf, 0xa4, 0x8a, 0x8b, 0xcb, 0xc2, 0xaa, 0x21, 0x65, 0x26, 0x42, 0x3d, 0xce, 0x82, 0x54, 0x1e, 0xb8, 0x2c, 0xac, 0x9c, 0x52, 0xd6, 0xaa, 0x52, 0x4a,
0xa3, 0x2e, 0xa4, 0x34, 0x03, 0xc7, 0xb9, 0x6f, 0x0b, 0x1c, 0x9b, 0xef, 0x16, 0x38, 0xce, 0xd7, 0x33, 0x71, 0xac, 0x7f, 0x5b, 0xe2, 0xd8, 0x78, 0xbf, 0xc4, 0x71, 0xae, 0x32, 0x71, 0x2c, 0x7a,
0x06, 0x8e, 0x65, 0x0f, 0x2a, 0x73, 0x7d, 0xdb, 0x83, 0x16, 0xa7, 0xb1, 0xf8, 0x0e, 0xa7, 0xf1, 0x50, 0x79, 0xd7, 0xb7, 0x3d, 0x68, 0x7e, 0x1a, 0x0b, 0xef, 0x71, 0x1a, 0xdf, 0x83, 0xb5, 0x57,
0x3d, 0x58, 0x7f, 0xe5, 0x85, 0x21, 0xe3, 0x5f, 0xc8, 0x29, 0xf4, 0x99, 0x7e, 0x00, 0xdd, 0x2b, 0x5e, 0x10, 0x30, 0xfe, 0xa5, 0x9c, 0x42, 0x9f, 0xe9, 0x47, 0xd0, 0xb9, 0x92, 0x57, 0xa4, 0x41,
0x99, 0x22, 0x0d, 0xe3, 0x28, 0x9c, 0xa9, 0x80, 0xbc, 0xa3, 0xb0, 0x17, 0x51, 0x38, 0xa3, 0x1f, 0x14, 0x06, 0x33, 0x95, 0x90, 0xb7, 0x15, 0xf6, 0x22, 0x0c, 0x66, 0xf4, 0x53, 0xb8, 0x5d, 0x18,
0xc3, 0xed, 0xd2, 0xd0, 0x22, 0x4f, 0xd1, 0xdb, 0xc0, 0x61, 0x8e, 0xab, 0x9b, 0x74, 0x13, 0x6e, 0x9a, 0xdf, 0x53, 0xf4, 0x36, 0x70, 0x98, 0xe3, 0xea, 0x26, 0xdd, 0x80, 0xdb, 0x6a, 0x19, 0xf6,
0xab, 0x65, 0xd8, 0xd3, 0xd1, 0x3d, 0xd8, 0x28, 0x77, 0xd4, 0x33, 0x9b, 0x2b, 0x98, 0x7d, 0x0e, 0x74, 0x74, 0x0f, 0xd6, 0x8b, 0x1d, 0xd5, 0xcc, 0xea, 0x39, 0xb3, 0x2f, 0x80, 0xfc, 0x68, 0xca,
0xe4, 0x47, 0x53, 0x96, 0xce, 0x44, 0xfd, 0x21, 0xcf, 0x34, 0x37, 0xcb, 0x21, 0x20, 0x26, 0xf8, 0x92, 0x99, 0xa8, 0x3f, 0x64, 0x37, 0xcd, 0x8d, 0x62, 0x0a, 0x88, 0x17, 0xfc, 0x1f, 0xb0, 0x99,
0x3f, 0x60, 0x33, 0x5d, 0x8f, 0x69, 0xe4, 0xf5, 0x18, 0xfa, 0x19, 0xac, 0x59, 0x0c, 0xd4, 0x8c, 0xae, 0xc7, 0xd4, 0xb2, 0x7a, 0x0c, 0x7d, 0x0c, 0xab, 0x16, 0x03, 0x35, 0xe3, 0x7d, 0x98, 0x17,
0x0f, 0x60, 0x41, 0xd4, 0x30, 0xb4, 0xee, 0xd9, 0x75, 0x0e, 0xd5, 0x47, 0xff, 0x12, 0xe6, 0x0e, 0x35, 0x0c, 0xad, 0x7b, 0x76, 0x9d, 0x43, 0xf5, 0xd1, 0xbf, 0x84, 0xfa, 0x61, 0x14, 0x9b, 0xd7,
0xe3, 0xc4, 0x4c, 0x27, 0x1c, 0x3b, 0x9d, 0x50, 0xba, 0x33, 0xcc, 0x55, 0x43, 0xce, 0x6c, 0x83, 0x09, 0xc7, 0xbe, 0x4e, 0x28, 0xdd, 0x19, 0x64, 0xaa, 0x21, 0x67, 0xb6, 0x41, 0x3c, 0x79, 0x6f,
0x78, 0xf2, 0xde, 0x84, 0x63, 0x7c, 0x70, 0x1e, 0xa7, 0x57, 0x5e, 0xea, 0x2b, 0x0d, 0x2a, 0xa1, 0xc2, 0x31, 0x3f, 0x38, 0x8f, 0x92, 0x2b, 0x2f, 0x19, 0x29, 0x0d, 0x2a, 0xa0, 0xb8, 0xfa, 0x73,
0xb8, 0xfa, 0x73, 0xa6, 0xb5, 0x07, 0xff, 0xd2, 0x5f, 0x39, 0x30, 0x2f, 0x96, 0x84, 0xd1, 0x87, 0xa6, 0xb5, 0x07, 0xff, 0xd2, 0x5f, 0x39, 0x30, 0x27, 0x96, 0x84, 0xd9, 0x87, 0xcc, 0xe7, 0x65,
0x8c, 0xe7, 0xe5, 0x6d, 0x86, 0x69, 0x9c, 0x23, 0x5c, 0x52, 0x19, 0x2e, 0x15, 0xd8, 0x1a, 0xe5, 0x34, 0xc3, 0x6b, 0x9c, 0x23, 0x5c, 0x52, 0x11, 0x2e, 0x14, 0xd8, 0x6a, 0xc5, 0x02, 0x1b, 0xba,
0x02, 0x1b, 0xba, 0x35, 0xd9, 0x2a, 0x2a, 0x57, 0x05, 0x40, 0xde, 0x87, 0xe6, 0x45, 0x9c, 0x60, 0x35, 0xd9, 0xca, 0x2b, 0x57, 0x39, 0x40, 0x3e, 0x84, 0xc6, 0x45, 0x14, 0x63, 0xaa, 0x85, 0x62,
0xa8, 0x85, 0x62, 0x01, 0x1d, 0xf1, 0xc7, 0x89, 0x2b, 0x70, 0xba, 0x0d, 0xcb, 0xc7, 0xb1, 0xcf, 0x01, 0x9d, 0xf1, 0x47, 0xb1, 0x2b, 0x70, 0xba, 0x0d, 0x4b, 0xc7, 0xd1, 0x88, 0x19, 0x49, 0xe3,
0x8c, 0xa0, 0xf1, 0xc6, 0xd3, 0xa0, 0x7f, 0xe5, 0x40, 0x4b, 0x13, 0x93, 0x2d, 0x68, 0xa2, 0xcf, 0x8d, 0xa7, 0x41, 0xff, 0xca, 0x81, 0xa6, 0x26, 0x26, 0x5b, 0xd0, 0x40, 0x9f, 0x5d, 0x70, 0x89,
0x2e, 0xb9, 0xc4, 0x3c, 0x61, 0x46, 0x3a, 0x57, 0x50, 0xa0, 0x01, 0x08, 0x37, 0xab, 0xbd, 0x43, 0xd9, 0x85, 0x19, 0xe9, 0x5c, 0x41, 0x81, 0x06, 0x20, 0xdc, 0xac, 0xf6, 0x0e, 0xb5, 0x2c, 0x99,
0x23, 0x0f, 0x66, 0x8a, 0x70, 0x0f, 0x6f, 0x19, 0xb1, 0xe6, 0x92, 0x51, 0x96, 0x50, 0xfa, 0x16, 0xc9, 0xd3, 0x3d, 0x8c, 0x32, 0x62, 0xcd, 0x05, 0xa3, 0x2c, 0xa0, 0xf4, 0xd7, 0x0e, 0x74, 0xad,
0x7a, 0xd6, 0x14, 0x78, 0xed, 0x84, 0x5e, 0xc6, 0x55, 0xaa, 0xa3, 0x64, 0x68, 0x42, 0x66, 0x7e, 0x39, 0x30, 0xee, 0x04, 0x5e, 0xca, 0xd5, 0x5d, 0x47, 0x09, 0xd1, 0x84, 0xcc, 0x0b, 0x46, 0xcd,
0xd1, 0xa8, 0xe4, 0x17, 0x37, 0x64, 0x11, 0x79, 0xe4, 0xdb, 0x34, 0x22, 0x5f, 0xfa, 0x2f, 0x0e, 0xbe, 0x60, 0x64, 0x09, 0x6e, 0xdd, 0x4c, 0x70, 0x1f, 0x42, 0x4b, 0xdd, 0x26, 0x98, 0x96, 0x9b,
0xf4, 0xf0, 0xf4, 0x82, 0x68, 0x7c, 0x12, 0x87, 0xc1, 0x68, 0x26, 0x4e, 0x51, 0x1f, 0x14, 0x66, 0x2e, 0x3f, 0xe2, 0x8c, 0xba, 0x14, 0x90, 0x13, 0xd1, 0xc7, 0xd0, 0x36, 0x7a, 0x70, 0xc2, 0x90,
0xc8, 0xdc, 0xcb, 0x4f, 0xd1, 0x86, 0xd1, 0xdf, 0x4c, 0x82, 0x48, 0x24, 0x57, 0xea, 0x0c, 0xf3, 0xf1, 0xab, 0x28, 0x79, 0xad, 0x6f, 0x34, 0xaa, 0x99, 0x55, 0x6f, 0x6a, 0x79, 0xf5, 0x86, 0xfe,
0x36, 0x6a, 0xdd, 0x39, 0x43, 0x87, 0x91, 0xb1, 0xe1, 0x04, 0x6f, 0x2e, 0xb9, 0x77, 0x1b, 0xc4, 0xb3, 0x03, 0x5d, 0xd4, 0x09, 0x3f, 0x1c, 0x9f, 0x44, 0x81, 0x3f, 0x9c, 0x09, 0xdd, 0xd0, 0xc7,
0x18, 0x1a, 0x81, 0xd4, 0xe3, 0x6c, 0x38, 0x09, 0xc2, 0x30, 0x90, 0xb4, 0x52, 0xbb, 0xea, 0xba, 0x8f, 0xf7, 0x6e, 0xee, 0x65, 0xba, 0x61, 0xc3, 0xe8, 0xc5, 0x26, 0x7e, 0x28, 0xae, 0x6c, 0x4a,
0xe8, 0xbf, 0x35, 0xa0, 0xa3, 0x2c, 0xf4, 0xc0, 0x1f, 0x33, 0xd4, 0x24, 0xed, 0x04, 0x73, 0xd5, 0x33, 0xb2, 0x36, 0xea, 0xf2, 0x39, 0x43, 0x37, 0x94, 0xb2, 0xc1, 0x04, 0xe3, 0xa1, 0x94, 0xa8,
0x37, 0x10, 0xdd, 0x6f, 0xb9, 0x4d, 0x03, 0x29, 0xcb, 0x7a, 0xae, 0x2a, 0x6b, 0xbc, 0x62, 0x63, 0x0d, 0x62, 0x66, 0x8e, 0x40, 0xe2, 0x71, 0x36, 0x98, 0xf8, 0x41, 0xe0, 0x4b, 0x5a, 0xa9, 0xb3,
0x9f, 0x7d, 0x8c, 0x37, 0xb9, 0x92, 0x5d, 0x01, 0xe8, 0xde, 0x3d, 0xd1, 0x3b, 0x5f, 0xf4, 0x0a, 0x55, 0x5d, 0xf4, 0x5f, 0x6b, 0xd0, 0x56, 0x76, 0x7f, 0x30, 0x1a, 0x33, 0xd4, 0x4f, 0xed, 0x5a,
0xc0, 0xf2, 0xc8, 0x0b, 0x25, 0x8f, 0xfc, 0x18, 0xba, 0x8a, 0x8d, 0x90, 0xbb, 0xf0, 0x92, 0x85, 0x33, 0x83, 0x32, 0x10, 0xdd, 0x6f, 0x39, 0x63, 0x03, 0x29, 0x1e, 0x60, 0xbd, 0x7c, 0x80, 0x18,
0xd2, 0x59, 0x67, 0xe2, 0x5a, 0x94, 0x7a, 0xe4, 0x9e, 0x1e, 0xd9, 0xfa, 0xb6, 0x91, 0x9a, 0x12, 0xb8, 0xa3, 0x11, 0xfb, 0x14, 0xf3, 0x03, 0x55, 0xc5, 0xce, 0x01, 0xdd, 0xbb, 0x27, 0x7a, 0xe7,
0x33, 0x60, 0x25, 0xbc, 0x67, 0xa9, 0x97, 0x5c, 0x68, 0xaf, 0xe7, 0xe7, 0x35, 0x52, 0x01, 0x93, 0xf2, 0x5e, 0x01, 0x58, 0x7e, 0x7e, 0xbe, 0xe0, 0xe7, 0x1f, 0x41, 0x47, 0xb1, 0x11, 0x72, 0x17,
0x6d, 0x98, 0xc7, 0x61, 0xda, 0xf1, 0xd4, 0x1b, 0x82, 0x24, 0x21, 0x5b, 0x30, 0xcf, 0xfc, 0xb1, 0xbe, 0x37, 0x57, 0x65, 0xeb, 0x4c, 0x5c, 0x8b, 0x52, 0x8f, 0xdc, 0xd3, 0x23, 0x9b, 0xdf, 0x36,
0xb0, 0x62, 0xb3, 0xa8, 0x6d, 0x9c, 0x91, 0x2b, 0x09, 0xd0, 0x2c, 0x11, 0x2d, 0x99, 0xa5, 0xed, 0x52, 0x53, 0xe2, 0xbd, 0x5a, 0x09, 0xef, 0x59, 0xe2, 0xc5, 0x17, 0xda, 0x97, 0x8e, 0xb2, 0xca,
0xb5, 0x16, 0xb0, 0xf9, 0xdc, 0xa7, 0xeb, 0x40, 0x8e, 0x19, 0xbf, 0x8a, 0xd3, 0xd7, 0x66, 0xea, 0xab, 0x80, 0xc9, 0x36, 0xcc, 0xe1, 0x30, 0xed, 0xce, 0xaa, 0xcd, 0x4b, 0x92, 0x90, 0x2d, 0x98,
0xf7, 0xd7, 0x73, 0xd0, 0x31, 0x60, 0xb4, 0xb0, 0x31, 0x2e, 0x78, 0xe8, 0x07, 0xde, 0x84, 0x71, 0x63, 0xa3, 0xb1, 0xf0, 0x0d, 0xa6, 0xae, 0x1a, 0x67, 0xe4, 0x4a, 0x02, 0x34, 0x76, 0x44, 0x0b,
0x96, 0x2a, 0x4d, 0x2d, 0xa1, 0xc2, 0xb9, 0x5d, 0x8e, 0x87, 0xf1, 0x94, 0x0f, 0x7d, 0x36, 0x4e, 0xc6, 0x6e, 0xfb, 0xc2, 0x79, 0x6c, 0x3e, 0x1f, 0xd1, 0x35, 0x20, 0xc7, 0x52, 0x6b, 0xcd, 0x0b,
0x99, 0xac, 0x5f, 0x3a, 0x6e, 0x09, 0x45, 0xba, 0x89, 0xf7, 0xc6, 0xa4, 0x93, 0xfa, 0x50, 0x42, 0xe5, 0x5f, 0xd7, 0xa1, 0x6d, 0xc0, 0x68, 0xb7, 0x63, 0x5c, 0xf0, 0x60, 0xe4, 0x7b, 0x13, 0xc6,
0x75, 0xd4, 0x25, 0x65, 0xd4, 0x2c, 0xa2, 0x2e, 0x29, 0x91, 0xb2, 0x6f, 0x98, 0xaf, 0xf1, 0x0d, 0x59, 0xa2, 0x34, 0xb5, 0x80, 0x0a, 0x97, 0x79, 0x39, 0x1e, 0x44, 0x53, 0x3e, 0x18, 0xb1, 0x71,
0x9f, 0xc0, 0x86, 0xf4, 0x02, 0x91, 0xdc, 0xce, 0xb0, 0xa4, 0x26, 0x37, 0xf4, 0x92, 0x6d, 0x58, 0xc2, 0x64, 0x55, 0xd4, 0x71, 0x0b, 0x28, 0xd2, 0x4d, 0xbc, 0x37, 0x26, 0x9d, 0xd4, 0x87, 0x02,
0xc1, 0x35, 0x6b, 0x05, 0xcf, 0x82, 0x9f, 0xcb, 0xda, 0x8e, 0xe3, 0x56, 0x70, 0xa4, 0x45, 0x73, 0xaa, 0x73, 0x39, 0x29, 0xa3, 0x46, 0x9e, 0xcb, 0x49, 0x89, 0x14, 0x3d, 0xce, 0x5c, 0x85, 0xc7,
0xb4, 0x68, 0x65, 0x71, 0xa7, 0x82, 0x0b, 0x5a, 0xef, 0x8d, 0x4d, 0xdb, 0x56, 0xb4, 0x25, 0x9c, 0xf9, 0x0c, 0xd6, 0xa5, 0x6f, 0x51, 0xb6, 0x39, 0x28, 0xa8, 0xc9, 0x0d, 0xbd, 0x64, 0x1b, 0x96,
0xde, 0x85, 0x3b, 0x42, 0x4d, 0x5e, 0xc6, 0x49, 0x1c, 0xc6, 0xe3, 0xd9, 0xe9, 0xf4, 0x2c, 0x1b, 0x71, 0xcd, 0x5a, 0xc1, 0x53, 0xff, 0xe7, 0xb2, 0x62, 0xe4, 0xb8, 0x25, 0x1c, 0x69, 0xd1, 0x1c,
0xa5, 0x41, 0x82, 0x01, 0x1e, 0xfd, 0x77, 0x07, 0xd6, 0xac, 0x5e, 0x15, 0x75, 0xfe, 0xa1, 0xd4, 0x2d, 0x5a, 0x59, 0x32, 0x2a, 0xe1, 0x82, 0xd6, 0x7b, 0x63, 0xd3, 0xb6, 0x14, 0x6d, 0x01, 0xa7,
0xd9, 0xbc, 0xa2, 0x23, 0x35, 0x6b, 0x55, 0x17, 0x60, 0x63, 0x5f, 0xe5, 0x04, 0x32, 0xbc, 0xfe, 0x9b, 0x70, 0x47, 0xa8, 0xc9, 0xcb, 0x28, 0x8e, 0x82, 0x68, 0x3c, 0x3b, 0x9d, 0x9e, 0xa5, 0xc3,
0x52, 0x15, 0x79, 0xf6, 0x61, 0x59, 0x4f, 0xad, 0x07, 0x4a, 0x35, 0xeb, 0x57, 0xd5, 0x4c, 0x8d, 0xc4, 0x8f, 0x31, 0x6d, 0xa4, 0xff, 0xe6, 0xc0, 0xaa, 0xd5, 0xab, 0x72, 0xd9, 0x3f, 0x94, 0x3a,
0x5f, 0x52, 0x03, 0x34, 0x8b, 0x3f, 0x91, 0xa1, 0x0a, 0xf3, 0xc5, 0x26, 0xd0, 0x2b, 0xe2, 0xf8, 0x9b, 0xd5, 0x89, 0xa4, 0x66, 0xad, 0x18, 0x9e, 0x4d, 0x12, 0xca, 0xa4, 0xfd, 0x2b, 0x55, 0x3a,
0x81, 0x1e, 0x2f, 0xba, 0x9e, 0x98, 0x43, 0xdc, 0xce, 0x28, 0x07, 0x33, 0xfa, 0xb7, 0x0e, 0x40, 0xda, 0x87, 0x25, 0x3d, 0xb5, 0x1e, 0x28, 0xd5, 0xac, 0x57, 0x56, 0x33, 0x35, 0x7e, 0x51, 0x0d,
0xb1, 0x3a, 0x3c, 0x79, 0xe5, 0x4f, 0xd5, 0x1e, 0xda, 0x6e, 0x01, 0x60, 0xb0, 0x62, 0x85, 0x72, 0xd0, 0x2c, 0xfe, 0x44, 0x26, 0x40, 0x6c, 0x24, 0x36, 0x81, 0xce, 0x16, 0xc7, 0xf7, 0xf5, 0x78,
0xd2, 0xdd, 0x74, 0x34, 0x86, 0xb7, 0xff, 0x43, 0x58, 0x1e, 0x87, 0xf1, 0x99, 0xb8, 0xe8, 0x3c, 0xd1, 0xf5, 0xc4, 0x1c, 0xe2, 0xb6, 0x87, 0x19, 0x98, 0xd2, 0xbf, 0x75, 0x00, 0xf2, 0xd5, 0xe1,
0x3e, 0x4d, 0x59, 0xa6, 0x4a, 0x9d, 0x4b, 0x12, 0xfe, 0xbe, 0x42, 0x6f, 0x70, 0xd7, 0x7f, 0xd7, 0xc9, 0xe7, 0xde, 0x19, 0xf7, 0xd0, 0x32, 0x3c, 0x31, 0xa6, 0x40, 0x56, 0x82, 0x28, 0xdd, 0x4d,
0xc8, 0x33, 0xe4, 0x62, 0xcf, 0x37, 0x9a, 0x11, 0xd9, 0xab, 0x78, 0xbf, 0x1b, 0x12, 0x52, 0x11, 0x5b, 0x63, 0x98, 0x53, 0x3c, 0x80, 0xa5, 0x71, 0x10, 0x9d, 0x89, 0xf0, 0xe9, 0xf1, 0x69, 0xc2,
0x68, 0x9f, 0x7c, 0x6b, 0x14, 0xf9, 0x19, 0x2c, 0xa5, 0xd2, 0xbd, 0x68, 0xdf, 0xd3, 0xfc, 0x06, 0x52, 0x55, 0x40, 0x5d, 0x94, 0xf0, 0xf7, 0x15, 0x9a, 0x47, 0x87, 0x86, 0x11, 0x1d, 0xe8, 0xdf,
0xdf, 0xd3, 0x4b, 0xad, 0x8b, 0xe5, 0xf7, 0x60, 0xc5, 0xf3, 0x2f, 0x59, 0xca, 0x03, 0x11, 0x24, 0xd5, 0xb2, 0x7b, 0x77, 0xbe, 0xe7, 0x1b, 0xcd, 0x88, 0xec, 0x95, 0xbc, 0xdf, 0x0d, 0xd7, 0x5c,
0x8a, 0x9b, 0x56, 0x7a, 0xcc, 0x65, 0x03, 0x17, 0x37, 0xe0, 0x43, 0x58, 0x1e, 0xc9, 0xc2, 0x73, 0x91, 0xbe, 0x9f, 0x7c, 0x6b, 0x6e, 0xfa, 0x18, 0x16, 0x13, 0xe9, 0x5e, 0xb4, 0xef, 0x69, 0xbc,
0x4e, 0xa9, 0x9e, 0x93, 0x0a, 0x18, 0x09, 0xe9, 0x3f, 0xeb, 0x64, 0xdc, 0x3e, 0xc3, 0x9b, 0x25, 0xc3, 0xf7, 0x74, 0x13, 0x2b, 0xb0, 0xfc, 0x1e, 0x2c, 0x7b, 0xa3, 0x4b, 0x96, 0x70, 0x5f, 0xa4,
0x62, 0xee, 0xae, 0x51, 0xda, 0xdd, 0x77, 0x55, 0xf2, 0xec, 0xeb, 0x3a, 0x86, 0x2a, 0x51, 0x48, 0x9e, 0x22, 0x7e, 0x4b, 0x8f, 0xb9, 0x64, 0xe0, 0x22, 0xac, 0x3e, 0x80, 0xa5, 0xa1, 0x2c, 0x67,
0x50, 0x15, 0x32, 0x6c, 0x91, 0x36, 0xdf, 0x45, 0xa4, 0x74, 0x07, 0x96, 0x4f, 0x19, 0xdf, 0xc7, 0x67, 0x94, 0xea, 0x91, 0x2a, 0x87, 0x91, 0x90, 0xfe, 0x93, 0xbe, 0xe2, 0xdb, 0x67, 0x78, 0xb3,
0x13, 0xd4, 0x9e, 0xef, 0x2e, 0xb4, 0x23, 0x76, 0x35, 0x94, 0x47, 0x2c, 0x43, 0x92, 0x56, 0xc4, 0x44, 0xcc, 0xdd, 0xd5, 0x0a, 0xbb, 0xfb, 0xae, 0xba, 0x92, 0x8f, 0x74, 0x75, 0x44, 0x15, 0x3e,
0xae, 0x04, 0x0d, 0x25, 0xb0, 0x52, 0xd0, 0xcb, 0x68, 0x90, 0xfe, 0x7d, 0x03, 0x16, 0x9f, 0x47, 0x24, 0xa8, 0xca, 0x23, 0xb6, 0x48, 0x1b, 0xef, 0x23, 0x52, 0xba, 0x03, 0x4b, 0xa7, 0x8c, 0xef,
0x97, 0x71, 0x30, 0x12, 0xe9, 0xf0, 0x84, 0x4d, 0x62, 0xfd, 0xde, 0x81, 0xff, 0xf1, 0xe2, 0x17, 0xe3, 0x09, 0x6a, 0xcf, 0xb7, 0x09, 0xad, 0x90, 0x5d, 0x0d, 0xe4, 0x11, 0xcb, 0x38, 0xdd, 0x0c,
0xd5, 0xd3, 0x84, 0xab, 0x3c, 0x55, 0x37, 0xf1, 0x0a, 0x4c, 0x8b, 0xc7, 0x35, 0xa9, 0x6d, 0x06, 0xd9, 0x95, 0xa0, 0xa1, 0x04, 0x96, 0x73, 0x7a, 0x99, 0x63, 0xd2, 0xbf, 0xaf, 0xc1, 0xc2, 0xf3,
0x42, 0x36, 0x60, 0x21, 0x35, 0x1f, 0x02, 0x55, 0xab, 0x78, 0xec, 0x99, 0x37, 0x1e, 0x7b, 0x44, 0xf0, 0x32, 0xf2, 0x87, 0xe2, 0x92, 0x3d, 0x61, 0x93, 0x48, 0xbf, 0xa2, 0xe0, 0x7f, 0x0c, 0xfb,
0x61, 0x44, 0x16, 0x86, 0xc5, 0x91, 0xb4, 0x5c, 0xdd, 0x14, 0x81, 0x66, 0xca, 0x54, 0x65, 0x1d, 0xa2, 0x26, 0x1b, 0x73, 0x75, 0xfb, 0xd5, 0x4d, 0x0c, 0x81, 0x49, 0xfe, 0x64, 0x27, 0xb5, 0xcd,
0x2f, 0xd3, 0x45, 0x15, 0x68, 0x9a, 0x20, 0x5e, 0xb8, 0x72, 0x80, 0xa4, 0x91, 0x0e, 0xc9, 0x84, 0x40, 0xc8, 0x3a, 0xcc, 0x27, 0xe6, 0xf3, 0xa2, 0x6a, 0xe5, 0x4f, 0x48, 0x73, 0xc6, 0x13, 0x92,
0x30, 0x00, 0x29, 0xbf, 0x25, 0xb6, 0xa5, 0x9a, 0x94, 0x60, 0xfa, 0x15, 0x90, 0x7d, 0xdf, 0x57, 0x28, 0xb7, 0xc8, 0x72, 0xb3, 0x38, 0x92, 0xa6, 0xab, 0x9b, 0x22, 0x7d, 0x4d, 0x98, 0xaa, 0xd7,
0x52, 0xc9, 0xe3, 0xe6, 0x62, 0x3f, 0x8e, 0xb5, 0x9f, 0x1a, 0xbe, 0x8d, 0x7a, 0xbe, 0x07, 0xd0, 0x63, 0x30, 0x5d, 0x50, 0xe9, 0xab, 0x09, 0x62, 0xc0, 0x95, 0x03, 0x24, 0x8d, 0x74, 0x48, 0x26,
0x39, 0x31, 0x1e, 0x43, 0x85, 0x00, 0xf5, 0x33, 0xa8, 0x12, 0xba, 0x81, 0x18, 0x13, 0x36, 0xcc, 0x84, 0x09, 0x48, 0xf1, 0x85, 0xb2, 0x25, 0xd5, 0xa4, 0x00, 0xd3, 0xaf, 0x81, 0xec, 0x8f, 0x46,
0x09, 0xe9, 0x1f, 0x01, 0x39, 0x0a, 0x32, 0x9e, 0xaf, 0x2f, 0xcf, 0x68, 0x74, 0x5a, 0x68, 0x66, 0x4a, 0x2a, 0x59, 0x36, 0x9e, 0xef, 0xc7, 0xb1, 0xf6, 0x53, 0xc1, 0xb7, 0x56, 0xcd, 0xf7, 0x00,
0x34, 0x0a, 0x13, 0x19, 0xcd, 0xbe, 0x2c, 0x54, 0x97, 0x37, 0xb6, 0x0d, 0xad, 0x40, 0x42, 0xda, 0xda, 0x27, 0xc6, 0x13, 0xab, 0x10, 0xa0, 0x7e, 0x5c, 0x55, 0x42, 0x37, 0x10, 0x63, 0xc2, 0x9a,
0x7f, 0x2e, 0x29, 0xc5, 0xd3, 0x94, 0x79, 0x3f, 0xde, 0xf4, 0x0a, 0xb4, 0xdc, 0xf3, 0xaf, 0x1c, 0x39, 0x21, 0xfd, 0x23, 0x20, 0x47, 0x7e, 0xca, 0xb3, 0xf5, 0x65, 0xf7, 0x24, 0x7d, 0xd9, 0x34,
0x58, 0x54, 0x5b, 0xc3, 0x7b, 0xca, 0x7a, 0x06, 0x56, 0x89, 0xa7, 0x89, 0xd5, 0x3f, 0xf8, 0x55, 0xef, 0x49, 0x0a, 0x13, 0xf7, 0xa4, 0x7d, 0x59, 0xfe, 0x2e, 0x6e, 0x6c, 0x1b, 0x9a, 0xbe, 0x84,
0x4f, 0x7a, 0xae, 0xee, 0xa4, 0x09, 0x34, 0x13, 0x8f, 0x5f, 0x88, 0x30, 0xbd, 0xed, 0x8a, 0xff, 0xb4, 0xff, 0x5c, 0x54, 0x8a, 0xa7, 0x29, 0xb3, 0x7e, 0x8c, 0xf4, 0x0a, 0xb4, 0xdc, 0xf3, 0xaf,
0x3a, 0x7d, 0x98, 0x2f, 0xd2, 0x07, 0x55, 0x94, 0x57, 0x8b, 0xca, 0xeb, 0xc5, 0x5f, 0xc8, 0xa2, 0x1c, 0x58, 0x50, 0x5b, 0xc3, 0x38, 0x65, 0x3d, 0x2e, 0xab, 0xeb, 0xac, 0x89, 0x55, 0x3f, 0x23,
0x7c, 0x01, 0x17, 0x32, 0x50, 0x0b, 0x2c, 0xcb, 0x40, 0x91, 0xba, 0x79, 0x3f, 0x1d, 0x40, 0xff, 0x96, 0x4f, 0xba, 0x5e, 0x75, 0xd2, 0x04, 0x1a, 0xb1, 0xc7, 0x2f, 0x44, 0x12, 0xdb, 0x72, 0xc5,
0x29, 0x0b, 0x19, 0x67, 0xfb, 0x61, 0x58, 0xe6, 0x7f, 0x17, 0xee, 0xd4, 0xf4, 0x29, 0x5b, 0xfb, 0x7f, 0x7d, 0x29, 0x99, 0xcb, 0x2f, 0x25, 0xaa, 0xd4, 0xaf, 0x16, 0x95, 0x55, 0xa1, 0xbf, 0x94,
0x3e, 0xac, 0x3e, 0x65, 0x67, 0xd3, 0xf1, 0x11, 0xbb, 0x2c, 0xaa, 0x0b, 0x04, 0x9a, 0xd9, 0x45, 0xa5, 0xfe, 0x1c, 0xce, 0x65, 0xa0, 0x16, 0x58, 0x94, 0x81, 0x22, 0x75, 0xb3, 0x7e, 0xda, 0x87,
0x7c, 0xa5, 0xce, 0x4b, 0xfc, 0x27, 0xef, 0x01, 0x84, 0x48, 0x33, 0xcc, 0x12, 0x36, 0x52, 0xda, 0xde, 0x53, 0x16, 0x30, 0xce, 0xf6, 0x83, 0xa0, 0xc8, 0x7f, 0x13, 0xee, 0x54, 0xf4, 0x29, 0x5b,
0xd4, 0x16, 0xc8, 0x69, 0xc2, 0x46, 0xf4, 0x13, 0x20, 0x26, 0x1f, 0xb5, 0x05, 0xb4, 0x80, 0xe9, 0xfb, 0x3e, 0xac, 0x3c, 0x65, 0x67, 0xd3, 0xf1, 0x11, 0xbb, 0xcc, 0x6b, 0x16, 0x04, 0x1a, 0xe9,
0xd9, 0x30, 0x9b, 0x65, 0x9c, 0x4d, 0xb4, 0xf1, 0x9b, 0x10, 0x7d, 0x08, 0xdd, 0x13, 0x6f, 0xe6, 0x45, 0x74, 0xa5, 0xce, 0x4b, 0xfc, 0x27, 0x1f, 0x00, 0x04, 0x48, 0x33, 0x48, 0x63, 0x36, 0x54,
0xb2, 0xaf, 0xd5, 0xeb, 0x3a, 0x66, 0x2f, 0xde, 0x0c, 0xd5, 0x33, 0xcf, 0x5e, 0x44, 0x37, 0x4d, 0xda, 0xd4, 0x12, 0xc8, 0x69, 0xcc, 0x86, 0xf4, 0x33, 0x20, 0x26, 0x1f, 0xb5, 0x05, 0xb4, 0x80,
0x61, 0x41, 0x12, 0x22, 0x53, 0x9f, 0x65, 0x3c, 0x88, 0x64, 0x61, 0x46, 0x31, 0x35, 0xa0, 0xca, 0xe9, 0xd9, 0x20, 0x9d, 0xa5, 0x9c, 0x4d, 0xb4, 0xf1, 0x9b, 0x10, 0x7d, 0x00, 0x9d, 0x13, 0x6f,
0x71, 0x37, 0x6a, 0x8e, 0x5b, 0x85, 0x2e, 0xfa, 0x3d, 0x46, 0x9d, 0xab, 0x85, 0x6d, 0xef, 0x41, 0xe6, 0xb2, 0x6f, 0xd4, 0x9b, 0x3d, 0xde, 0x89, 0xbc, 0x19, 0xaa, 0x67, 0x76, 0x27, 0x12, 0xdd,
0xcf, 0x4a, 0xe1, 0xc9, 0x22, 0xcc, 0xed, 0x1f, 0x1d, 0xad, 0xdc, 0x22, 0x1d, 0x58, 0x7c, 0x71, 0x34, 0x81, 0x79, 0x49, 0x88, 0x4c, 0x47, 0x2c, 0xe5, 0x7e, 0x28, 0xcb, 0x3d, 0x8a, 0xa9, 0x01,
0x72, 0x70, 0xfc, 0xfc, 0xf8, 0xd9, 0x8a, 0x83, 0x8d, 0x27, 0x47, 0x2f, 0x4e, 0xb1, 0xd1, 0xd8, 0x95, 0x8e, 0xbb, 0x56, 0x71, 0xdc, 0x2a, 0x75, 0xd1, 0xaf, 0x3c, 0xea, 0x5c, 0x2d, 0x6c, 0x7b,
0xfb, 0xcd, 0x26, 0xb4, 0xf3, 0xe8, 0x91, 0xfc, 0x0c, 0x7a, 0x56, 0xc2, 0x4e, 0xee, 0xaa, 0x23, 0x0f, 0xba, 0x56, 0x61, 0x80, 0x2c, 0x40, 0x7d, 0xff, 0xe8, 0x68, 0xf9, 0x16, 0x69, 0xc3, 0xc2,
0xac, 0xab, 0x00, 0x0c, 0xee, 0xd5, 0x77, 0xaa, 0xa3, 0x7a, 0xff, 0x17, 0xbf, 0xfd, 0xaf, 0x7f, 0x8b, 0x93, 0x83, 0xe3, 0xe7, 0xc7, 0xcf, 0x96, 0x1d, 0x6c, 0x3c, 0x39, 0x7a, 0x71, 0x8a, 0x8d,
0x68, 0xf4, 0xc9, 0xc6, 0xee, 0xe5, 0xc7, 0xbb, 0x2a, 0x23, 0xdf, 0x15, 0x85, 0x67, 0x59, 0xe7, 0xda, 0xde, 0x6f, 0x37, 0xa0, 0x95, 0x65, 0x8f, 0xe4, 0x67, 0xd0, 0xb5, 0xca, 0x00, 0x64, 0x53,
0x7e, 0x0d, 0x4b, 0x76, 0x42, 0x4f, 0xee, 0xd9, 0xce, 0xba, 0x34, 0xdb, 0x7b, 0x37, 0xf4, 0xaa, 0x1d, 0x61, 0x55, 0x5d, 0xa1, 0x7f, 0xb7, 0xba, 0x53, 0x1d, 0xd5, 0x87, 0xbf, 0xf8, 0xdd, 0x7f,
0xe9, 0xee, 0x89, 0xe9, 0x36, 0xc8, 0xba, 0x39, 0x5d, 0x1e, 0xd5, 0x31, 0xf1, 0x32, 0x61, 0x7e, 0xfe, 0xba, 0xd6, 0x23, 0xeb, 0xbb, 0x97, 0x9f, 0xee, 0xaa, 0x7b, 0xfe, 0xae, 0x28, 0x67, 0xcb,
0x17, 0x42, 0x34, 0xbf, 0xfa, 0xef, 0x45, 0x06, 0x77, 0xaa, 0xdf, 0x80, 0xa8, 0x8f, 0x46, 0x68, 0xea, 0xf9, 0x6b, 0x58, 0xb4, 0xcb, 0x04, 0xe4, 0xae, 0xed, 0xac, 0x0b, 0xb3, 0x7d, 0x70, 0x43,
0x5f, 0x4c, 0x45, 0xc8, 0x0a, 0x4e, 0x65, 0x7e, 0x16, 0x42, 0x7e, 0x0a, 0xed, 0xfc, 0x0d, 0x9c, 0xaf, 0x9a, 0xee, 0xae, 0x98, 0x6e, 0x9d, 0xac, 0x99, 0xd3, 0x65, 0x59, 0x1d, 0x13, 0xef, 0x1d,
0x6c, 0x1a, 0x2f, 0xfe, 0xe6, 0xab, 0xfa, 0xa0, 0x5f, 0xed, 0x50, 0x9b, 0xb8, 0x2b, 0x38, 0xdf, 0xe6, 0xd7, 0x26, 0x44, 0xf3, 0xab, 0xfe, 0x0a, 0xa5, 0x7f, 0xa7, 0xfc, 0x65, 0x89, 0xfa, 0x14,
0xa6, 0x15, 0xce, 0x9f, 0x3a, 0xdb, 0xe4, 0x08, 0x6e, 0x2b, 0x8f, 0x71, 0xc6, 0xfe, 0x3f, 0x3b, 0x85, 0xf6, 0xc4, 0x54, 0x84, 0x2c, 0xe3, 0x54, 0xe6, 0xc7, 0x26, 0xe4, 0xa7, 0xd0, 0xca, 0x5e,
0xa9, 0xf9, 0x9a, 0xe5, 0x91, 0x43, 0x3e, 0x83, 0x96, 0xfe, 0x2c, 0x80, 0x6c, 0xd4, 0x7f, 0x9b, 0xd6, 0xc9, 0x86, 0xf1, 0x1d, 0x81, 0xf9, 0x56, 0xdf, 0xef, 0x95, 0x3b, 0xd4, 0x26, 0x36, 0x05,
0x30, 0xd8, 0xac, 0xe0, 0xca, 0x50, 0xf6, 0x01, 0x8a, 0x57, 0x70, 0xd2, 0xbf, 0xe9, 0xb1, 0x3e, 0xe7, 0xdb, 0xb4, 0xc4, 0xf9, 0x73, 0x67, 0x9b, 0x1c, 0xc1, 0x6d, 0xe5, 0x31, 0xce, 0xd8, 0xff,
0x17, 0x62, 0xcd, 0x93, 0xf9, 0x58, 0x7c, 0x04, 0x60, 0x3f, 0xb2, 0x93, 0xef, 0x14, 0xf4, 0xb5, 0x65, 0x27, 0x15, 0xdf, 0xc8, 0x3c, 0x74, 0xc8, 0x63, 0x68, 0xea, 0x8f, 0x0d, 0xc8, 0x7a, 0xf5,
0xcf, 0xef, 0xdf, 0xc0, 0x90, 0x6e, 0x08, 0xd9, 0xad, 0x90, 0x25, 0x94, 0x5d, 0xc4, 0xae, 0x74, 0x17, 0x0f, 0xfd, 0x8d, 0x12, 0xae, 0x0c, 0x65, 0x1f, 0x20, 0x7f, 0x5b, 0x27, 0xbd, 0x9b, 0x3e,
0x76, 0xfd, 0x13, 0xe8, 0x18, 0x4f, 0xe5, 0xc4, 0x28, 0x89, 0x96, 0x5e, 0xe5, 0x07, 0x83, 0xba, 0x01, 0xc8, 0x84, 0x58, 0xf1, 0x10, 0x3f, 0x16, 0x9f, 0x16, 0xd8, 0x4f, 0xf7, 0xe4, 0x3b, 0x39,
0x2e, 0xc5, 0x7d, 0x5d, 0x70, 0x5f, 0xa2, 0x6d, 0xe4, 0x2e, 0x9e, 0x85, 0xf0, 0x48, 0x7e, 0x84, 0x7d, 0xe5, 0xa3, 0xfe, 0x3b, 0x18, 0xd2, 0x75, 0x21, 0xbb, 0x65, 0xb2, 0x88, 0xb2, 0x0b, 0xd9,
0xc6, 0xa3, 0xde, 0xce, 0x48, 0xf1, 0x8c, 0x6f, 0xbf, 0xb0, 0xe5, 0xe7, 0x5d, 0x79, 0x66, 0xa3, 0x95, 0x7e, 0xf9, 0xfb, 0x09, 0xb4, 0x8d, 0x07, 0x78, 0x62, 0x14, 0x5a, 0x0b, 0x6f, 0xfd, 0xfd,
0xab, 0x82, 0x6b, 0x87, 0x14, 0x5c, 0xc9, 0x0f, 0x61, 0x51, 0xbd, 0xa1, 0x91, 0xdb, 0xc5, 0xb9, 0x7e, 0x55, 0x97, 0xe2, 0xbe, 0x26, 0xb8, 0x2f, 0xd2, 0x16, 0x72, 0x17, 0x8f, 0x4d, 0x78, 0x24,
0x1a, 0xb9, 0xd6, 0x60, 0xa3, 0x0c, 0x2b, 0x66, 0x6b, 0x82, 0x59, 0x8f, 0x74, 0x90, 0xd9, 0x98, 0x3f, 0x42, 0xe3, 0x51, 0x2f, 0x72, 0x24, 0xff, 0x38, 0xc0, 0x7e, 0xb7, 0xcb, 0xce, 0xbb, 0xf4,
0xf1, 0x00, 0x79, 0x84, 0xb0, 0x6c, 0x57, 0x35, 0xb3, 0xdc, 0xcc, 0x6a, 0x4b, 0xb5, 0xb9, 0x99, 0x78, 0x47, 0x57, 0x04, 0xd7, 0x36, 0xc9, 0xb9, 0x92, 0x1f, 0xc2, 0x82, 0x7a, 0x99, 0x23, 0xb7,
0xd5, 0xd7, 0x51, 0x6d, 0x33, 0xd3, 0xe6, 0xb5, 0xab, 0xab, 0xd0, 0x7f, 0x0e, 0x5d, 0xf3, 0xc1, 0xf3, 0x73, 0x35, 0xee, 0x5a, 0xfd, 0xf5, 0x22, 0xac, 0x98, 0xad, 0x0a, 0x66, 0x5d, 0xd2, 0x46,
0x96, 0x0c, 0x8c, 0x9d, 0x97, 0x1e, 0x77, 0x07, 0x77, 0x6b, 0xfb, 0x6c, 0x71, 0x93, 0xae, 0x39, 0x66, 0x63, 0xc6, 0x7d, 0xe4, 0x11, 0xc0, 0x92, 0x5d, 0x2b, 0x4d, 0x33, 0x33, 0xab, 0x2c, 0x00,
0x0d, 0xf9, 0x09, 0x2c, 0x1b, 0x6f, 0x06, 0xa7, 0xb3, 0x68, 0x94, 0x1f, 0x67, 0xf5, 0x2d, 0x61, 0x67, 0x66, 0x56, 0x5d, 0x9d, 0xb5, 0xcd, 0x4c, 0x9b, 0xd7, 0xae, 0xae, 0x6d, 0xff, 0x39, 0x74,
0x50, 0x17, 0xfb, 0xd1, 0x4d, 0xc1, 0x78, 0x95, 0x5a, 0x8c, 0xf1, 0x28, 0x9f, 0x40, 0xc7, 0xe0, 0xcc, 0x67, 0x60, 0xd2, 0x37, 0x76, 0x5e, 0x78, 0x32, 0xee, 0x6f, 0x56, 0xf6, 0xd9, 0xe2, 0x26,
0xf1, 0x4d, 0x7c, 0x37, 0x8d, 0x2e, 0xb3, 0x7e, 0xff, 0xc8, 0x21, 0xbf, 0x76, 0xa0, 0x6b, 0xbe, 0x1d, 0x73, 0x1a, 0xf2, 0x13, 0x58, 0x32, 0x5e, 0x22, 0x4e, 0x67, 0xe1, 0x30, 0x3b, 0xce, 0xf2,
0x40, 0x11, 0x2b, 0x9b, 0x29, 0xf1, 0xe9, 0x9b, 0x7d, 0x26, 0x23, 0xfa, 0x95, 0x58, 0xe4, 0xc9, 0x0b, 0x45, 0xbf, 0x2a, 0xf7, 0xa3, 0x1b, 0x82, 0xf1, 0x0a, 0xb5, 0x18, 0xe3, 0x51, 0x3e, 0x81,
0xf6, 0xb1, 0x25, 0xe4, 0xb7, 0x56, 0x4d, 0x79, 0xc7, 0xfc, 0xde, 0xe9, 0xba, 0xdc, 0x69, 0xbe, 0xb6, 0xc1, 0xe3, 0x5d, 0x7c, 0x37, 0x8c, 0x2e, 0xf3, 0x55, 0xe0, 0xa1, 0x43, 0x7e, 0xe3, 0x40,
0xb5, 0x5c, 0xef, 0xbe, 0x15, 0x0f, 0x53, 0xd7, 0x8f, 0x1c, 0xf2, 0xa9, 0xfc, 0x6c, 0x4d, 0x07, 0xc7, 0x7c, 0xd7, 0x22, 0xd6, 0x6d, 0xa6, 0xc0, 0xa7, 0x67, 0xf6, 0x99, 0x8c, 0xe8, 0xd7, 0x62,
0x1a, 0xc4, 0x30, 0xf0, 0xb2, 0xd8, 0xcc, 0x8f, 0xc1, 0xb6, 0x9c, 0x47, 0x0e, 0xf9, 0x0b, 0xf9, 0x91, 0x27, 0xdb, 0xc7, 0x96, 0x90, 0xdf, 0x5a, 0x95, 0xea, 0x1d, 0xf3, 0x2b, 0xaa, 0xeb, 0x62,
0xa9, 0x93, 0x1a, 0x2b, 0xa4, 0xff, 0xae, 0xe3, 0xe9, 0x03, 0xb1, 0xa3, 0xf7, 0xe9, 0x1d, 0x6b, 0xa7, 0xf9, 0x82, 0x73, 0xbd, 0xfb, 0x56, 0x3c, 0x77, 0x5d, 0x3f, 0x74, 0xc8, 0xe7, 0xf2, 0x63,
0x47, 0x65, 0x0f, 0x77, 0x02, 0x50, 0x44, 0x8d, 0xa4, 0x14, 0x42, 0xe5, 0xb6, 0x5f, 0x0d, 0x2c, 0x38, 0x9d, 0x68, 0x10, 0xc3, 0xc0, 0x8b, 0x62, 0x33, 0x3f, 0x31, 0xdb, 0x72, 0x1e, 0x3a, 0xe4,
0xed, 0x53, 0xd5, 0x91, 0x16, 0x72, 0xfc, 0x99, 0x54, 0x48, 0x45, 0x9f, 0xe5, 0xc7, 0x5a, 0x8d, 0x2f, 0xe4, 0x07, 0x54, 0x6a, 0xac, 0x90, 0xfe, 0xfb, 0x8e, 0xa7, 0xf7, 0xc5, 0x8e, 0x3e, 0xa4,
0xfe, 0x06, 0x83, 0xba, 0x2e, 0xc5, 0xff, 0xbb, 0x82, 0xff, 0x7b, 0xe4, 0xae, 0xc9, 0x7f, 0xf7, 0x77, 0xac, 0x1d, 0x15, 0x3d, 0xdc, 0x09, 0x40, 0x9e, 0x35, 0x92, 0x42, 0x0a, 0x95, 0xd9, 0x7e,
0xad, 0x19, 0x2d, 0x5e, 0x93, 0xaf, 0xa0, 0x77, 0x14, 0xc7, 0xaf, 0xa7, 0x49, 0x9e, 0x0c, 0xd8, 0x39, 0xb1, 0xb4, 0x4f, 0x55, 0x67, 0x5a, 0xc8, 0xf1, 0x67, 0x52, 0x21, 0x15, 0x7d, 0x9a, 0x1d,
0xf1, 0x0f, 0x46, 0xac, 0x83, 0xd2, 0xa6, 0xe8, 0x07, 0x82, 0xf3, 0x5d, 0x72, 0xc7, 0xe6, 0x5c, 0x6b, 0x39, 0xfb, 0xeb, 0xf7, 0xab, 0xba, 0x14, 0xff, 0xef, 0x0a, 0xfe, 0x1f, 0x90, 0x4d, 0x93,
0xc4, 0xb0, 0xd7, 0xc4, 0x83, 0xd5, 0xdc, 0xef, 0xe7, 0x1b, 0x19, 0xd8, 0x7c, 0xcc, 0x50, 0xb2, 0xff, 0xee, 0x5b, 0x33, 0x5b, 0xbc, 0x26, 0x5f, 0x43, 0xf7, 0x28, 0x8a, 0x5e, 0x4f, 0xe3, 0xec,
0x32, 0x87, 0x75, 0x13, 0xe7, 0x73, 0x64, 0x9a, 0xe7, 0x23, 0x87, 0x9c, 0x40, 0xf7, 0x29, 0x1b, 0x32, 0x60, 0xe7, 0x3f, 0x98, 0xb1, 0xf6, 0x0b, 0x9b, 0xa2, 0x1f, 0x09, 0xce, 0x9b, 0xe4, 0x8e,
0xc5, 0x3e, 0x53, 0x31, 0xcb, 0x5a, 0xb1, 0xf2, 0x3c, 0xd6, 0x19, 0xf4, 0x2c, 0xd0, 0xf6, 0x04, 0xcd, 0x39, 0xcf, 0x61, 0xaf, 0x89, 0x07, 0x2b, 0x99, 0xdf, 0xcf, 0x36, 0xd2, 0xb7, 0xf9, 0x98,
0x89, 0x37, 0x4b, 0xd9, 0xd7, 0xbb, 0x6f, 0x55, 0x30, 0x74, 0xad, 0x3d, 0x81, 0x0e, 0xe0, 0x2c, 0xa9, 0x64, 0x69, 0x0e, 0x2b, 0x12, 0x67, 0x73, 0xa4, 0x9a, 0xe7, 0x43, 0x87, 0x9c, 0x40, 0xe7,
0x4f, 0x50, 0x8a, 0xf8, 0x2c, 0x4f, 0x50, 0x89, 0xf8, 0x2c, 0x4f, 0xa0, 0x03, 0x48, 0x12, 0x62, 0x29, 0x1b, 0x46, 0x23, 0xa6, 0x72, 0x96, 0xd5, 0x7c, 0xe5, 0x59, 0xae, 0xd3, 0xef, 0x5a, 0xa0,
0x1c, 0x58, 0x0a, 0x12, 0xf3, 0xdb, 0xe3, 0xa6, 0xd0, 0x72, 0x70, 0xff, 0x66, 0x02, 0x7b, 0xb6, 0xed, 0x09, 0x62, 0x6f, 0x96, 0xb0, 0x6f, 0x76, 0xdf, 0xaa, 0x64, 0xe8, 0x5a, 0x7b, 0x02, 0x9d,
0x6d, 0x7b, 0xb6, 0x53, 0xe8, 0x3d, 0x65, 0x52, 0x58, 0xb2, 0x0c, 0x37, 0xb0, 0x5d, 0x8b, 0x59, 0xc0, 0x59, 0x9e, 0xa0, 0x90, 0xf1, 0x59, 0x9e, 0xa0, 0x94, 0xf1, 0x59, 0x9e, 0x40, 0x27, 0x90,
0xb2, 0x2b, 0xbb, 0x1d, 0xd1, 0x67, 0x3b, 0x7a, 0x51, 0x03, 0x23, 0x3f, 0x85, 0xce, 0x33, 0xc6, 0x24, 0xc0, 0x3c, 0xb0, 0x90, 0x24, 0x66, 0xd1, 0xe3, 0xa6, 0xd4, 0xb2, 0x7f, 0xef, 0x66, 0x02,
0x75, 0xdd, 0x2d, 0xbf, 0x83, 0x4b, 0x85, 0xb8, 0x41, 0x4d, 0xd9, 0x8e, 0xde, 0x17, 0xdc, 0x06, 0x7b, 0xb6, 0x6d, 0x7b, 0xb6, 0x53, 0xe8, 0x3e, 0x65, 0x52, 0x58, 0xb2, 0x0c, 0xd7, 0xb7, 0x5d,
0xa4, 0x9f, 0x73, 0xdb, 0x65, 0xfe, 0x98, 0x49, 0x27, 0x30, 0x0c, 0xfc, 0x6b, 0xf2, 0x63, 0xc1, 0x8b, 0x59, 0xb2, 0x2b, 0xba, 0x1d, 0xd1, 0x67, 0x3b, 0x7a, 0x51, 0x03, 0x23, 0x3f, 0x85, 0xf6,
0x3c, 0x2f, 0x9f, 0x6f, 0x18, 0xd5, 0x1c, 0x93, 0xf9, 0x72, 0x09, 0xaf, 0xe3, 0x8c, 0x39, 0xfe, 0x33, 0xc6, 0x75, 0xdd, 0x2d, 0x8b, 0xc1, 0x85, 0x42, 0x5c, 0xbf, 0xa2, 0x6c, 0x47, 0xef, 0x09,
0xee, 0x5b, 0x55, 0xc5, 0xbe, 0x26, 0x11, 0x74, 0x8c, 0x27, 0x91, 0xdc, 0xa0, 0xaa, 0xef, 0x2c, 0x6e, 0x7d, 0xd2, 0xcb, 0xb8, 0xed, 0xb2, 0xd1, 0x98, 0x49, 0x27, 0x30, 0xf0, 0x47, 0xd7, 0xe4,
0xb9, 0x41, 0xd5, 0xbc, 0xa0, 0xd0, 0x2d, 0x31, 0x0f, 0x25, 0xf7, 0x8b, 0x79, 0xe4, 0xab, 0x49, 0xc7, 0x82, 0x79, 0x56, 0x94, 0x5f, 0x37, 0xaa, 0x39, 0x26, 0xf3, 0xa5, 0x02, 0x5e, 0xc5, 0x19,
0x31, 0xd3, 0xee, 0x5b, 0x6f, 0xc2, 0xaf, 0xc9, 0x2b, 0xf1, 0x99, 0x89, 0x59, 0x5b, 0x2c, 0x62, 0xef, 0xf8, 0xbb, 0x6f, 0x55, 0x69, 0xfc, 0x9a, 0x84, 0xd0, 0x36, 0x1e, 0x5a, 0x32, 0x83, 0x2a,
0x80, 0x72, 0x19, 0x32, 0x17, 0x96, 0xd1, 0x65, 0xc7, 0x05, 0x72, 0x2a, 0x71, 0x33, 0xbe, 0x32, 0xbf, 0xde, 0x64, 0x06, 0x55, 0xf1, 0x2e, 0x43, 0xb7, 0xc4, 0x3c, 0x94, 0xdc, 0xcb, 0xe7, 0x91,
0xc2, 0x29, 0xab, 0xc6, 0xaa, 0xb5, 0xe4, 0xc6, 0x52, 0x5a, 0xbe, 0xb3, 0x9a, 0x72, 0x9a, 0x8e, 0x6f, 0x31, 0xf9, 0x4c, 0xbb, 0x6f, 0xbd, 0x09, 0xbf, 0x26, 0xaf, 0xc4, 0xc7, 0x2b, 0x66, 0x6d,
0xac, 0x64, 0x8d, 0xc0, 0x88, 0xac, 0xac, 0x22, 0x83, 0x11, 0x59, 0xd9, 0xc5, 0x04, 0x8c, 0xac, 0x31, 0xcf, 0x01, 0x8a, 0x65, 0xc8, 0x4c, 0x58, 0x46, 0x97, 0x9d, 0x17, 0xc8, 0xa9, 0x44, 0x64,
0x8a, 0xc4, 0x24, 0x8f, 0xac, 0x2a, 0x39, 0x4f, 0xee, 0x0c, 0xab, 0x59, 0xcc, 0xd9, 0x82, 0xf8, 0x7c, 0x65, 0xa4, 0x53, 0x56, 0x8d, 0x55, 0x6b, 0xc9, 0x8d, 0xa5, 0xb4, 0x6c, 0x67, 0x15, 0xe5,
0xfc, 0xfb, 0x0f, 0xfe, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x2e, 0x7d, 0x20, 0xe1, 0x30, 0x2e, 0x00, 0x34, 0x9d, 0x59, 0xc9, 0x1a, 0x81, 0x91, 0x59, 0x59, 0x45, 0x06, 0x23, 0xb3, 0xb2, 0x8b, 0x09,
0x00, 0x98, 0x59, 0xe5, 0x17, 0x93, 0x2c, 0xb3, 0x2a, 0xdd, 0x79, 0x32, 0x67, 0x58, 0xbe, 0xc5, 0x9c,
0xcd, 0x8b, 0x8f, 0xca, 0xff, 0xe0, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x14, 0x4c, 0x36, 0x7a,
0x86, 0x2e, 0x00, 0x00,
} }

@ -442,8 +442,13 @@ message NodeInfo {
message LightningNode { message LightningNode {
uint32 last_update = 1 [ json_name = "last_update" ]; uint32 last_update = 1 [ json_name = "last_update" ];
string pub_key = 2 [ json_name = "pub_key" ]; string pub_key = 2 [ json_name = "pub_key" ];
string address = 3 [ json_name = "address" ]; string alias = 3 [ json_name = "alias" ];
string alias = 4 [ json_name = "alias" ]; repeated NodeAddress addresses = 4 [ json_name = "addresses" ];
}
message NodeAddress {
string network = 1 [ json_name = "network" ];
string addr = 2 [ json_name = "addr" ];
} }
message RoutingPolicy { message RoutingPolicy {

@ -1111,11 +1111,14 @@
"pub_key": { "pub_key": {
"type": "string" "type": "string"
}, },
"address": {
"type": "string"
},
"alias": { "alias": {
"type": "string" "type": "string"
},
"addresses": {
"type": "array",
"items": {
"$ref": "#/definitions/lnrpcNodeAddress"
}
} }
} }
}, },
@ -1244,6 +1247,17 @@
"lnrpcNewWitnessAddressRequest": { "lnrpcNewWitnessAddressRequest": {
"type": "object" "type": "object"
}, },
"lnrpcNodeAddress": {
"type": "object",
"properties": {
"network": {
"type": "string"
},
"addr": {
"type": "string"
}
}
},
"lnrpcNodeInfo": { "lnrpcNodeInfo": {
"type": "object", "type": "object",
"properties": { "properties": {

@ -50,6 +50,16 @@ func (c CreditsAmount) ToSatoshi() int64 {
return int64(c / 1000) return int64(c / 1000)
} }
// addressType specifies the network protocol and version that should be used
// when connecting to a node at a particular address.
type addressType uint8
const (
tcp4Addr addressType = 1
tcp6Addr addressType = 2
onionAddr addressType = 3
)
// writeElement is a one-stop shop to write the big endian representation of // writeElement is a one-stop shop to write the big endian representation of
// any element which is to be serialized for the wire protocol. The passed // any element which is to be serialized for the wire protocol. The passed
// io.Writer should be backed by an appropriatly sized byte slice, or be able // io.Writer should be backed by an appropriatly sized byte slice, or be able
@ -292,16 +302,46 @@ func writeElement(w io.Writer, element interface{}) error {
} }
case *net.TCPAddr: case *net.TCPAddr:
var ip [16]byte if e.IP.To4() != nil {
copy(ip[:], e.IP.To16()) var descriptor [1]byte
if _, err := w.Write(ip[:]); err != nil { descriptor[0] = uint8(tcp4Addr)
if _, err := w.Write(descriptor[:]); err != nil {
return err
}
var ip [4]byte
copy(ip[:], e.IP.To4())
if _, err := w.Write(ip[:]); err != nil {
return err
}
} else {
var descriptor [1]byte
descriptor[0] = uint8(tcp6Addr)
if _, err := w.Write(descriptor[:]); err != nil {
return err
}
var ip [16]byte
copy(ip[:], e.IP.To16())
if _, err := w.Write(ip[:]); err != nil {
return err
}
}
var port [2]byte
binary.BigEndian.PutUint16(port[:], uint16(e.Port))
if _, err := w.Write(port[:]); err != nil {
return err
}
case []net.Addr:
// Write out the number of addresses.
if err := writeElement(w, uint16(len(e))); err != nil {
return err return err
} }
var port [4]byte // Append the actual addresses.
binary.BigEndian.PutUint32(port[:], uint32(e.Port)) for _, address := range e {
if _, err := w.Write(port[:]); err != nil { if err := writeElement(w, address); err != nil {
return err return err
}
} }
case RGB: case RGB:
err := writeElements(w, err := writeElements(w,
@ -578,21 +618,44 @@ func readElement(r io.Reader, element interface{}) error {
TxPosition: binary.BigEndian.Uint16(txPosition[:]), TxPosition: binary.BigEndian.Uint16(txPosition[:]),
} }
case **net.TCPAddr: case *[]net.Addr:
var ip [16]byte var addresses []net.Addr
if _, err = io.ReadFull(r, ip[:]); err != nil { var numAddrs [2]byte
if _, err = io.ReadFull(r, numAddrs[:]); err != nil {
return err return err
} }
var port [4]byte for i := 0; i < int(binary.BigEndian.Uint16(numAddrs[:])); i++ {
if _, err = io.ReadFull(r, port[:]); err != nil { var descriptor [1]byte
return err if _, err = io.ReadFull(r, descriptor[:]); err != nil {
} return err
}
*e = &net.TCPAddr{ address := &net.TCPAddr{}
IP: (net.IP)(ip[:]), switch descriptor[0] {
Port: int(binary.BigEndian.Uint32(port[:])), case 1:
var ip [4]byte
if _, err = io.ReadFull(r, ip[:]); err != nil {
return err
}
address.IP = (net.IP)(ip[:])
case 2:
var ip [16]byte
if _, err = io.ReadFull(r, ip[:]); err != nil {
return err
}
address.IP = (net.IP)(ip[:])
}
var port [2]byte
if _, err = io.ReadFull(r, port[:]); err != nil {
return err
}
address.Port = int(binary.BigEndian.Uint16(port[:]))
addresses = append(addresses, address)
} }
*e = addresses
case *RGB: case *RGB:
err := readElements(r, err := readElements(r,
&e.red, &e.red,

@ -56,7 +56,9 @@ var (
someSig, _ = btcec.ParseSignature(sigStr, btcec.S256()) someSig, _ = btcec.ParseSignature(sigStr, btcec.S256())
someSigBytes = someSig.Serialize() someSigBytes = someSig.Serialize()
someAddress = &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333} someAddress = &net.TCPAddr{IP: (net.IP)([]byte{0x7f, 0x0, 0x0, 0x1}), Port: 8333}
someOtherAddress, _ = net.ResolveTCPAddr("tcp", "[2001:db8:85a3:0:0:8a2e:370:7334]:80")
someAddresses = []net.Addr{someAddress, someOtherAddress}
maxUint32 uint32 = (1 << 32) - 1 maxUint32 uint32 = (1 << 32) - 1
maxUint24 uint32 = (1 << 24) - 1 maxUint24 uint32 = (1 << 24) - 1

@ -87,27 +87,19 @@ type NodeAnnouncement struct {
// announcements. // announcements.
Timestamp uint32 Timestamp uint32
// Address includes two specification fields: 'ipv6' and // NodeID is a public key which is used as node identification.
// 'port' on which the node is accepting incoming connections.
Address *net.TCPAddr
// NodeID is a public key which is used as node
// identification.
NodeID *btcec.PublicKey NodeID *btcec.PublicKey
// RGBColor is used to customize their node's appearance in // RGBColor is used to customize their node's appearance in
// maps and graphs // maps and graphs
RGBColor RGB RGBColor RGB
// TODO(roasbeef): add the global features here // Alias is used to customize their node's appearance in maps and graphs
// pad is used to reserve to additional bytes for future
// usage.
pad uint16
// Alias is used to customize their node's appearance in maps
// and graphs
Alias Alias Alias Alias
// Address includes two specification fields: 'ipv6' and 'port' on which
// the node is accepting incoming connections.
Addresses []net.Addr
} }
// A compile time check to ensure NodeAnnouncement implements the // A compile time check to ensure NodeAnnouncement implements the
@ -131,27 +123,24 @@ func (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error {
return readElements(r, return readElements(r,
&a.Signature, &a.Signature,
&a.Timestamp, &a.Timestamp,
&a.Address,
&a.NodeID, &a.NodeID,
&a.RGBColor, &a.RGBColor,
&a.pad,
&a.Alias, &a.Alias,
&a.Addresses,
) )
} }
// Encode serializes the target NodeAnnouncement into the passed io.Writer // Encode serializes the target NodeAnnouncement into the passed io.Writer
// observing the protocol version specified. // observing the protocol version specified.
// //
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error { func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error {
return writeElements(w, return writeElements(w,
a.Signature, a.Signature,
a.Timestamp, a.Timestamp,
a.Address,
a.NodeID, a.NodeID,
a.RGBColor, a.RGBColor,
a.pad,
a.Alias, a.Alias,
a.Addresses,
) )
} }
@ -168,34 +157,19 @@ func (a *NodeAnnouncement) Command() uint32 {
// //
// This is part of the lnwire.Message interface. // This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) MaxPayloadLength(pver uint32) uint32 { func (a *NodeAnnouncement) MaxPayloadLength(pver uint32) uint32 {
var length uint32
// Signature - 64 bytes // Signature - 64 bytes
length += 64
// Timestamp - 4 bytes // Timestamp - 4 bytes
length += 4
// Ipv6 - 16 bytes
length += 16
// Port - 4 bytes
length += 4
// NodeID - 33 bytes // NodeID - 33 bytes
length += 33
// RGBColor - 3 bytes // RGBColor - 3 bytes
length += 3
// pad - 2 bytes
length += 2
// Alias - 32 bytes // Alias - 32 bytes
length += 32 // NumAddresses - 2 bytes
// AddressDescriptor - 1 byte
// Ipv4 - 4 bytes (optional)
// Ipv6 - 16 bytes (optional)
// Port - 2 bytes (optional)
// 158 // Base size, 140, but can be variable due to multiple addresses
return length return 8192
} }
// DataToSign returns the part of the message that should be signed. // DataToSign returns the part of the message that should be signed.
@ -205,11 +179,10 @@ func (a *NodeAnnouncement) DataToSign() ([]byte, error) {
var w bytes.Buffer var w bytes.Buffer
err := writeElements(&w, err := writeElements(&w,
a.Timestamp, a.Timestamp,
a.Address,
a.NodeID, a.NodeID,
a.RGBColor, a.RGBColor,
a.pad,
a.Alias, a.Alias,
a.Addresses,
) )
if err != nil { if err != nil {
return nil, err return nil, err

@ -13,11 +13,10 @@ func TestNodeAnnouncementEncodeDecode(t *testing.T) {
cua := &NodeAnnouncement{ cua := &NodeAnnouncement{
Signature: someSig, Signature: someSig,
Timestamp: maxUint32, Timestamp: maxUint32,
Address: someAddress,
NodeID: pubKey, NodeID: pubKey,
RGBColor: someRGB, RGBColor: someRGB,
pad: maxUint16,
Alias: someAlias, Alias: someAlias,
Addresses: someAddresses,
} }
// Next encode the NA message into an empty bytes buffer. // Next encode the NA message into an empty bytes buffer.
@ -39,7 +38,7 @@ func TestNodeAnnouncementEncodeDecode(t *testing.T) {
} }
} }
func TestNodeAnnoucementValidation(t *testing.T) { func TestNodeAnnouncementValidation(t *testing.T) {
getKeys := func(s string) (*btcec.PrivateKey, *btcec.PublicKey) { getKeys := func(s string) (*btcec.PrivateKey, *btcec.PublicKey) {
return btcec.PrivKeyFromBytes(btcec.S256(), []byte(s)) return btcec.PrivKeyFromBytes(btcec.S256(), []byte(s))
} }
@ -47,13 +46,11 @@ func TestNodeAnnoucementValidation(t *testing.T) {
nodePrivKey, nodePubKey := getKeys("node-id-1") nodePrivKey, nodePubKey := getKeys("node-id-1")
var hash []byte var hash []byte
na := &NodeAnnouncement{ na := &NodeAnnouncement{
Timestamp: maxUint32, Timestamp: maxUint32,
Address: someAddress, Addresses: someAddresses,
NodeID: nodePubKey, NodeID: nodePubKey,
RGBColor: someRGB, RGBColor: someRGB,
pad: maxUint16,
Alias: someAlias, Alias: someAlias,
} }
@ -68,15 +65,14 @@ func TestNodeAnnoucementValidation(t *testing.T) {
} }
} }
func TestNodeAnnoucementPayloadLength(t *testing.T) { func TestNodeAnnouncementPayloadLength(t *testing.T) {
na := &NodeAnnouncement{ na := &NodeAnnouncement{
Signature: someSig, Signature: someSig,
Timestamp: maxUint32, Timestamp: maxUint32,
Address: someAddress,
NodeID: pubKey, NodeID: pubKey,
RGBColor: someRGB, RGBColor: someRGB,
pad: maxUint16,
Alias: someAlias, Alias: someAlias,
Addresses: someAddresses,
} }
var b bytes.Buffer var b bytes.Buffer
@ -85,8 +81,19 @@ func TestNodeAnnoucementPayloadLength(t *testing.T) {
} }
serializedLength := uint32(b.Len()) serializedLength := uint32(b.Len())
if serializedLength != na.MaxPayloadLength(0) { if serializedLength != 164 {
t.Fatalf("payload length estimate is incorrect: expected %v "+ t.Fatalf("payload length estimate is incorrect: expected %v "+
"got %v", serializedLength, na.MaxPayloadLength(0)) "got %v", 164, serializedLength)
}
if na.MaxPayloadLength(0) != 8192 {
t.Fatalf("max payload length doesn't match: expected 8192, got %v",
na.MaxPayloadLength(0))
}
}
func TestValidateAlias(t *testing.T) {
if err := someAlias.Validate(); err != nil {
t.Fatalf("alias was invalid: %v", err)
} }
} }

@ -285,7 +285,7 @@ func addToTopologyChange(graph *channeldb.ChannelGraph, update *TopologyChange,
// No further data munging or db queries are required. // No further data munging or db queries are required.
case *lnwire.NodeAnnouncement: case *lnwire.NodeAnnouncement:
nodeUpdate := &NetworkNodeUpdate{ nodeUpdate := &NetworkNodeUpdate{
Addresses: []net.Addr{m.Address}, Addresses: m.Addresses,
IdentityKey: m.NodeID, IdentityKey: m.NodeID,
Alias: m.Alias.String(), Alias: m.Alias.String(),
} }

@ -20,7 +20,9 @@ import (
) )
var ( var (
testAddr, _ = net.ResolveTCPAddr("tcp", "10.0.0.1:9000") testAddr = &net.TCPAddr{IP: (net.IP)([]byte{0xA, 0x0, 0x0, 0x1}),
Port: 9000}
testAddrs = []net.Addr{testAddr}
testHash = [32]byte{ testHash = [32]byte{
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab, 0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
@ -41,7 +43,7 @@ func createGraphNode() (*channeldb.LightningNode, error) {
pub := priv.PubKey().SerializeCompressed() pub := priv.PubKey().SerializeCompressed()
return &channeldb.LightningNode{ return &channeldb.LightningNode{
LastUpdate: time.Unix(updateTime, 0), LastUpdate: time.Unix(updateTime, 0),
Address: testAddr, Addresses: testAddrs,
PubKey: priv.PubKey(), PubKey: priv.PubKey(),
Color: color.RGBA{1, 2, 3, 0}, Color: color.RGBA{1, 2, 3, 0},
Alias: "kek" + string(pub[:]), Alias: "kek" + string(pub[:]),
@ -63,7 +65,7 @@ func createTestWireNode() (*lnwire.NodeAnnouncement, error) {
return &lnwire.NodeAnnouncement{ return &lnwire.NodeAnnouncement{
Timestamp: uint32(prand.Int31()), Timestamp: uint32(prand.Int31()),
Address: testAddr, Addresses: testAddrs,
NodeID: priv.PubKey(), NodeID: priv.PubKey(),
Alias: alias, Alias: alias,
}, nil }, nil
@ -444,9 +446,9 @@ func TestNodeUpdateNotification(t *testing.T) {
// The notification received should directly map the // The notification received should directly map the
// announcement originally sent. // announcement originally sent.
nodeNtfn := ntfns[0] nodeNtfn := ntfns[0]
if nodeNtfn.Addresses[0] != ann.Address { if nodeNtfn.Addresses[0] != ann.Addresses[0] {
t.Fatalf("node address doesn't match: expected %v, got %v", t.Fatalf("node address doesn't match: expected %v, got %v",
nodeNtfn.Addresses[0], ann.Address) nodeNtfn.Addresses[0], ann.Addresses[0])
} }
if !nodeNtfn.IdentityKey.IsEqual(ann.NodeID) { if !nodeNtfn.IdentityKey.IsEqual(ann.NodeID) {
t.Fatalf("node identity keys don't match: expected %x, "+ t.Fatalf("node identity keys don't match: expected %x, "+

@ -135,10 +135,12 @@ func parseTestGraph(path string) (*channeldb.ChannelGraph, func(), aliasMap, err
// We'll use this fake address for the IP address of all the nodes in // We'll use this fake address for the IP address of all the nodes in
// our tests. This value isn't needed for path finding so it doesn't // our tests. This value isn't needed for path finding so it doesn't
// need to be unique. // need to be unique.
var testAddrs []net.Addr
testAddr, err := net.ResolveTCPAddr("tcp", "192.0.0.1:8888") testAddr, err := net.ResolveTCPAddr("tcp", "192.0.0.1:8888")
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
testAddrs = append(testAddrs, testAddr)
// Next, create a temporary graph database for usage within the test. // Next, create a temporary graph database for usage within the test.
graph, cleanUp, err := makeTestGraph() graph, cleanUp, err := makeTestGraph()
@ -162,7 +164,7 @@ func parseTestGraph(path string) (*channeldb.ChannelGraph, func(), aliasMap, err
dbNode := &channeldb.LightningNode{ dbNode := &channeldb.LightningNode{
LastUpdate: time.Now(), LastUpdate: time.Now(),
Address: testAddr, Addresses: testAddrs,
PubKey: pub, PubKey: pub,
Alias: node.Alias, Alias: node.Alias,
} }

@ -693,7 +693,7 @@ func (r *ChannelRouter) processNetworkAnnouncement(msg lnwire.Message) bool {
node := &channeldb.LightningNode{ node := &channeldb.LightningNode{
LastUpdate: msgTimestamp, LastUpdate: msgTimestamp,
Address: msg.Address, Addresses: msg.Addresses,
PubKey: msg.NodeID, PubKey: msg.NodeID,
Alias: msg.Alias.String(), Alias: msg.Alias.String(),
} }
@ -945,7 +945,7 @@ func (r *ChannelRouter) syncChannelGraph(syncReq *syncRequest) error {
ann := &lnwire.NodeAnnouncement{ ann := &lnwire.NodeAnnouncement{
Signature: r.fakeSig, Signature: r.fakeSig,
Timestamp: uint32(node.LastUpdate.Unix()), Timestamp: uint32(node.LastUpdate.Unix()),
Address: node.Address, Addresses: node.Addresses,
NodeID: node.PubKey, NodeID: node.PubKey,
Alias: alias, Alias: alias,
} }

@ -1381,12 +1381,21 @@ func (r *rpcServer) DescribeGraph(context.Context,
// within the graph), collating their current state into the RPC // within the graph), collating their current state into the RPC
// response. // response.
err := graph.ForEachNode(func(node *channeldb.LightningNode) error { err := graph.ForEachNode(func(node *channeldb.LightningNode) error {
nodeAddrs := make([]*lnrpc.NodeAddress, 0)
for _, addr := range node.Addresses {
nodeAddr := &lnrpc.NodeAddress{
Network: addr.Network(),
Addr: addr.String(),
}
nodeAddrs = append(nodeAddrs, nodeAddr)
}
resp.Nodes = append(resp.Nodes, &lnrpc.LightningNode{ resp.Nodes = append(resp.Nodes, &lnrpc.LightningNode{
LastUpdate: uint32(node.LastUpdate.Unix()), LastUpdate: uint32(node.LastUpdate.Unix()),
PubKey: hex.EncodeToString(node.PubKey.SerializeCompressed()), PubKey: hex.EncodeToString(node.PubKey.SerializeCompressed()),
Address: node.Address.String(), Addresses: nodeAddrs,
Alias: node.Alias, Alias: node.Alias,
}) })
return nil return nil
}) })
if err != nil { if err != nil {
@ -1516,12 +1525,20 @@ func (r *rpcServer) GetNodeInfo(_ context.Context, in *lnrpc.NodeInfoRequest) (*
return nil, err return nil, err
} }
nodeAddrs := make([]*lnrpc.NodeAddress, 0)
for _, addr := range node.Addresses {
nodeAddr := &lnrpc.NodeAddress{
Network: addr.Network(),
Addr: addr.String(),
}
nodeAddrs = append(nodeAddrs, nodeAddr)
}
// TODO(roasbeef): list channels as well? // TODO(roasbeef): list channels as well?
return &lnrpc.NodeInfo{ return &lnrpc.NodeInfo{
Node: &lnrpc.LightningNode{ Node: &lnrpc.LightningNode{
LastUpdate: uint32(node.LastUpdate.Unix()), LastUpdate: uint32(node.LastUpdate.Unix()),
PubKey: in.PubKey, PubKey: in.PubKey,
Address: node.Address.String(), Addresses: nodeAddrs,
Alias: node.Alias, Alias: node.Alias,
}, },
NumChannels: numChannels, NumChannels: numChannels,

@ -159,11 +159,12 @@ func newServer(listenAddrs []string, notifier chainntnfs.ChainNotifier,
if !ok { if !ok {
return nil, fmt.Errorf("default listener must be TCP") return nil, fmt.Errorf("default listener must be TCP")
} }
selfAddrs := []net.Addr{selfAddr}
chanGraph := chanDB.ChannelGraph() chanGraph := chanDB.ChannelGraph()
self := &channeldb.LightningNode{ self := &channeldb.LightningNode{
LastUpdate: time.Now(), LastUpdate: time.Now(),
Address: selfAddr, Addresses: selfAddrs,
PubKey: privKey.PubKey(), PubKey: privKey.PubKey(),
// TODO(roasbeef): make alias configurable // TODO(roasbeef): make alias configurable
Alias: hex.EncodeToString(serializedPubKey[:10]), Alias: hex.EncodeToString(serializedPubKey[:10]),